using System.Text.Json; using Backend.Data; using Microsoft.EntityFrameworkCore; namespace Backend.Security; public static class AdminPermissionCatalog { public const string Dashboard = "dashboard"; public const string Years = "years"; public const string Nominations = "nominations"; public const string Categories = "categories"; public const string Candidates = "candidates"; public const string Clips = "clips"; public const string Risk = "risk"; public const string Audit = "audit"; public const string Analytics = "analytics"; public const string Winners = "winners"; public const string Content = "content"; public const string Settings = "settings"; public const string Team = "team"; public static readonly string[] AllPermissionKeys = [ Dashboard, Years, Nominations, Categories, Candidates, Clips, Risk, Audit, Analytics, Winners, Content, Settings, Team, ]; public static readonly string[] SeasonReadPermissionKeys = [ Dashboard, Years, Nominations, Categories, Candidates, Clips, Analytics, Winners, ]; public static bool IsKnownPermission(string permissionKey) => AllPermissionKeys.Contains(permissionKey, StringComparer.OrdinalIgnoreCase); public static string[] DefaultPermissionKeys(string? role) { return AdminRoles.Normalize(role) switch { AdminRoles.Owner => AllPermissionKeys, AdminRoles.Creator => AllPermissionKeys, AdminRoles.Admin => AllPermissionKeys, AdminRoles.Member => [Dashboard, Nominations, Categories, Candidates, Clips, Content], AdminRoles.Reviewer => [Dashboard, Nominations, Clips, Risk, Audit], AdminRoles.OrganizationTeam => [Dashboard, Content, Analytics, Winners, Settings], AdminRoles.ContentAdmin => [Content, Settings], _ => [], }; } public static string[] NormalizePermissionKeys(string? role, IEnumerable permissionKeys) { var normalizedRole = AdminRoles.Normalize(role); var permissions = permissionKeys .Where(IsKnownPermission) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); if (normalizedRole is AdminRoles.Owner or AdminRoles.Creator) { return AllPermissionKeys; } if (DefaultPermissionKeys(normalizedRole).Contains(Settings, StringComparer.OrdinalIgnoreCase) && !permissions.Contains(Settings, StringComparer.OrdinalIgnoreCase)) { permissions.Add(Settings); } return permissions .OrderBy(item => item) .ToArray(); } public static async Task GetPermissionKeysAsync( AwardsDbContext db, string? role, CancellationToken cancellationToken = default) { var normalizedRole = AdminRoles.Normalize(role); if (normalizedRole is AdminRoles.Owner or AdminRoles.Creator) { return AllPermissionKeys; } var fallback = DefaultPermissionKeys(normalizedRole); var overrideJson = await db.TeamRolePermissions .AsNoTracking() .Where(item => item.Role == normalizedRole) .Select(item => item.PermissionsJson) .FirstOrDefaultAsync(cancellationToken); if (string.IsNullOrWhiteSpace(overrideJson)) { return fallback; } try { return NormalizePermissionKeys(normalizedRole, JsonSerializer.Deserialize(overrideJson) ?? fallback); } catch (JsonException) { return fallback; } } public static async Task HasPermissionAsync( AwardsDbContext db, string? role, string permissionKey, CancellationToken cancellationToken = default) { var permissions = await GetPermissionKeysAsync(db, role, cancellationToken); return permissions.Contains(permissionKey, StringComparer.OrdinalIgnoreCase); } public static async Task HasAnyPermissionAsync( AwardsDbContext db, string? role, IEnumerable permissionKeys, CancellationToken cancellationToken = default) { var permissions = await GetPermissionKeysAsync(db, role, cancellationToken); return permissionKeys.Any(permission => permissions.Contains(permission, StringComparer.OrdinalIgnoreCase)); } }