diff --git a/CHANGELOG.md b/CHANGELOG.md index e396ad7..08f0173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ --- +## v4.3.2 - 11/12/2025 +**REFATORAÇÃO**: Mudança no result pattern e na classe de erro +- Remove a redundância de codigo na criação de um Error +- Remove sobrecargas na criação de Result com Errors +- Simplifica as respostas de Errors +- Remove método redundante do middleware de validação do token + +--- + ## v4.3.1 - 09/12/2025 **REFATORAÇÃO**: Remove o método de busca por id da entidade nos IAiModelService Adiciona relacionamento entre entidade `ProductEmbeddings` e `Company` para uma melhor busca diff --git a/Directory.Build.props b/Directory.Build.props index 7ef75cb..e5753e4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ Samuel Zedec Copyright © $([System.DateTime]::Now.Year) Sistema de gestão financeira para um lanchonete local - 4.3.1 + 4.3.2 diff --git a/src/Riber.Api/Common/Api/GlobalExceptionHandler.cs b/src/Riber.Api/Common/Api/GlobalExceptionHandler.cs index 357cbd7..5dfa7fe 100644 --- a/src/Riber.Api/Common/Api/GlobalExceptionHandler.cs +++ b/src/Riber.Api/Common/Api/GlobalExceptionHandler.cs @@ -11,28 +11,30 @@ namespace Riber.Api.Common.Api; /// Trata exceções globais na aplicação registrando erros e formatando /// uma resposta JSON padronizada para o cliente. /// -public sealed class GlobalExceptionHandler(ILogger logger) : IExceptionHandler +public sealed class GlobalExceptionHandler( + ILogger logger) + : IExceptionHandler { public async ValueTask TryHandleAsync( - HttpContext httpContext, - Exception exception, + HttpContext httpContext, + Exception exception, CancellationToken cancellationToken) { - logger.LogError(exception, "Exception occurred: {ExceptionType} - {Message}", + logger.LogError(exception, "Exception occurred: {ExceptionType} - {Message}", exception.GetType().Name, exception.Message); - - (HttpStatusCode statusCode, string message, Dictionary details) = MapExceptionToError(exception); - await httpContext.WriteErrorResponse(statusCode, message, details); + + (HttpStatusCode statusCode, string message, Dictionary? details) = MapExceptionToError(exception); + await httpContext.WriteErrorResponse(statusCode, message, details, cancellationToken); return true; } - private static (HttpStatusCode StatusCode, string Message, Dictionary Details) MapExceptionToError(Exception exception) + private static (HttpStatusCode, string, Dictionary?) MapExceptionToError(Exception exception) => exception switch { - RequestTimeoutException timeoutEx => (timeoutEx.Code, timeoutEx.Message, []), - ValidationException validationEx => (HttpStatusCode.BadRequest, string.Empty, validationEx.Details), - Layer.ApplicationException applicationEx => (applicationEx.Code, applicationEx.Message, []), - DomainException domainEx => (HttpStatusCode.UnprocessableContent, domainEx.Message, []), - _ => (HttpStatusCode.InternalServerError, "Erro inesperado no servidor.", []) + RequestTimeoutException timeoutEx => (timeoutEx.Code, timeoutEx.Message, null), + ValidationException validationEx => (HttpStatusCode.BadRequest, "Dados Inválidos.", validationEx.Details), + Layer.ApplicationException applicationEx => (applicationEx.Code, applicationEx.Message, null), + DomainException domainEx => (HttpStatusCode.UnprocessableContent, domainEx.Message, null), + _ => (HttpStatusCode.InternalServerError, "Erro inesperado no servidor.", null) }; } \ No newline at end of file diff --git a/src/Riber.Api/Extensions/HttpContextExtension.cs b/src/Riber.Api/Extensions/HttpContextExtension.cs index ac4213e..49cf05d 100644 --- a/src/Riber.Api/Extensions/HttpContextExtension.cs +++ b/src/Riber.Api/Extensions/HttpContextExtension.cs @@ -17,16 +17,15 @@ public static async Task WriteErrorResponse( this HttpContext context, HttpStatusCode code, string message, - Dictionary details) + Dictionary? details = null, + CancellationToken cancellationToken = default) { - var response = details.Count == 0 - ? Result.Failure(message, code) - : Result.Failure(details, code); - + var response = Result.Failure(message, code, details); var jsonResponse = JsonSerializer.Serialize(response, JsonOptions); + context.Response.StatusCode = (int)code; context.Response.ContentType = "application/json"; - await context.Response.WriteAsync(jsonResponse); + await context.Response.WriteAsync(jsonResponse, cancellationToken); } } \ No newline at end of file diff --git a/src/Riber.Api/Middlewares/SecurityStampMiddleware.cs b/src/Riber.Api/Middlewares/SecurityStampMiddleware.cs index 449a546..7dff201 100644 --- a/src/Riber.Api/Middlewares/SecurityStampMiddleware.cs +++ b/src/Riber.Api/Middlewares/SecurityStampMiddleware.cs @@ -20,29 +20,20 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) (string? userId, string? tokenSecurityStamp) = ExtractUserClaims(context.User); if (!Guid.TryParse(userId, out var userIdParse) || string.IsNullOrWhiteSpace(tokenSecurityStamp)) { - await RespondUnauthorized(context, "Token do usuário inválido ou mal formado."); + await context.WriteErrorResponse(HttpStatusCode.Unauthorized, "Token do usuário inválido ou mal formado."); return; } - + var user = await userQueryService.FindByIdAsync(userIdParse); if (user is null || user.SecurityStamp != tokenSecurityStamp) { - await RespondUnauthorized(context, "Security stamp inválido ou usuário não encontrado."); + await context.WriteErrorResponse(HttpStatusCode.Unauthorized, "Security stamp inválido ou usuário não encontrado."); return; } await next(context); } - private static async Task RespondUnauthorized(HttpContext context, string message) - { - await context.WriteErrorResponse( - code: HttpStatusCode.Unauthorized, - message: message, - details: [] - ); - } - private static (string? userId, string? securityStamp) ExtractUserClaims(ClaimsPrincipal user) { var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value; diff --git a/src/Riber.Application/Common/Result.cs b/src/Riber.Application/Common/Result.cs index 0a2afe6..0b90884 100644 --- a/src/Riber.Application/Common/Result.cs +++ b/src/Riber.Application/Common/Result.cs @@ -45,17 +45,19 @@ public static Result Success( public static Result Failure( string message, HttpStatusCode statusCode = HttpStatusCode.BadRequest) - => new(new EmptyResult(), false, new Error(message, statusCode), statusCode); + { + var error = new Error(message, statusCode, null); + return new Result(new EmptyResult(), false, error, statusCode); + } public static Result Failure( string message, - HttpStatusCode statusCode = HttpStatusCode.BadRequest) - => new(default, false, new Error(message, statusCode), statusCode); - - public static Result Failure( - Dictionary details, - HttpStatusCode statusCode = HttpStatusCode.BadRequest) - => new(default, false, new Error(details, statusCode), statusCode); + HttpStatusCode statusCode = HttpStatusCode.BadRequest, + Dictionary? details = null) + { + var error = new Error(message, statusCode, details); + return new Result(default, false, error, statusCode); + } #endregion } diff --git a/src/Riber.Domain/Abstractions/Error.cs b/src/Riber.Domain/Abstractions/Error.cs index 31c8019..c3d1f05 100644 --- a/src/Riber.Domain/Abstractions/Error.cs +++ b/src/Riber.Domain/Abstractions/Error.cs @@ -12,7 +12,7 @@ public sealed class Error public string Type { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; - public Dictionary Details { get; set; } = []; + public Dictionary? Details { get; init; } #endregion @@ -21,17 +21,11 @@ public sealed class Error [JsonConstructor] public Error() { } - public Error(string message, HttpStatusCode statusCode) + public Error(string message, HttpStatusCode statusCode, Dictionary? details) { Message = message; Type = statusCode.ToString(); - } - - public Error(Dictionary details, HttpStatusCode statusCode) - { - Message = "Dados Inválidos."; Details = details; - Type = statusCode.ToString(); } #endregion