refactor: AdminApi 剔除租户侧能力
This commit is contained in:
@@ -6,8 +6,6 @@ using TakeoutSaaS.Domain.Identity.Enums;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Services;
|
||||
|
||||
@@ -23,8 +21,7 @@ public sealed class AdminAuthService(
|
||||
IMenuRepository menuRepository,
|
||||
IPasswordHasher<IdentityUser> passwordHasher,
|
||||
IJwtTokenService jwtTokenService,
|
||||
IRefreshTokenStore refreshTokenStore,
|
||||
ITenantProvider tenantProvider) : IAdminAuthService
|
||||
IRefreshTokenStore refreshTokenStore) : IAdminAuthService
|
||||
{
|
||||
/// <summary>
|
||||
/// 管理后台登录:验证账号密码并生成令牌。
|
||||
@@ -159,92 +156,6 @@ public sealed class AdminAuthService(
|
||||
return menu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户的权限概览(校验当前租户)。
|
||||
/// </summary>
|
||||
public async Task<UserPermissionDto?> GetUserPermissionsAsync(long userId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var user = await userRepository.FindByIdAsync(userId, cancellationToken);
|
||||
if (user == null || user.TenantId != tenantId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 解析角色集合
|
||||
var roleCodes = await ResolveUserRolesAsync(user.Portal, user.TenantId, user.Id, cancellationToken);
|
||||
// 2. (空行后) 解析权限集合
|
||||
var permissionCodes = await ResolveUserPermissionsAsync(user.Portal, user.TenantId, user.Id, cancellationToken);
|
||||
|
||||
// 3. (空行后) 返回概览
|
||||
return new UserPermissionDto
|
||||
{
|
||||
UserId = user.Id,
|
||||
TenantId = user.TenantId,
|
||||
MerchantId = user.MerchantId,
|
||||
Account = user.Account,
|
||||
DisplayName = user.DisplayName,
|
||||
Roles = roleCodes,
|
||||
Permissions = permissionCodes,
|
||||
CreatedAt = user.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按租户分页查询用户权限概览。
|
||||
/// </summary>
|
||||
public async Task<PagedResult<UserPermissionDto>> SearchUserPermissionsAsync(
|
||||
string? keyword,
|
||||
int page,
|
||||
int pageSize,
|
||||
string? sortBy,
|
||||
bool sortDescending,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 获取当前租户
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 2. (空行后) 查询用户列表
|
||||
var users = await userRepository.SearchAsync(tenantId, keyword, cancellationToken);
|
||||
|
||||
// 3. (空行后) 排序
|
||||
var sorted = 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)
|
||||
};
|
||||
|
||||
// 4. (空行后) 分页
|
||||
var paged = sorted
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToList();
|
||||
|
||||
// 5. (空行后) 解析角色与权限
|
||||
var resolved = await ResolveRolesAndPermissionsAsync(PortalType.Tenant, tenantId, paged, cancellationToken);
|
||||
// 6. (空行后) 映射为 DTO
|
||||
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();
|
||||
|
||||
// 7. (空行后) 返回分页结果
|
||||
return new PagedResult<UserPermissionDto>(items, page, pageSize, users.Count);
|
||||
}
|
||||
|
||||
private async Task<CurrentUserProfile> BuildProfileAsync(IdentityUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 解析角色集合
|
||||
@@ -495,68 +406,4 @@ public sealed class AdminAuthService(
|
||||
var permissions = await permissionRepository.GetByIdsAsync(permissionIds, cancellationToken);
|
||||
return permissions.Select(x => x.Code).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
}
|
||||
|
||||
private async Task<Dictionary<long, (string[] roles, string[] permissions)>> ResolveRolesAndPermissionsAsync(
|
||||
PortalType portal,
|
||||
long? tenantId,
|
||||
IReadOnlyCollection<IdentityUser> users,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取用户-角色关系
|
||||
var userIds = users.Select(x => x.Id).ToArray();
|
||||
var userRoleRelations = await userRoleRepository.GetByUserIdsAsync(portal, tenantId, userIds, cancellationToken);
|
||||
var roleIds = userRoleRelations.Select(x => x.RoleId).Distinct().ToArray();
|
||||
|
||||
// 2. (空行后) 读取角色定义
|
||||
var roles = roleIds.Length == 0
|
||||
? Array.Empty<Role>()
|
||||
: await roleRepository.GetByIdsAsync(portal, 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<RolePermission>()
|
||||
: await rolePermissionRepository.GetByRoleIdsAsync(portal, tenantId, roleIds, cancellationToken);
|
||||
|
||||
// 4. (空行后) 读取权限定义
|
||||
var permissionIds = rolePermissions.Select(x => x.PermissionId).Distinct().ToArray();
|
||||
var permissions = permissionIds.Length == 0
|
||||
? Array.Empty<Permission>()
|
||||
: await permissionRepository.GetByIdsAsync(permissionIds, cancellationToken);
|
||||
var permissionCodeMap = permissions.ToDictionary(p => p.Id, p => p.Code, comparer: EqualityComparer<long>.Default);
|
||||
|
||||
// 5. (空行后) 构建 Role -> PermissionId[] 映射
|
||||
var rolePermissionsLookup = rolePermissions
|
||||
.GroupBy(rp => rp.RoleId)
|
||||
.ToDictionary(g => g.Key, g => g.Select(rp => rp.PermissionId).ToArray(), comparer: EqualityComparer<long>.Default);
|
||||
|
||||
// 6. (空行后) 按用户聚合角色码与权限码
|
||||
var result = new Dictionary<long, (string[] roles, string[] permissions)>();
|
||||
foreach (var userId in userIds)
|
||||
{
|
||||
// 6.1 解析用户角色码
|
||||
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();
|
||||
|
||||
// 6.2 (空行后) 解析用户权限码
|
||||
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();
|
||||
|
||||
// 6.3 (空行后) 写入结果
|
||||
result[userId] = (roleCodes, permissionCodes);
|
||||
}
|
||||
|
||||
// 7. (空行后) 返回聚合结果
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user