using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.EntityFrameworkCore; using WorkClub.Domain.Enums; using WorkClub.Infrastructure.Data; namespace WorkClub.Api.Auth; public class ClubRoleClaimsTransformation : IClaimsTransformation { private readonly IHttpContextAccessor _httpContextAccessor; private readonly AppDbContext _context; public ClubRoleClaimsTransformation( IHttpContextAccessor httpContextAccessor, AppDbContext context) { _httpContextAccessor = httpContextAccessor; _context = context; } public Task TransformAsync(ClaimsPrincipal principal) { if (principal.Identity is not ClaimsIdentity identity || !identity.IsAuthenticated) { return Task.FromResult(principal); } var clubsClaim = principal.FindFirst("clubs")?.Value; if (string.IsNullOrEmpty(clubsClaim)) { return Task.FromResult(principal); } // Parse comma-separated club UUIDs var clubIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(id => id.Trim()) .ToArray(); if (clubIds.Length == 0) { return Task.FromResult(principal); } var tenantId = _httpContextAccessor.HttpContext?.Request.Headers["X-Tenant-Id"].FirstOrDefault(); if (string.IsNullOrEmpty(tenantId) || !clubIds.Contains(tenantId)) { return Task.FromResult(principal); } var userIdClaim = principal.FindFirst("preferred_username")?.Value; if (string.IsNullOrEmpty(userIdClaim)) { return Task.FromResult(principal); } // Look up the user's role in the database for the requested tenant _httpContextAccessor.HttpContext!.Items["TenantId"] = tenantId; var memberRole = GetMemberRole(userIdClaim, tenantId); if (memberRole.HasValue) { var mappedRole = MapClubRoleToAspNetRole(memberRole.Value); identity.AddClaim(new Claim(ClaimTypes.Role, mappedRole)); } return Task.FromResult(principal); } private ClubRole? GetMemberRole(string externalUserId, string tenantId) { try { var member = _context.Members .FirstOrDefault(m => m.Email == externalUserId && m.TenantId == tenantId); return member?.Role; } catch { return null; } } private static string MapClubRoleToAspNetRole(ClubRole clubRole) { return clubRole switch { ClubRole.Admin => "Admin", ClubRole.Manager => "Manager", ClubRole.Member => "Member", ClubRole.Viewer => "Viewer", _ => "Viewer" }; } }