Methodes cles

Signatures et logique des methodes principales de Place API - handlers, services et methodes de domaine

Methodes cles

Handlers de commandes

LoginCommandHandler.Handle

Fichier : Features/Auth/Login/V1/Login.csSignature :

public async Task<Result<AuthTokensResponse>> Handle(
    LoginCommand request, CancellationToken cancellationToken)

Logique :

  1. Extraire les informations de l'appareil via IDeviceInfoProvider
  2. Normaliser l'email via le value object Email
  3. Rechercher l'utilisateur par email dans UserManager
  4. Verifier le mot de passe via SignInManager.CheckPasswordSignInAsync (avec lockout)
  5. Verifier que le compte est actif (IsActive) et que l'email est confirme
  6. Si 2FA active : creer un challenge via ITwoFactorChallengeService et retourner TwoFactorRequiredError
  7. Verifier l'expiration du mot de passe via IPasswordExpiryService
  8. Construire la reponse tokens via IAuthTokenResponseBuilder.BuildAsync
  9. Enregistrer le login (User.RecordLogin()) et dispatcher les evenements de domaine
  10. Logger le succes via ISecurityAudit et enregistrer les metriques

RegisterCommandHandler.Handle

Fichier : Features/Auth/Register/V1/Register.csSignature :

public async Task<Result<AuthTokensResponse>> Handle(
    RegisterCommand request, CancellationToken cancellationToken)

Logique :

  1. Normaliser l'email
  2. Creer l'utilisateur via IUserRegistrationService.CreateUserWithPasswordAsync
  3. Gerer les cas d'erreur avec pattern matching sur UserCreationResult :
    • DuplicateEmail : retourner ConflictError
    • WeakPassword : retourner BadRequestError
    • CreationFailed : retourner BadRequestError
    • Success : construire la reponse tokens
  4. L'evenement SendConfirmationEmailOnUserRegistered est publie via notification MediatR

RefreshTokenCommandHandler.Handle

Fichier : Features/Auth/RefreshToken/V1/RefreshToken.csSignature :

public async Task<Result<AuthTokensResponse>> Handle(
    RefreshTokenCommand request, CancellationToken cancellationToken)

Logique detaillee :

  1. Extraire les informations de l'appareil
  2. Hasher le refresh token recu avec HMAC-SHA256 + pepper
  3. Rechercher la session par hash du refresh token
  4. Si session non trouvee :
    • Rechercher par PreviousRefreshTokenHash (token precedent)
    • Si trouve et dans la periode de grace (30 secondes) : rejeter silencieusement
    • Si trouve hors grace : replay detecte -> revoquer toutes les sessions de l'utilisateur
    • Si non trouve : token invalide
  5. Si session revoquee :
    • Si revoquee pour TokenRotation : replay detecte -> revoquer toutes les sessions
    • Sinon : retourner SessionRevokedError
  6. Verifier l'expiration de la session
  7. Verifier le binding de session (IP et DeviceId) si EnforceSessionBinding est active
  8. Verifier que l'utilisateur est toujours actif
  9. Construire les nouveaux claims avec ClaimsBuilder.BuildClaims
  10. Generer un nouveau access token et un nouveau refresh token
  11. Rotation du token : SessionWriter.RotateTokenAsync (l'ancien hash devient PreviousRefreshTokenHash)
  12. Construire et retourner la reponse

LogoutCommandHandler

Revoque la session courante en utilisant l'identifiant de session extrait du token JWT.

SocialLoginCommandHandler

  1. Valide le token du provider social (Google, Facebook, Apple)
  2. Recherche un UserLogin existant pour ce provider
  3. Si l'utilisateur existe : connexion directe
  4. Sinon : creation d'un nouveau compte via CreateUserWithExternalProviderAsync
  5. Remplit le profil social (FillSocialProfile)

Methodes de domaine (entites)

User.Register (factory)

public static User Register(
    string username, string normalizedEmail,
    string? firstName, string? lastName, string? imageUrl)

Cree une nouvelle instance de User avec IsActive = true et EmailConfirmed = false.

User.RecordLogin

public void RecordLogin()

Met a jour LastLoginAt et ajoute un UserLoggedInEvent aux evenements de domaine.

User.Activate / User.Deactivate

public void Activate(string? reason)
public void Deactivate(string? reason)

Change l'etat IsActive et ajoute un evenement de domaine (UserActivatedEvent / UserDeactivatedEvent). Operateurs idempotents : si l'etat est deja le meme, rien ne se passe.

UserSession.Create (factory)

internal static UserSession Create(NewSessionData data, DateTime createdAt)

Cree une session a partir des donnees de session (utilisateur, token, appareil) et emet un SessionCreatedEvent.

UserSession.Revoke

internal bool Revoke(RevocationReason? reason, DateTime revokedAt)

Marque la session comme revoquee. Retourne false si deja revoquee (idempotent). Emet un SessionRevokedEvent.

UserSession.UpdateActivity

internal void UpdateActivity(HashedToken newRefreshTokenHash, DateTime now)

Met a jour le hash du refresh token et deplace l'ancien vers PreviousRefreshTokenHash. Met a jour LastActivityAt.

HashedToken.FromRaw

public static HashedToken FromRaw(string rawToken, byte[] pepper)

Hash un token brut avec HMAC-SHA256 et un pepper. Produit un Hash complet et un Fingerprint (8 premiers caracteres du hash).

OtpRecord.IncrementAttempt / MarkUsed

public void IncrementAttempt()
public void MarkUsed()

TwoFactorChallenge.IncrementAttempt / MarkConsumed

public void IncrementAttempt()
public void MarkConsumed()

Methodes de services

AuditLogWriter.WriteAsync

public async Task WriteAsync(AuditEventV1 auditEvent, CancellationToken cancellationToken)
  1. Convertit AuditEventV1 en entite AuditLog (mapping des enums en strings snake_case)
  2. Persiste en base via AuditContext
  3. Enregistre les metriques de performance
  4. Broadcast via SignalR vers le groupe audit-admins
  5. En cas d'echec du broadcast, logue un warning sans bloquer

ClaimsBuilder.BuildClaims

public static IReadOnlyList<Claim> BuildClaims(User user, IReadOnlyList<string> roles, SessionId sessionId)

Construit la liste des claims JWT pour un utilisateur donne, incluant les roles et l'identifiant de session.

MessagingPersistenceBehavior.Handle

public async Task<TResponse> Handle(
    TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
  1. Extraire le message de la commande (IMessagingCommand.Message)
  2. Creer un SentMessage avec le statut Pending et le persister
  3. Executer le handler reel (envoi SMTP, SNS, push)
  4. En cas de succes : mettre a jour le statut en Sent
  5. En cas d'echec : mettre a jour le statut en Failed avec le message d'erreur
  6. Dans le finally : persister le resultat final

SendEmailCommandHandler.Handle

public async Task<Unit> Handle(SendEmailCommand request, CancellationToken cancellationToken)
  1. Rendre le template MJML via ITemplateRenderer.Render()
  2. Envoyer l'email via IEmailSender.SendAsync()