308 lines
13 KiB
C#
308 lines
13 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using OrpaonVision.Core.Results;
|
|
using OrpaonVision.Model.Security;
|
|
using OrpaonVision.ConfigApp.Infrastructure.Services;
|
|
|
|
namespace OrpaonVision.ConfigApp.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// 权限验证服务实现。
|
|
/// </summary>
|
|
public sealed class AuthorizationService : IAuthorizationService
|
|
{
|
|
private readonly ILogger<AuthorizationService> _logger;
|
|
private readonly IUserService _userService;
|
|
private readonly IUserRoleService _userRoleService;
|
|
private readonly IRolePermissionService _rolePermissionService;
|
|
|
|
// 缓存用户权限
|
|
private readonly Dictionary<Guid, List<PermissionModel>> _userPermissionCache = new();
|
|
private readonly Dictionary<Guid, List<RoleModel>> _userRoleCache = new();
|
|
private readonly Dictionary<Guid, DateTime> _cacheTimestamps = new();
|
|
|
|
/// <summary>
|
|
/// 构造函数。
|
|
/// </summary>
|
|
public AuthorizationService(
|
|
ILogger<AuthorizationService> logger,
|
|
IUserService userService,
|
|
IUserRoleService userRoleService,
|
|
IRolePermissionService rolePermissionService)
|
|
{
|
|
_logger = logger;
|
|
_userService = userService;
|
|
_userRoleService = userRoleService;
|
|
_rolePermissionService = rolePermissionService;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<bool> CheckUserHasPermission(Guid userId, string permissionCode)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogDebug("检查用户权限: {UserId} - {PermissionCode}", userId, permissionCode);
|
|
|
|
// 获取用户权限
|
|
var permissionsResult = GetUserPermissions(userId);
|
|
if (!permissionsResult.Succeeded)
|
|
{
|
|
return Result<bool>.Fail(permissionsResult.Code, permissionsResult.Message, permissionsResult.Errors.ToArray());
|
|
}
|
|
|
|
var hasPermission = permissionsResult.Data.Any(p => p.Code.Equals(permissionCode, StringComparison.OrdinalIgnoreCase));
|
|
|
|
_logger.LogDebug("用户权限检查结果: {UserId} - {PermissionCode} - {HasPermission}", userId, permissionCode, hasPermission);
|
|
return Result<bool>.Success(hasPermission, message: hasPermission ? "用户拥有指定权限" : "用户不拥有指定权限");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "检查用户权限失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "CHECK_PERMISSION_FAILED", "检查用户权限失败。", traceId);
|
|
return Result<bool>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<bool> CheckUserHasPermission(Guid userId, Guid permissionId)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogDebug("检查用户权限: {UserId} - {PermissionId}", userId, permissionId);
|
|
|
|
// 获取用户权限
|
|
var permissionsResult = GetUserPermissions(userId);
|
|
if (!permissionsResult.Succeeded)
|
|
{
|
|
return Result<bool>.Fail(permissionsResult.Code, permissionsResult.Message, permissionsResult.Errors.ToArray());
|
|
}
|
|
|
|
var hasPermission = permissionsResult.Data.Any(p => p.Id == permissionId);
|
|
|
|
_logger.LogDebug("用户权限检查结果: {UserId} - {PermissionId} - {HasPermission}", userId, permissionId, hasPermission);
|
|
return Result<bool>.Success(hasPermission, message: hasPermission ? "用户拥有指定权限" : "用户不拥有指定权限");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "检查用户权限失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "CHECK_PERMISSION_FAILED", "检查用户权限失败。", traceId);
|
|
return Result<bool>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<bool> CheckUserHasRole(Guid userId, string roleName)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogDebug("检查用户角色: {UserId} - {RoleName}", userId, roleName);
|
|
|
|
// 获取用户角色
|
|
var rolesResult = GetUserRoles(userId);
|
|
if (!rolesResult.Succeeded)
|
|
{
|
|
return Result<bool>.Fail(rolesResult.Code, rolesResult.Message, rolesResult.Errors.ToArray());
|
|
}
|
|
|
|
var hasRole = rolesResult.Data.Any(r => r.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
_logger.LogDebug("用户角色检查结果: {UserId} - {RoleName} - {HasRole}", userId, roleName, hasRole);
|
|
return Result<bool>.Success(hasRole, message: hasRole ? "用户拥有指定角色" : "用户不拥有指定角色");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "检查用户角色失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "CHECK_ROLE_FAILED", "检查用户角色失败。", traceId);
|
|
return Result<bool>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<List<PermissionModel>> GetUserPermissions(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
// 检查缓存
|
|
if (_userPermissionCache.TryGetValue(userId, out var cachedPermissions) &&
|
|
_cacheTimestamps.TryGetValue(userId, out var cacheTime) &&
|
|
DateTime.UtcNow.Subtract(cacheTime).TotalMinutes < 5) // 5分钟缓存
|
|
{
|
|
_logger.LogDebug("从缓存获取用户权限: {UserId}", userId);
|
|
return Result<List<PermissionModel>>.Success(cachedPermissions, message: "从缓存获取用户权限成功。");
|
|
}
|
|
|
|
_logger.LogDebug("重新计算用户权限: {UserId}", userId);
|
|
|
|
// 获取用户角色
|
|
var rolesResult = _userRoleService.GetUserRoles(userId).Result;
|
|
if (!rolesResult.Succeeded)
|
|
{
|
|
return Result<List<PermissionModel>>.Fail(rolesResult.Code, rolesResult.Message, rolesResult.Errors.ToArray());
|
|
}
|
|
|
|
var allPermissions = new List<PermissionModel>();
|
|
|
|
// 获取每个角色的权限
|
|
foreach (var role in rolesResult.Data)
|
|
{
|
|
var rolePermissionsResult = _rolePermissionService.GetRolePermissions(role.Id).Result;
|
|
if (rolePermissionsResult.Succeeded)
|
|
{
|
|
allPermissions.AddRange(rolePermissionsResult.Data);
|
|
}
|
|
}
|
|
|
|
// 去重
|
|
var uniquePermissions = allPermissions
|
|
.GroupBy(p => p.Id)
|
|
.Select(g => g.First())
|
|
.ToList();
|
|
|
|
// 更新缓存
|
|
_userPermissionCache[userId] = uniquePermissions;
|
|
_cacheTimestamps[userId] = DateTime.UtcNow;
|
|
|
|
_logger.LogDebug("用户权限计算完成: {UserId} - {PermissionCount}", userId, uniquePermissions.Count);
|
|
return Result<List<PermissionModel>>.Success(uniquePermissions, message: "获取用户权限成功。");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "获取用户权限失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "GET_USER_PERMISSIONS_FAILED", "获取用户权限失败。", traceId);
|
|
return Result<List<PermissionModel>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<List<RoleModel>> GetUserRoles(Guid userId)
|
|
{
|
|
try
|
|
{
|
|
// 检查缓存
|
|
if (_userRoleCache.TryGetValue(userId, out var cachedRoles) &&
|
|
_cacheTimestamps.TryGetValue(userId, out var cacheTime) &&
|
|
DateTime.UtcNow.Subtract(cacheTime).TotalMinutes < 5) // 5分钟缓存
|
|
{
|
|
_logger.LogDebug("从缓存获取用户角色: {UserId}", userId);
|
|
return Result<List<RoleModel>>.Success(cachedRoles, message: "从缓存获取用户角色成功。");
|
|
}
|
|
|
|
_logger.LogDebug("重新获取用户角色: {UserId}", userId);
|
|
|
|
var rolesResult = _userRoleService.GetUserRoles(userId).Result;
|
|
if (!rolesResult.Succeeded)
|
|
{
|
|
return Result<List<RoleModel>>.Fail(rolesResult.Code, rolesResult.Message, rolesResult.Errors.ToArray());
|
|
}
|
|
|
|
// 更新缓存
|
|
_userRoleCache[userId] = rolesResult.Data.ToList();
|
|
_cacheTimestamps[userId] = DateTime.UtcNow;
|
|
|
|
_logger.LogDebug("用户角色获取完成: {UserId} - {RoleCount}", userId, rolesResult.Data.Count);
|
|
return Result<List<RoleModel>>.Success(rolesResult.Data.ToList(), message: "获取用户角色成功。");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "获取用户角色失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "GET_USER_ROLES_FAILED", "获取用户角色失败。", traceId);
|
|
return Result<List<RoleModel>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<bool> Authorize(Guid userId, string module, string action)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogDebug("权限验证: {UserId} - {Module}.{Action}", userId, module, action);
|
|
|
|
// 构建权限编码
|
|
var permissionCode = $"{module}.{action}";
|
|
|
|
// 检查用户权限
|
|
var checkResult = CheckUserHasPermission(userId, permissionCode);
|
|
if (!checkResult.Succeeded)
|
|
{
|
|
return Result<bool>.Fail(checkResult.Code, checkResult.Message, checkResult.Errors.ToArray());
|
|
}
|
|
|
|
_logger.LogDebug("权限验证结果: {UserId} - {Module}.{Action} - {Authorized}", userId, module, action, checkResult.Data);
|
|
return Result<bool>.Success(checkResult.Data, message: checkResult.Data ? "权限验证通过" : "权限验证失败");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "权限验证失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "AUTHORIZE_FAILED", "权限验证失败。", traceId);
|
|
return Result<bool>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Result<Dictionary<string, bool>> BatchCheckPermissions(Guid userId, List<string> permissionCodes)
|
|
{
|
|
try
|
|
{
|
|
if (permissionCodes == null || !permissionCodes.Any())
|
|
{
|
|
return Result<Dictionary<string, bool>>.Success(new Dictionary<string, bool>(), message: "权限代码列表为空。");
|
|
}
|
|
|
|
_logger.LogDebug("批量权限检查: {UserId} - {Count}个权限", userId, permissionCodes.Count);
|
|
|
|
// 获取用户权限
|
|
var permissionsResult = GetUserPermissions(userId);
|
|
if (!permissionsResult.Succeeded)
|
|
{
|
|
return Result<Dictionary<string, bool>>.Fail(permissionsResult.Code, permissionsResult.Message, permissionsResult.Errors.ToArray());
|
|
}
|
|
|
|
var userPermissions = permissionsResult.Data;
|
|
var results = new Dictionary<string, bool>();
|
|
|
|
foreach (var permissionCode in permissionCodes)
|
|
{
|
|
var hasPermission = userPermissions.Any(p => p.Code.Equals(permissionCode, StringComparison.OrdinalIgnoreCase));
|
|
results[permissionCode] = hasPermission;
|
|
}
|
|
|
|
_logger.LogDebug("批量权限检查完成: {UserId} - {Count}个权限", userId, results.Count);
|
|
return Result<Dictionary<string, bool>>.Success(results, message: "批量权限检查成功。");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var traceId = Guid.NewGuid().ToString("N");
|
|
_logger.LogError(ex, "批量权限检查失败。TraceId: {TraceId}", traceId);
|
|
var result = Result.FromException(ex, "BATCH_CHECK_PERMISSIONS_FAILED", "批量权限检查失败。", traceId);
|
|
return Result<Dictionary<string, bool>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清除用户缓存。
|
|
/// </summary>
|
|
public void ClearUserCache(Guid userId)
|
|
{
|
|
_userPermissionCache.Remove(userId);
|
|
_userRoleCache.Remove(userId);
|
|
_cacheTimestamps.Remove(userId);
|
|
_logger.LogDebug("已清除用户缓存: {UserId}", userId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清除所有缓存。
|
|
/// </summary>
|
|
public void ClearAllCache()
|
|
{
|
|
_userPermissionCache.Clear();
|
|
_userRoleCache.Clear();
|
|
_cacheTimestamps.Clear();
|
|
_logger.LogDebug("已清除所有权限缓存");
|
|
}
|
|
}
|