using Books.Api.Domain.UserAccess; namespace Books.Api.Authorization; /// /// Context for the currently selected company in a request. /// Extracted from X-Company-Id header and validated against user access. /// public class CompanyContext { /// /// The currently selected company ID. /// public string? CompanyId { get; init; } /// /// The user's role for the selected company. /// public CompanyRole? Role { get; init; } /// /// Whether a valid company is selected and the user has access. /// public bool HasCompanySelected => CompanyId != null && Role != null; /// /// Check if the user has at least the required role for the selected company. /// public bool HasRole(CompanyRole minimumRole) { if (Role == null) return false; return minimumRole switch { CompanyRole.Viewer => true, CompanyRole.Accountant => Role is CompanyRole.Owner or CompanyRole.Accountant, CompanyRole.Owner => Role is CompanyRole.Owner, _ => false }; } /// /// Require the user to have at least the specified role. /// Throws DomainException if not. /// public void RequireRole(CompanyRole minimumRole) { if (!HasCompanySelected) { throw new Domain.DomainException( "NO_COMPANY_SELECTED", "No company selected. Set X-Company-Id header.", "Ingen virksomhed valgt. Sæt X-Company-Id header."); } if (!HasRole(minimumRole)) { var roleDescription = minimumRole switch { CompanyRole.Owner => "ejer", CompanyRole.Accountant => "bogholder", CompanyRole.Viewer => "læser", _ => "ukendt" }; throw new Domain.DomainException( "INSUFFICIENT_PERMISSIONS", $"This operation requires {minimumRole} role", $"Denne handling kræver {roleDescription}-rolle"); } } /// /// Require that the user can write (Owner or Accountant). /// public void RequireWrite() => RequireRole(CompanyRole.Accountant); /// /// Require that the user is Owner. /// public void RequireOwner() => RequireRole(CompanyRole.Owner); }