first commit
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
using Fitness_core_BE.DTOs.Rbac;
|
||||
using Fitness_core_BE.Exceptions;
|
||||
using Fitness_core_BE.Helpers;
|
||||
using Fitness_core_BE.Infra.UoW;
|
||||
using Fitness_core_BE.Interfaces;
|
||||
using Fitness_core_BE.Interfaces.Services;
|
||||
using Fitness_core_BE.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Fitness_core_BE.Services
|
||||
{
|
||||
public class GymRoleService : IGymRoleService
|
||||
{
|
||||
private readonly IGymRoleRepository _gymRoleRepository;
|
||||
private readonly INavItemRepository _navItemRepository;
|
||||
private readonly UserRoleHelper _userRoleHelper;
|
||||
private readonly IUnitOfWork _uow;
|
||||
|
||||
public GymRoleService(
|
||||
IGymRoleRepository gymRoleRepository,
|
||||
INavItemRepository navItemRepository,
|
||||
UserRoleHelper userRoleHelper,
|
||||
IUnitOfWork uow)
|
||||
{
|
||||
_gymRoleRepository = gymRoleRepository;
|
||||
_navItemRepository = navItemRepository;
|
||||
_userRoleHelper = userRoleHelper;
|
||||
_uow = uow;
|
||||
}
|
||||
|
||||
public async Task<List<GymRoleDto>> GetRolesAsync(HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var roles = await _gymRoleRepository.GetRolesByClientId(clientId);
|
||||
return roles.Select(ToDto).ToList();
|
||||
}
|
||||
|
||||
public async Task<GymRoleDto> CreateRoleAsync(CreateGymRoleRequest request, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var role = new GymRole { FKClientId = clientId, Name = request.Name };
|
||||
var created = await _gymRoleRepository.CreateRole(role);
|
||||
await _uow.SaveChangesAsync();
|
||||
return ToDto(created);
|
||||
}
|
||||
|
||||
public async Task<GymRoleDto> UpdateRoleAsync(Guid gymRoleId, UpdateGymRoleRequest request, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var role = await GetOwnedRole(gymRoleId, clientId);
|
||||
|
||||
if (request.Name != null) role.Name = request.Name;
|
||||
if (request.IsActive.HasValue) role.IsActive = request.IsActive.Value;
|
||||
|
||||
var updated = await _gymRoleRepository.UpdateRole(role);
|
||||
await _uow.SaveChangesAsync();
|
||||
return ToDto(updated);
|
||||
}
|
||||
|
||||
public async Task DeleteRoleAsync(Guid gymRoleId, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var role = await GetOwnedRole(gymRoleId, clientId);
|
||||
await _gymRoleRepository.DeleteRole(role);
|
||||
await _uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<GymRoleDto> SetRolePermissionsAsync(Guid gymRoleId, SetRolePermissionsRequest request, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var role = await GetOwnedRole(gymRoleId, clientId);
|
||||
var requestedKeys = request.NavKeys?.Distinct().ToList() ?? new List<string>();
|
||||
var assignableKeys = (await _navItemRepository.GetActiveNavItemsOrdered())
|
||||
.Where(item => !item.IsOwnerOnly && item.Key != "dashboard")
|
||||
.Select(item => item.Key)
|
||||
.ToHashSet();
|
||||
var invalidKeys = requestedKeys.Where(key => !assignableKeys.Contains(key)).ToList();
|
||||
if (invalidKeys.Count > 0)
|
||||
throw new BadRequestException($"Invalid role permission: {string.Join(", ", invalidKeys)}.");
|
||||
|
||||
await _gymRoleRepository.ReplacePermissions(gymRoleId, requestedKeys);
|
||||
await _uow.SaveChangesAsync();
|
||||
|
||||
var refreshed = await _gymRoleRepository.GetRoleById(gymRoleId)
|
||||
?? throw new NotFoundException("Role not found.");
|
||||
return ToDto(refreshed);
|
||||
}
|
||||
|
||||
public async Task AssignStaffRoleAsync(Guid staffId, AssignStaffRoleRequest request, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await GetOwnerClientId(httpContext);
|
||||
var assigned = await _gymRoleRepository.AssignStaffRole(staffId, clientId, request.GymRoleId);
|
||||
if (!assigned)
|
||||
throw new NotFoundException("Staff member or role not found for this gym.");
|
||||
await _uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// Every public method funnels through here: only a caller who resolves to a Client
|
||||
// (the gym owner) can manage roles. Staff — regardless of any nav-section permission
|
||||
// they've been granted, including "staff" — are rejected before any GymRole/
|
||||
// GymRolePermission data is ever touched.
|
||||
private async Task<Guid> GetOwnerClientId(HttpContext httpContext)
|
||||
{
|
||||
var userId = DataExtractor.GetUserIdFromContext(httpContext);
|
||||
return await _userRoleHelper.GetOwnedClientId(userId)
|
||||
?? throw new UnauthorizedAccessException("Only the gym owner can manage roles and permissions.");
|
||||
}
|
||||
|
||||
private async Task<GymRole> GetOwnedRole(Guid gymRoleId, Guid clientId)
|
||||
{
|
||||
var role = await _gymRoleRepository.GetRoleById(gymRoleId)
|
||||
?? throw new NotFoundException("Role not found.");
|
||||
if (role.FKClientId != clientId)
|
||||
throw new NotFoundException("Role not found.");
|
||||
return role;
|
||||
}
|
||||
|
||||
private static GymRoleDto ToDto(GymRole role) => new()
|
||||
{
|
||||
GymRoleId = role.GymRoleId,
|
||||
Name = role.Name,
|
||||
IsActive = role.IsActive,
|
||||
NavKeys = role.Permissions?.Select(p => p.NavItemKey).ToList() ?? new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user