130 lines
5.7 KiB
C#
130 lines
5.7 KiB
C#
using MediatR;
|
|
using TakeoutSaaS.Application.Identity.Contracts;
|
|
using TakeoutSaaS.Application.Identity.Queries;
|
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
|
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
|
|
|
/// <summary>
|
|
/// 租户用户权限分页查询处理器。
|
|
/// </summary>
|
|
public sealed class SearchUserPermissionsQueryHandler(
|
|
IIdentityUserRepository identityUserRepository,
|
|
IUserRoleRepository userRoleRepository,
|
|
IRoleRepository roleRepository,
|
|
IPermissionRepository permissionRepository,
|
|
IRolePermissionRepository rolePermissionRepository,
|
|
ITenantProvider tenantProvider)
|
|
: IRequestHandler<SearchUserPermissionsQuery, PagedResult<UserPermissionDto>>
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<PagedResult<UserPermissionDto>> Handle(SearchUserPermissionsQuery request, CancellationToken cancellationToken)
|
|
{
|
|
// 1. 获取租户并查询用户
|
|
var tenantId = tenantProvider.GetCurrentTenantId();
|
|
var users = await identityUserRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
|
|
|
|
// 2. 排序与分页
|
|
var sorted = SortUsers(users, request.SortBy, request.SortDescending);
|
|
var paged = sorted
|
|
.Skip((request.Page - 1) * request.PageSize)
|
|
.Take(request.PageSize)
|
|
.ToList();
|
|
|
|
// 3. 解析角色与权限
|
|
var resolved = await ResolveRolesAndPermissionsAsync(tenantId, paged, cancellationToken);
|
|
var items = paged.Select(user => new UserPermissionDto
|
|
{
|
|
UserId = user.Id,
|
|
TenantId = user.TenantId,
|
|
MerchantId = user.MerchantId,
|
|
Account = user.Account,
|
|
DisplayName = user.DisplayName,
|
|
Roles = resolved[user.Id].roles,
|
|
Permissions = resolved[user.Id].permissions,
|
|
CreatedAt = user.CreatedAt
|
|
}).ToList();
|
|
|
|
return new PagedResult<UserPermissionDto>(items, request.Page, request.PageSize, users.Count);
|
|
}
|
|
|
|
private static IOrderedEnumerable<Domain.Identity.Entities.IdentityUser> SortUsers(
|
|
IReadOnlyCollection<Domain.Identity.Entities.IdentityUser> users,
|
|
string? sortBy,
|
|
bool sortDescending)
|
|
{
|
|
return sortBy?.ToLowerInvariant() switch
|
|
{
|
|
"account" => sortDescending
|
|
? users.OrderByDescending(x => x.Account)
|
|
: users.OrderBy(x => x.Account),
|
|
"displayname" => sortDescending
|
|
? users.OrderByDescending(x => x.DisplayName)
|
|
: users.OrderBy(x => x.DisplayName),
|
|
_ => sortDescending
|
|
? users.OrderByDescending(x => x.CreatedAt)
|
|
: users.OrderBy(x => x.CreatedAt)
|
|
};
|
|
}
|
|
|
|
private async Task<Dictionary<long, (string[] roles, string[] permissions)>> ResolveRolesAndPermissionsAsync(
|
|
long tenantId,
|
|
IReadOnlyCollection<Domain.Identity.Entities.IdentityUser> users,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
// 1. 查询用户角色关系
|
|
var userIds = users.Select(x => x.Id).ToArray();
|
|
var userRoleRelations = await userRoleRepository.GetByUserIdsAsync(tenantId, userIds, cancellationToken);
|
|
var roleIds = userRoleRelations.Select(x => x.RoleId).Distinct().ToArray();
|
|
|
|
// 2. 查询角色信息
|
|
var roles = roleIds.Length == 0
|
|
? Array.Empty<Domain.Identity.Entities.Role>()
|
|
: await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken);
|
|
var roleCodeMap = roles.ToDictionary(r => r.Id, r => r.Code, comparer: EqualityComparer<long>.Default);
|
|
|
|
// 3. 查询角色-权限关系
|
|
var rolePermissions = roleIds.Length == 0
|
|
? Array.Empty<Domain.Identity.Entities.RolePermission>()
|
|
: await rolePermissionRepository.GetByRoleIdsAsync(tenantId, roleIds, cancellationToken);
|
|
var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray();
|
|
|
|
// 4. 查询权限详情
|
|
var permissions = permissionIds.Length == 0
|
|
? Array.Empty<Domain.Identity.Entities.Permission>()
|
|
: await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken);
|
|
var permissionCodeMap = permissions.ToDictionary(p => p.Id, p => p.Code, comparer: EqualityComparer<long>.Default);
|
|
|
|
var rolePermissionsLookup = rolePermissions
|
|
.GroupBy(rp => rp.RoleId)
|
|
.ToDictionary(g => g.Key, g => g.Select(rp => rp.PermissionId).ToArray(), comparer: EqualityComparer<long>.Default);
|
|
|
|
var result = new Dictionary<long, (string[] roles, string[] permissions)>();
|
|
foreach (var userId in userIds)
|
|
{
|
|
// 5. 聚合用户角色与权限编码
|
|
var rolesForUser = userRoleRelations.Where(ur => ur.UserId == userId).Select(ur => ur.RoleId).Distinct().ToArray();
|
|
var roleCodes = rolesForUser
|
|
.Select(rid => roleCodeMap.GetValueOrDefault(rid))
|
|
.Where(c => !string.IsNullOrWhiteSpace(c))
|
|
.Select(c => c!)
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToArray();
|
|
|
|
var permissionCodes = rolesForUser
|
|
.SelectMany(rid => rolePermissionsLookup.GetValueOrDefault(rid) ?? Array.Empty<long>())
|
|
.Select(pid => permissionCodeMap.GetValueOrDefault(pid))
|
|
.Where(code => !string.IsNullOrWhiteSpace(code))
|
|
.Select(code => code!)
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToArray();
|
|
|
|
result[userId] = (roleCodes, permissionCodes);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|