Files
TakeoutSaaS.TenantApi/src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs

88 lines
3.3 KiB
C#

using MediatR;
using System.Text.Json;
using TakeoutSaaS.Application.Identity.Abstractions;
using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
/// <summary>
/// 恢复用户处理器。
/// </summary>
public sealed class RestoreIdentityUserCommandHandler(
IIdentityUserRepository identityUserRepository,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor,
IAdminAuthService adminAuthService,
IOperationLogRepository operationLogRepository)
: IRequestHandler<RestoreIdentityUserCommand, bool>
{
/// <inheritdoc />
public async Task<bool> Handle(RestoreIdentityUserCommand request, CancellationToken cancellationToken)
{
// 1. 获取操作者档案并判断权限
var currentTenantId = tenantProvider.GetCurrentTenantId();
var operatorProfile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken);
var isSuperAdmin = IdentityUserAccess.IsSuperAdmin(operatorProfile);
// 2. (空行后) 校验跨租户访问权限
if (!isSuperAdmin && request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
{
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户恢复用户");
}
// 3. (空行后) 查询用户实体(包含已删除)
var user = await identityUserRepository.GetForUpdateIncludingDeletedAsync(currentTenantId, request.UserId, isSuperAdmin, cancellationToken);
if (user == null)
{
return false;
}
if (!isSuperAdmin && user.TenantId != currentTenantId)
{
return false;
}
if (!user.DeletedAt.HasValue)
{
return false;
}
// 4. (空行后) 恢复软删除状态
user.DeletedAt = null;
user.DeletedBy = null;
await identityUserRepository.SaveChangesAsync(cancellationToken);
// 5. (空行后) 写入操作日志
var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName)
? operatorProfile.Account
: operatorProfile.DisplayName;
if (string.IsNullOrWhiteSpace(operatorName))
{
operatorName = $"user:{currentUserAccessor.UserId}";
}
var log = new OperationLog
{
OperationType = "identity-user:restore",
TargetType = "identity_user",
TargetIds = JsonSerializer.Serialize(new[] { user.Id }),
OperatorId = currentUserAccessor.UserId.ToString(),
OperatorName = operatorName,
Parameters = JsonSerializer.Serialize(new { userId = user.Id, tenantId = user.TenantId }),
Result = JsonSerializer.Serialize(new { userId = user.Id }),
Success = true
};
await operationLogRepository.AddAsync(log, cancellationToken);
await operationLogRepository.SaveChangesAsync(cancellationToken);
return true;
}
}