T3(customer): add full CRUD controller, service impl, DTO, and JWT auth#65
T3(customer): add full CRUD controller, service impl, DTO, and JWT auth#65devin-ai-integration[bot] wants to merge 1 commit into
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| existing.PhoneNumber = dto.PhoneNumber; | ||
| existing.Address = dto.Address; | ||
| existing.City = dto.City; |
There was a problem hiding this comment.
🔴 Updating a customer silently erases phone number, address, and city when those fields are omitted
Optional customer fields are overwritten with null (dto.PhoneNumber / dto.Address / dto.City assigned directly at CustomerController.cs:78-80) instead of being preserved like name and email are, so any update request that omits those fields wipes out the stored values.
Impact: A user updating only their name or email loses their phone number, address, and city data.
Inconsistent null-coalescing between required and optional fields in the Update action
In the Update method at src/Services/Customer/Customer.API/Controllers/CustomerController.cs:76-81, Name and Email use the null-coalescing operator (??) so a null DTO value preserves the existing database value:
existing.Name = dto.Name ?? existing.Name;
existing.Email = dto.Email ?? existing.Email;But the three optional fields are assigned directly without the same guard:
existing.PhoneNumber = dto.PhoneNumber;
existing.Address = dto.Address;
existing.City = dto.City;When a PUT request omits PhoneNumber, Address, or City (they deserialize as null from the CustomerDto), the existing stored values are overwritten with null. This is an inconsistency: the code intends partial-update semantics (as evidenced by the ?? pattern on the other fields and on Gender at line 81), but three fields use full-replace semantics instead.
| existing.PhoneNumber = dto.PhoneNumber; | |
| existing.Address = dto.Address; | |
| existing.City = dto.City; | |
| existing.PhoneNumber = dto.PhoneNumber ?? existing.PhoneNumber; | |
| existing.Address = dto.Address ?? existing.Address; | |
| existing.City = dto.City ?? existing.City; |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Good catch — the inconsistency is real. The direct assignment for PhoneNumber/Address/City was implemented per the task spec, but this does create different semantics vs the ??-guarded Name/Email/Gender fields. Escalating to the author to confirm whether partial-update semantics (null-coalescing) should apply to all fields.
Summary
Implements the Customer microservice API layer: full CRUD endpoints, service implementation, DTO, and JWT Bearer authentication.
JWT auth pipeline added to
Program.cs— readsJwt:Secret/Issuer/Audiencefromappsettings.json, registersJwtBearerDefaultsas default auth scheme withTokenValidationParameters(issuer, audience, lifetime, signing key).UseAuthentication()+UseAuthorization()middleware wired before controller mapping.CustomerService : ICustomerService— EF Core implementation inCustomer.Infrastructure.Services:GetAllAsync()→OrderBy(c => c.Name)CreateAsync()/UpdateAsync()→ setsCreatedDate/UpdatedDatetoDateTime.UtcNowDeleteAsync()→ returnsfalseif not foundCustomerController—[Authorize]at class level (all endpoints require valid Bearer JWT):GET /api/customer→ returnsIEnumerable<CustomerDto>GET /api/customer/{id}→ 200 or 404POST /api/customer→ validatesName+Emailrequired, mapsGenderstring →Genderenum viaEnum.TryParse, returns 201 withCreatedAtActionPUT /api/customer/{id}→ partial update (null fields keep existing values, exceptPhoneNumber/Address/Citywhich are always overwritten)DELETE /api/customer/{id}→ 204 or 404CustomerDto— flat DTO withoutOrderscollection (key difference from monolith'sCustomerVM).Uses
Entities = Customer.Domain.Entitiesnamespace alias throughout to resolveCustomerentity vsCustomernamespace ambiguity.Part of the Customer microservice carve-out stacked PR chain (T3/T5).
Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/df4fd98794c34738bf5a70c588276dcb
Requested by: @mbatchelor81