< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Command.Services.PasswordResetTokenRetirement
Assembly: ArturRios.Heimdall.Command
File(s): /home/runner/work/heimdall-api/heimdall-api/src/Application/ArturRios.Heimdall.Command/Services/PasswordResetTokenRetirement.cs
Line coverage
90%
Covered lines: 9
Uncovered lines: 1
Coverable lines: 10
Total lines: 49
Line coverage: 90%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage
100%
Covered methods: 1
Fully covered methods: 0
Total methods: 1
Method coverage: 100%
Full method coverage: 0%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
RetireLiveAsync()75%4490%

File(s)

/home/runner/work/heimdall-api/heimdall-api/src/Application/ArturRios.Heimdall.Command/Services/PasswordResetTokenRetirement.cs

#LineLine coverage
 1using ArturRios.Data.Relational.Core.Interfaces;
 2using ArturRios.Heimdall.Domain.Entities;
 3using Microsoft.EntityFrameworkCore;
 4
 5namespace ArturRios.Heimdall.Command.Services;
 6
 7/// <summary>
 8///     Retires a person's outstanding password-reset links when their address changes (UC-08,
 9///     FR-PE-17): a reset link was mailed to the address being replaced, and it would otherwise let
 10///     whoever reads that mailbox set the password for the rest of its lifetime. The counterpart of
 11///     <see cref="EmailVerificationTokenRetirement" />, and it leaves the same things alone.
 12/// </summary>
 13/// <remarks>
 14///     Already-expired tokens are left alone — AF-13a refuses them either way, and rewriting them
 15///     would only make a dead token report a different reason for being dead — and another person's
 16///     tokens are never touched.
 17/// </remarks>
 18public static class PasswordResetTokenRetirement
 19{
 20    /// <summary>
 21    ///     Marks every live (unused, unexpired at <paramref name="now" />) reset token of the person
 22    ///     with internal id <paramref name="personId" /> as used.
 23    /// </summary>
 24    /// <returns>The update errors of the first failed write, or <c>null</c> when all succeeded.</returns>
 25    public static async Task<IEnumerable<string>?> RetireLiveAsync(
 26        IAsyncReadOnlyRepository<PasswordResetToken, long> tokenReader,
 27        IAsyncRepository<PasswordResetToken, long> tokenWriter,
 28        long personId,
 29        DateTime now)
 30    {
 6831        var live = await tokenReader.Query()
 6832            .Where(x => x.PersonId == personId && !x.Used && x.ExpiresAt > now)
 6833            .ToListAsync();
 34
 14635        foreach (var outstanding in live)
 36        {
 537            outstanding.Used = true;
 38
 539            var update = await tokenWriter.UpdateAsync(outstanding);
 40
 541            if (!update.Success)
 42            {
 043                return update.Errors;
 44            }
 45        }
 46
 6847        return null;
 6848    }
 49}

Methods/Properties

RetireLiveAsync()