Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WarcraftArchive API

RESTful API for WarcraftArchive — a personal World of Warcraft progress tracker for characters, warbands, content, and weekly routines.

Features

  • Character Management — Create and manage your WoW roster with class, race, level, covenant, and warband
  • Warband System — Group characters into warbands with custom display ordering
  • Content Catalogue — Track dungeons, raids, and activities per expansion
  • Progress Tracking — Per-character content tracking with status, frequency, difficulty, and custom motives
  • Dashboard — Aggregated weekly summary of trackings grouped by status
  • Data Export/Import — CSV export & import for characters and trackings
  • Admin Panel — User management for self-hosted multi-user instances
  • JWT Authentication — Access + refresh token flow with BCrypt password hashing
  • Household Connections — User-consented PKCE S256 connection flow with isolated rotating tokens
  • Seed Support — Optional admin user and demo data seeding on first run

Tech Stack

  • .NET 9.0 — ASP.NET Core Minimal API
  • Entity Framework Core 9.0 — SQLite provider
  • JWT Authentication — BCrypt password hashing
  • Swagger/OpenAPI — via Swashbuckle

Prerequisites

Installation

cd WarcraftArchive.Api
cp .env.example .env
# Edit .env — set JWT_SECRET_KEY at minimum
dotnet restore
dotnet ef database update

Development

dotnet run
# API available at http://localhost:5020
# Swagger UI at http://localhost:5020/swagger

Production (Docker)

docker build -t warcraftarchive-api .
docker run -p 8080:8080 -v warcraftarchive-data:/data warcraftarchive-api

See the root docker-compose.casaos.yml for CasaOS deployment.

API Endpoints

Authentication

Method Route Description
POST /auth/register Register new user
POST /auth/login Login
POST /auth/refresh Refresh JWT token
POST /auth/logout Revoke refresh token

Characters

Method Route Description
GET /characters List user's characters
GET /characters/{id} Get character by ID
POST /characters Create a character
PUT /characters/{id} Update a character
DELETE /characters/{id} Delete a character

Warbands

Method Route Description
GET /warbands List user's warbands
GET /warbands/{id} Get warband by ID
POST /warbands Create a warband
PUT /warbands/{id} Update a warband
DELETE /warbands/{id} Delete a warband
PUT /warbands/reorder Reorder warbands

Content

Method Route Description
GET /contents List content (optional ?expansion=)
GET /contents/{id} Get content by ID
POST /contents Create a content entry
PUT /contents/{id} Update a content entry
DELETE /contents/{id} Delete a content entry

Trackings

Method Route Description
GET /trackings List trackings (filters: characterId, status, frequency, expansion, motiveId, contentId)
GET /trackings/{id} Get tracking by ID
POST /trackings Create a tracking entry
PUT /trackings/{id} Update a tracking entry
DELETE /trackings/{id} Delete a tracking entry

Motives

Method Route Description
GET /motives List user's motives
GET /motives/{id} Get motive by ID
POST /motives Create a motive
PUT /motives/{id} Update a motive
DELETE /motives/{id} Delete a motive

All Character, Content, Tracking, Warband, and Motive list/detail/write routes derive ownership from the authenticated JWT. Detail, update, and delete requests for another user's ID return the same 404 as a missing ID. Character create/update also returns 404 for a supplied missing or foreign warbandId. Content create/update validates the complete distinct motiveIds list before writing and returns 404 if any ID is missing or foreign; mixed-owner lists are never partially attached. Tracking creation applies the same non-enumerating 404 behavior to foreign or missing character/content IDs.

Dashboard

Method Route Description
GET /dashboard/weekly Weekly tracking summary grouped by status
GET /dashboard/quick-status Lightweight owner-scoped counts for Household

Normal JWT callers receive their own status. Household callers use a separate opaque integration access token and must have the dashboard.read scope; the connection's persisted user identity is the only owner used by the query.

Household connection protocol v1

Method Route Authentication Description
POST /api/integrations/household/v1/authorize Normal WarcraftArchive JWT Approve or deny consent and return an allowlisted redirect
POST /api/integrations/household/v1/token PKCE code or rotating refresh token Issue integration-only access/refresh tokens
POST /api/integrations/household/v1/revoke Token in body Idempotently revoke only the identified connection
GET /api/integrations/household/v1/me Integration access token Return active connection identity and scopes
PATCH /api/integrations/household/v1/trackings/{id}/status Integration access token with tracking.status.write Update only the status of an owned tracking

