mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-06-01 01:54:00 +00:00
Format all markdown files in active directories
This commit is contained in:
@@ -4,24 +4,28 @@ This document describes the active architecture of The Biergarten App.
|
||||
|
||||
## High-Level Overview
|
||||
|
||||
The Biergarten App is a monorepo with a clear split between the backend and the active
|
||||
website:
|
||||
The Biergarten App is a monorepo with a clear split between the backend and the
|
||||
active website:
|
||||
|
||||
- **Backend**: .NET 10 Web API with SQL Server and a layered architecture
|
||||
- **Frontend**: React 19 + React Router 7 website in `src/Website`
|
||||
- **Architecture Style**: Layered backend plus server-rendered React frontend
|
||||
|
||||
The legacy Next.js frontend has been retained in `src/Website-v1` for reference only and is
|
||||
documented in [archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||
The legacy Next.js frontend has been retained in `src/Website-v1` for reference
|
||||
only and is documented in
|
||||
[archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||
|
||||
## Diagrams
|
||||
|
||||
For visual representations, see:
|
||||
|
||||
- [architecture.svg](diagrams-out/architecture.svg) - Layered architecture diagram
|
||||
- [architecture.svg](diagrams-out/architecture.svg) - Layered architecture
|
||||
diagram
|
||||
- [deployment.svg](diagrams-out/deployment.svg) - Docker deployment diagram
|
||||
- [authentication-flow.svg](diagrams-out/authentication-flow.svg) - Authentication workflow
|
||||
- [database-schema.svg](diagrams-out/database-schema.svg) - Database relationships
|
||||
- [authentication-flow.svg](diagrams-out/authentication-flow.svg) -
|
||||
Authentication workflow
|
||||
- [database-schema.svg](diagrams-out/database-schema.svg) - Database
|
||||
relationships
|
||||
|
||||
## Backend Architecture
|
||||
|
||||
@@ -218,7 +222,8 @@ public interface IAuthRepository
|
||||
|
||||
### Active Website (`src/Website`)
|
||||
|
||||
The current website is a React Router 7 application with server-side rendering enabled.
|
||||
The current website is a React Router 7 application with server-side rendering
|
||||
enabled.
|
||||
|
||||
```text
|
||||
src/Website/
|
||||
@@ -244,20 +249,22 @@ src/Website/
|
||||
|
||||
### Theme System
|
||||
|
||||
The active website uses semantic DaisyUI theme tokens backed by four Biergarten themes:
|
||||
The active website uses semantic DaisyUI theme tokens backed by four Biergarten
|
||||
themes:
|
||||
|
||||
- Biergarten Lager
|
||||
- Biergarten Stout
|
||||
- Biergarten Cassis
|
||||
- Biergarten Weizen
|
||||
|
||||
All component styling should prefer semantic tokens such as `primary`, `success`,
|
||||
`surface`, and `highlight` instead of hard-coded color values.
|
||||
All component styling should prefer semantic tokens such as `primary`,
|
||||
`success`, `surface`, and `highlight` instead of hard-coded color values.
|
||||
|
||||
### Legacy Frontend
|
||||
|
||||
The previous Next.js frontend has been archived at `src/Website-v1`. Active product and
|
||||
engineering documentation should point to `src/Website`, while legacy notes live in
|
||||
The previous Next.js frontend has been archived at `src/Website-v1`. Active
|
||||
product and engineering documentation should point to `src/Website`, while
|
||||
legacy notes live in
|
||||
[archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||
|
||||
## Security Architecture
|
||||
@@ -387,8 +394,8 @@ For details, see [Docker Guide](docker.md).
|
||||
|
||||
### Health Checks
|
||||
|
||||
**SQL Server**: Validates database connectivity **API**: Checks service health and
|
||||
dependencies
|
||||
**SQL Server**: Validates database connectivity **API**: Checks service health
|
||||
and dependencies
|
||||
|
||||
**Configuration**:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Docker Guide
|
||||
|
||||
This document covers Docker deployment, configuration, and troubleshooting for The
|
||||
Biergarten App.
|
||||
This document covers Docker deployment, configuration, and troubleshooting for
|
||||
The Biergarten App.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -13,7 +13,8 @@ The project uses Docker Compose to orchestrate multiple services:
|
||||
- .NET API
|
||||
- Test runners
|
||||
|
||||
See the [deployment diagram](diagrams/pdf/deployment.pdf) for visual representation.
|
||||
See the [deployment diagram](diagrams/pdf/deployment.pdf) for visual
|
||||
representation.
|
||||
|
||||
## Docker Compose Environments
|
||||
|
||||
@@ -144,7 +145,11 @@ api.core / tests (start when ready)
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', "sqlcmd -S localhost -U sa -P '${DB_PASSWORD}' -C -Q 'SELECT 1'"]
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"sqlcmd -S localhost -U sa -P '${DB_PASSWORD}' -C -Q 'SELECT 1'",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
@@ -209,16 +214,16 @@ Each environment uses isolated bridge networks:
|
||||
All containers are configured via environment variables from `.env` files:
|
||||
|
||||
```yaml
|
||||
env_file: '.env.dev' # or .env.test, .env.prod
|
||||
env_file: ".env.dev" # or .env.test, .env.prod
|
||||
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: 'Development'
|
||||
DOTNET_RUNNING_IN_CONTAINER: 'true'
|
||||
DB_SERVER: '${DB_SERVER}'
|
||||
DB_NAME: '${DB_NAME}'
|
||||
DB_USER: '${DB_USER}'
|
||||
DB_PASSWORD: '${DB_PASSWORD}'
|
||||
JWT_SECRET: '${JWT_SECRET}'
|
||||
ASPNETCORE_ENVIRONMENT: "Development"
|
||||
DOTNET_RUNNING_IN_CONTAINER: "true"
|
||||
DB_SERVER: "${DB_SERVER}"
|
||||
DB_NAME: "${DB_NAME}"
|
||||
DB_USER: "${DB_USER}"
|
||||
DB_PASSWORD: "${DB_PASSWORD}"
|
||||
JWT_SECRET: "${JWT_SECRET}"
|
||||
```
|
||||
|
||||
For complete list, see [Environment Variables](environment-variables.md).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Environment Variables
|
||||
|
||||
This document covers the active environment variables used by the current Biergarten
|
||||
stack.
|
||||
This document covers the active environment variables used by the current
|
||||
Biergarten stack.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -19,8 +19,8 @@ Direct environment variable access via `Environment.GetEnvironmentVariable()`.
|
||||
|
||||
### Frontend (`src/Website`)
|
||||
|
||||
The active website reads runtime values from the server environment for its auth and API
|
||||
integration.
|
||||
The active website reads runtime values from the server environment for its auth
|
||||
and API integration.
|
||||
|
||||
### Docker
|
||||
|
||||
@@ -54,14 +54,15 @@ Provide complete connection string:
|
||||
DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
|
||||
```
|
||||
|
||||
**Priority**: `DB_CONNECTION_STRING` is checked first. If not found, connection string is
|
||||
built from components.
|
||||
**Priority**: `DB_CONNECTION_STRING` is checked first. If not found, connection
|
||||
string is built from components.
|
||||
|
||||
**Implementation**: See `DefaultSqlConnectionFactory.cs`
|
||||
|
||||
### JWT Authentication Secrets (Backend)
|
||||
|
||||
The backend uses separate secrets for different token types to enable independent key rotation and validation isolation.
|
||||
The backend uses separate secrets for different token types to enable
|
||||
independent key rotation and validation isolation.
|
||||
|
||||
```bash
|
||||
# Access token secret (1-hour tokens)
|
||||
@@ -131,8 +132,8 @@ DOTNET_RUNNING_IN_CONTAINER=true # Flag for container execution
|
||||
|
||||
## Frontend Variables (`src/Website`)
|
||||
|
||||
The active website does not use the old Next.js/Prisma environment model. Its core runtime
|
||||
variables are:
|
||||
The active website does not use the old Next.js/Prisma environment model. Its
|
||||
core runtime variables are:
|
||||
|
||||
```bash
|
||||
API_BASE_URL=http://localhost:8080 # Base URL for the .NET API
|
||||
@@ -208,9 +209,10 @@ cp .env.example .env.dev
|
||||
|
||||
## Legacy Frontend Variables
|
||||
|
||||
Variables for the archived Next.js frontend (`src/Website-v1`) have been removed from this
|
||||
active reference. See [archive/legacy-website-v1.md](archive/legacy-website-v1.md) if you
|
||||
need the legacy Prisma, Cloudinary, Mapbox, or SparkPost notes.
|
||||
Variables for the archived Next.js frontend (`src/Website-v1`) have been removed
|
||||
from this active reference. See
|
||||
[archive/legacy-website-v1.md](archive/legacy-website-v1.md) if you need the
|
||||
legacy Prisma, Cloudinary, Mapbox, or SparkPost notes.
|
||||
|
||||
**Docker Compose Mapping**:
|
||||
|
||||
@@ -243,8 +245,8 @@ need the legacy Prisma, Cloudinary, Mapbox, or SparkPost notes.
|
||||
| `MSSQL_PID` | | | ✓ | No | SQL Server edition |
|
||||
| `DOTNET_RUNNING_IN_CONTAINER` | ✓ | | ✓ | No | Container flag |
|
||||
|
||||
\* Either `DB_CONNECTION_STRING` OR the component variables (`DB_SERVER`, `DB_NAME`,
|
||||
`DB_USER`, `DB_PASSWORD`) must be provided.
|
||||
\* Either `DB_CONNECTION_STRING` OR the component variables (`DB_SERVER`,
|
||||
`DB_NAME`, `DB_USER`, `DB_PASSWORD`) must be provided.
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -258,8 +260,8 @@ Variables are validated at startup:
|
||||
|
||||
### Frontend Validation
|
||||
|
||||
The active website relies on runtime defaults for local development and the surrounding
|
||||
server environment in deployed environments.
|
||||
The active website relies on runtime defaults for local development and the
|
||||
surrounding server environment in deployed environments.
|
||||
|
||||
- `API_BASE_URL` defaults to `http://localhost:8080`
|
||||
- `SESSION_SECRET` falls back to a development-only local secret
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Getting Started
|
||||
|
||||
This guide covers local setup for the current Biergarten stack: the .NET backend in
|
||||
`src/Core` and the active React Router frontend in `src/Website`.
|
||||
This guide covers local setup for the current Biergarten stack: the .NET backend
|
||||
in `src/Core` and the active React Router frontend in `src/Website`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -128,8 +128,9 @@ dotnet run --project API/API.Core/API.Core.csproj
|
||||
|
||||
## Legacy Frontend Note
|
||||
|
||||
The previous Next.js frontend now lives in `src/Website-v1` and is not the active website.
|
||||
Legacy setup details have been moved to [docs/archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||
The previous Next.js frontend now lives in `src/Website-v1` and is not the
|
||||
active website. Legacy setup details have been moved to
|
||||
[docs/archive/legacy-website-v1.md](archive/legacy-website-v1.md).
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Testing
|
||||
|
||||
This document describes the testing strategy and how to run tests for The Biergarten App.
|
||||
This document describes the testing strategy and how to run tests for The
|
||||
Biergarten App.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -9,13 +10,15 @@ The project uses a multi-layered testing approach across backend and frontend:
|
||||
- **API.Specs** - BDD integration tests using Reqnroll (Gherkin)
|
||||
- **Infrastructure.Repository.Tests** - Unit tests for data access layer
|
||||
- **Service.Auth.Tests** - Unit tests for authentication business logic
|
||||
- **Storybook Vitest project** - Browser-based interaction tests for shared website stories
|
||||
- **Storybook Playwright suite** - Browser checks against Storybook-rendered components
|
||||
- **Storybook Vitest project** - Browser-based interaction tests for shared
|
||||
website stories
|
||||
- **Storybook Playwright suite** - Browser checks against Storybook-rendered
|
||||
components
|
||||
|
||||
## Running Tests with Docker (Recommended)
|
||||
|
||||
The easiest way to run all tests is using Docker Compose, which sets up an isolated test
|
||||
environment:
|
||||
The easiest way to run all tests is using Docker Compose, which sets up an
|
||||
isolated test environment:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
|
||||
@@ -98,7 +101,8 @@ npm run test:storybook
|
||||
|
||||
**Purpose**:
|
||||
|
||||
- Verifies shared stories such as form fields, submit buttons, navbar states, toasts, and the theme gallery
|
||||
- Verifies shared stories such as form fields, submit buttons, navbar states,
|
||||
toasts, and the theme gallery
|
||||
- Runs in browser mode via Vitest and Storybook integration
|
||||
|
||||
### Frontend Playwright Storybook Tests
|
||||
@@ -113,7 +117,8 @@ npm run test:storybook:playwright
|
||||
|
||||
- Storybook dependencies installed
|
||||
- Playwright browser dependencies installed
|
||||
- The command will start or reuse the Storybook server defined in `playwright.storybook.config.ts`
|
||||
- The command will start or reuse the Storybook server defined in
|
||||
`playwright.storybook.config.ts`
|
||||
|
||||
## Test Coverage
|
||||
|
||||
@@ -278,7 +283,8 @@ Scenario: User login with valid credentials
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Tests run automatically in CI/CD pipelines using the test Docker Compose configuration:
|
||||
Tests run automatically in CI/CD pipelines using the test Docker Compose
|
||||
configuration:
|
||||
|
||||
```bash
|
||||
# CI/CD command
|
||||
@@ -292,7 +298,8 @@ Exit codes:
|
||||
- `0` - All tests passed
|
||||
- Non-zero - Test failures occurred
|
||||
|
||||
Frontend UI checks should also be included in CI for the active website workspace:
|
||||
Frontend UI checks should also be included in CI for the active website
|
||||
workspace:
|
||||
|
||||
```bash
|
||||
cd src/Website
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The Core project implements comprehensive JWT token validation across three token types:
|
||||
The Core project implements comprehensive JWT token validation across three
|
||||
token types:
|
||||
|
||||
- **Access Tokens**: Short-lived (1 hour) tokens for API authentication
|
||||
- **Refresh Tokens**: Long-lived (21 days) tokens for obtaining new access tokens
|
||||
- **Confirmation Tokens**: Short-lived (30 minutes) tokens for email confirmation
|
||||
- **Refresh Tokens**: Long-lived (21 days) tokens for obtaining new access
|
||||
tokens
|
||||
- **Confirmation Tokens**: Short-lived (30 minutes) tokens for email
|
||||
confirmation
|
||||
|
||||
## Components
|
||||
|
||||
@@ -17,10 +20,13 @@ The Core project implements comprehensive JWT token validation across three toke
|
||||
Low-level JWT operations.
|
||||
|
||||
**Methods:**
|
||||
|
||||
- `GenerateJwt()` - Creates signed JWT tokens
|
||||
- `ValidateJwtAsync()` - Validates token signature, expiration, and format
|
||||
|
||||
**Implementation:** [JwtInfrastructure.cs](Infrastructure.Jwt/JwtInfrastructure.cs)
|
||||
**Implementation:**
|
||||
[JwtInfrastructure.cs](Infrastructure.Jwt/JwtInfrastructure.cs)
|
||||
|
||||
- Uses Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler
|
||||
- Algorithm: HS256 (HMAC-SHA256)
|
||||
- Validates token lifetime, signature, and well-formedness
|
||||
@@ -32,16 +38,20 @@ Low-level JWT operations.
|
||||
High-level token validation with context (token type, user extraction).
|
||||
|
||||
**Methods:**
|
||||
|
||||
- `ValidateAccessTokenAsync(string token)` - Validates access tokens
|
||||
- `ValidateRefreshTokenAsync(string token)` - Validates refresh tokens
|
||||
- `ValidateConfirmationTokenAsync(string token)` - Validates confirmation tokens
|
||||
|
||||
**Returns:** `ValidatedToken` record containing:
|
||||
|
||||
- `UserId` (Guid)
|
||||
- `Username` (string)
|
||||
- `Principal` (ClaimsPrincipal) - Full JWT claims
|
||||
|
||||
**Implementation:** [TokenValidationService.cs](Service.Auth/TokenValidationService.cs)
|
||||
**Implementation:**
|
||||
[TokenValidationService.cs](Service.Auth/TokenValidationService.cs)
|
||||
|
||||
- Reads token secrets from environment variables
|
||||
- Extracts and validates claims (Sub, UniqueName)
|
||||
- Throws `UnauthorizedException` on validation failure
|
||||
@@ -51,15 +61,18 @@ High-level token validation with context (token type, user extraction).
|
||||
Token generation (existing service extended).
|
||||
|
||||
**Methods:**
|
||||
|
||||
- `GenerateAccessToken(UserAccount)` - Creates 1-hour access token
|
||||
- `GenerateRefreshToken(UserAccount)` - Creates 21-day refresh token
|
||||
- `GenerateConfirmationToken(UserAccount)` - Creates 30-minute confirmation token
|
||||
- `GenerateConfirmationToken(UserAccount)` - Creates 30-minute confirmation
|
||||
token
|
||||
|
||||
### Integration Points
|
||||
|
||||
#### [ConfirmationService](Service.Auth/IConfirmationService.cs)
|
||||
|
||||
**Flow:**
|
||||
|
||||
1. Receives confirmation token from user
|
||||
2. Calls `TokenValidationService.ValidateConfirmationTokenAsync()`
|
||||
3. Extracts user ID from validated token
|
||||
@@ -69,6 +82,7 @@ Token generation (existing service extended).
|
||||
#### [RefreshTokenService](Service.Auth/RefreshTokenService.cs)
|
||||
|
||||
**Flow:**
|
||||
|
||||
1. Receives refresh token from user
|
||||
2. Calls `TokenValidationService.ValidateRefreshTokenAsync()`
|
||||
3. Retrieves user account via `AuthRepository.GetUserByIdAsync()`
|
||||
@@ -78,6 +92,7 @@ Token generation (existing service extended).
|
||||
#### [AuthController](API.Core/Controllers/AuthController.cs)
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
- `POST /api/auth/register` - Register new user
|
||||
- `POST /api/auth/login` - Authenticate user
|
||||
- `POST /api/auth/confirm?token=...` - Confirm email
|
||||
@@ -88,11 +103,13 @@ Token generation (existing service extended).
|
||||
### Token Secrets
|
||||
|
||||
Three independent secrets enable:
|
||||
|
||||
- **Key rotation** - Rotate each secret type independently
|
||||
- **Isolation** - Compromise of one secret doesn't affect others
|
||||
- **Different expiration** - Different token types can expire at different rates
|
||||
|
||||
**Environment Variables:**
|
||||
|
||||
```bash
|
||||
ACCESS_TOKEN_SECRET=... # Signs 1-hour access tokens
|
||||
REFRESH_TOKEN_SECRET=... # Signs 21-day refresh tokens
|
||||
@@ -111,6 +128,7 @@ Each token is validated for:
|
||||
### Error Handling
|
||||
|
||||
Validation failures return HTTP 401 Unauthorized:
|
||||
|
||||
- Invalid signature → "Invalid token"
|
||||
- Expired token → "Invalid token" (message doesn't reveal reason for security)
|
||||
- Missing claims → "Invalid token"
|
||||
@@ -149,16 +167,19 @@ Validation failures return HTTP 401 Unauthorized:
|
||||
### Unit Tests
|
||||
|
||||
**TokenValidationService.test.cs**
|
||||
|
||||
- Happy path: Valid token extraction
|
||||
- Error cases: Invalid, expired, malformed tokens
|
||||
- Missing/invalid claims scenarios
|
||||
|
||||
**RefreshTokenService.test.cs**
|
||||
|
||||
- Successful refresh with valid token
|
||||
- Invalid/expired refresh token rejection
|
||||
- Non-existent user handling
|
||||
|
||||
**ConfirmationService.test.cs**
|
||||
|
||||
- Successful confirmation with valid token
|
||||
- Token validation failures
|
||||
- User not found scenarios
|
||||
@@ -166,16 +187,19 @@ Validation failures return HTTP 401 Unauthorized:
|
||||
### BDD Tests (Reqnroll)
|
||||
|
||||
**TokenRefresh.feature**
|
||||
|
||||
- Successful token refresh
|
||||
- Invalid/expired token rejection
|
||||
- Missing token validation
|
||||
|
||||
**Confirmation.feature**
|
||||
|
||||
- Successful email confirmation
|
||||
- Expired/tampered token rejection
|
||||
- Missing token validation
|
||||
|
||||
**AccessTokenValidation.feature**
|
||||
|
||||
- Protected endpoint access token validation
|
||||
- Invalid/expired access token rejection
|
||||
- Token type mismatch (refresh used as access token)
|
||||
|
||||
Reference in New Issue
Block a user