using Dpz.Core.Public.Entity.Auth;

namespace Dpz.Core.Service.Mediator.Features.Auth.Commands;

public class GrantApplicationAccessCommandHandler(
    IRepository<AllowedClient> allowedClientRepository,
    IRepository<DpzApplication> applicationRepository,
    IRepository<User> userRepository
) : IRequestHandler<GrantApplicationAccessCommand, ResponseResult>
{
    public async ValueTask<ResponseResult> Handle(
        GrantApplicationAccessCommand request,
        CancellationToken cancellationToken
    )
    {
        if (string.IsNullOrWhiteSpace(request.Account) || string.IsNullOrWhiteSpace(request.AppId))
        {
            return ResponseResult.Fail("参数不能为空");
        }

        var userExists = await userRepository
            .SearchFor(x => x.Id == request.Account)
            .AnyAsync(cancellationToken);
        if (!userExists)
        {
            return ResponseResult.Fail("用户不存在");
        }

        var application = await applicationRepository
            .SearchFor(x => x.ClientId == request.AppId)
            .FirstOrDefaultAsync(cancellationToken);
        if (application == null)
        {
            return ResponseResult.Fail("应用不存在");
        }

        var exists = await allowedClientRepository
            .SearchFor(x => x.Account == request.Account && x.ApplicationId == request.AppId)
            .AnyAsync(cancellationToken);
        if (exists)
        {
            return ResponseResult.Fail("该用户已拥有此应用权限");
        }

        await allowedClientRepository.InsertAsync(
            new AllowedClient
            {
                Account = request.Account,
                ApplicationId = request.AppId,
                ApplicationName = application.DisplayName ?? request.AppId,
                AllowedTime = DateTime.Now,
            },
            cancellationToken
        );

        return ResponseResult.Ok("授权成功");
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个基于 MediatR 模式的命令处理器(Command Handler),用于处理授予用户应用访问权限的业务逻辑。

核心功能

处理 GrantApplicationAccessCommand 命令,为指定用户授予访问特定应用的权限。

类结构

依赖注入(构造函数)

public GrantApplicationAccessCommandHandler(
    IRepository<AllowedClient> allowedClientRepository,    // 已授权客户端仓储
    IRepository<DpzApplication> applicationRepository,     // 应用程序仓储
    IRepository<User> userRepository                       // 用户仓储
)

使用主构造函数语法(C# 12+)注入三个仓储接口。

处理流程(Handle 方法)

1. 参数验证

if (string.IsNullOrWhiteSpace(request.Account) || string.IsNullOrWhiteSpace(request.AppId))
    return ResponseResult.Fail("参数不能为空");

验证用户账号和应用ID不能为空。

2. 用户存在性检查

var userExists = await userRepository
    .SearchFor(x => x.Id == request.Account)
    .AnyAsync(cancellationToken);
if (!userExists)
    return ResponseResult.Fail("用户不存在");

查询数据库确认用户是否存在。

3. 应用存在性检查

var application = await applicationRepository
    .SearchFor(x => x.ClientId == request.AppId)
    .FirstOrDefaultAsync(cancellationToken);
if (application == null)
    return ResponseResult.Fail("应用不存在");

根据 ClientId 查找应用,获取完整应用信息。

4. 重复授权检查

var exists = await allowedClientRepository
    .SearchFor(x => x.Account == request.Account && x.ApplicationId == request.AppId)
    .AnyAsync(cancellationToken);
if (exists)
    return ResponseResult.Fail("该用户已拥有此应用权限");

防止重复授权同一个应用给同一个用户。

5. 创建授权记录

await allowedClientRepository.InsertAsync(
    new AllowedClient
    {
        Account = request.Account,
        ApplicationId = request.AppId,
        ApplicationName = application.DisplayName ?? request.AppId,  // 使用应用显示名称或ID
        AllowedTime = DateTime.Now,
    },
    cancellationToken
);

插入新的授权记录到数据库。

6. 返回成功结果

return ResponseResult.Ok("授权成功");

设计模式

  • CQRS(命令查询职责分离): 通过 MediatR 实现
  • Repository 模式: 数据访问抽象
  • 依赖注入: 松耦合设计

优点

  • ✅ 清晰的业务逻辑分层
  • ✅ 完善的验证流程
  • ✅ 支持异步操作和取消令牌
  • ✅ 防止数据不一致(重复授权检查)
评论加载中...