92 lines
2.7 KiB
C#
92 lines
2.7 KiB
C#
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; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles ClubRoleRequirement when no resource is passed (e.g., [Authorize(Policy = "ClubViewer")]).
|
|
/// Uses current_club_id claim to determine the club context.
|
|
/// </summary>
|
|
public sealed class ClubRoleHandler : AuthorizationHandler<ClubRoleRequirement>
|
|
{
|
|
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);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles ClubRoleRequirement when a specific clubId resource is passed.
|
|
/// </summary>
|
|
public sealed class ClubRoleResourceHandler : AuthorizationHandler<ClubRoleRequirement, Guid>
|
|
{
|
|
protected override Task HandleRequirementAsync(
|
|
AuthorizationHandlerContext context,
|
|
ClubRoleRequirement requirement,
|
|
Guid clubId)
|
|
{
|
|
return ClubRoleHelper.CheckClubRole(context, requirement, clubId);
|
|
}
|
|
}
|