mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
* Integrate Spectre.Console into seed application, use async data loading * Replace stored-procedure repositories with Dapper-based repositories Removes the USP_* stored procedures for Auth, Location, and Brewery data access in favour of services built with Dapper. Adds a new Features.Locations slice and optimistic concurrency support for the Brewery slice. * Add new documentation for Dapper migration/database schema * Update FluentAssertions to most recent open source ver * Update XML doc comment in backend projects * Modify brewery location dto to include denormalized data * - Updated column names from 'Timer' to 'RowVersion' in schema.sql for - Introduced new BeerPost entity and updated BreweryPost and BreweryPostLocation entities to use 'RowVersion' for concurrency. - Modified UserAccount, UserCredential, UserVerification, City, StateProvince, and Country entities to use 'RowVersion' instead of 'Timer'. - Updated tests and command handlers to reflect changes in concurrency token from 'Timer' to 'RowVersion'. - Adjusted BreweryDto and BreweryDtoMapper to include 'RowVersion' and updated mapping logic accordingly. - Ensured all repository methods and interfaces are aligned with the new concurrency handling approach. * updates * Add BeerStyle entity and related properties; refactor BreweryDto to remove BeerPosts * Fix Api.Specs test failures: stale Timer column refs and missing test.user fixture * Remove repository tests, usages of registration dto used in repo * archive old stored procs/functions * update stale docs * Add instructions for generating cryptographically secure base64 secrets on macOS/Linux and Windows
95 lines
4.0 KiB
C#
95 lines
4.0 KiB
C#
using System.Security.Claims;
|
|
using Domain.Entities;
|
|
|
|
namespace Features.Auth.Services;
|
|
|
|
/// <summary>
|
|
/// Identifies the kind of token being generated or validated.
|
|
/// </summary>
|
|
public enum TokenType
|
|
{
|
|
/// <summary>A short-lived token used to authorize API requests.</summary>
|
|
AccessToken,
|
|
|
|
/// <summary>A long-lived token used to obtain new access tokens.</summary>
|
|
RefreshToken,
|
|
|
|
/// <summary>A short-lived token used to confirm a user's email/account.</summary>
|
|
ConfirmationToken,
|
|
}
|
|
|
|
/// <summary>Represents the result of successfully validating a token.</summary>
|
|
public record ValidatedToken(Guid UserId, string Username, ClaimsPrincipal Principal);
|
|
|
|
/// <summary>Represents the result of refreshing a user's session.</summary>
|
|
public record RefreshTokenResult(UserAccount UserAccount, string RefreshToken, string AccessToken);
|
|
|
|
/// <summary>
|
|
/// Defines the expiration windows, in hours, for each type of token issued by <see cref="ITokenService" />.
|
|
/// </summary>
|
|
public static class TokenServiceExpirationHours
|
|
{
|
|
/// <summary>1 hour.</summary>
|
|
public const double AccessTokenHours = 1;
|
|
|
|
/// <summary>21 days.</summary>
|
|
public const double RefreshTokenHours = 504;
|
|
|
|
/// <summary>30 minutes.</summary>
|
|
public const double ConfirmationTokenHours = 0.5;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Defines operations for generating and validating JWTs used for access, refresh, and account confirmation.
|
|
/// </summary>
|
|
public interface ITokenService
|
|
{
|
|
/// <summary>
|
|
/// Generates a signed access token for the given user, expiring after
|
|
/// <see cref="TokenServiceExpirationHours.AccessTokenHours" /> hours.
|
|
/// </summary>
|
|
string GenerateAccessToken(UserAccount user);
|
|
|
|
/// <summary>
|
|
/// Generates a signed refresh token for the given user, expiring after
|
|
/// <see cref="TokenServiceExpirationHours.RefreshTokenHours" /> hours.
|
|
/// </summary>
|
|
string GenerateRefreshToken(UserAccount user);
|
|
|
|
/// <summary>
|
|
/// Generates a signed confirmation token for the given user, expiring after
|
|
/// <see cref="TokenServiceExpirationHours.ConfirmationTokenHours" /> hours.
|
|
/// </summary>
|
|
string GenerateConfirmationToken(UserAccount user);
|
|
|
|
/// <summary>Generates a token of the type specified by <typeparamref name="T" />.</summary>
|
|
/// <typeparam name="T">Must be <see cref="TokenType" />.</typeparam>
|
|
string GenerateToken<T>(UserAccount user)
|
|
where T : struct, Enum;
|
|
|
|
/// <summary>Validates an access token's signature and expiration and extracts the caller's identity.</summary>
|
|
/// <exception cref="Domain.Exceptions.UnauthorizedException">
|
|
/// Thrown when the token is missing required claims, has a malformed user ID, or otherwise fails validation.
|
|
/// </exception>
|
|
Task<ValidatedToken> ValidateAccessTokenAsync(string token);
|
|
|
|
/// <summary>Validates a refresh token's signature and expiration and extracts the caller's identity.</summary>
|
|
/// <exception cref="Domain.Exceptions.UnauthorizedException">
|
|
/// Thrown when the token is missing required claims, has a malformed user ID, or otherwise fails validation.
|
|
/// </exception>
|
|
Task<ValidatedToken> ValidateRefreshTokenAsync(string token);
|
|
|
|
/// <summary>Validates a confirmation token's signature and expiration and extracts the caller's identity.</summary>
|
|
/// <exception cref="Domain.Exceptions.UnauthorizedException">
|
|
/// Thrown when the token is missing required claims, has a malformed user ID, or otherwise fails validation.
|
|
/// </exception>
|
|
Task<ValidatedToken> ValidateConfirmationTokenAsync(string token);
|
|
|
|
/// <summary>Validates a refresh token and issues a new access/refresh token pair for the associated user.</summary>
|
|
/// <exception cref="Domain.Exceptions.UnauthorizedException">
|
|
/// Thrown when the refresh token is invalid or expired, or when the user account it refers to no
|
|
/// longer exists.
|
|
/// </exception>
|
|
Task<RefreshTokenResult> RefreshTokenAsync(string refreshTokenString);
|
|
}
|