fengling-console/Controllers/UsersController.cs
Sam c8cb7c06bc feat: 添加Console API认证和OpenIddict集成
- 配置AuthService使用OpenIddict reference tokens
- 添加fengling-api客户端用于introspection验证
- 配置Console API通过OpenIddict验证reference tokens
- 实现Tenant/Users/Roles/OAuthClients CRUD API
- 添加GatewayController服务注册API
- 重构Repository和Service层支持多租户

BREAKING CHANGE: API认证现在使用OpenIddict reference tokens
2026-02-08 19:01:25 +08:00

220 lines
8.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace Fengling.Console.Controllers;
/// <summary>
/// 用户管理控制器
/// 提供用户的增删改查以及密码重置等功能
/// </summary>
[ApiController]
[Route("api/console/[controller]")]
[Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
private readonly ILogger<UsersController> _logger;
public UsersController(IUserService userService, ILogger<UsersController> logger)
{
_userService = userService;
_logger = logger;
}
/// <summary>
/// 获取用户列表
/// </summary>
/// <param name="query">分页查询参数支持按用户名、邮箱和租户ID筛选</param>
/// <returns>分页的用户列表,包含用户基本信息和状态</returns>
/// <response code="200">成功返回用户分页列表</response>
/// <response code="500">服务器内部错误</response>
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(typeof(PagedResultDto<UserDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<PagedResultDto<UserDto>>> GetUsers([FromQuery] UserQueryDto query)
{
try
{
var (items, totalCount) = await _userService.GetUsersAsync(query.Page, query.PageSize, query.UserName, query.Email, query.TenantId);
var result = new PagedResultDto<UserDto>
{
Items = items.ToList(),
TotalCount = totalCount,
Page = query.Page,
PageSize = query.PageSize
};
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting users");
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 获取单个用户详情
/// </summary>
/// <param name="id">用户ID</param>
/// <returns>用户的详细信息,包括角色、租户等信息</returns>
/// <response code="200">成功返回用户详情</response>
/// <response code="404">用户不存在</response>
/// <response code="500">服务器内部错误</response>
[HttpGet("{id}")]
[Produces("application/json")]
[ProducesResponseType(typeof(UserDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<UserDto>> GetUser(long id)
{
try
{
var user = await _userService.GetUserAsync(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting user {UserId}", id);
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 创建新用户
/// </summary>
/// <param name="dto">创建用户所需的配置信息</param>
/// <returns>创建的用户详情</returns>
/// <response code="201">成功创建用户</response>
/// <response code="400">请求参数无效或用户名/邮箱已存在</response>
/// <response code="500">服务器内部错误</response>
[HttpPost]
[Produces("application/json")]
[ProducesResponseType(typeof(UserDto), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<UserDto>> CreateUser([FromBody] CreateUserDto dto)
{
try
{
var user = await _userService.CreateUserAsync(dto);
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error creating user");
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating user");
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="dto">需要更新的用户配置信息</param>
/// <returns>无内容响应</returns>
/// <response code="204">成功更新用户</response>
/// <response code="404">用户不存在</response>
/// <response code="500">服务器内部错误</response>
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUser(long id, [FromBody] UpdateUserDto dto)
{
try
{
await _userService.UpdateUserAsync(id, dto);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "User not found: {UserId}", id);
return NotFound();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating user {UserId}", id);
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 重置用户密码
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="dto">包含新密码的请求体</param>
/// <returns>无内容响应</returns>
/// <response code="204">成功重置密码</response>
/// <response code="404">用户不存在</response>
/// <response code="400">密码不符合复杂度要求</response>
/// <response code="500">服务器内部错误</response>
[HttpPut("{id}/password")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> ResetPassword(long id, [FromBody] ResetPasswordDto dto)
{
try
{
await _userService.ResetPasswordAsync(id, dto);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "User not found: {UserId}", id);
return NotFound();
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error resetting password for user {UserId}", id);
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error resetting password for user {UserId}", id);
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="id">用户ID</param>
/// <returns>无内容响应</returns>
/// <response code="204">成功删除用户</response>
/// <response code="404">用户不存在</response>
/// <response code="500">服务器内部错误</response>
[HttpDelete("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteUser(long id)
{
try
{
await _userService.DeleteUserAsync(id);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "User not found: {UserId}", id);
return NotFound();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting user {UserId}", id);
return StatusCode(500, new { message = ex.Message });
}
}
}