Document the new FastAPI server and WebUI
build / Linux x86_64 (push) Successful in 2m55s
build / Windows x64 (Wine) (push) Successful in 3m50s

This commit is contained in:
2026-09-14 19:41:35 -04:00
parent 7b7d31bdfa
commit bf1fa04f11
+48 -29
View File
@@ -404,52 +404,68 @@ Requirements & behaviour:
## Server setup
The catalog + store API is a single-file, stdlib-only HTTP server
(`app/api.py`) — no pip install needed on the server.
The server is a **FastAPI** app (`server/`) with an admin **WebUI** and a
JSON API. It owns the catalog, metadata, covers, and the game/video store
archives, and serves them to the desktop app. Users log in with a username +
password; the app holds a **per-user API token** (roles: `admin`, `editor`,
`user`).
Run it directly (dev):
```bash
PSP_DATA_DIR=/data \
PSP_DATS_DIR=/data/dats \
pip install -r requirements-server.txt
PSP_DB_PATH=/data/library.sqlite \
PSP_COVERS_DIR=/data/covers \
PSP_GAMES_ROOTS=/data/umd_games \
PSP_VIDEO_ROOTS=/data/umd_videos \
PSP_STORE_DIR=/data/store \
PSP_API_TOKEN=<long-random-secret> \
python3 -m app.api --host 0.0.0.0 --port 8000
PSP_STORE_VIDEOS_DIR=/data/store_videos \
PSP_ADMIN_USERNAME=admin \
PSP_ADMIN_PASSWORD=<change-me> \
uvicorn server.main:app --host 0.0.0.0 --port 8000
```
Endpoints:
On first boot it creates the `PSP_ADMIN_USERNAME` account (log in and change
the password). The admin WebUI lives at `/`:
- **Dashboard** — storage, catalog counts, recent downloads.
- **Games & Videos** — browse the catalog, edit metadata, upload covers.
- **Store** — upload/delete game and video archives.
- **Users** — create users, assign roles, reset passwords.
API endpoints:
| Endpoint | Description |
|---|---|
| `GET /api/summary` | release counts per system |
| `POST /api/auth/login` | username/password → API token |
| `GET /api/auth/me` | current user |
| `GET /api/users`, `POST`, `PATCH`, `DELETE` | user management *(admin)* |
| `GET /api/releases?system=&q=&limit=&offset=` | search the catalog |
| `GET /api/releases/<id>` | one release + its rom hashes |
| `GET /api/library?system=&refresh=` | your scanned library |
| `GET /api/cover/<id>` | cover image (fetched on demand) |
| `GET /api/covers/<name>.zip` | offline cover bundle (public) |
| `GET /api/store` | list store archives *(token)* |
| `GET /api/store/download/<name>` | stream one archive *(token)* |
| `GET /api/releases/<id>` | release detail + metadata + rom hashes |
| `PATCH /api/releases/<id>` | edit metadata *(editor+)* |
| `GET /api/cover/<id>` | cover image |
| `POST /api/cover/<id>` | upload/replace cover *(editor+)* |
| `GET /api/store?system=games|videos` | list store archives |
| `GET /api/store/download/<system>/<name>` | stream an archive *(user+)* |
| `POST /api/store/upload`, `DELETE /api/store/<system>/<name>` | manage archives *(editor+)* |
| `GET /api/stats` | dashboard numbers *(admin)* |
Token protection: set `PSP_API_TOKEN`; the client sends
`Authorization: Bearer <token>`. Leave it unset to allow anonymous access
(not recommended).
Authentication is `Authorization: Bearer <token>` for the API and a session
cookie for the WebUI.
### Docker (Unraid)
`docker-compose.yml` builds the API image and attaches it to Unraid's `br0`
macvlan bridge so it gets its own LAN IP (e.g. `192.168.1.100`, plain HTTP on 8000):
`docker-compose.yml` builds the server image and attaches it to Unraid's `br0`
macvlan bridge so it gets its own LAN IP:
```bash
# in /path/to/psppt/
cp .env.example .env # then edit: LAN IP, share paths, API token
cp .env.example .env # then edit: LAN IP, share paths, admin password
docker compose up -d --build
```
The compose file reads the LAN IP and Unraid share paths from `.env` and
mounts them into `/data/store`, `/data/umd_games` and `/data/umd_videos`
(the store is mounted read-only).
The compose file reads the LAN IP and Unraid share paths from `.env` and mounts
them into `/data/store`, `/data/store_videos`, `/data/umd_games` and
`/data/umd_videos` (the store mounts are writable so the WebUI can manage
archives).
### TLS (optional)
@@ -460,10 +476,13 @@ ports 80/443 on your router to it.
### Client
In the GUI: **Settings → Store** → enter the **Server URL** (e.g.
`http://<server-ip>:8000` or `https://psp.example.com`) and the same **API
token**, then pick **Server** in the Store tab's source selector. Use
**Archive.org** or **Local folder** the same way.
In the GUI: **Settings → Store** → enter the **Server URL**, **Server
username**, and **Server password**, then **Save settings** (the app logs in
and stores the per-user token). Pick **Server** in the Store tab's source
selector. When a server is configured it is authoritative for covers and
metadata — if it's unreachable the app shows an error instead of falling back
to public sources. Use **Archive.org**, **Local folder**, or **NoPayStation**
the same way as before.
## PSP Sync