- 配置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
220 lines
8.1 KiB
C#
220 lines
8.1 KiB
C#
|
||
|
||
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 });
|
||
}
|
||
}
|
||
}
|