< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Command.Services.LastSystemAdminGuard
Assembly: ArturRios.Heimdall.Command
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Application/ArturRios.Heimdall.Command/Services/LastSystemAdminGuard.cs
Line coverage
100%
Covered lines: 3
Uncovered lines: 0
Coverable lines: 3
Total lines: 43
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
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
WouldLeaveNoneAsync()100%11100%

File(s)

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

#LineLine coverage
 1using ArturRios.Data.Relational.Core.Interfaces;
 2using ArturRios.Heimdall.Domain.Entities;
 3using ArturRios.Heimdall.Domain.Enums;
 4using Microsoft.EntityFrameworkCore;
 5
 6namespace ArturRios.Heimdall.Command.Services;
 7
 8/// <summary>
 9///     NFR-32: whether taking a System Admin out — deleting them (UC-09, UC-10) or suspending them for erasure
 10///     (UC-42 and the anonymisation pass's retry) — would leave the system without an active System Admin.
 11/// </summary>
 12/// <remarks>
 13///     <para>
 14///         <b>Why.</b> Only a System Admin creates scopes, changes roles and reaches the retention tooling, and
 15///         the seeder re-creates the master user only on the next start, and only when its variables are set.
 16///         An administrator deleted or erased by mistake, or two deleting each other at once, would otherwise
 17///         lock everyone out until then (#203).
 18///     </para>
 19///     <para>
 20///         <b>Who counts.</b> An active System Admin (<see cref="Person.Active" />): not logically deleted, no
 21///         erasure requested, processing not restricted — the same definition NFR-12 uses for owners. A
 22///         restriction is the subject's right and is never refused (UC-44), so the rule is that no
 23///         administrator's <em>removal</em> may leave none, not that one always exists.
 24///     </para>
 25///     <para>
 26///         <b>Asked under the System Admin lock.</b> Every caller asks inside its transaction, once
 27///         <c>IInvariantLocks</c> holds the System Admin set, and decides whether the guard applies from the
 28///         person as read under it (<see cref="LockedPerson.IsLiveSystemAdmin" />), so two administrators
 29///         removing each other at once run one after the other, and the second is refused.
 30///     </para>
 31/// </remarks>
 32public static class LastSystemAdminGuard
 33{
 34    /// <summary>
 35    ///     Whether no System Admin but the person <paramref name="personId" /> is active, so taking them out
 36    ///     would leave the system without one.
 37    /// </summary>
 38    public static async Task<bool> WouldLeaveNoneAsync(
 39        long personId, IAsyncReadOnlyRepository<Person, long> personReader) =>
 1240        !await personReader.Query()
 1241            .Where(Person.Active)
 1242            .AnyAsync(other => other.Id != personId && other.RoleId == (long)Roles.SystemAdmin);
 43}

Methods/Properties

WouldLeaveNoneAsync()