using Microsoft.AspNetCore.Mvc; using Tiku.Application.Auth; namespace Tiku.Api.Middleware; public sealed class ExceptionHandlingMiddleware( RequestDelegate next, ILogger logger, IHostEnvironment environment) { public async Task InvokeAsync(HttpContext context) { try { await next(context); } catch (Exception exception) { if (exception is AuthException authException) { await WriteAuthProblemAsync(context, authException); return; } logger.LogError(exception, "Unhandled API exception"); var problem = new ProblemDetails { Title = "An unexpected error occurred.", Status = StatusCodes.Status500InternalServerError, Detail = environment.IsDevelopment() ? exception.Message : null, Instance = context.Request.Path }; problem.Extensions["traceId"] = context.TraceIdentifier; context.Response.StatusCode = StatusCodes.Status500InternalServerError; await context.Response.WriteAsJsonAsync(problem); } } private static async Task WriteAuthProblemAsync(HttpContext context, AuthException exception) { var status = exception.Code switch { "tenant_access_denied" => StatusCodes.Status403Forbidden, "sms_rate_limited" => StatusCodes.Status429TooManyRequests, "auth_provider_not_configured" => StatusCodes.Status503ServiceUnavailable, "session_revoked" => StatusCodes.Status401Unauthorized, _ => StatusCodes.Status401Unauthorized }; var problem = new ProblemDetails { Title = exception.Message, Status = status, Instance = context.Request.Path }; problem.Extensions["code"] = exception.Code; problem.Extensions["traceId"] = context.TraceIdentifier; context.Response.StatusCode = status; await context.Response.WriteAsJsonAsync(problem); } }