using System.Security.Claims; using Data.SeaHavenIndustries; using SeaHaven.Services.Exceptions; namespace SeaHaven.Services.Helpers { /// /// Claims-derived authorization for work-order media mutations. /// True multi-tenant CustomerId/TenantId is not modeled on WorkOrder/JWT; /// scope is role + Assigned () for Technician. /// public static class WorkOrderMediaAuthorization { private static readonly string[] StaffRoles = { "Admin", "Manager", "Dispatcher", "Supervisor" }; 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(); } /// /// Staff: any in-scope (non-deleted/non-template) work order. /// Technician: only work orders assigned to the caller. Out-of-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) { if (user is null || !(user.Identity?.IsAuthenticated ?? false) || string.IsNullOrWhiteSpace(actorId)) { throw Forbidden(); } } private static bool IsStaff(ClaimsPrincipal user) => StaffRoles.Any(user.IsInRole); private static WorkOrderBoardValidationException Forbidden() => new( "Forbidden", "You are not allowed to mutate work order media."); } }