feat: 补全租户端认证接口
- 新增 GET /api/tenant/v1/auth/profile 获取当前用户信息 - 新增 GET /api/tenant/v1/auth/permissions 获取当前用户权限码 - 新增 GET /api/tenant/v1/auth/menu 获取当前用户菜单树 - 移除 MeController,功能合并至 AuthController Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,15 +2,17 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TakeoutSaaS.Application.Identity.Abstractions;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Web.Api;
|
||||
using TakeoutSaaS.Shared.Web.Security;
|
||||
|
||||
namespace TakeoutSaaS.TenantApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 租户管理端登录认证。
|
||||
/// </summary>
|
||||
/// <remarks>仅允许租户管理员登录获取 Token。</remarks>
|
||||
/// <remarks>提供登录、刷新 Token、获取用户信息及菜单等能力。</remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/tenant/v{version:apiVersion}/auth")]
|
||||
@@ -51,4 +53,87 @@ public sealed class AuthController(IAdminAuthService authService) : BaseApiContr
|
||||
// 2. 返回新的令牌
|
||||
return ApiResponse<TokenResponse>.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户信息。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 示例响应:
|
||||
/// <code>
|
||||
/// {
|
||||
/// "success": true,
|
||||
/// "code": 200,
|
||||
/// "data": {
|
||||
/// "userId": "900123456789012345",
|
||||
/// "account": "admin",
|
||||
/// "displayName": "租户管理员",
|
||||
/// "tenantId": "100000000000000001",
|
||||
/// "roles": ["tenant-admin"],
|
||||
/// "permissions": ["identity:profile:read", "merchant:read"]
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>当前用户档案信息。</returns>
|
||||
[HttpGet("profile")]
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<CurrentUserProfile>> GetProfile(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 从 JWT 中获取当前用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<CurrentUserProfile>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 读取用户档案并返回
|
||||
var profile = await authService.GetProfileAsync(userId, cancellationToken);
|
||||
return ApiResponse<CurrentUserProfile>.Ok(profile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户的权限码列表。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>权限码数组。</returns>
|
||||
[HttpGet("permissions")]
|
||||
[ProducesResponseType(typeof(ApiResponse<string[]>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<string[]>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<string[]>> GetPermissions(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 从 JWT 中获取当前用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<string[]>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 读取用户档案获取权限
|
||||
var profile = await authService.GetProfileAsync(userId, cancellationToken);
|
||||
return ApiResponse<string[]>.Ok(profile.Permissions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户的菜单树(按权限过滤)。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>当前用户可见的菜单树。</returns>
|
||||
[HttpGet("menu")]
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<MenuNodeDto>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<MenuNodeDto>>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<IReadOnlyList<MenuNodeDto>>> GetMenuTree(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 获取当前用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<IReadOnlyList<MenuNodeDto>>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 生成菜单树
|
||||
var menu = await authService.GetMenuTreeAsync(userId, cancellationToken);
|
||||
return ApiResponse<IReadOnlyList<MenuNodeDto>>.Ok(menu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TakeoutSaaS.Application.Identity.Abstractions;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Web.Api;
|
||||
using TakeoutSaaS.Shared.Web.Security;
|
||||
|
||||
namespace TakeoutSaaS.TenantApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 当前租户管理员信息。
|
||||
/// </summary>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize(Roles = "tenant-admin")]
|
||||
[Route("api/tenant/v{version:apiVersion}/me")]
|
||||
public sealed class MeController(IAdminAuthService authService) : BaseApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前用户档案。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>当前用户档案信息。</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<CurrentUserProfile>> Get(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 从 JWT 中解析用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<CurrentUserProfile>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 查询用户档案并返回
|
||||
var profile = await authService.GetProfileAsync(userId, cancellationToken);
|
||||
return ApiResponse<CurrentUserProfile>.Ok(profile);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user