2026-09-16 18:02:02 -03:00
|
|
|
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<TeamPermissionResult<TeamPermissionProfileDTO>> GetProfileAsync(
|
|
|
|
|
string userId,
|
|
|
|
|
ClaimsPrincipal caller,
|
|
|
|
|
CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
if (!IsAdmin(caller))
|
|
|
|
|
return TeamPermissionResult<TeamPermissionProfileDTO>.Failure(TeamPermissionResultStatus.Forbidden);
|
|
|
|
|
|
|
|
|
|
var user = await _dataService.GetUserAsync(userId, cancellationToken);
|
|
|
|
|
return user is null
|
|
|
|
|
? TeamPermissionResult<TeamPermissionProfileDTO>.Failure(TeamPermissionResultStatus.NotFound)
|
|
|
|
|
: TeamPermissionResult<TeamPermissionProfileDTO>.Success(BuildProfile(user));
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-25 12:03:35 -03:00
|
|
|
public async Task<TeamPermissionResult<EffectivePermissionsDTO>> GetEffectivePermissionsAsync(
|
|
|
|
|
ClaimsPrincipal caller,
|
|
|
|
|
CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var userId = caller?.Identity?.IsAuthenticated == true
|
|
|
|
|
? caller.FindFirstValue(ClaimTypes.NameIdentifier)
|
|
|
|
|
: null;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(userId))
|
|
|
|
|
return TeamPermissionResult<EffectivePermissionsDTO>.Failure(TeamPermissionResultStatus.Unauthorized);
|
|
|
|
|
|
|
|
|
|
var user = await _dataService.GetUserAsync(userId, cancellationToken);
|
|
|
|
|
if (user is null)
|
|
|
|
|
return TeamPermissionResult<EffectivePermissionsDTO>.Failure(TeamPermissionResultStatus.Unauthorized);
|
|
|
|
|
|
|
|
|
|
return TeamPermissionResult<EffectivePermissionsDTO>.Success(new EffectivePermissionsDTO
|
|
|
|
|
{
|
|
|
|
|
Permissions = TeamPermissionKeys.All
|
|
|
|
|
.Where(key => _policy.IsAllowed(user.RoleName, key, user.Overrides))
|
|
|
|
|
.ToList()
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-16 18:02:02 -03:00
|
|
|
public async Task<TeamPermissionResult<TeamPermissionProfileDTO>> SetOverrideAsync(
|
|
|
|
|
string userId,
|
|
|
|
|
string permissionKey,
|
|
|
|
|
UserPermissionState state,
|
|
|
|
|
ClaimsPrincipal caller,
|
|
|
|
|
CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
if (!IsAdmin(caller))
|
|
|
|
|
return TeamPermissionResult<TeamPermissionProfileDTO>.Failure(TeamPermissionResultStatus.Forbidden);
|
|
|
|
|
|
|
|
|
|
var canonicalKey = TeamPermissionKeys.All.FirstOrDefault(
|
|
|
|
|
key => string.Equals(key, permissionKey, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
if (canonicalKey is null)
|
|
|
|
|
return TeamPermissionResult<TeamPermissionProfileDTO>.Failure(
|
|
|
|
|
TeamPermissionResultStatus.InvalidPermissionKey);
|
|
|
|
|
|
|
|
|
|
var user = await _dataService.GetUserAsync(userId, cancellationToken);
|
|
|
|
|
if (user is null)
|
|
|
|
|
return TeamPermissionResult<TeamPermissionProfileDTO>.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<TeamPermissionProfileDTO>.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;
|
|
|
|
|
}
|