feat: add CLI commands for user management

Adds subcommands to the binary for admin tasks without needing
the web UI: list users, set passwords, promote/demote roles,
and lock/unlock accounts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-04-07 13:37:39 +02:00
commit a456d0096a
5 changed files with 275 additions and 12 deletions

View file

@ -14,13 +14,24 @@ make test # Run tests
make container # Build container image
```
### CLI Admin Commands
```bash
favoritter user list # List all users
favoritter user set-password <user> # Change a user's password
favoritter user promote <user> # Promote user to admin
favoritter user demote <user> # Remove admin role
favoritter user lock <user> # Disable user account
favoritter user unlock <user> # Enable user account
```
## Architecture
Single Go binary serving HTML (server-rendered templates + HTMX) and a JSON API. SQLite for storage, filesystem for uploaded images. All templates and static assets are embedded via `go:embed`.
### Directory Layout
- `cmd/favoritter/` — Entry point, wiring, graceful shutdown
- `cmd/favoritter/` — Entry point, wiring, graceful shutdown, CLI admin commands (`cli_*.go`)
- `internal/config/` — Environment variable configuration
- `internal/database/` — SQLite connection, PRAGMAs, migration runner
- `internal/model/` — Domain types (no logic, no DB)
@ -37,7 +48,7 @@ Single Go binary serving HTML (server-rendered templates + HTMX) and a JSON API.
### Key Design Decisions
- **Go 1.22+ stdlib router** — no framework, `http.ServeMux` with method routing
- **3 external dependencies** — modernc.org/sqlite (pure Go), golang.org/x/crypto (Argon2id), gorilla/feeds
- **Minimal dependencies** — modernc.org/sqlite (pure Go), golang.org/x/crypto (Argon2id), gorilla/feeds, google/uuid, golang.org/x/term
- **`SetMaxOpenConns(1)`** — SQLite works best with a single writer; PRAGMAs are set once on the single connection
- **Templates embedded in binary**`//go:embed` for single-binary deployment; dev mode reads from disk for live reload
- **Middleware chain order matters** — Recovery → SecurityHeaders → BasePath → RealIP → Logger → SessionLoader → CSRF → MustResetGuard