Files
vtuber-awards/Backend/Security/AdminPermissionCatalog.cs
T
AzuTear 441ef2b850
CI - Build & Verify / Build, Typecheck & Hygiene (push) Successful in 59s
CI - Build & Verify / Deploy to award.noveria.net (push) Failing after 53s
Update release notes and deploy workspace
2026-06-29 17:49:54 +02:00

158 lines
5.0 KiB
C#

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 Voting = "voting";
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,
Voting,
Winners,
Content,
Settings,
Team,
];
public static readonly string[] SeasonReadPermissionKeys =
[
Dashboard,
Years,
Nominations,
Categories,
Candidates,
Clips,
Analytics,
Voting,
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, Voting, Content],
AdminRoles.Reviewer => [Dashboard, Nominations, Clips, Risk, Audit],
AdminRoles.OrganizationTeam => [Dashboard, Content, Analytics, Voting, Winners, Settings],
AdminRoles.ContentAdmin => [Content, Settings],
_ => [],
};
}
public static string[] NormalizePermissionKeys(string? role, IEnumerable<string> 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);
}
var hasAnalytics = permissions.Contains(Analytics, StringComparer.OrdinalIgnoreCase);
var hasWinners = permissions.Contains(Winners, StringComparer.OrdinalIgnoreCase);
if ((hasAnalytics || hasWinners)
&& !permissions.Contains(Voting, StringComparer.OrdinalIgnoreCase))
{
permissions.Add(Voting);
}
return permissions
.OrderBy(item => item)
.ToArray();
}
public static async Task<string[]> 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<string[]>(overrideJson) ?? fallback);
}
catch (JsonException)
{
return fallback;
}
}
public static async Task<bool> 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<bool> HasAnyPermissionAsync(
AwardsDbContext db,
string? role,
IEnumerable<string> permissionKeys,
CancellationToken cancellationToken = default)
{
var permissions = await GetPermissionKeysAsync(db, role, cancellationToken);
return permissionKeys.Any(permission => permissions.Contains(permission, StringComparer.OrdinalIgnoreCase));
}
}