feat: 添加用户权限洞察查询与示例

This commit is contained in:
2025-12-02 15:49:04 +08:00
parent 5a4ce12d61
commit 8fbd40ecf2
12 changed files with 458 additions and 1 deletions

View File

@@ -55,6 +55,29 @@ public sealed class AuthController(IAdminAuthService authService) : BaseApiContr
/// <summary>
/// 获取当前用户信息
/// </summary>
/// <remarks>
/// 示例:
/// <code>
/// GET /api/admin/v1/auth/profile
/// Header: Authorization: Bearer &lt;JWT&gt;
/// 响应:
/// {
/// "success": true,
/// "code": 200,
/// "message": "操作成功",
/// "data": {
/// "userId": "900123456789012345",
/// "account": "admin@tenant1",
/// "displayName": "租户管理员",
/// "tenantId": "100000000000000001",
/// "merchantId": null,
/// "roles": ["TenantAdmin"],
/// "permissions": ["identity:permission:read", "merchant:read", "order:read"],
/// "avatar": "https://cdn.example.com/avatar.png"
/// }
/// }
/// </code>
/// </remarks>
[HttpGet("profile")]
[PermissionAuthorize("identity:profile:read")]
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status200OK)]
@@ -70,4 +93,41 @@ public sealed class AuthController(IAdminAuthService authService) : BaseApiContr
var profile = await authService.GetProfileAsync(userId, cancellationToken);
return ApiResponse<CurrentUserProfile>.Ok(profile);
}
/// <summary>
/// 查询指定用户的角色与权限概览(当前租户范围)。
/// </summary>
/// <remarks>
/// 示例:
/// <code>
/// GET /api/admin/v1/auth/permissions/900123456789012346
/// Header: Authorization: Bearer &lt;JWT&gt;
/// 响应:
/// {
/// "success": true,
/// "code": 200,
/// "data": {
/// "userId": "900123456789012346",
/// "tenantId": "100000000000000001",
/// "merchantId": "200000000000000001",
/// "account": "ops.manager",
/// "displayName": "运营经理",
/// "roles": ["OpsManager", "Reporter"],
/// "permissions": ["delivery:read", "order:read", "payment:read"],
/// "createdAt": "2025-12-01T08:30:00Z"
/// }
/// }
/// </code>
/// </remarks>
[HttpGet("permissions/{userId:long}")]
[PermissionAuthorize("identity:permission:read")]
[ProducesResponseType(typeof(ApiResponse<UserPermissionDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<UserPermissionDto>), StatusCodes.Status404NotFound)]
public async Task<ApiResponse<UserPermissionDto>> GetUserPermissions(long userId, CancellationToken cancellationToken)
{
var result = await authService.GetUserPermissionsAsync(userId, cancellationToken);
return result is null
? ApiResponse<UserPermissionDto>.Error(ErrorCodes.NotFound, "用户不存在或不属于当前租户")
: ApiResponse<UserPermissionDto>.Ok(result);
}
}

View File

@@ -0,0 +1,71 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.Identity.Abstractions;
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}/users/permissions")]
public sealed class UserPermissionsController(IAdminAuthService authService) : BaseApiController
{
/// <summary>
/// 分页查询当前租户用户的角色与权限概览。
/// </summary>
/// <remarks>
/// 示例:
/// <code>
/// GET /api/admin/v1/users/permissions?keyword=ops&amp;page=1&amp;pageSize=20&amp;sortBy=createdAt&amp;sortDescending=true
/// Header: Authorization: Bearer &lt;JWT&gt;
/// 响应:
/// {
/// "success": true,
/// "code": 200,
/// "data": {
/// "items": [
/// {
/// "userId": "900123456789012346",
/// "tenantId": "100000000000000001",
/// "merchantId": "200000000000000001",
/// "account": "ops.manager",
/// "displayName": "运营经理",
/// "roles": ["OpsManager", "Reporter"],
/// "permissions": ["delivery:read", "order:read", "payment:read"],
/// "createdAt": "2025-12-01T08:30:00Z"
/// }
/// ],
/// "page": 1,
/// "pageSize": 20,
/// "totalCount": 1,
/// "totalPages": 1
/// }
/// }
/// </code>
/// </remarks>
[HttpGet]
[PermissionAuthorize("identity:permission:read")]
[ProducesResponseType(typeof(ApiResponse<PagedResult<UserPermissionDto>>), StatusCodes.Status200OK)]
public async Task<ApiResponse<PagedResult<UserPermissionDto>>> Search(
[FromQuery] SearchUserPermissionsQuery query,
CancellationToken cancellationToken)
{
var result = await authService.SearchUserPermissionsAsync(
query.Keyword,
query.Page,
query.PageSize,
query.SortBy,
query.SortDescending,
cancellationToken);
return ApiResponse<PagedResult<UserPermissionDto>>.Ok(result);
}
}