diff --git a/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs b/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs index a1bb668..d8f1604 100644 --- a/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs +++ b/src/Api/TakeoutSaaS.AdminApi/Controllers/TenantRolesController.cs @@ -31,15 +31,24 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [FromQuery] SearchRolesQuery query, CancellationToken cancellationToken) { - // 1. 校验路由租户与上下文一致 + // 1. 校验路由租户与上下文一致(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } - // 2. 查询角色分页 - var result = await mediator.Send(query, cancellationToken); + // 2. 绑定租户并查询角色分页 + var request = new SearchRolesQuery + { + TenantId = tenantId, + Keyword = query.Keyword, + Page = query.Page, + PageSize = query.PageSize, + SortBy = query.SortBy, + SortDescending = query.SortDescending + }; + var result = await mediator.Send(request, cancellationToken); // 3. 返回分页数据 return ApiResponse>.Ok(result); @@ -54,15 +63,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task> Detail(long tenantId, long roleId, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 查询角色详情 - var result = await mediator.Send(new RoleDetailQuery { RoleId = roleId }, cancellationToken); + var result = await mediator.Send(new RoleDetailQuery { RoleId = roleId, TenantId = tenantId }, cancellationToken); // 3. 返回数据或 404 return result is null @@ -81,15 +90,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [FromBody, Required] CreateRoleCommand command, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 创建角色 - var result = await mediator.Send(command, cancellationToken); + var result = await mediator.Send(command with { TenantId = tenantId }, cancellationToken); // 3. 返回创建结果 return ApiResponse.Ok(result); @@ -108,15 +117,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [FromBody, Required] UpdateRoleCommand command, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 绑定角色 ID - command = command with { RoleId = roleId }; + command = command with { RoleId = roleId, TenantId = tenantId }; // 3. 执行更新 var result = await mediator.Send(command, cancellationToken); @@ -135,15 +144,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] public async Task> Delete(long tenantId, long roleId, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 执行删除 - var command = new DeleteRoleCommand { RoleId = roleId }; + var command = new DeleteRoleCommand { RoleId = roleId, TenantId = tenantId }; var result = await mediator.Send(command, cancellationToken); // 3. 返回结果 @@ -162,15 +171,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te long roleId, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 查询角色详情并提取权限 - var detail = await mediator.Send(new RoleDetailQuery { RoleId = roleId }, cancellationToken); + var detail = await mediator.Send(new RoleDetailQuery { RoleId = roleId, TenantId = tenantId }, cancellationToken); if (detail is null) { return ApiResponse>.Error(StatusCodes.Status404NotFound, "角色不存在"); @@ -192,15 +201,15 @@ public sealed class TenantRolesController(IMediator mediator, ITenantProvider te [FromBody, Required] BindRolePermissionsCommand command, CancellationToken cancellationToken) { - // 1. 校验租户上下文 + // 1. 校验租户上下文(超管 tenantId=0 放行) var currentTenantId = tenantProvider.GetCurrentTenantId(); - if (tenantId != currentTenantId) + if (currentTenantId != 0 && tenantId != currentTenantId) { return ApiResponse.Error(StatusCodes.Status400BadRequest, "租户上下文不一致"); } // 2. 绑定角色 ID - command = command with { RoleId = roleId }; + command = command with { RoleId = roleId, TenantId = tenantId }; // 3. 覆盖授权 var result = await mediator.Send(command, cancellationToken); diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs index aec3397..c51933f 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/BindRolePermissionsCommand.cs @@ -8,5 +8,6 @@ namespace TakeoutSaaS.Application.Identity.Commands; public sealed record BindRolePermissionsCommand : IRequest { public long RoleId { get; init; } + public long? TenantId { get; init; } public long[] PermissionIds { get; init; } = Array.Empty(); } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs index dadc2a3..289d937 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/CreateRoleCommand.cs @@ -8,6 +8,11 @@ namespace TakeoutSaaS.Application.Identity.Commands; /// public sealed record CreateRoleCommand : IRequest { + /// + /// 租户 ID(空则取当前上下文)。 + /// + public long? TenantId { get; init; } + public string Name { get; init; } = string.Empty; public string Code { get; init; } = string.Empty; public string? Description { get; init; } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs index 09085c4..7f9845b 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteRoleCommand.cs @@ -8,4 +8,9 @@ namespace TakeoutSaaS.Application.Identity.Commands; public sealed record DeleteRoleCommand : IRequest { public long RoleId { get; init; } + + /// + /// 租户 ID(空则取当前上下文)。 + /// + public long? TenantId { get; init; } } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs index b4d58a2..264951e 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateRoleCommand.cs @@ -9,6 +9,12 @@ namespace TakeoutSaaS.Application.Identity.Commands; public sealed record UpdateRoleCommand : IRequest { public long RoleId { get; init; } + + /// + /// 租户 ID(空则取当前上下文)。 + /// + public long? TenantId { get; init; } + public string Name { get; init; } = string.Empty; public string? Description { get; init; } } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs index d5a6d0e..295060c 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/BindRolePermissionsCommandHandler.cs @@ -16,7 +16,7 @@ public sealed class BindRolePermissionsCommandHandler( public async Task Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken) { // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); // 2. 覆盖式绑定权限 await rolePermissionRepository.ReplaceRolePermissionsAsync(tenantId, request.RoleId, request.PermissionIds, cancellationToken); diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs index 71fdcca..4d2fa30 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateRoleCommandHandler.cs @@ -18,7 +18,7 @@ public sealed class CreateRoleCommandHandler( public async Task Handle(CreateRoleCommand request, CancellationToken cancellationToken) { // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); // 2. 构建角色实体 var role = new Role diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs index 66ab38c..d281e06 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteRoleCommandHandler.cs @@ -16,7 +16,7 @@ public sealed class DeleteRoleCommandHandler( public async Task Handle(DeleteRoleCommand request, CancellationToken cancellationToken) { // 1. 获取租户上下文 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); // 2. 删除角色 await roleRepository.DeleteAsync(request.RoleId, tenantId, cancellationToken); diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs index 3dc6b5b..3615164 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs @@ -20,7 +20,7 @@ public sealed class RoleDetailQueryHandler( public async Task Handle(RoleDetailQuery request, CancellationToken cancellationToken) { // 1. 获取租户上下文并查询角色 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken); if (role is null) { diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs index 7309de3..74e2844 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchRolesQueryHandler.cs @@ -18,7 +18,7 @@ public sealed class SearchRolesQueryHandler( public async Task> Handle(SearchRolesQuery request, CancellationToken cancellationToken) { // 1. 获取租户上下文并查询角色 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); var roles = await roleRepository.SearchAsync(tenantId, request.Keyword, cancellationToken); // 2. 排序 diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs index 49898de..a3181e8 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateRoleCommandHandler.cs @@ -17,7 +17,7 @@ public sealed class UpdateRoleCommandHandler( public async Task Handle(UpdateRoleCommand request, CancellationToken cancellationToken) { // 1. 获取租户上下文并查询角色 - var tenantId = tenantProvider.GetCurrentTenantId(); + var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId(); var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken); if (role == null) { diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs index c5ee067..e1d00ad 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Queries/RoleDetailQuery.cs @@ -12,4 +12,9 @@ public sealed class RoleDetailQuery : IRequest /// 角色 ID。 /// public long RoleId { get; init; } + + /// + /// 租户 ID(空则取当前上下文)。 + /// + public long? TenantId { get; init; } } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs index c4160a2..ae135f7 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Queries/SearchRolesQuery.cs @@ -9,6 +9,11 @@ namespace TakeoutSaaS.Application.Identity.Queries; /// public sealed class SearchRolesQuery : IRequest> { + /// + /// 指定查询的租户 ID(空则取当前上下文)。 + /// + public long? TenantId { get; init; } + public string? Keyword { get; init; } public int Page { get; init; } = 1; public int PageSize { get; init; } = 20;