kaya-oidc 0.0.6 can run several providers in one app (OIDCProviders), each with its own login route and namespaced session state. Adopt it: providers are configured in indexed, contiguous OIDC_<n>_* blocks (0-based) with OIDC_<n>_PROVIDER naming the provider in its login URL and session keys. The old unindexed OIDC_ISSUER/OIDC_CLIENT_ID/... names are no longer read; startup fails with a rename hint when they are set. With no OIDC variables at all, the single dev mock provider named "default" is used, as before. The platform now authenticates through OIDCProviders: auth.current_user returns the session's user (sessions stay single-identity, so at most one provider is logged in) and require_auth/route handlers use it, while the websocket path keeps scanning for any provider's user. New routes expose the configuration to the SPA and keep old links working: GET /api/auth/providers lists the login URLs, GET /auth/login redirects to the first provider and GET /auth/logout to whichever provider the session is logged in with. The lobby renders one login button per provider from that endpoint. Update the env examples, compose and k8s manifests to the indexed scheme, document the multiple-provider setup and the migration, and cover it with config, auth and route tests.
92 lines
3.4 KiB
Markdown
92 lines
3.4 KiB
Markdown
# tavolo
|
|
|
|
A platform for multiplayer card games. The first game is **scopone
|
|
scientifico** — the four-player, fixed-partnership Italian card game:
|
|
|
|
- **`server/`** — backend: Python + [kaya](https://github.com/woggioni/kaya)
|
|
framework, OIDC login, live games in Redis, match statistics in Postgres.
|
|
A monorepo of three distributions sharing the `tavolo` namespace: the
|
|
game-independent `tavolo-platform`, the scopone game `tavolo-scopone`,
|
|
and the `tavolo-app` composition root wiring them together.
|
|
See [server/README.md](server/README.md).
|
|
- **`web/`** — frontend: Rust + [Sycamore](https://sycamore.dev) compiled to
|
|
WebAssembly, built with [Trunk](https://trunkrs.dev) and styled with
|
|
[Bootstrap](https://getbootstrap.com) 5.3 (MIT, vendored under
|
|
`web/vendor/` so builds work offline) plus the custom felt theme in
|
|
`web/theme.css`. Card images are the
|
|
CC0 *woodcut napoletane* deck traced from a 1902 Naples print
|
|
([SONDLecT/woodcut-napoletane](https://github.com/SONDLecT/woodcut-napoletane)).
|
|
|
|
## Run the whole stack
|
|
|
|
```sh
|
|
docker compose up --build
|
|
```
|
|
|
|
Postgres, Redis, a mock OIDC provider (test users `alice`, `bob`, `carol`,
|
|
`dave`), the database migrator and the app all come up together. The app —
|
|
frontend and API — listens on `http://127.0.0.1:8080`.
|
|
|
|
Because both the browser and the app talk to the OIDC issuer at
|
|
`http://mockoauth:8180/tavolo`, add a host entry once:
|
|
|
|
```sh
|
|
echo "127.0.0.1 mockoauth" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
## Between hands
|
|
|
|
When a hand ends but the match is not decided, the game pauses on a
|
|
**scoring summary screen**: every player sees how each category was won
|
|
(carte, denara, settebello, primiera, scope — plus napola and asso
|
|
pigliatutto when enabled)
|
|
with the running totals and
|
|
must click "Understood" before the next hand is dealt. If someone is away
|
|
the next hand is dealt automatically after `HAND_ACK_TIMEOUT_SECONDS`
|
|
(default 30s). The match-ending hand is explained on the final screen.
|
|
|
|
## On your turn
|
|
|
|
Every turn shows a countdown (`TURN_TIMEOUT_SECONDS`, default 30s). If a
|
|
player does not move — disconnected or fallen asleep — the server plays a
|
|
random legal card for them (randomizing among the legal captures when the
|
|
rules require a capture), so one absent player cannot stall the table.
|
|
|
|
## Development
|
|
|
|
Backend (from `server/`):
|
|
|
|
```sh
|
|
cd server
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -r requirements.txt
|
|
.venv/bin/pip install -e ./packages/tavolo-platform -e ./packages/tavolo-scopone -e './packages/tavolo-app[dev]'
|
|
.venv/bin/python -m unittest discover -s tests -t .
|
|
.venv/bin/python -m unittest discover -s packages/tavolo-platform/tests
|
|
.venv/bin/python -m unittest discover -s packages/tavolo-scopone/tests
|
|
```
|
|
|
|
Frontend (from `web/`), with the backend running on :8080:
|
|
|
|
```sh
|
|
cd web
|
|
trunk serve # SPA on http://localhost:8000, /api /auth /ws proxied
|
|
```
|
|
|
|
Trunk proxies `/api`, `/auth` and `/ws` to `127.0.0.1:8080` (see
|
|
`web/Trunk.toml`). For the login redirect to land back on the dev server,
|
|
run the backend with:
|
|
|
|
```sh
|
|
OIDC_0_PROVIDER=default \
|
|
OIDC_0_ISSUER=http://localhost:8180/tavolo \
|
|
OIDC_0_CLIENT_ID=tavolo \
|
|
OIDC_0_REDIRECT_URI=http://localhost:8080/auth/default/callback \
|
|
OIDC_0_POST_LOGIN_REDIRECT=http://localhost:8000/ \
|
|
OIDC_0_POST_LOGOUT_REDIRECT=http://localhost:8000/ \
|
|
.venv/bin/granian --host 127.0.0.1 --port 8080 tavolo.app:app
|
|
```
|
|
|
|
Card images are committed under `web/assets/cards/`; `web/fetch-cards.sh`
|
|
re-downloads them if needed.
|