using System.Security.Claims; using Data.SeaHavenIndustries; using SeaHaven.Services.Exceptions; namespace SeaHaven.Services.Helpers { /// /// Claims-derived authorization for work-order media read/mutations. /// Callers must resolve the work order via ApplyBaseScope plus /// ApplyAccountScope when the principal carries /// . Staff may access any /// resulting work order; technicians only when /// matches the actor. Delete is staff-only. /// Staff without an account claim remain org-wide (base scope only). /// public static class WorkOrderMediaAuthorization { private static readonly string[] StaffRoles = { "Admin", "Manager", "Dispatcher", "Supervisor" }; public static int? ResolveAccountId(ClaimsPrincipal user) { var raw = user?.FindFirstValue(SeaHavenClaimTypes.AccountId); if (string.IsNullOrWhiteSpace(raw)) return null; return int.TryParse(raw, out var accountId) ? accountId : null; } public static void EnsureCanRead(ClaimsPrincipal user, string? actorId) { EnsureAuthenticated(user, actorId, "You are not allowed to view work order media."); if (IsStaff(user) || user.IsInRole("User")) return; throw Forbidden("You are not allowed to view work order media."); } public static void EnsureCanMutate(ClaimsPrincipal user, string? actorId) { EnsureAuthenticated(user, actorId); if (IsStaff(user) || user.IsInRole("User")) return; throw Forbidden(); } public static void EnsureCanDelete(ClaimsPrincipal user, string? actorId) { EnsureAuthenticated(user, actorId); // Technician (User) may upload/categorize assigned media but not delete. if (IsStaff(user)) return; throw Forbidden(); } /// /// Caller-scope check after a base+account scoped work-order load. /// Staff: any resulting work order. /// Technician: only when assigned to the caller. /// Out of caller scope → NotFound (no disclosure). /// public static void EnsureWorkOrderInCallerScope( ClaimsPrincipal user, string actorId, WorkOrder workOrder) { if (IsStaff(user)) return; if (user.IsInRole("User") && string.Equals(workOrder.AssignTo, actorId, StringComparison.Ordinal)) { return; } throw new WorkOrderBoardValidationException("NotFound", "Work order not found."); } private static void EnsureAuthenticated( ClaimsPrincipal user, string? actorId, string? forbiddenMessage = null) { if (user is null || !(user.Identity?.IsAuthenticated ?? false) || string.IsNullOrWhiteSpace(actorId)) { throw Forbidden(forbiddenMessage); } } private static bool IsStaff(ClaimsPrincipal user) => StaffRoles.Any(user.IsInRole); private static WorkOrderBoardValidationException Forbidden(string? message = null) => new( "Forbidden", message ?? "You are not allowed to mutate work order media."); } }