diff --git a/web/backend/API/API.Core/API.Core.csproj b/web/backend/API/API.Core/API.Core.csproj index 6e9825d..4fe70b9 100644 --- a/web/backend/API/API.Core/API.Core.csproj +++ b/web/backend/API/API.Core/API.Core.csproj @@ -8,33 +8,27 @@ - - - - + + + + - + - - - - - - - - - - + + + + + + + + + + diff --git a/web/backend/API/API.Core/Authentication/JwtAuthenticationHandler.cs b/web/backend/API/API.Core/Authentication/JwtAuthenticationHandler.cs index 3833c64..539c903 100644 --- a/web/backend/API/API.Core/Authentication/JwtAuthenticationHandler.cs +++ b/web/backend/API/API.Core/Authentication/JwtAuthenticationHandler.cs @@ -44,29 +44,19 @@ public class JwtAuthenticationHandler( { // Use the same access-token secret source as TokenService to avoid mismatched validation. string? secret = Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET"); - if (string.IsNullOrWhiteSpace(secret)) secret = configuration["Jwt:SecretKey"]; + if (string.IsNullOrWhiteSpace(secret)) + secret = configuration["Jwt:SecretKey"]; - if (string.IsNullOrWhiteSpace(secret)) return AuthenticateResult.Fail("JWT secret is not configured"); + if (string.IsNullOrWhiteSpace(secret)) + return AuthenticateResult.Fail("JWT secret is not configured"); // Check if Authorization header exists - if ( - !Request.Headers.TryGetValue( - "Authorization", - out StringValues authHeaderValue - ) - ) + if (!Request.Headers.TryGetValue("Authorization", out StringValues authHeaderValue)) return AuthenticateResult.Fail("Authorization header is missing"); string authHeader = authHeaderValue.ToString(); - if ( - !authHeader.StartsWith( - "Bearer ", - StringComparison.OrdinalIgnoreCase - ) - ) - return AuthenticateResult.Fail( - "Invalid authorization header format" - ); + if (!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) + return AuthenticateResult.Fail("Invalid authorization header format"); string token = authHeader.Substring("Bearer ".Length).Trim(); @@ -81,9 +71,7 @@ public class JwtAuthenticationHandler( } catch (Exception ex) { - return AuthenticateResult.Fail( - $"Token validation failed: {ex.Message}" - ); + return AuthenticateResult.Fail($"Token validation failed: {ex.Message}"); } } @@ -97,7 +85,10 @@ public class JwtAuthenticationHandler( Response.ContentType = "application/json"; Response.StatusCode = 401; - ResponseBody response = new() { Message = "Unauthorized: Invalid or missing authentication token" }; + ResponseBody response = new() + { + Message = "Unauthorized: Invalid or missing authentication token", + }; await Response.WriteAsJsonAsync(response); } } @@ -106,6 +97,4 @@ public class JwtAuthenticationHandler( /// Options for the JWT authentication scheme handled by . /// /// No additional options are defined beyond those provided by . -public class JwtAuthenticationOptions : AuthenticationSchemeOptions -{ -} \ No newline at end of file +public class JwtAuthenticationOptions : AuthenticationSchemeOptions { } diff --git a/web/backend/API/API.Core/Controllers/NotFoundController.cs b/web/backend/API/API.Core/Controllers/NotFoundController.cs index 1f3a31e..35c3890 100644 --- a/web/backend/API/API.Core/Controllers/NotFoundController.cs +++ b/web/backend/API/API.Core/Controllers/NotFoundController.cs @@ -24,4 +24,4 @@ public class NotFoundController : ControllerBase { return NotFound(new { message = "Route not found." }); } -} \ No newline at end of file +} diff --git a/web/backend/API/API.Core/Controllers/ProtectedController.cs b/web/backend/API/API.Core/Controllers/ProtectedController.cs index 4efa192..02199d4 100644 --- a/web/backend/API/API.Core/Controllers/ProtectedController.cs +++ b/web/backend/API/API.Core/Controllers/ProtectedController.cs @@ -31,8 +31,8 @@ public class ProtectedController : ControllerBase new ResponseBody { Message = "Protected endpoint accessed successfully", - Payload = new { userId, username } + Payload = new { userId, username }, } ); } -} \ No newline at end of file +} diff --git a/web/backend/API/API.Core/GlobalException.cs b/web/backend/API/API.Core/GlobalException.cs index 78e8325..ae37dc6 100644 --- a/web/backend/API/API.Core/GlobalException.cs +++ b/web/backend/API/API.Core/GlobalException.cs @@ -14,8 +14,7 @@ namespace API.Core; /// consistent JSON error responses with appropriate HTTP status codes. /// /// Logger used to record unhandled exceptions before they are translated into a response. -public class GlobalExceptionFilter(ILogger logger) - : IExceptionFilter +public class GlobalExceptionFilter(ILogger logger) : IExceptionFilter { /// /// Logs the exception and sets to an appropriate error response, @@ -84,10 +83,7 @@ public class GlobalExceptionFilter(ILogger logger) case ValidationException fluentValidationException: Dictionary errors = fluentValidationException .Errors.GroupBy(e => e.PropertyName) - .ToDictionary( - g => g.Key, - g => g.Select(e => e.ErrorMessage).ToArray() - ); + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); context.Result = new BadRequestObjectResult( new { message = "Validation failed", errors } @@ -96,41 +92,33 @@ public class GlobalExceptionFilter(ILogger logger) break; case ConflictException ex: - context.Result = new ObjectResult( - new ResponseBody { Message = ex.Message } - ) + context.Result = new ObjectResult(new ResponseBody { Message = ex.Message }) { - StatusCode = 409 + StatusCode = 409, }; context.ExceptionHandled = true; break; case NotFoundException ex: - context.Result = new ObjectResult( - new ResponseBody { Message = ex.Message } - ) + context.Result = new ObjectResult(new ResponseBody { Message = ex.Message }) { - StatusCode = 404 + StatusCode = 404, }; context.ExceptionHandled = true; break; case UnauthorizedException ex: - context.Result = new ObjectResult( - new ResponseBody { Message = ex.Message } - ) + context.Result = new ObjectResult(new ResponseBody { Message = ex.Message }) { - StatusCode = 401 + StatusCode = 401, }; context.ExceptionHandled = true; break; case ForbiddenException ex: - context.Result = new ObjectResult( - new ResponseBody { Message = ex.Message } - ) + context.Result = new ObjectResult(new ResponseBody { Message = ex.Message }) { - StatusCode = 403 + StatusCode = 403, }; context.ExceptionHandled = true; break; @@ -140,33 +128,28 @@ public class GlobalExceptionFilter(ILogger logger) new ResponseBody { Message = "A database error occurred." } ) { - StatusCode = 503 + StatusCode = 503, }; context.ExceptionHandled = true; break; case Domain.Exceptions.ValidationException ex: - context.Result = new ObjectResult( - new ResponseBody { Message = ex.Message } - ) + context.Result = new ObjectResult(new ResponseBody { Message = ex.Message }) { - StatusCode = 400 + StatusCode = 400, }; context.ExceptionHandled = true; break; default: context.Result = new ObjectResult( - new ResponseBody - { - Message = "An unexpected error occurred" - } + new ResponseBody { Message = "An unexpected error occurred" } ) { - StatusCode = 500 + StatusCode = 500, }; context.ExceptionHandled = true; break; } } -} \ No newline at end of file +} diff --git a/web/backend/API/API.Core/Program.cs b/web/backend/API/API.Core/Program.cs index 1bc9b48..326a1e1 100644 --- a/web/backend/API/API.Core/Program.cs +++ b/web/backend/API/API.Core/Program.cs @@ -17,7 +17,11 @@ using Shared.Application.Behaviors; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Global Exception Filter -builder.Services.AddControllers(options => { options.Filters.Add(); }) +builder + .Services.AddControllers(options => + { + options.Filters.Add(); + }) .AddApplicationPart(typeof(BreweryController).Assembly) .AddApplicationPart(typeof(UserController).Assembly) .AddApplicationPart(typeof(AuthController).Assembly); @@ -51,14 +55,12 @@ builder.Services.AddHealthChecks(); // Configure logging for container output builder.Logging.ClearProviders(); builder.Logging.AddConsole(); -if (!builder.Environment.IsProduction()) builder.Logging.AddDebug(); +if (!builder.Environment.IsProduction()) + builder.Logging.AddDebug(); // Configure Dependency Injection ------------------------------------------------------------------------------------- -builder.Services.AddSingleton< - ISqlConnectionFactory, - DefaultSqlConnectionFactory ->(); +builder.Services.AddSingleton(); builder.Services.AddFeaturesBreweries(); builder.Services.AddFeaturesUserManagement(); @@ -75,10 +77,7 @@ builder.Services.AddScoped(); // Configure JWT Authentication builder .Services.AddAuthentication("JWT") - .AddScheme( - "JWT", - options => { } - ); + .AddScheme("JWT", options => { }); builder.Services.AddAuthorization(); @@ -106,4 +105,4 @@ lifetime.ApplicationStopping.Register(() => app.Logger.LogInformation("Application is shutting down gracefully..."); }); -app.Run(); \ No newline at end of file +app.Run();