< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.WebApi.Retention.TokenRetentionService
Assembly: ArturRios.Heimdall.WebApi
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Presentation/ArturRios.Heimdall.WebApi/Retention/TokenRetentionService.cs
Line coverage
96%
Covered lines: 25
Uncovered lines: 1
Coverable lines: 26
Total lines: 66
Line coverage: 96.1%
Branch coverage
75%
Covered branches: 6
Total branches: 8
Branch coverage: 75%
Method coverage
80%
Covered methods: 4
Fully covered methods: 4
Total methods: 5
Method coverage: 80%
Full method coverage: 80%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_PassName()100%210%
get_StartupDescription()100%11100%
RunAsync()75%44100%
Summarise(...)75%44100%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Presentation/ArturRios.Heimdall.WebApi/Retention/TokenRetentionService.cs

#LineLine coverage
 1using ArturRios.Heimdall.Command.Input;
 2using ArturRios.Heimdall.Command.Output;
 3using ArturRios.Heimdall.Shared.Retention;
 4using ArturRios.Mediator.Command;
 5
 6namespace ArturRios.Heimdall.WebApi.Retention;
 7
 8/// <summary>
 9///     Runs <see cref="PurgeExpiredTokensCommand" /> on an interval, so the single-use token
 10///     retention period of NFR-19 is enforced without anyone having to call anything.
 11/// </summary>
 12public class TokenRetentionService(
 13    IServiceScopeFactory scopeFactory,
 14    DataRetentionOptions retention,
 15    ILogger<TokenRetentionService> logger)
 96816    : ScheduledPassService(scopeFactory, retention.PurgeInterval, logger)
 17{
 018    public override string PassName => "token-retention";
 19
 20    protected override string StartupDescription =>
 96621        $"Token retention purge scheduled every {retention.PurgeInterval}, removing tokens more than " +
 96622        $"{retention.SingleUseTokenGrace} past expiry and scope owner invitations " +
 96623        $"{retention.ScopeInvitationRetention} after they ended or expired";
 24
 25    protected override async Task<ScheduledPassResult> RunAsync(IServiceProvider scope)
 26    {
 227        var mediator = scope.GetRequiredService<CommandMediator>();
 28
 229        var result = await mediator
 230            .ExecuteCommandAsync<PurgeExpiredTokensCommand, PurgeExpiredTokensCommandOutput>(
 231                new PurgeExpiredTokensCommand());
 32
 233        if (!result.Success)
 34        {
 135            return ScheduledPassResult.Failure("Token retention purge", result.Errors, result.Data?.TotalPurged ?? 0);
 36        }
 37
 138        var purged = result.Data!;
 39
 140        return new ScheduledPassResult(Summarise(purged), false, purged.TotalPurged);
 241    }
 42
 43    /// <summary>
 44    ///     The line logged for a run: <c>null</c> when nothing was removed and nothing is left, otherwise
 45    ///     the total, the rows still due after the run, and every term of the total.
 46    /// </summary>
 47    /// <remarks>
 48    ///     A term left out makes the parts disagree with the total (#225): a run that purged only
 49    ///     application credentials once logged "removed 3 rows" over a list of zeroes. The rows still due
 50    ///     are what a run left at its batch cap (#206); a number that does not fall from run to run is a
 51    ///     backlog that is not draining.
 52    /// </remarks>
 53    public static string? Summarise(PurgeExpiredTokensCommandOutput purged) =>
 454        purged.TotalPurged == 0 && purged.Backlog == 0
 455            ? null
 456            : $"Token retention purge removed {purged.TotalPurged} rows " +
 457              $"({purged.Backlog} still due after this run): " +
 458              $"{purged.PasswordResetTokensPurged} password reset, " +
 459              $"{purged.EmailVerificationTokensPurged} email verification, " +
 460              $"{purged.TwoFactorEmailCodesPurged} two-factor email, " +
 461              $"{purged.PendingRegistrationsPurged} pending registration, " +
 462              $"{purged.ApplicationCredentialsPurged} application credential, " +
 463              $"{purged.AttemptNoticeBudgetsPurged} attempt-notice budget, " +
 464              $"{purged.GoogleIdTokenUsesPurged} used Google ID token, " +
 465              $"{purged.ScopeOwnerInvitationsPurged} scope owner invitation";
 66}