mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
update api docs
This commit is contained in:
@@ -12,11 +12,6 @@ namespace API.Core.Authentication;
|
||||
/// Custom ASP.NET Core authentication handler that validates bearer JWT access tokens
|
||||
/// supplied in the <c>Authorization</c> header against the <c>JWT</c> authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitored options for the <c>JWT</c> authentication scheme.</param>
|
||||
/// <param name="logger">The logger factory used by the base <see cref="AuthenticationHandler{TOptions}" />.</param>
|
||||
/// <param name="encoder">The URL encoder used by the base <see cref="AuthenticationHandler{TOptions}" />.</param>
|
||||
/// <param name="tokenInfrastructure">The infrastructure service used to validate JWT access tokens.</param>
|
||||
/// <param name="configuration">The application configuration, used as a fallback source for the JWT secret key.</param>
|
||||
public class JwtAuthenticationHandler(
|
||||
IOptionsMonitor<JwtAuthenticationOptions> options,
|
||||
ILoggerFactory logger,
|
||||
@@ -31,15 +26,9 @@ public class JwtAuthenticationHandler(
|
||||
/// <remarks>
|
||||
/// The signing secret is resolved first from the <c>ACCESS_TOKEN_SECRET</c> environment variable, falling
|
||||
/// back to the <c>Jwt:SecretKey</c> configuration value, to stay consistent with the secret source used
|
||||
/// when tokens are issued. Authentication fails if the secret is not configured, the
|
||||
/// <c>Authorization</c> header is missing, the header does not use the <c>Bearer</c> scheme, or the
|
||||
/// token fails validation.
|
||||
/// when tokens are issued. Fails if the secret is not configured, the <c>Authorization</c> header is
|
||||
/// missing or not <c>Bearer</c>-scheme, or the token fails validation.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// A successful <see cref="AuthenticateResult" /> containing the validated
|
||||
/// <see cref="System.Security.Claims.ClaimsPrincipal" />
|
||||
/// on success, or a failure result describing why authentication could not be completed.
|
||||
/// </returns>
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
// Use the same access-token secret source as TokenService to avoid mismatched validation.
|
||||
@@ -78,8 +67,6 @@ public class JwtAuthenticationHandler(
|
||||
/// <summary>
|
||||
/// Writes a JSON 401 Unauthorized response when authentication fails or is required but not supplied.
|
||||
/// </summary>
|
||||
/// <param name="properties">The authentication properties associated with the challenge.</param>
|
||||
/// <returns>A task that completes once the response body has been written.</returns>
|
||||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Response.ContentType = "application/json";
|
||||
@@ -96,5 +83,4 @@ public class JwtAuthenticationHandler(
|
||||
/// <summary>
|
||||
/// Options for the <c>JWT</c> authentication scheme handled by <see cref="JwtAuthenticationHandler" />.
|
||||
/// </summary>
|
||||
/// <remarks>No additional options are defined beyond those provided by <see cref="AuthenticationSchemeOptions" />.</remarks>
|
||||
public class JwtAuthenticationOptions : AuthenticationSchemeOptions { }
|
||||
|
||||
@@ -6,7 +6,6 @@ namespace API.Core.Controllers;
|
||||
/// Handles requests that do not match any other route, used as the application's fallback controller.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Excluded from API explorer/Swagger output via <c>[ApiExplorerSettings(IgnoreApi = true)]</c>.
|
||||
/// Wired up as the fallback target via <c>app.MapFallbackToController("Handle404", "NotFound")</c> in
|
||||
/// <c>Program.cs</c>.
|
||||
/// </remarks>
|
||||
@@ -15,10 +14,6 @@ namespace API.Core.Controllers;
|
||||
[Route("error")] // required
|
||||
public class NotFoundController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a generic 404 response for any request that did not match a defined route.
|
||||
/// </summary>
|
||||
/// <returns>A <c>404 Not Found</c> result with a JSON body containing a "Route not found." message.</returns>
|
||||
[HttpGet("404")] //required
|
||||
public IActionResult Handle404()
|
||||
{
|
||||
|
||||
@@ -14,13 +14,9 @@ namespace API.Core.Controllers;
|
||||
public class ProtectedController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the authenticated caller's user ID and username, extracted from the JWT claims.
|
||||
/// Returns the authenticated caller's user ID and username extracted from the JWT claims.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <c>200 OK</c> result wrapping a <see cref="ResponseBody{T}" /> whose payload contains the
|
||||
/// caller's <c>userId</c> (from <see cref="ClaimTypes.NameIdentifier" />) and <c>username</c>
|
||||
/// (from <see cref="ClaimTypes.Name" />), either of which may be <c>null</c> if not present in the token.
|
||||
/// </returns>
|
||||
/// <returns><c>userId</c> and <c>username</c> may be <c>null</c> if not present in the token.</returns>
|
||||
[HttpGet]
|
||||
public ActionResult<ResponseBody<object>> Get()
|
||||
{
|
||||
|
||||
@@ -13,67 +13,17 @@ namespace API.Core;
|
||||
/// MVC exception filter that converts unhandled exceptions raised by controller actions into
|
||||
/// consistent JSON error responses with appropriate HTTP status codes.
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger used to record unhandled exceptions before they are translated into a response.</param>
|
||||
public class GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger) : IExceptionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs the exception and sets <see cref="ExceptionContext.Result" /> to an appropriate error response,
|
||||
/// marking the exception as handled.
|
||||
/// Logs the exception and sets <see cref="ExceptionContext.Result" /> to an appropriate error response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Maps exception types to responses as follows:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="FluentValidation.ValidationException" /> → <c>400 Bad Request</c> with per-property
|
||||
/// validation error messages.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="ConflictException" /> → <c>409 Conflict</c> with a <see cref="ResponseBody" />
|
||||
/// message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="NotFoundException" /> → <c>404 Not Found</c> with a <see cref="ResponseBody" />
|
||||
/// message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="UnauthorizedException" /> → <c>401 Unauthorized</c> with a
|
||||
/// <see cref="ResponseBody" /> message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="ForbiddenException" /> → <c>403 Forbidden</c> with a <see cref="ResponseBody" />
|
||||
/// message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="SqlException" /> → <c>503 Service Unavailable</c> with a generic database error
|
||||
/// message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>
|
||||
/// <see cref="Domain.Exceptions.ValidationException" /> → <c>400 Bad Request</c> with a
|
||||
/// <see cref="ResponseBody" /> message.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Any other exception → <c>500 Internal Server Error</c> with a generic error message.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// Maps <see cref="FluentValidation.ValidationException" /> to 400, <see cref="ConflictException" /> to 409,
|
||||
/// <see cref="NotFoundException" /> to 404, <see cref="UnauthorizedException" /> to 401,
|
||||
/// <see cref="ForbiddenException" /> to 403, <see cref="SqlException" /> to 503,
|
||||
/// <see cref="Domain.Exceptions.ValidationException" /> to 400, and anything else to 500.
|
||||
/// </remarks>
|
||||
/// <param name="context">
|
||||
/// The context for the unhandled exception, including the exception itself and the result to
|
||||
/// populate.
|
||||
/// </param>
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
logger.LogError(context.Exception, "Unhandled exception occurred");
|
||||
|
||||
@@ -3,8 +3,7 @@ using Infrastructure.Email;
|
||||
namespace API.Specs.Mocks;
|
||||
|
||||
/// <summary>
|
||||
/// Mock email provider for testing that doesn't actually send emails.
|
||||
/// Tracks sent emails for verification in tests if needed.
|
||||
/// Test double for <see cref="IEmailProvider" /> that records sent emails instead of delivering them.
|
||||
/// </summary>
|
||||
public class MockEmailProvider : IEmailProvider
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user