@startuml update-profile !include ../../../pipeline/diagrams/biergarten-weizen-theme.puml skinparam sequenceMessageAlign center skinparam maxMessageSize 200 title User Authentication Flow - Update Profile actor User participant "API\nController" as API participant "MediatR pipeline\n(ValidationBehavior)" as Mediator box "Handler Layer" #F1F3EA participant "UpdateProfileHandler" as UpdateProfileHandler participant "UserManager" as UserMgr end box box "Repository / Cross-slice" #DBEEDD participant "DapperUserStore\n(IUserStore/IUserPasswordStore/\nIUserEmailStore)" as UserStore end box database "SQL Server" as DB note over UserMgr ASP.NET Core Identity's UserManager replaces the deleted AuthRepository: handlers no longer issue SQL or call Argon2 directly, they delegate to UserManager, which in turn calls DapperUserStore (persistence) and Argon2PasswordHasher (IPasswordHasher). end note User -> API: PATCH /api/auth/profile\n{firstName, lastName, dateOfBirth}\n(requires Bearer access token) activate API API -> Mediator: Send(UpdateProfileCommand(\n GetAuthenticatedUserId(),\n firstName, lastName, dateOfBirth)) activate Mediator note right of Mediator ValidationBehavior runs UpdateProfileValidator (same name/DateOfBirth rules as registration) end note alt Validation fails Mediator -> API: throws FluentValidation.ValidationException API -> User: 400 Bad Request else Validation succeeds Mediator -> UpdateProfileHandler: Handle(command) activate UpdateProfileHandler UpdateProfileHandler -> UserMgr: FindByIdAsync(userAccountId) activate UserMgr UserMgr -> UserStore: FindByIdAsync(userAccountId) UserStore --> UserMgr: ApplicationUser or null UserMgr --> UpdateProfileHandler: ApplicationUser or null deactivate UserMgr alt Account not found UpdateProfileHandler -> Mediator: throw NotFoundException Mediator -> API: propagate API -> User: 404 Not Found else Account found UpdateProfileHandler -> UpdateProfileHandler: user.FirstName = ...\nuser.LastName = ...\nuser.DateOfBirth = ... note right of UpdateProfileHandler First/last name and date of birth aren't tracked by any Identity store interface - mutated directly on the ApplicationUser, then saved via UserManager.UpdateAsync. end note UpdateProfileHandler -> UserMgr: UpdateAsync(user) activate UserMgr UserMgr -> UserStore: UpdateAsync(user) UserStore -> DB: UPDATE dbo.UserAccount\nSET FirstName = @FirstName,\n LastName = @LastName,\n DateOfBirth = @DateOfBirth, ... UserStore --> UserMgr: IdentityResult UserMgr --> UpdateProfileHandler: IdentityResult deactivate UserMgr alt !result.Succeeded UpdateProfileHandler -> Mediator: throw ConflictException Mediator -> API: propagate API -> User: 409 Conflict else result.Succeeded UpdateProfileHandler --> Mediator: UpdateProfilePayload(\n user.Id, firstName,\n lastName, dateOfBirth) deactivate UpdateProfileHandler Mediator --> API: UpdateProfilePayload deactivate Mediator API -> User: 200 OK\n{message: "Profile updated successfully.",\npayload: {...}} end end end deactivate API @enduml