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; /// /// 租户用户权限分页查询处理器。 /// public sealed class SearchUserPermissionsQueryHandler( IIdentityUserRepository identityUserRepository, IUserRoleRepository userRoleRepository, IRoleRepository roleRepository, IPermissionRepository permissionRepository, IRolePermissionRepository rolePermissionRepository, ITenantProvider tenantProvider) : IRequestHandler> { /// public async Task> 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(items, request.Page, request.PageSize, users.Count); } private static IOrderedEnumerable SortUsers( IReadOnlyCollection 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> ResolveRolesAndPermissionsAsync( long tenantId, IReadOnlyCollection 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() : await roleRepository.GetByIdsAsync(tenantId, roleIds, cancellationToken); var roleCodeMap = roles.ToDictionary(r => r.Id, r => r.Code, comparer: EqualityComparer.Default); // 3. 查询角色-权限关系 var rolePermissions = roleIds.Length == 0 ? Array.Empty() : await rolePermissionRepository.GetByRoleIdsAsync(tenantId, roleIds, cancellationToken); var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray(); // 4. 查询权限详情 var permissions = permissionIds.Length == 0 ? Array.Empty() : await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken); var permissionCodeMap = permissions.ToDictionary(p => p.Id, p => p.Code, comparer: EqualityComparer.Default); var rolePermissionsLookup = rolePermissions .GroupBy(rp => rp.RoleId) .ToDictionary(g => g.Key, g => g.Select(rp => rp.PermissionId).ToArray(), comparer: EqualityComparer.Default); var result = new Dictionary(); 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()) .Select(pid => permissionCodeMap.GetValueOrDefault(pid)) .Where(code => !string.IsNullOrWhiteSpace(code)) .Select(code => code!) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); result[userId] = (roleCodes, permissionCodes); } return result; } }