Files
the-biergarten-app/docs/website/diagrams-src/auth/resend-confirmation.puml

98 lines
3.1 KiB
Plaintext

@startuml resend-confirmation
!include ../../../pipeline/diagrams/biergarten-weizen-theme.puml
skinparam sequenceMessageAlign center
skinparam maxMessageSize 200
title User Authentication Flow - Resend Confirmation Email
actor User
participant "API\nController" as API
participant "MediatR pipeline\n(ValidationBehavior)" as Mediator
box "Handler Layer" #F1F3EA
participant "ResendConfirmationEmailHandler" as ResendHandler
participant "UserManager<ApplicationUser>" as UserMgr
participant "TokenService" as TokenSvc
end box
box "Infrastructure Layer" #EBECE3
participant "Email\nProvider" as SMTP
participant "Template\nProvider" as Template
end box
box "Repository / Cross-slice" #DBEEDD
participant "DapperUserStore\n(IUserStore/IUserPasswordStore/\nIUserEmailStore)" as UserStore
participant "EmailDispatcher\n(Features.Emails)" as EmailDispatcher
end box
database "SQL Server" as DB
note over UserMgr
ASP.NET Core Identity's UserManager<TUser>
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<TUser>).
end note
User -> API: POST /api/auth/confirm/resend?userId=<id>\n(requires Bearer access token)
activate API
API -> Mediator: Send(ResendConfirmationEmailCommand(userId))
activate Mediator
Mediator -> ResendHandler: Handle(command)
activate ResendHandler
ResendHandler -> UserMgr: FindByIdAsync(userId)
activate UserMgr
UserMgr -> UserStore: FindByIdAsync(userId)
activate UserStore
UserStore -> DB: SELECT ...\nFROM dbo.UserAccount\nWHERE UserAccountID = @Id
activate DB
DB --> UserStore: row or null
deactivate DB
UserStore --> UserMgr: ApplicationUser or null
deactivate UserStore
UserMgr --> ResendHandler: ApplicationUser or null
deactivate UserMgr
alt User not found
ResendHandler -> ResendHandler: return silently\n(prevents user enumeration)
else User found
ResendHandler -> UserMgr: IsEmailConfirmedAsync(user)
UserMgr --> ResendHandler: bool
alt Already confirmed
ResendHandler -> ResendHandler: return silently (no-op)
else Not yet confirmed
ResendHandler -> TokenSvc: GenerateConfirmationToken(user)
activate TokenSvc
TokenSvc --> ResendHandler: confirmation token
deactivate TokenSvc
ResendHandler -> Mediator: Send(SendResendConfirmationEmailCommand)
activate Mediator
Mediator -> EmailDispatcher: SendResendConfirmationEmailAsync(\n firstName, email, confirmationToken)
activate EmailDispatcher
EmailDispatcher -> Template: Render email\n(same Razor pipeline as registration)
EmailDispatcher -> SMTP: SendAsync(email, subject, body)
deactivate EmailDispatcher
deactivate Mediator
end
end
ResendHandler --> Mediator: (void)
deactivate ResendHandler
Mediator --> API: (void)
deactivate Mediator
API -> User: 200 OK\n{message: "confirmation email has been resent"}
note right of API
Always 200 OK regardless of outcome above -
same user-enumeration precaution as a not-found
user or an already-confirmed account.
end note
deactivate API
@enduml