< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Command.Registration.CommandServiceCollectionExtensions
Assembly: ArturRios.Heimdall.Command
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Application/ArturRios.Heimdall.Command/Registration/CommandServiceCollectionExtensions.cs
Line coverage
100%
Covered lines: 92
Uncovered lines: 0
Coverable lines: 92
Total lines: 176
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
100%
Covered methods: 2
Fully covered methods: 2
Total methods: 2
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddCommandHandlers(...)100%11100%
AddTwoFactorServices(...)100%11100%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Application/ArturRios.Heimdall.Command/Registration/CommandServiceCollectionExtensions.cs

#LineLine coverage
 1using ArturRios.Heimdall.Command.Auditing;
 2using ArturRios.Heimdall.Command.Handlers;
 3using ArturRios.Heimdall.Command.Input;
 4using ArturRios.Heimdall.Command.Input.Validation;
 5using ArturRios.Heimdall.Command.Output;
 6using ArturRios.Heimdall.Command.Services;
 7using ArturRios.Mediator.Command;
 8using FluentValidation;
 9using Microsoft.Extensions.DependencyInjection;
 10
 11namespace ArturRios.Heimdall.Command.Registration;
 12
 13public static class CommandServiceCollectionExtensions
 14{
 15    /// <summary>
 16    ///     Registers the command mediator, the audit log writer and the audited command handlers (with their
 17    ///     validators) of the scope, person, authentication, application and scope permission use cases.
 18    /// </summary>
 19    public static IServiceCollection AddCommandHandlers(this IServiceCollection services)
 20    {
 21        // #219: commands are dispatched without a cancellation token, by design. A write that has begun
 22        // must finish or roll back as one unit, not stop halfway because the client went away, so the
 23        // controllers hand ExecuteCommandAsync no HttpContext.RequestAborted and the command handlers
 24        // forward no token to EF Core. Queries are the opposite: they receive the request's token.
 97325        services.AddScoped<CommandMediator>();
 97326        services.AddScoped<IAuditLogWriter, AuditLogWriter>();
 97327        services.AddScoped<IValidator<CreateScopeCommand>, CreateScopeCommandValidator>();
 97328        services.AddAuditedCommandHandler<CreateScopeCommand, CreateScopeCommandOutput, CreateScopeCommandHandler>();
 97329        services.AddScoped<IValidator<UpdateScopeCommand>, UpdateScopeCommandValidator>();
 97330        services.AddAuditedCommandHandler<UpdateScopeCommand, UpdateScopeCommandOutput, UpdateScopeCommandHandler>();
 97331        services.AddAuditedCommandHandler<DeleteScopeCommand, DeleteScopeCommandOutput, DeleteScopeCommandHandler>();
 97332        services.AddAuditedCommandHandler<HardDeleteScopeCommand, HardDeleteScopeCommandOutput, HardDeleteScopeCommandHa
 33        // UC-24 does have a validator despite carrying a single field: Enabled is nullable so an
 34        // omitted value is refused (NFR-10) rather than binding to false and disabling the setting.
 97335        services.AddScoped<IValidator<SetGoogleSignInCommand>, SetGoogleSignInCommandValidator>();
 97336        services.AddAuditedCommandHandler<SetGoogleSignInCommand, SetGoogleSignInCommandOutput, SetGoogleSignInCommandHa
 97337        services.AddScoped<IValidator<SetSelfRegistrationCommand>, SetSelfRegistrationCommandValidator>();
 97338        services.AddAuditedCommandHandler<SetSelfRegistrationCommand, SetSelfRegistrationCommandOutput, SetSelfRegistrat
 97339        services.AddScoped<IValidator<SetScopeEmailLinksCommand>, SetScopeEmailLinksCommandValidator>();
 97340        services.AddAuditedCommandHandler<SetScopeEmailLinksCommand, SetScopeEmailLinksCommandOutput, SetScopeEmailLinks
 41        // UC-50 (FR-SR-12): no validator — both identifiers are route values already constrained to
 42        // GUIDs. Audited like every write, with the registration as target.
 97343        services.AddAuditedCommandHandler<DiscardPendingRegistrationCommand, DiscardPendingRegistrationCommandOutput, Di
 97344        services.AddScoped<IValidator<CreateAdminCommand>, CreateAdminCommandValidator>();
 97345        services.AddAuditedCommandHandler<CreateAdminCommand, CreatePersonCommandOutput, CreateAdminCommandHandler>();
 97346        services.AddScoped<IValidator<CreateUserCommand>, CreateUserCommandValidator>();
 97347        services.AddAuditedCommandHandler<CreateUserCommand, CreatePersonCommandOutput, CreateUserCommandHandler>();
 97348        services.AddScoped<IValidator<CreateScopeOwnerCommand>, CreateScopeOwnerCommandValidator>();
 97349        services.AddAuditedCommandHandler<CreateScopeOwnerCommand, CreatePersonCommandOutput, CreateScopeOwnerCommandHan
 50        // No validator: UC-21's request carries no body — both identifiers are route values already
 51        // constrained to GUIDs — so there is nothing left for NFR-10 to validate.
 97352        services.AddAuditedCommandHandler<AddScopeOwnerCommand, AddScopeOwnerCommandOutput, AddScopeOwnerCommandHandler>
 53        // UC-58: an owner or a System Admin withdraws an open scope owner invitation.
 97354        services.AddAuditedCommandHandler<WithdrawScopeOwnerInvitationCommand, WithdrawScopeOwnerInvitationCommandOutput
 55        // UC-60/UC-61: the invitee accepts or declines; no validator — the route's id is the whole input.
 97356        services.AddAuditedCommandHandler<AcceptScopeOwnerInvitationCommand, AcceptScopeOwnerInvitationCommandOutput, Ac
 97357        services.AddAuditedCommandHandler<DeclineScopeOwnerInvitationCommand, DeclineScopeOwnerInvitationCommandOutput, 
 58        // Likewise no validator for UC-22: both identifiers are route values.
 97359        services.AddAuditedCommandHandler<RemoveScopeOwnerCommand, RemoveScopeOwnerCommandOutput, RemoveScopeOwnerComman
 60        // Likewise no validator for UC-23: both identifiers are route values.
 97361        services.AddAuditedCommandHandler<PromoteScopeUserCommand, PromoteScopeUserCommandOutput, PromoteScopeUserComman
 97362        services.AddScoped<IValidator<UpdatePersonCommand>, UpdatePersonCommandValidator>();
 97363        services.AddAuditedCommandHandler<UpdatePersonCommand, UpdatePersonCommandOutput, UpdatePersonCommandHandler>();
 97364        services.AddAuditedCommandHandler<DeletePersonCommand, DeletePersonCommandOutput, DeletePersonCommandHandler>();
 97365        services.AddAuditedCommandHandler<HardDeletePersonCommand, HardDeletePersonCommandOutput, HardDeletePersonComman
 97366        services.AddScoped<IValidator<LoginCommand>, LoginCommandValidator>();
 97367        services.AddAuditedCommandHandler<LoginCommand, LoginCommandOutput, LoginCommandHandler>();
 97368        services.AddScoped<IValidator<PasswordRecoveryCommand>, PasswordRecoveryCommandValidator>();
 97369        services.AddAuditedCommandHandler<PasswordRecoveryCommand, PasswordRecoveryCommandOutput, PasswordRecoveryComman
 97370        services.AddScoped<IValidator<RegisterCommand>, RegisterCommandValidator>();
 97371        services.AddAuditedCommandHandler<RegisterCommand, RegisterCommandOutput, RegisterCommandHandler>();
 97372        services.AddScoped<IValidator<ResetPasswordCommand>, ResetPasswordCommandValidator>();
 97373        services.AddAuditedCommandHandler<ResetPasswordCommand, ResetPasswordCommandOutput, ResetPasswordCommandHandler>
 97374        services.AddScoped<IValidator<VerifyEmailCommand>, VerifyEmailCommandValidator>();
 97375        services.AddAuditedCommandHandler<VerifyEmailCommand, VerifyEmailCommandOutput, VerifyEmailCommandHandler>();
 97376        services.AddScoped<IValidator<RequestErasureCommand>, RequestErasureCommandValidator>();
 97377        services
 97378            .AddAuditedCommandHandler<RequestErasureCommand, RequestErasureCommandOutput,
 97379                RequestErasureCommandHandler>();
 97380        services
 97381            .AddAuditedCommandHandler<ExportMyDataCommand, DataExportCommandOutput,
 97382                ExportMyDataCommandHandler>();
 97383        services
 97384            .AddAuditedCommandHandler<RestrictProcessingCommand, RestrictProcessingCommandOutput,
 97385                RestrictProcessingCommandHandler>();
 97386        services
 97387            .AddAuditedCommandHandler<LiftProcessingRestrictionCommand,
 97388                LiftProcessingRestrictionCommandOutput, LiftProcessingRestrictionCommandHandler>();
 97389        services
 97390            .AddAuditedCommandHandler<ReapplyErasuresCommand, ReapplyErasuresCommandOutput,
 97391                ReapplyErasuresCommandHandler>();
 92        // No validator: UC-15's request carries no caller-supplied input at all — the person comes
 93        // from the bearer token — so there is nothing for NFR-10 to validate.
 97394        services.AddAuditedCommandHandler<ResendVerificationEmailCommand, ResendVerificationEmailCommandOutput, ResendVe
 95        // Likewise no validator for UC-25, for a different reason: the use case defines no 400 flow
 96        // and needs none, since an absent ID token fails verification (AF-25a, 401) and an empty
 97        // scope identifier matches no scope (AF-25b, 403).
 97398        services.AddAuditedCommandHandler<GoogleSignInCommand, GoogleSignInCommandOutput, GoogleSignInCommandHandler>();
 99        // No validator for UC-26 either, and for UC-15's reason: the sign-out request carries no
 100        // caller-supplied input — the Google User comes from the bearer token.
 973101        services.AddAuditedCommandHandler<GoogleSignOutCommand, GoogleSignOutCommandOutput, GoogleSignOutCommandHandler>
 102        // UC-28 needs no validator either: both fields are typed route parameters, so there is no
 103        // caller-supplied input NFR-10 could reject that the route would not have refused first.
 973104        services.AddAuditedCommandHandler<DeleteGoogleUserCommand, DeleteGoogleUserCommandOutput, DeleteGoogleUserComman
 973105        services.AddAuditedCommandHandler<HardDeleteGoogleUserCommand, HardDeleteGoogleUserCommandOutput, HardDeleteGoog
 973106        services.AddScoped<IValidator<CreateApplicationCommand>, CreateApplicationCommandValidator>();
 973107        services.AddAuditedCommandHandler<CreateApplicationCommand, CreateApplicationCommandOutput, CreateApplicationCom
 973108        services.AddScoped<IValidator<UpdateApplicationCommand>, UpdateApplicationCommandValidator>();
 973109        services.AddAuditedCommandHandler<UpdateApplicationCommand, UpdateApplicationCommandOutput, UpdateApplicationCom
 973110        services.AddAuditedCommandHandler<DeleteApplicationCommand, DeleteApplicationCommandOutput, DeleteApplicationCom
 973111        services.AddAuditedCommandHandler<HardDeleteApplicationCommand, HardDeleteApplicationCommandOutput, HardDeleteAp
 973112        services.AddScoped<IValidator<IssueApplicationCredentialCommand>, IssueApplicationCredentialCommandValidator>();
 973113        services.AddAuditedCommandHandler<IssueApplicationCredentialCommand, IssueApplicationCredentialCommandOutput, Is
 973114        services.AddAuditedCommandHandler<RevokeApplicationCredentialCommand, RevokeApplicationCredentialCommandOutput, 
 973115        services.AddScoped<IValidator<IssueApplicationTokenCommand>, IssueApplicationTokenCommandValidator>();
 973116        services.AddAuditedCommandHandler<IssueApplicationTokenCommand, IssueApplicationTokenCommandOutput, IssueApplica
 973117        services.AddScoped<IValidator<CreateScopePermissionCommand>, CreateScopePermissionCommandValidator>();
 973118        services.AddAuditedCommandHandler<CreateScopePermissionCommand, CreateScopePermissionCommandOutput, CreateScopeP
 973119        services.AddScoped<IValidator<UpdateScopePermissionCommand>, UpdateScopePermissionCommandValidator>();
 973120        services.AddAuditedCommandHandler<UpdateScopePermissionCommand, UpdateScopePermissionCommandOutput, UpdateScopeP
 973121        services.AddAuditedCommandHandler<DeleteScopePermissionCommand, DeleteScopePermissionCommandOutput, DeleteScopeP
 973122        services.AddAuditedCommandHandler<HardDeleteScopePermissionCommand, HardDeleteScopePermissionCommandOutput, Hard
 123
 973124        return services;
 125    }
 126
 127    /// <summary>
 128    ///     Registers the TOTP secret protector and verifier, the two-factor services and the audited command
 129    ///     handlers of the two-factor use cases (UC-36 to UC-40, UC-46).
 130    /// </summary>
 131    public static IServiceCollection AddTwoFactorServices(this IServiceCollection services)
 132    {
 973133        services.AddScoped<ITotpSecretProtector, TotpSecretProtector>();
 134        // Shared by UC-37's confirmation and ITwoFactorFactorVerifier (UC-38/39/40): the TOTP secret,
 135        // the clock-drift window, and the single-use rule that keeps an app code from being replayed
 136        // live in one place rather than a copy per call site.
 973137        services.AddScoped<ITotpCodeVerifier, TotpCodeVerifier>();
 973138        services.AddScoped<IValidator<EnableTwoFactorAuthCommand>, EnableTwoFactorAuthCommandValidator>();
 973139        services.AddAuditedCommandHandler<EnableTwoFactorAuthCommand, EnableTwoFactorAuthCommandOutput, EnableTwoFactorA
 140
 141        // UC-37 (FR-2F-04/05): no validator — which code(s) are required depends on the pending row's
 142        // AppEnabled/EmailEnabled, a database read the handler alone can make.
 973143        services.AddAuditedCommandHandler<ConfirmTwoFactorAuthCommand, ConfirmTwoFactorAuthCommandOutput, ConfirmTwoFact
 144
 145        // UC-38 (FR-2F-06…FR-2F-09): no validator either — same reason as UC-37, plus the challenge
 146        // token itself is validated inside the handler, the same "opaque token as a body value"
 147        // shape UC-13's ResetPasswordCommand uses.
 973148        services.AddAuditedCommandHandler<VerifyTwoFactorAuthCommand, VerifyTwoFactorAuthCommandOutput, VerifyTwoFactorA
 149
 150        // UC-46 (FR-2F-16): no validator — the challenge token is the whole of the input and is
 151        // validated inside the handler, the same shape UC-38 uses.
 973152        services.AddAuditedCommandHandler<ResendTwoFactorChallengeCodeCommand, ResendTwoFactorChallengeCodeCommandOutput
 153
 154        // Shared by UC-11's AF-11g, UC-36's Email method and UC-46's reissue: retire-then-issue is
 155        // one step in one place, so the three cannot drift and leave two live codes for one
 156        // configuration — the retirement is what makes a code single-use in practice.
 973157        services.AddScoped<ITwoFactorEmailCodeIssuer, TwoFactorEmailCodeIssuer>();
 158
 159        // Shared by VerifyTwoFactorAuthCommandHandler (UC-38), DisableTwoFactorAuthCommandHandler
 160        // (UC-39), and RegenerateRecoveryCodesCommandHandler (UC-40) — the "code against TOTP, or
 161        // against the current email code, or against an unused recovery code" comparison lives in
 162        // exactly one place.
 973163        services.AddScoped<ITwoFactorFactorVerifier, TwoFactorFactorVerifier>();
 164
 165        // UC-39 (FR-2F-11): no validator — which shape of second factor (code vs. recoveryCode) is
 166        // valid depends on a database read (the pending row's AppEnabled/EmailEnabled), the same
 167        // reason UC-37/UC-38 have none.
 973168        services.AddAuditedCommandHandler<DisableTwoFactorAuthCommand, DisableTwoFactorAuthCommandOutput, DisableTwoFact
 169
 170        // UC-40 (FR-2F-12): no validator either, same reason as UC-39 — reuses ITwoFactorFactorVerifier
 171        // (registered above) rather than reimplementing the second-factor check.
 973172        services.AddAuditedCommandHandler<RegenerateRecoveryCodesCommand, RegenerateRecoveryCodesCommandOutput, Regenera
 173
 973174        return services;
 175    }
 176}