fengling-console/Controllers/RolesController.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

303 lines
12 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 RolesController : ControllerBase
{
private readonly IRoleService _roleService;
private readonly ILogger<RolesController> _logger;
public RolesController(IRoleService roleService, ILogger<RolesController> logger)
{
_roleService = roleService;
_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<RoleDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<PagedResultDto<RoleDto>>> GetRoles([FromQuery] RoleQueryDto query)
{
try
{
var (items, totalCount) = await _roleService.GetRolesAsync(query.Page, query.PageSize, query.Name, query.TenantId);
var result = new PagedResultDto<RoleDto>
{
Items = items.ToList(),
TotalCount = totalCount,
Page = query.Page,
PageSize = query.PageSize
};
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting roles");
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(RoleDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<RoleDto>> GetRole(long id)
{
try
{
var role = await _roleService.GetRoleAsync(id);
if (role == null)
{
return NotFound();
}
return Ok(role);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting role {RoleId}", id);
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}/users")]
[Produces("application/json")]
[ProducesResponseType(typeof(IEnumerable<UserDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<IEnumerable<UserDto>>> GetRoleUsers(long id)
{
try
{
var users = await _roleService.GetRoleUsersAsync(id);
return Ok(users);
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Role not found: {RoleId}", id);
return NotFound();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting users for role {RoleId}", 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(RoleDto), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<RoleDto>> CreateRole([FromBody] CreateRoleDto dto)
{
try
{
var role = await _roleService.CreateRoleAsync(dto);
return CreatedAtAction(nameof(GetRole), new { id = role.Id }, role);
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error creating role");
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating role");
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}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateRole(long id, [FromBody] UpdateRoleDto dto)
{
try
{
await _roleService.UpdateRoleAsync(id, dto);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Role not found: {RoleId}", id);
return NotFound();
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error updating role {RoleId}", id);
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating role {RoleId}", 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="400">请求参数无效(如角色下有关联用户)</response>
/// <response code="500">服务器内部错误</response>
[HttpDelete("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteRole(long id)
{
try
{
await _roleService.DeleteRoleAsync(id);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Role not found: {RoleId}", id);
return NotFound();
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error deleting role {RoleId}", id);
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting role {RoleId}", id);
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 将用户添加到角色
/// </summary>
/// <param name="id">角色ID</param>
/// <param name="userId">用户ID</param>
/// <returns>无内容响应</returns>
/// <response code="204">成功添加用户到角色</response>
/// <response code="404">角色或用户不存在</response>
/// <response code="400">请求参数无效或用户已在角色中</response>
/// <response code="500">服务器内部错误</response>
[HttpPost("{id}/users/{userId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> AddUserToRole(long id, long userId)
{
try
{
await _roleService.AddUserToRoleAsync(id, userId);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Role or user not found: RoleId={RoleId}, UserId={UserId}", id, userId);
return NotFound();
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error adding user {UserId} to role {RoleId}", userId, id);
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding user {UserId} to role {RoleId}", userId, id);
return StatusCode(500, new { message = ex.Message });
}
}
/// <summary>
/// 将用户从角色中移除
/// </summary>
/// <param name="id">角色ID</param>
/// <param name="userId">用户ID</param>
/// <returns>无内容响应</returns>
/// <response code="204">成功从角色中移除用户</response>
/// <response code="404">角色或用户不存在</response>
/// <response code="400">请求参数无效</response>
/// <response code="500">服务器内部错误</response>
[HttpDelete("{id}/users/{userId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> RemoveUserFromRole(long id, long userId)
{
try
{
await _roleService.RemoveUserFromRoleAsync(id, userId);
return NoContent();
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Role or user not found: RoleId={RoleId}, UserId={UserId}", id, userId);
return NotFound();
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Validation error removing user {UserId} from role {RoleId}", userId, id);
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error removing user {UserId} from role {RoleId}", userId, id);
return StatusCode(500, new { message = ex.Message });
}
}
}