AccountMergeLedger owns what a merge does to Bifrost records: PlanAsync (dry run, block codes), CommitAsync (one save, total, idempotent), UndoLocalAsync (journal replay), FinalizeDueAsync (AccountMergeSweeper) and StandingAsync/ResolveAsync. Votes and concept appraisals are voided by a stamp that a model query filter hides from every tally. The actor accessor no longer ORs several credentials under SingleOrDefault (a latent crash); a frozen or folded account resolves to no account on every route, the OIDC authorize and chat refusal deny it, and patron intake follows the alias. Migration AddAccountMerges is additive. No UI, no Heimdall call, nothing deployed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
62 lines
2 KiB
C#
62 lines
2 KiB
C#
using Bifrost.Web.Domain;
|
|
using Bifrost.Web.Features.Membership;
|
|
|
|
namespace Bifrost.Web.Features.Shared;
|
|
|
|
public sealed record CurrentBifrostActor(bool IsAuthenticated, UserAccount? UserAccount)
|
|
{
|
|
/// <summary>Set when the account behind this sign-in is frozen or folded by an account merge; the actor then has no account.</summary>
|
|
public MergeStanding? Merge { get; init; }
|
|
|
|
public static readonly CurrentBifrostActor Anonymous = new(false, null);
|
|
|
|
public Bifrost.Web.Domain.Membership? Membership => UserAccount?.Membership;
|
|
|
|
public string DisplayName =>
|
|
UserAccount?.MemberProfile?.Nickname
|
|
?? UserAccount?.DisplayName
|
|
?? UserAccount?.GitHubLogin
|
|
?? "Guest";
|
|
|
|
public bool IsActiveMember => Membership?.Status == MembershipStatus.Active;
|
|
|
|
public IReadOnlyCollection<MemberRole> Roles =>
|
|
Membership?.RoleAssignments
|
|
.Select(x => x.Role)
|
|
.Distinct()
|
|
.ToArray()
|
|
?? [];
|
|
|
|
public bool IsPlatformAdmin =>
|
|
Membership?.IsPlatformAdmin == true ||
|
|
Roles.Contains(MemberRole.PlatformAdmin);
|
|
|
|
public bool CanManageMembership => IsPlatformAdmin;
|
|
|
|
public bool CanManageProjects =>
|
|
IsPlatformAdmin ||
|
|
Membership?.CanManageProjects == true ||
|
|
Roles.Contains(MemberRole.Producer);
|
|
|
|
public bool CanAssignWork =>
|
|
CanManageProjects ||
|
|
Roles.Contains(MemberRole.Maintainer);
|
|
|
|
public bool CanReviewWork =>
|
|
IsPlatformAdmin ||
|
|
Roles.Contains(MemberRole.Producer) ||
|
|
Roles.Contains(MemberRole.Maintainer);
|
|
|
|
public bool CanManageLedger =>
|
|
IsPlatformAdmin ||
|
|
Membership?.CanManageLedger == true ||
|
|
Roles.Contains(MemberRole.LedgerReviewer);
|
|
|
|
public bool CanModerateMotions =>
|
|
IsPlatformAdmin ||
|
|
Membership?.CanModerateMotions == true ||
|
|
Roles.Contains(MemberRole.Producer) ||
|
|
Roles.Contains(MemberRole.Maintainer);
|
|
|
|
public decimal EffectiveVotingWeight => Membership?.EffectiveVotingWeight ?? 0m;
|
|
}
|