feat(auth): add DB-backed login, token management, and idempotent auth migration

This commit is contained in:
2026-04-03 12:55:34 +00:00
parent 5168e52e4b
commit 06b1805b92
28 changed files with 1609 additions and 140 deletions
+13 -1
View File
@@ -30,6 +30,9 @@ When deploying to production, set environment variables directly instead of usin
### Key configuration options
- **DB repository switch**: `PORTFOLIOHUB_DB_ENABLED` (enables DB-backed persistence)
- **Initial user bootstrap**: `PORTFOLIOHUB_BOOTSTRAP_USERNAME`, `PORTFOLIOHUB_BOOTSTRAP_EMAIL`
- **Initial user password**: `PORTFOLIOHUB_BOOTSTRAP_PASSWORD`
- **Session/token TTL**: `PORTFOLIOHUB_SESSION_TOKEN_TTL_HOURS`, `PORTFOLIOHUB_CLIENT_TOKEN_DEFAULT_TTL_DAYS`
- **TimescaleDB / PostgreSQL**: `TIMESCALEDB_*` (single source of DB connection settings)
- **Redis**: `REDIS_*` (for caching and sessions)
- **Loki**: `LOKI_*` (for centralized logging)
@@ -61,7 +64,7 @@ The repository now includes a `portfoliohub` CLI that mirrors the main portfolio
```bash
portfoliohub --help
portfoliohub user list
portfoliohub user create --username alice --email alice@example.com --force
portfoliohub user create --username alice --password password123 --email alice@example.com --force
portfoliohub user get <user-id>
portfoliohub user update <user-id> --username alice-updated --force
portfoliohub user delete <user-id> --force
@@ -168,6 +171,13 @@ User management is exposed through both HTTP API and CLI.
- Permission: `admin` only
- Supported operations: list, get, create, update, delete
Frontend and app authentication is exposed through `/auth`.
- `POST /auth/login`: username/password login, returns bearer session token
- `GET /auth/tokens`: list current user's issued tokens
- `POST /auth/tokens`: issue a client token for app/script usage
- `DELETE /auth/tokens/{token_id}`: revoke a previously issued token
Example API calls:
```bash
@@ -182,6 +192,8 @@ curl -X POST "http://localhost:8000/users" \
The default `.env.example` includes example tokens for development.
When `PORTFOLIOHUB_DB_ENABLED=true` and both `PORTFOLIOHUB_BOOTSTRAP_USERNAME` and `PORTFOLIOHUB_BOOTSTRAP_PASSWORD` are set, the app creates that admin user automatically on startup only if the `users` table is empty. This is intended for first-run bootstrap, not recurring synchronization.
## Planned next steps
1. Apply and verify Alembic migrations against a real PostgreSQL/Timescale instance.