From 539bf2aa519422712da92adb0dd1db2badb900b4 Mon Sep 17 00:00:00 2001 From: Samuel Zedec Date: Tue, 11 Nov 2025 12:54:29 -0400 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20ajustar=20construtor=20e=20m?= =?UTF-8?q?=C3=A9todos=20de=20falha=20em=20`Error`=20e=20`Result`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Torna o campo `Details` em `Error` opcional usando `Dictionary?` - Unifica sobrecargas de métodos de falha para incluir detalhes opcionais no erro - Reestrutura lógica para melhorar a legibilidade e consistência --- src/Riber.Application/Common/Result.cs | 18 ++++++++++-------- src/Riber.Domain/Abstractions/Error.cs | 10 ++-------- 2 files changed, 12 insertions(+), 16 deletions(-) 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 From 6854015c446f99dc0db561917bb834818acbac19 Mon Sep 17 00:00:00 2001 From: Samuel Zedec Date: Tue, 11 Nov 2025 12:54:48 -0400 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20ajustar=20m=C3=A9todo=20de=20ex?= =?UTF-8?q?tens=C3=A3o=20`WriteErrorResponse`=20para=20aceitar=20`Cancella?= =?UTF-8?q?tionToken`=20e=20detalhes=20opcionais?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Torna o parâmetro `details` opcional usando `Dictionary?` - Adiciona suporte a `CancellationToken` para o método - Simplifica a lógica de criação de resposta de erro --- src/Riber.Api/Extensions/HttpContextExtension.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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 From fa5fe37c52a924983d15358be8637497fd5e3f0c Mon Sep 17 00:00:00 2001 From: Samuel Zedec Date: Tue, 11 Nov 2025 12:55:05 -0400 Subject: [PATCH 3/4] refactor: simplificar `SecurityStampMiddleware` e ajustar `GlobalExceptionHandler` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove método redundante `RespondUnauthorized` em `SecurityStampMiddleware` - Adapta chamadas para usar `WriteErrorResponse` diretamente - Ajusta `MapExceptionToError` em `GlobalExceptionHandler` para detalhes opcionais e mensagens padronizadas --- .../Common/Api/GlobalExceptionHandler.cs | 28 ++++++++++--------- .../Middlewares/SecurityStampMiddleware.cs | 15 ++-------- 2 files changed, 18 insertions(+), 25 deletions(-) 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/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; From 54c305ee5921020b4b9fdf10d2c74a473b4349f2 Mon Sep 17 00:00:00 2001 From: Samuel Zedec Date: Tue, 11 Nov 2025 12:58:47 -0400 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20atualizar=20vers=C3=A3o=20para=204?= =?UTF-8?q?.3.2=20e=20adicionar=20changelog=20com=20refatora=C3=A7=C3=B5es?= =?UTF-8?q?=20no=20padr=C3=A3o=20de=20resultados=20e=20valida=C3=A7=C3=A3o?= =?UTF-8?q?=20de=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove redundâncias na criação de `Error` e `Result` - Simplifica respostas de erros e ajusta o middleware de validação de token --- CHANGELOG.md | 9 +++++++++ Directory.Build.props | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) 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