- Added MaxIpLimit to roles, allowing for the configuration of simultaneous IP limits for users. - Updated role creation and update commands to include MaxIpLimit, ensuring proper handling in the application logic. - Enhanced user management by introducing a DELETE endpoint for user accounts, with appropriate checks to prevent self-deletion. - Updated documentation to reflect changes in role and user management, clarifying the new IP limit functionality and user deletion process. - Adjusted related tests to cover new functionality and ensure robust validation of role and user management features.
86 lines
3.3 KiB
C#
86 lines
3.3 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using PnvPanel.Application.Admin.Roles;
|
|
using PnvPanel.Application.Admin.Users;
|
|
using PnvPanel.Application.Common.Interfaces;
|
|
using PnvPanel.Application.Common.Models;
|
|
|
|
namespace PnvPanel.Infrastructure.Identity;
|
|
|
|
internal sealed class RoleService(RoleManager<AppRole> roleManager, UserManager<AppUser> userManager) : IRoleService
|
|
{
|
|
public async Task<Result<RoleDto>> CreateRoleAsync(string name, int maxConfigs, int maxIpLimit, CancellationToken cancellationToken)
|
|
{
|
|
if (await roleManager.RoleExistsAsync(name))
|
|
return Result.Failure<RoleDto>(RoleErrors.DuplicateName);
|
|
|
|
var role = new AppRole(name) { MaxConfigs = maxConfigs, MaxIpLimit = maxIpLimit, IsSystem = false };
|
|
var result = await roleManager.CreateAsync(role);
|
|
if (!result.Succeeded)
|
|
{
|
|
return Result.Failure<RoleDto>(Error.Validation(
|
|
"Roles.CreateFailed", string.Join("; ", result.Errors.Select(e => e.Description))));
|
|
}
|
|
|
|
return Result.Success(ToDto(role));
|
|
}
|
|
|
|
public async Task<Result<RoleDto>> UpdateRoleAsync(Guid roleId, int maxConfigs, int maxIpLimit, CancellationToken cancellationToken)
|
|
{
|
|
var role = await roleManager.FindByIdAsync(roleId.ToString());
|
|
if (role is null)
|
|
return Result.Failure<RoleDto>(RoleErrors.NotFound);
|
|
|
|
role.MaxConfigs = maxConfigs;
|
|
role.MaxIpLimit = maxIpLimit;
|
|
await roleManager.UpdateAsync(role);
|
|
|
|
return Result.Success(ToDto(role));
|
|
}
|
|
|
|
public async Task<Result> DeleteRoleAsync(Guid roleId, CancellationToken cancellationToken)
|
|
{
|
|
var role = await roleManager.FindByIdAsync(roleId.ToString());
|
|
if (role is null)
|
|
return Result.Failure(RoleErrors.NotFound);
|
|
|
|
if (role.IsSystem)
|
|
return Result.Failure(RoleErrors.CannotModifySystemRole);
|
|
|
|
var usersInRole = await userManager.GetUsersInRoleAsync(role.Name!);
|
|
if (usersInRole.Count > 0)
|
|
return Result.Failure(RoleErrors.RoleInUse);
|
|
|
|
await roleManager.DeleteAsync(role);
|
|
return Result.Success();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<RoleDto>> ListRolesAsync(CancellationToken cancellationToken)
|
|
{
|
|
return await roleManager.Roles
|
|
.OrderBy(r => r.Name)
|
|
.Select(r => new RoleDto(r.Id, r.Name!, r.MaxConfigs, r.MaxIpLimit, r.IsSystem))
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<Result> ChangeUserRoleAsync(Guid userId, Guid roleId, CancellationToken cancellationToken)
|
|
{
|
|
var user = await userManager.FindByIdAsync(userId.ToString());
|
|
if (user is null)
|
|
return Result.Failure(UserErrors.NotFound);
|
|
|
|
var role = await roleManager.FindByIdAsync(roleId.ToString());
|
|
if (role is null)
|
|
return Result.Failure(RoleErrors.NotFound);
|
|
|
|
var currentRoles = await userManager.GetRolesAsync(user);
|
|
if (currentRoles.Count > 0)
|
|
await userManager.RemoveFromRolesAsync(user, currentRoles);
|
|
|
|
await userManager.AddToRoleAsync(user, role.Name!);
|
|
return Result.Success();
|
|
}
|
|
|
|
private static RoleDto ToDto(AppRole role) => new(role.Id, role.Name!, role.MaxConfigs, role.MaxIpLimit, role.IsSystem);
|
|
}
|