Backend (IAM Service):
- New GetRolePermissionsQuery + Handler: reads permissions from role_claims
- New UpdateRolePermissionsCommand + Handler: validates permission names
against StaffPermissions enum, replaces role_claims, blocks system roles
- New endpoints: GET/PUT /api/v1/roles/{id}/permissions
- GetRolesQuery: batch-fetch permissions per role via role_claims join
- RoleResponse: add Permissions field to API response
- Seeded role_claims for Admin (7), Merchant (7), MerchantAdmin (6),
MerchantStaff (2), SuperAdmin (All), Support (2)
Frontend (Blazor WASM):
- IamApiService: add Permissions to RoleDto, UpdateRolePermissionsAsync()
- RolePermissions.razor: replace hardcoded GetPermissionsForRole() with
API-driven permission toggles from role_claims data
- Editable toggles for non-system roles, disabled for system roles
- Save/Cancel buttons appear when permissions modified
- 7 permission types matching StaffPermissions enum
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
91 lines
3.4 KiB
C#
91 lines
3.4 KiB
C#
using MediatR;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using IamService.Domain.AggregatesModel.RoleAggregate;
|
|
using IamService.Domain.Exceptions;
|
|
using IamService.Infrastructure;
|
|
|
|
namespace IamService.API.Application.Commands.Roles;
|
|
|
|
/// <summary>
|
|
/// EN: Command to update permissions for a role (stored in role_claims table).
|
|
/// VI: Command để cập nhật permissions cho một role (lưu trong bảng role_claims).
|
|
/// </summary>
|
|
public record UpdateRolePermissionsCommand(
|
|
Guid RoleId,
|
|
List<string> Permissions) : IRequest<bool>;
|
|
|
|
/// <summary>
|
|
/// EN: Valid permission names matching MerchantService StaffPermissions enum.
|
|
/// VI: Tên permission hợp lệ khớp với StaffPermissions enum của MerchantService.
|
|
/// </summary>
|
|
public static class ValidPermissions
|
|
{
|
|
public static readonly HashSet<string> Names = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
"ViewSales", "ProcessPayment", "RefundOrder",
|
|
"ManageInventory", "ViewReports", "ManageStaff", "ManageSettings", "All"
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Handler for UpdateRolePermissionsCommand.
|
|
/// VI: Handler cho UpdateRolePermissionsCommand.
|
|
/// </summary>
|
|
public class UpdateRolePermissionsCommandHandler : IRequestHandler<UpdateRolePermissionsCommand, bool>
|
|
{
|
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
|
private readonly IamServiceContext _dbContext;
|
|
private readonly ILogger<UpdateRolePermissionsCommandHandler> _logger;
|
|
|
|
public UpdateRolePermissionsCommandHandler(
|
|
RoleManager<ApplicationRole> roleManager,
|
|
IamServiceContext dbContext,
|
|
ILogger<UpdateRolePermissionsCommandHandler> logger)
|
|
{
|
|
_roleManager = roleManager;
|
|
_dbContext = dbContext;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<bool> Handle(UpdateRolePermissionsCommand request, CancellationToken cancellationToken)
|
|
{
|
|
var role = await _roleManager.FindByIdAsync(request.RoleId.ToString())
|
|
?? throw new DomainException($"Role with ID {request.RoleId} not found");
|
|
|
|
if (role.IsSystemRole)
|
|
throw new DomainException("Cannot modify permissions of system roles");
|
|
|
|
// EN: Validate all permission names
|
|
// VI: Kiểm tra tất cả tên permission
|
|
var invalid = request.Permissions.Where(p => !ValidPermissions.Names.Contains(p)).ToList();
|
|
if (invalid.Any())
|
|
throw new DomainException($"Invalid permissions: {string.Join(", ", invalid)}");
|
|
|
|
// EN: Remove existing permission claims
|
|
// VI: Xóa permission claims hiện tại
|
|
var existing = await _dbContext.RoleClaims
|
|
.Where(rc => rc.RoleId == request.RoleId && rc.ClaimType == "permission")
|
|
.ToListAsync(cancellationToken);
|
|
_dbContext.RoleClaims.RemoveRange(existing);
|
|
|
|
// EN: Add new permission claims
|
|
// VI: Thêm permission claims mới
|
|
foreach (var perm in request.Permissions.Distinct())
|
|
{
|
|
_dbContext.RoleClaims.Add(new IdentityRoleClaim<Guid>
|
|
{
|
|
RoleId = request.RoleId,
|
|
ClaimType = "permission",
|
|
ClaimValue = perm
|
|
});
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync(cancellationToken);
|
|
_logger.LogInformation("Updated permissions for role {RoleName}: [{Permissions}]",
|
|
role.Name, string.Join(", ", request.Permissions));
|
|
|
|
return true;
|
|
}
|
|
}
|