The browser entry point is /#/integrations/household/authorize?client_id=household&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256&scope=profile.read%20dashboard.read. It preserves the complete request through normal login, asks for consent, and receives only a one-time authorization-code redirect. Access and refresh tokens are returned only by the backend token exchange. Supported scopes are profile.read, dashboard.read, and tracking.status.write.

The tracking status PATCH derives ownership only from the Household connection and returns 404 unless both the tracking's character and content belong to that user. Its response includes tracking, character, and content IDs; labels/details; status and difficulty IDs/labels; and the frequency period. Allowed status transitions are:

  • NotStarted -> Pending
  • Pending -> NotStarted or InProgress
  • InProgress -> Pending or Finished
  • Finished -> NotStarted, InProgress, LastDay, or LastWeek
  • LastDay -> NotStarted or Finished
  • LastWeek -> NotStarted or Finished
  • Repeating the current status is idempotent.

LastDay is valid only for Daily trackings and LastWeek only for Weekly trackings.

Authorization codes expire after five minutes, are stored only as SHA-256 hashes, require PKCE S256, and are single-use. Access tokens expire after 15 minutes. Refresh tokens expire after 30 days, rotate on every use, and reuse revokes only that connection's token family. All integration credentials are persisted only as hashes. Redirect URIs use exact ordinal matching: no wildcard scheme, host, port, path, or prefix matching.

Data (Admin)

Method Route Description
GET /admin/data/export/characters Export characters as CSV
GET /admin/data/export/trackings Export trackings as CSV
POST /admin/data/import Import characters/trackings CSV

Admin

Method Route Description
GET /admin/users List all users
POST /admin/users Create a user
PUT /admin/users/{id} Update a user
DELETE /admin/users/{id} Delete a user

Project Structure

WarcraftArchive.Api/
├── Application/
│   ├── Interfaces/       # Service interfaces
│   └── Services/         # Business logic implementations
├── Common/               # Shared helpers and extensions
├── Configuration/        # Strongly-typed settings (JWT, CORS, DB, Seed)
├── Contracts/            # Request/Response DTOs
├── Domain/
│   ├── Entities/
│   │   ├── Auth/         # User, RefreshToken
│   │   └── Warcraft/     # Character, Warband, Content, Tracking, Motive
│   └── Enums/            # Domain enumerations
├── Endpoints/            # Minimal API endpoint maps
├── Infrastructure/
│   └── Persistence/
│       ├── Configurations/  # IEntityTypeConfiguration classes
│       └── AppDbContext.cs
├── Middleware/            # Exception handling middleware
├── Migrations/            # EF Core migrations
└── Program.cs             # App bootstrap, DI, middleware pipeline

Environment Variables

Variable Description Default
DATABASE_PATH SQLite database file path /data/warcraftarchive.db
JWT_SECRET_KEY JWT signing key (32+ chars) (required)
JWT_ISSUER JWT issuer claim WarcraftArchive.Api
JWT_AUDIENCE JWT audience claim WarcraftArchive.Client
JWT_ACCESS_TOKEN_MINUTES Access token lifetime (minutes) 15
JWT_REFRESH_TOKEN_DAYS Refresh token lifetime (days) 30
HOUSEHOLD_CLIENT_ID Registered integration client id household
HOUSEHOLD_REDIRECT_URIS Comma-separated exact callback allowlist (empty; integration disabled)
HOUSEHOLD_ACCESS_TOKEN_MINUTES Integration access-token lifetime 15
HOUSEHOLD_REFRESH_TOKEN_DAYS Integration refresh-token lifetime 30
HOUSEHOLD_AUTHORIZATION_CODE_MINUTES One-time authorization-code lifetime 5
CORS_ALLOWED_ORIGINS Comma-separated allowed origins (empty)
SEED_ADMIN_ENABLED Create admin user on first run false
SEED_ADMIN_EMAIL Admin user email admin@local
SEED_ADMIN_USERNAME Admin username admin
SEED_ADMIN_PASSWORD Admin password (set in .env)
DEMO_IMPORT_ENABLED Import demo CSV data on first run false
CSV_DATA_PATH Path to demo CSV files /data/csv

License

MIT

About

RESTful API for tracking World of Warcraft characters, progress, and structured weekly content routines.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages