< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Command.Services.PasswordRecoveryEligibility
Assembly: ArturRios.Heimdall.Command
File(s): /home/runner/work/heimdall-api/heimdall-api/src/Application/ArturRios.Heimdall.Command/Services/PasswordRecoveryEligibility.cs
Line coverage
100%
Covered lines: 11
Uncovered lines: 0
Coverable lines: 11
Total lines: 66
Line coverage: 100%
Branch coverage
100%
Covered branches: 16
Total branches: 16
Branch coverage: 100%
Method coverage
100%
Covered methods: 1
Fully covered methods: 1
Total methods: 1
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Of(...)100%1616100%

File(s)

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

#LineLine coverage
 1using ArturRios.Heimdall.Domain.Entities;
 2using ArturRios.Heimdall.Domain.Enums;
 3
 4namespace ArturRios.Heimdall.Command.Services;
 5
 6/// <summary>The outcome of <see cref="PasswordRecoveryEligibility.Of" />.</summary>
 7public enum RecoveryEligibility
 8{
 9    /// <summary>A reset link would let this person sign in again.</summary>
 10    Eligible,
 11
 12    /// <summary>Processing of the person is restricted (NFR-24); sending would be processing them.</summary>
 13    Restricted,
 14
 15    /// <summary>The person is logically deleted, or their record has been anonymised (NFR-20).</summary>
 16    Deleted,
 17
 18    /// <summary>
 19    ///     The account could not sign in whatever its password: a <c>User</c> whose scope is logically
 20    ///     deleted or missing (FR-AU-06), or a <c>ScopeAdmin</c> with no live scope (FR-AU-07).
 21    /// </summary>
 22    CannotSignIn
 23}
 24
 25/// <summary>
 26///     Who a password-reset link is worth sending to: UC-12's rule, shared with UC-52 so the anonymous
 27///     recovery and the administrator's request cannot disagree (FR-PR-02, FR-PR-05). Run again when
 28///     a reset or verification link is followed (UC-13, UC-14: FR-PR-08, FR-EV-08), so a link issued
 29///     before the account changed cannot act on it afterwards.
 30/// </summary>
 31/// <remarks>
 32///     It mirrors the account checks UC-11 applies at login: a link is only worth issuing to someone
 33///     who could use the resulting password. UC-12 needs only yes or no, since it answers every caller
 34///     alike; UC-52's caller is authenticated and owed the reason, so the outcome names it. The
 35///     restriction is checked first, as UC-12 always has, so a person both restricted and deleted is
 36///     reported as restricted. An anonymised record counts as deleted whatever its flag says: it
 37///     belongs to nobody, and its address is a placeholder.
 38/// </remarks>
 39public static class PasswordRecoveryEligibility
 40{
 41    /// <summary>
 42    ///     Evaluates <paramref name="person" />. <c>ScopeMembership.Scope</c> and every
 43    ///     <c>ScopeOwnerships[].Scope</c> must be loaded.
 44    /// </summary>
 45    public static RecoveryEligibility Of(Person person)
 46    {
 15547        if (person.ProcessingRestrictedAt is not null)
 48        {
 1049            return RecoveryEligibility.Restricted;
 50        }
 51
 14552        if (person.IsDeleted || person.AnonymisedAt is not null)
 53        {
 1454            return RecoveryEligibility.Deleted;
 55        }
 56
 13157        var maySignIn = person.RoleId switch
 13158        {
 2759            (long)Roles.User => person.ScopeMembership is { Scope.IsDeleted: false },
 3360            (long)Roles.ScopeAdmin => person.ScopeOwnerships.Any(ownership => !ownership.Scope.IsDeleted),
 8961            _ => true
 13162        };
 63
 13164        return maySignIn ? RecoveryEligibility.Eligible : RecoveryEligibility.CannotSignIn;
 65    }
 66}