feat: 增加角色/权限管理 API 与应用层命令
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Application.Identity.Queries;
|
||||
using TakeoutSaaS.Module.Authorization.Attributes;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Web.Api;
|
||||
|
||||
namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 权限管理。
|
||||
/// </summary>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/permissions")]
|
||||
public sealed class PermissionsController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页查询权限。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 示例:GET /api/admin/v1/permissions?keyword=order&page=1&pageSize=20
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[PermissionAuthorize("identity:permission:read")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PermissionDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<PermissionDto>>> Search([FromQuery] SearchPermissionsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
return ApiResponse<PagedResult<PermissionDto>>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建权限。
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[PermissionAuthorize("identity:permission:create")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PermissionDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PermissionDto>> Create([FromBody, Required] CreatePermissionCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<PermissionDto>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新权限。
|
||||
/// </summary>
|
||||
[HttpPut("{permissionId:long}")]
|
||||
[PermissionAuthorize("identity:permission:update")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PermissionDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PermissionDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<PermissionDto>> Update(long permissionId, [FromBody, Required] UpdatePermissionCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
command = command with { PermissionId = permissionId };
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return result is null
|
||||
? ApiResponse<PermissionDto>.Error(StatusCodes.Status404NotFound, "权限不存在")
|
||||
: ApiResponse<PermissionDto>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除权限。
|
||||
/// </summary>
|
||||
[HttpDelete("{permissionId:long}")]
|
||||
[PermissionAuthorize("identity:permission:delete")]
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long permissionId, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new DeletePermissionCommand { PermissionId = permissionId };
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
}
|
||||
93
src/Api/TakeoutSaaS.AdminApi/Controllers/RolesController.cs
Normal file
93
src/Api/TakeoutSaaS.AdminApi/Controllers/RolesController.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Application.Identity.Queries;
|
||||
using TakeoutSaaS.Module.Authorization.Attributes;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Web.Api;
|
||||
|
||||
namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 角色管理。
|
||||
/// </summary>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/roles")]
|
||||
public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页查询角色。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 示例:
|
||||
/// GET /api/admin/v1/roles?keyword=ops&page=1&pageSize=20
|
||||
/// Header: Authorization: Bearer <JWT> + X-Tenant-Id
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[PermissionAuthorize("identity:role:read")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<RoleDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<RoleDto>>> Search([FromQuery] SearchRolesQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
return ApiResponse<PagedResult<RoleDto>>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建角色。
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[PermissionAuthorize("identity:role:create")]
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<RoleDto>> Create([FromBody, Required] CreateRoleCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<RoleDto>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新角色。
|
||||
/// </summary>
|
||||
[HttpPut("{roleId:long}")]
|
||||
[PermissionAuthorize("identity:role:update")]
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<RoleDto>> Update(long roleId, [FromBody, Required] UpdateRoleCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
command = command with { RoleId = roleId };
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return result is null
|
||||
? ApiResponse<RoleDto>.Error(StatusCodes.Status404NotFound, "角色不存在")
|
||||
: ApiResponse<RoleDto>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除角色。
|
||||
/// </summary>
|
||||
[HttpDelete("{roleId:long}")]
|
||||
[PermissionAuthorize("identity:role:delete")]
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long roleId, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new DeleteRoleCommand { RoleId = roleId };
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绑定角色权限(覆盖式)。
|
||||
/// </summary>
|
||||
[HttpPut("{roleId:long}/permissions")]
|
||||
[PermissionAuthorize("identity:role:bind-permission")]
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> BindPermissions(long roleId, [FromBody, Required] BindRolePermissionsCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
command = command with { RoleId = roleId };
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using MediatR;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 为用户分配角色(覆盖式)。
|
||||
/// </summary>
|
||||
public sealed record AssignUserRolesCommand : IRequest<bool>
|
||||
{
|
||||
public long UserId { get; init; }
|
||||
public long[] RoleIds { get; init; } = Array.Empty<long>();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using MediatR;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 绑定角色权限(覆盖式)。
|
||||
/// </summary>
|
||||
public sealed record BindRolePermissionsCommand : IRequest<bool>
|
||||
{
|
||||
public long RoleId { get; init; }
|
||||
public long[] PermissionIds { get; init; } = Array.Empty<long>();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 创建权限。
|
||||
/// </summary>
|
||||
public sealed record CreatePermissionCommand : IRequest<PermissionDto>
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Code { get; init; } = string.Empty;
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 创建角色。
|
||||
/// </summary>
|
||||
public sealed record CreateRoleCommand : IRequest<RoleDto>
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Code { get; init; } = string.Empty;
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using MediatR;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 删除权限。
|
||||
/// </summary>
|
||||
public sealed record DeletePermissionCommand : IRequest<bool>
|
||||
{
|
||||
public long PermissionId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using MediatR;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 删除角色。
|
||||
/// </summary>
|
||||
public sealed record DeleteRoleCommand : IRequest<bool>
|
||||
{
|
||||
public long RoleId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 更新权限。
|
||||
/// </summary>
|
||||
public sealed record UpdatePermissionCommand : IRequest<PermissionDto?>
|
||||
{
|
||||
public long PermissionId { get; init; }
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 更新角色。
|
||||
/// </summary>
|
||||
public sealed record UpdateRoleCommand : IRequest<RoleDto?>
|
||||
{
|
||||
public long RoleId { get; init; }
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using TakeoutSaaS.Shared.Abstractions.Serialization;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 权限 DTO。
|
||||
/// </summary>
|
||||
public sealed class PermissionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 权限 ID(雪花,序列化为字符串)。
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||
public long Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户 ID。
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||
public long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 权限编码(租户内唯一)。
|
||||
/// </summary>
|
||||
public string Code { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 描述。
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using TakeoutSaaS.Shared.Abstractions.Serialization;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 角色 DTO。
|
||||
/// </summary>
|
||||
public sealed class RoleDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色 ID(雪花,序列化为字符串)。
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||
public long Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户 ID。
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||
public long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 角色编码(租户内唯一)。
|
||||
/// </summary>
|
||||
public string Code { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 描述。
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 用户角色分配处理器。
|
||||
/// </summary>
|
||||
public sealed class AssignUserRolesCommandHandler(
|
||||
IUserRoleRepository userRoleRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<AssignUserRolesCommand, bool>
|
||||
{
|
||||
public async Task<bool> Handle(AssignUserRolesCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
await userRoleRepository.ReplaceUserRolesAsync(tenantId, request.UserId, request.RoleIds, cancellationToken);
|
||||
await userRoleRepository.SaveChangesAsync(cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 绑定角色权限处理器。
|
||||
/// </summary>
|
||||
public sealed class BindRolePermissionsCommandHandler(
|
||||
IRolePermissionRepository rolePermissionRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<BindRolePermissionsCommand, bool>
|
||||
{
|
||||
public async Task<bool> Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
await rolePermissionRepository.ReplaceRolePermissionsAsync(tenantId, request.RoleId, request.PermissionIds, cancellationToken);
|
||||
await rolePermissionRepository.SaveChangesAsync(cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
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.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 创建权限处理器。
|
||||
/// </summary>
|
||||
public sealed class CreatePermissionCommandHandler(
|
||||
IPermissionRepository permissionRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<CreatePermissionCommand, PermissionDto>
|
||||
{
|
||||
public async Task<PermissionDto> Handle(CreatePermissionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var permission = new Permission
|
||||
{
|
||||
TenantId = tenantId,
|
||||
Name = request.Name,
|
||||
Code = request.Code,
|
||||
Description = request.Description
|
||||
};
|
||||
|
||||
await permissionRepository.AddAsync(permission, cancellationToken);
|
||||
await permissionRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new PermissionDto
|
||||
{
|
||||
Id = permission.Id,
|
||||
TenantId = permission.TenantId,
|
||||
Name = permission.Name,
|
||||
Code = permission.Code,
|
||||
Description = permission.Description
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
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.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 创建角色处理器。
|
||||
/// </summary>
|
||||
public sealed class CreateRoleCommandHandler(
|
||||
IRoleRepository roleRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<CreateRoleCommand, RoleDto>
|
||||
{
|
||||
public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var role = new Role
|
||||
{
|
||||
TenantId = tenantId,
|
||||
Name = request.Name,
|
||||
Code = request.Code,
|
||||
Description = request.Description
|
||||
};
|
||||
|
||||
await roleRepository.AddAsync(role, cancellationToken);
|
||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new RoleDto
|
||||
{
|
||||
Id = role.Id,
|
||||
TenantId = role.TenantId,
|
||||
Name = role.Name,
|
||||
Code = role.Code,
|
||||
Description = role.Description
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 删除权限处理器。
|
||||
/// </summary>
|
||||
public sealed class DeletePermissionCommandHandler(
|
||||
IPermissionRepository permissionRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<DeletePermissionCommand, bool>
|
||||
{
|
||||
public async Task<bool> Handle(DeletePermissionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
await permissionRepository.DeleteAsync(request.PermissionId, tenantId, cancellationToken);
|
||||
await permissionRepository.SaveChangesAsync(cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 删除角色处理器。
|
||||
/// </summary>
|
||||
public sealed class DeleteRoleCommandHandler(
|
||||
IRoleRepository roleRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<DeleteRoleCommand, bool>
|
||||
{
|
||||
public async Task<bool> Handle(DeleteRoleCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
await roleRepository.DeleteAsync(request.RoleId, tenantId, cancellationToken);
|
||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Application.Identity.Queries;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 权限分页查询处理器。
|
||||
/// </summary>
|
||||
public sealed class SearchPermissionsQueryHandler(
|
||||
IPermissionRepository permissionRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<SearchPermissionsQuery, PagedResult<PermissionDto>>
|
||||
{
|
||||
public async Task<PagedResult<PermissionDto>> Handle(SearchPermissionsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var permissions = await permissionRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
|
||||
|
||||
var sorted = request.SortBy?.ToLowerInvariant() switch
|
||||
{
|
||||
"name" => request.SortDescending
|
||||
? permissions.OrderByDescending(x => x.Name)
|
||||
: permissions.OrderBy(x => x.Name),
|
||||
"code" => request.SortDescending
|
||||
? permissions.OrderByDescending(x => x.Code)
|
||||
: permissions.OrderBy(x => x.Code),
|
||||
_ => request.SortDescending
|
||||
? permissions.OrderByDescending(x => x.CreatedAt)
|
||||
: permissions.OrderBy(x => x.CreatedAt)
|
||||
};
|
||||
|
||||
var paged = sorted
|
||||
.Skip((request.Page - 1) * request.PageSize)
|
||||
.Take(request.PageSize)
|
||||
.ToList();
|
||||
|
||||
var items = paged.Select(permission => new PermissionDto
|
||||
{
|
||||
Id = permission.Id,
|
||||
TenantId = permission.TenantId,
|
||||
Name = permission.Name,
|
||||
Code = permission.Code,
|
||||
Description = permission.Description
|
||||
}).ToList();
|
||||
|
||||
return new PagedResult<PermissionDto>(items, request.Page, request.PageSize, permissions.Count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Application.Identity.Queries;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 角色分页查询处理器。
|
||||
/// </summary>
|
||||
public sealed class SearchRolesQueryHandler(
|
||||
IRoleRepository roleRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<SearchRolesQuery, PagedResult<RoleDto>>
|
||||
{
|
||||
public async Task<PagedResult<RoleDto>> Handle(SearchRolesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var roles = await roleRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
|
||||
|
||||
var sorted = request.SortBy?.ToLowerInvariant() switch
|
||||
{
|
||||
"name" => request.SortDescending
|
||||
? roles.OrderByDescending(x => x.Name)
|
||||
: roles.OrderBy(x => x.Name),
|
||||
_ => request.SortDescending
|
||||
? roles.OrderByDescending(x => x.CreatedAt)
|
||||
: roles.OrderBy(x => x.CreatedAt)
|
||||
};
|
||||
|
||||
var paged = sorted
|
||||
.Skip((request.Page - 1) * request.PageSize)
|
||||
.Take(request.PageSize)
|
||||
.ToList();
|
||||
|
||||
var items = paged.Select(role => new RoleDto
|
||||
{
|
||||
Id = role.Id,
|
||||
TenantId = role.TenantId,
|
||||
Name = role.Name,
|
||||
Code = role.Code,
|
||||
Description = role.Description
|
||||
}).ToList();
|
||||
|
||||
return new PagedResult<RoleDto>(items, request.Page, request.PageSize, roles.Count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 更新权限处理器。
|
||||
/// </summary>
|
||||
public sealed class UpdatePermissionCommandHandler(
|
||||
IPermissionRepository permissionRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<UpdatePermissionCommand, PermissionDto?>
|
||||
{
|
||||
public async Task<PermissionDto?> Handle(UpdatePermissionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var permission = await permissionRepository.FindByIdAsync(request.PermissionId, tenantId, cancellationToken);
|
||||
if (permission == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
permission.Name = request.Name;
|
||||
permission.Description = request.Description;
|
||||
|
||||
await permissionRepository.UpdateAsync(permission, cancellationToken);
|
||||
await permissionRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new PermissionDto
|
||||
{
|
||||
Id = permission.Id,
|
||||
TenantId = permission.TenantId,
|
||||
Name = permission.Name,
|
||||
Code = permission.Code,
|
||||
Description = permission.Description
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 更新角色处理器。
|
||||
/// </summary>
|
||||
public sealed class UpdateRoleCommandHandler(
|
||||
IRoleRepository roleRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
: IRequestHandler<UpdateRoleCommand, RoleDto?>
|
||||
{
|
||||
public async Task<RoleDto?> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken);
|
||||
if (role == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
role.Name = request.Name;
|
||||
role.Description = request.Description;
|
||||
|
||||
await roleRepository.UpdateAsync(role, cancellationToken);
|
||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new RoleDto
|
||||
{
|
||||
Id = role.Id,
|
||||
TenantId = role.TenantId,
|
||||
Name = role.Name,
|
||||
Code = role.Code,
|
||||
Description = role.Description
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询权限。
|
||||
/// </summary>
|
||||
public sealed class SearchPermissionsQuery : IRequest<PagedResult<PermissionDto>>
|
||||
{
|
||||
public string? Keyword { get; init; }
|
||||
public int Page { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 20;
|
||||
public string? SortBy { get; init; }
|
||||
public bool SortDescending { get; init; } = true;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
|
||||
namespace TakeoutSaaS.Application.Identity.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询角色。
|
||||
/// </summary>
|
||||
public sealed class SearchRolesQuery : IRequest<PagedResult<RoleDto>>
|
||||
{
|
||||
public string? Keyword { get; init; }
|
||||
public int Page { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 20;
|
||||
public string? SortBy { get; init; }
|
||||
public bool SortDescending { get; init; } = true;
|
||||
}
|
||||
Reference in New Issue
Block a user