82 lines
2.8 KiB
C#
82 lines
2.8 KiB
C#
using MediatR;
|
|
using TakeoutSaaS.Application.Identity.Commands;
|
|
using TakeoutSaaS.Application.Identity.Contracts;
|
|
using TakeoutSaaS.Domain.Identity.Entities;
|
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
|
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
|
|
|
/// <summary>
|
|
/// 创建角色处理器。
|
|
/// </summary>
|
|
public sealed class CreateRoleCommandHandler(
|
|
IRoleRepository roleRepository,
|
|
ITenantProvider tenantProvider)
|
|
: IRequestHandler<CreateRoleCommand, RoleDto>
|
|
{
|
|
/// <summary>
|
|
/// 处理创建角色请求。
|
|
/// </summary>
|
|
/// <param name="request">创建命令。</param>
|
|
/// <param name="cancellationToken">取消标记。</param>
|
|
/// <returns>创建后的角色 DTO。</returns>
|
|
public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
|
|
{
|
|
// 1. 获取租户上下文并校验跨租户
|
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
|
if (currentTenantId <= 0)
|
|
{
|
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
|
}
|
|
|
|
// 2. (空行后) 禁止跨租户创建
|
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
|
{
|
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户创建角色");
|
|
}
|
|
|
|
// 3. (空行后) 使用当前租户创建角色
|
|
var tenantId = currentTenantId;
|
|
|
|
// 4. (空行后) 归一化输入并校验唯一
|
|
var name = request.Name?.Trim() ?? string.Empty;
|
|
var code = request.Code?.Trim() ?? string.Empty;
|
|
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(code))
|
|
{
|
|
throw new BusinessException(ErrorCodes.BadRequest, "角色名称与编码不能为空");
|
|
}
|
|
|
|
var exists = await roleRepository.FindByCodeAsync(code, tenantId, cancellationToken);
|
|
if (exists is not null)
|
|
{
|
|
throw new BusinessException(ErrorCodes.Conflict, "角色编码已存在");
|
|
}
|
|
|
|
// 5. (空行后) 构建角色实体
|
|
var role = new Role
|
|
{
|
|
TenantId = tenantId,
|
|
Name = name,
|
|
Code = code,
|
|
Description = request.Description
|
|
};
|
|
|
|
// 6. (空行后) 持久化
|
|
await roleRepository.AddAsync(role, cancellationToken);
|
|
await roleRepository.SaveChangesAsync(cancellationToken);
|
|
|
|
// 7. (空行后) 返回 DTO
|
|
return new RoleDto
|
|
{
|
|
Id = role.Id,
|
|
TenantId = role.TenantId,
|
|
Name = role.Name,
|
|
Code = role.Code,
|
|
Description = role.Description
|
|
};
|
|
}
|
|
}
|