using Data.SeaHavenIndustries.Enums; using SeaHaven.DataServices.Dto; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.Constants; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; using System.Security.Claims; namespace SeaHaven.Services.Implementation; public sealed class TeamPermissionService : ITeamPermissionService { private readonly ITeamPermissionOverrideDataService _dataService; private readonly ITeamPermissionPolicy _policy; public TeamPermissionService( ITeamPermissionOverrideDataService dataService, ITeamPermissionPolicy policy) { _dataService = dataService; _policy = policy; } public async Task> GetProfileAsync( string userId, ClaimsPrincipal caller, CancellationToken cancellationToken) { if (!IsAdmin(caller)) return TeamPermissionResult.Failure(TeamPermissionResultStatus.Forbidden); var user = await _dataService.GetUserAsync(userId, cancellationToken); return user is null ? TeamPermissionResult.Failure(TeamPermissionResultStatus.NotFound) : TeamPermissionResult.Success(BuildProfile(user)); } public async Task> GetEffectivePermissionsAsync( ClaimsPrincipal caller, CancellationToken cancellationToken) { var userId = caller?.Identity?.IsAuthenticated == true ? caller.FindFirstValue(ClaimTypes.NameIdentifier) : null; if (string.IsNullOrWhiteSpace(userId)) return TeamPermissionResult.Failure(TeamPermissionResultStatus.Unauthorized); var user = await _dataService.GetUserAsync(userId, cancellationToken); if (user is null) return TeamPermissionResult.Failure(TeamPermissionResultStatus.Unauthorized); return TeamPermissionResult.Success(new EffectivePermissionsDTO { Permissions = TeamPermissionKeys.All .Where(key => _policy.IsAllowed(user.RoleName, key, user.Overrides)) .ToList() }); } public async Task> SetOverrideAsync( string userId, string permissionKey, UserPermissionState state, ClaimsPrincipal caller, CancellationToken cancellationToken) { if (!IsAdmin(caller)) return TeamPermissionResult.Failure(TeamPermissionResultStatus.Forbidden); var canonicalKey = TeamPermissionKeys.All.FirstOrDefault( key => string.Equals(key, permissionKey, StringComparison.OrdinalIgnoreCase)); if (canonicalKey is null) return TeamPermissionResult.Failure( TeamPermissionResultStatus.InvalidPermissionKey); var user = await _dataService.GetUserAsync(userId, cancellationToken); if (user is null) return TeamPermissionResult.Failure(TeamPermissionResultStatus.NotFound); await _dataService.SetOverrideAsync(userId, canonicalKey, state, cancellationToken); var updatedOverrides = user.Overrides.ToDictionary( pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase); updatedOverrides[canonicalKey] = state; return TeamPermissionResult.Success( BuildProfile(new TeamPermissionUserData { UserId = user.UserId, RoleName = user.RoleName, Overrides = updatedOverrides })); } private TeamPermissionProfileDTO BuildProfile(TeamPermissionUserData user) { return new TeamPermissionProfileDTO { UserId = user.UserId, RoleName = user.RoleName, Permissions = TeamPermissionKeys.All .Select(key => new TeamPermissionValueDTO { PermissionKey = key, OverrideState = user.Overrides.TryGetValue(key, out var state) ? state : UserPermissionState.Unset, IsGranted = _policy.IsAllowed(user.RoleName, key, user.Overrides) }) .ToList() }; } private static bool IsAdmin(ClaimsPrincipal? caller) => caller?.IsInRole("Admin") == true; }