From b2a90cf8af0043d09a86eda677673ff2bbbc3a6d Mon Sep 17 00:00:00 2001
From: MSuMshk <2039814060@qq.com>
Date: Sat, 27 Dec 2025 06:23:03 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E5=90=8E=E7=AB=AF=E4=B8=8E=E6=97=A5=E5=BF=97=E5=BA=93=E8=BF=81?=
=?UTF-8?q?=E7=A7=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/UsersController.cs | 212 +++++
.../appsettings.Development.json | 5 +-
.../appsettings.Production.json | 5 +-
.../appsettings.Seed.Development.json | 14 +
.../appsettings.Development.json | 5 +-
.../appsettings.Production.json | 5 +-
.../appsettings.Development.json | 5 +-
.../appsettings.Production.json | 5 +-
.../CreateTenantManuallyCommandHandler.cs | 3 +-
.../SelfRegisterTenantCommandHandler.cs | 4 +-
.../BatchIdentityUserOperationCommand.cs | 26 +
.../ChangeIdentityUserStatusCommand.cs | 25 +
.../Commands/CreateIdentityUserCommand.cs | 66 ++
.../Commands/DeleteIdentityUserCommand.cs | 19 +
.../ResetIdentityUserPasswordCommand.cs | 20 +
.../Commands/RestoreIdentityUserCommand.cs | 19 +
.../Commands/UpdateIdentityUserCommand.cs | 58 ++
.../Contracts/BatchIdentityUserFailureItem.cs | 21 +
.../BatchIdentityUserOperationResult.cs | 27 +
.../ResetIdentityUserPasswordResult.cs | 17 +
.../Identity/Contracts/UserDetailDto.cs | 94 +++
.../Identity/Contracts/UserListItemDto.cs | 73 ++
...atchIdentityUserOperationCommandHandler.cs | 318 ++++++++
.../ChangeIdentityUserStatusCommandHandler.cs | 150 ++++
.../CreateIdentityUserCommandHandler.cs | 190 +++++
.../DeleteIdentityUserCommandHandler.cs | 125 +++
.../GetIdentityUserDetailQueryHandler.cs | 104 +++
...ResetAdminPasswordByTokenCommandHandler.cs | 8 +
...ResetIdentityUserPasswordCommandHandler.cs | 100 +++
.../RestoreIdentityUserCommandHandler.cs | 87 +++
.../SearchIdentityUsersQueryHandler.cs | 144 ++++
.../UpdateIdentityUserCommandHandler.cs | 172 +++++
.../Identity/IdentityUserAccess.cs | 19 +
.../Models/IdentityUserBatchOperation.cs | 32 +
.../Queries/GetIdentityUserDetailQuery.cs | 20 +
.../Queries/SearchIdentityUsersQuery.cs | 77 ++
.../Identity/Services/AdminAuthService.cs | 92 ++-
...chIdentityUserOperationCommandValidator.cs | 24 +
.../CreateIdentityUserCommandValidator.cs | 37 +
.../SearchIdentityUsersQueryValidator.cs | 28 +
.../UpdateIdentityUserCommandValidator.cs | 38 +
.../Identity/Entities/IdentityUser.cs | 41 +
.../Identity/Enums/IdentityUserStatus.cs | 22 +
.../Repositories/IIdentityUserRepository.cs | 172 +++++
.../Repositories/IUserRoleRepository.cs | 9 +
.../Repositories/IOperationLogRepository.cs | 24 +
.../AppServiceCollectionExtensions.cs | 2 +
.../Persistence/EfIdentityUserRepository.cs | 318 ++++++++
.../Persistence/EfPermissionRepository.cs | 27 +-
.../Persistence/EfRolePermissionRepository.cs | 6 +-
.../Identity/Persistence/EfRoleRepository.cs | 19 +-
.../Persistence/EfUserRoleRepository.cs | 27 +-
.../Identity/Persistence/IdentityDbContext.cs | 17 +
.../Repositories/EfOperationLogRepository.cs | 24 +
...ddIdentityUserManagementFields.Designer.cs | 726 ++++++++++++++++++
...6174411_AddIdentityUserManagementFields.cs | 178 +++++
.../IdentityDbContextModelSnapshot.cs | 45 ++
57 files changed, 4117 insertions(+), 33 deletions(-)
create mode 100644 src/Api/TakeoutSaaS.AdminApi/Controllers/UsersController.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/BatchIdentityUserOperationCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/ChangeIdentityUserStatusCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/CreateIdentityUserCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/DeleteIdentityUserCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/ResetIdentityUserPasswordCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/RestoreIdentityUserCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Contracts/BatchIdentityUserFailureItem.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Contracts/BatchIdentityUserOperationResult.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Contracts/ResetIdentityUserPasswordResult.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Contracts/UserDetailDto.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Contracts/UserListItemDto.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/BatchIdentityUserOperationCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ChangeIdentityUserStatusCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateIdentityUserCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteIdentityUserCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/GetIdentityUserDetailQueryHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/ResetIdentityUserPasswordCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/RestoreIdentityUserCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchIdentityUsersQueryHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/IdentityUserAccess.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Models/IdentityUserBatchOperation.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/GetIdentityUserDetailQuery.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Queries/SearchIdentityUsersQuery.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/BatchIdentityUserOperationCommandValidator.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/CreateIdentityUserCommandValidator.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/SearchIdentityUsersQueryValidator.cs
create mode 100644 src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Identity/Enums/IdentityUserStatus.cs
create mode 100644 src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/IOperationLogRepository.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Logs/Repositories/EfOperationLogRepository.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.Designer.cs
create mode 100644 src/Infrastructure/TakeoutSaaS.Infrastructure/Migrations/IdentityDb/20251226174411_AddIdentityUserManagementFields.cs
diff --git a/src/Api/TakeoutSaaS.AdminApi/Controllers/UsersController.cs b/src/Api/TakeoutSaaS.AdminApi/Controllers/UsersController.cs
new file mode 100644
index 0000000..412e8e9
--- /dev/null
+++ b/src/Api/TakeoutSaaS.AdminApi/Controllers/UsersController.cs
@@ -0,0 +1,212 @@
+using MediatR;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.ComponentModel.DataAnnotations;
+using TakeoutSaaS.Application.Identity.Commands;
+using TakeoutSaaS.Application.Identity.Contracts;
+using TakeoutSaaS.Application.Identity.Queries;
+using TakeoutSaaS.Module.Authorization.Attributes;
+using TakeoutSaaS.Shared.Abstractions.Constants;
+using TakeoutSaaS.Shared.Abstractions.Results;
+using TakeoutSaaS.Shared.Web.Api;
+
+namespace TakeoutSaaS.AdminApi.Controllers;
+
+///
+/// 用户管理。
+///
+[ApiVersion("1.0")]
+[Authorize]
+[Route("api/admin/v{version:apiVersion}/users")]
+public sealed class UsersController(IMediator mediator) : BaseApiController
+{
+ ///
+ /// 用户分页列表。
+ ///
+ [HttpGet]
+ [PermissionAuthorize("identity:user:read")]
+ [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)]
+ public async Task>> List(
+ [FromQuery] SearchIdentityUsersQuery query,
+ CancellationToken cancellationToken)
+ {
+ // 1. 查询用户分页
+ var result = await mediator.Send(query, cancellationToken);
+
+ // 2. 返回分页数据
+ return ApiResponse>.Ok(result);
+ }
+
+ ///
+ /// 用户详情。
+ ///
+ [HttpGet("{userId:long}")]
+ [PermissionAuthorize("identity:user:read")]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)]
+ public async Task> Detail(long userId, [FromQuery] bool includeDeleted, CancellationToken cancellationToken)
+ {
+ // 1. 查询用户详情
+ var result = await mediator.Send(new GetIdentityUserDetailQuery
+ {
+ UserId = userId,
+ IncludeDeleted = includeDeleted
+ }, cancellationToken);
+
+ // 2. 返回详情或 404
+ return result == null
+ ? ApiResponse.Error(ErrorCodes.NotFound, "用户不存在")
+ : ApiResponse.Ok(result);
+ }
+
+ ///
+ /// 用户权限明细。
+ ///
+ [HttpGet("{userId:long}/permissions")]
+ [PermissionAuthorize("identity:user:read")]
+ [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)]
+ [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status404NotFound)]
+ public async Task>> Permissions(long userId, CancellationToken cancellationToken)
+ {
+ // 1. 查询用户详情并提取权限
+ var detail = await mediator.Send(new GetIdentityUserDetailQuery { UserId = userId }, cancellationToken);
+ if (detail == null)
+ {
+ return ApiResponse>.Error(ErrorCodes.NotFound, "用户不存在");
+ }
+
+ // 2. 返回权限编码列表
+ return ApiResponse>.Ok(detail.Permissions);
+ }
+
+ ///
+ /// 创建用户。
+ ///
+ [HttpPost]
+ [PermissionAuthorize("identity:user:create")]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ public async Task> Create([FromBody, Required] CreateIdentityUserCommand command, CancellationToken cancellationToken)
+ {
+ // 1. 创建用户
+ var result = await mediator.Send(command, cancellationToken);
+
+ // 2. 返回创建结果
+ return ApiResponse.Ok(result);
+ }
+
+ ///
+ /// 更新用户。
+ ///
+ [HttpPut("{userId:long}")]
+ [PermissionAuthorize("identity:user:update")]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)]
+ public async Task> Update(long userId, [FromBody, Required] UpdateIdentityUserCommand command, CancellationToken cancellationToken)
+ {
+ // 1. 绑定用户 ID
+ if (command.UserId == 0)
+ {
+ command = command with { UserId = userId };
+ }
+
+ // 2. (空行后) 执行更新
+ var result = await mediator.Send(command, cancellationToken);
+
+ // 3. (空行后) 返回结果或 404
+ return result == null
+ ? ApiResponse.Error(ErrorCodes.NotFound, "用户不存在")
+ : ApiResponse.Ok(result);
+ }
+
+ ///
+ /// 删除用户。
+ ///
+ [HttpDelete("{userId:long}")]
+ [PermissionAuthorize("identity:user:delete")]
+ [ProducesResponseType(typeof(ApiResponse