using Microsoft.AspNetCore.Authorization; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Koogle.Infrastructure.Security; public static class ClubRoleHelper { public static Task CheckClubRole( AuthorizationHandlerContext context, ClubRoleRequirement requirement, Guid clubId) { static int Rank(string role) => role switch { "Admin" => 3, "Editor" => 2, "Viewer" => 1, _ => 0 }; var requiredRank = Rank(requirement.RequiredRole); // Read all club_role claims var claims = context.User.FindAll("club_role"); foreach (var c in claims) { // Format: "{clubId}:{roleName}" var parts = c.Value.Split(':', 2); if (parts.Length != 2) continue; if (Guid.TryParse(parts[0], out var claimClubId) && claimClubId == clubId) { var userRole = parts[1]; if (Rank(userRole) >= requiredRank) { context.Succeed(requirement); break; } } } return Task.CompletedTask; } } public sealed class ClubRoleRequirement : IAuthorizationRequirement { public ClubRoleRequirement(string requiredRole) => RequiredRole = requiredRole; public string RequiredRole { get; } } /// /// Handles ClubRoleRequirement when no resource is passed (e.g., [Authorize(Policy = "ClubViewer")]). /// Uses current_club_id claim to determine the club context. /// public sealed class ClubRoleHandler : AuthorizationHandler { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, ClubRoleRequirement requirement) { // Get current club from claims var currentClubClaim = context.User.FindFirst("current_club_id"); if (currentClubClaim == null || !Guid.TryParse(currentClubClaim.Value, out var clubId)) { return Task.CompletedTask; // No club context, fail } return ClubRoleHelper.CheckClubRole(context, requirement, clubId); } } /// /// Handles ClubRoleRequirement when a specific clubId resource is passed. /// public sealed class ClubRoleResourceHandler : AuthorizationHandler { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, ClubRoleRequirement requirement, Guid clubId) { return ClubRoleHelper.CheckClubRole(context, requirement, clubId); } }