feat(api): PUT /api/v1/users/{id}/permisos/overrides + excepciones domain + ExceptionFilter [UDT-009]
This commit is contained in:
@@ -246,6 +246,30 @@ public sealed class UsuariosController : ControllerBase
|
||||
return Ok(MapToPermisosResponse(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the grant/deny override sets for a usuario.
|
||||
/// Requires administracion:usuarios:gestionar.
|
||||
/// </summary>
|
||||
[HttpPut("{id:int}/permisos/overrides")]
|
||||
[RequirePermission("administracion:usuarios:gestionar")]
|
||||
[ProducesResponseType(typeof(UsuarioPermisosResponse), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> UpdatePermisosOverrides(
|
||||
[FromRoute] int id,
|
||||
[FromBody] UpdatePermisosOverridesRequest request)
|
||||
{
|
||||
var command = new UpdateUsuarioPermisosOverridesCommand(
|
||||
Id: id,
|
||||
Grant: request.Grant ?? [],
|
||||
Deny: request.Deny ?? []);
|
||||
|
||||
var result = await _dispatcher.Send<UpdateUsuarioPermisosOverridesCommand, UsuarioPermisosDto>(command);
|
||||
return Ok(MapToPermisosResponse(result));
|
||||
}
|
||||
|
||||
private static UsuarioPermisosResponse MapToPermisosResponse(UsuarioPermisosDto dto)
|
||||
=> new(
|
||||
RolPermisos: dto.RolPermisos,
|
||||
@@ -266,6 +290,11 @@ public sealed record PermisosOverridesShape(
|
||||
IReadOnlyList<string> Grant,
|
||||
IReadOnlyList<string> Deny);
|
||||
|
||||
/// <summary>UDT-009: PUT permisos/overrides request body.</summary>
|
||||
public sealed record UpdatePermisosOverridesRequest(
|
||||
IReadOnlyList<string>? Grant,
|
||||
IReadOnlyList<string>? Deny);
|
||||
|
||||
/// <summary>Create user request body — nullable to catch missing field scenarios.</summary>
|
||||
public sealed record CreateUsuarioRequest(
|
||||
string? Username,
|
||||
|
||||
@@ -169,6 +169,35 @@ public sealed class ExceptionFilter : IExceptionFilter
|
||||
context.ExceptionHandled = true;
|
||||
break;
|
||||
|
||||
// UDT-009: permiso override validation errors
|
||||
case InvalidPermisoCodesException ipce:
|
||||
context.Result = new ObjectResult(new Microsoft.AspNetCore.Mvc.ProblemDetails
|
||||
{
|
||||
Type = "about:blank",
|
||||
Title = "invalid-permiso-codes",
|
||||
Status = 400,
|
||||
Extensions = { ["invalidCodes"] = ipce.InvalidCodes }
|
||||
})
|
||||
{
|
||||
StatusCode = StatusCodes.Status400BadRequest
|
||||
};
|
||||
context.ExceptionHandled = true;
|
||||
break;
|
||||
|
||||
case GrantDenyOverlapException gdoe:
|
||||
context.Result = new ObjectResult(new Microsoft.AspNetCore.Mvc.ProblemDetails
|
||||
{
|
||||
Type = "about:blank",
|
||||
Title = "grant-deny-overlap",
|
||||
Status = 400,
|
||||
Extensions = { ["overlap"] = gdoe.Overlap }
|
||||
})
|
||||
{
|
||||
StatusCode = StatusCodes.Status400BadRequest
|
||||
};
|
||||
context.ExceptionHandled = true;
|
||||
break;
|
||||
|
||||
case ValidationException validationEx:
|
||||
var errors = validationEx.Errors
|
||||
.GroupBy(e => e.PropertyName)
|
||||
|
||||
Reference in New Issue
Block a user