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