Files
tavolo/server/packages/tavolo-platform/src/tavolo/platform/mixin.py
T
woggioni 915a294dc8 Support multiple OIDC providers
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.
2026-10-01 12:38:29 +00:00

52 lines
1.7 KiB
Python

"""The :class:`PlatformMixin`: mounts the whole platform on a kaya app.
``Platform`` bundles the collaborators every platform endpoint needs —
the game registry, the live-game store, the deadline scheduler and the
OIDC providers used for authentication — so route and websocket modules
never reach for module-global state. :class:`PlatformMixin` is a plain
:class:`~kaya.core.KayaMixin`: applying it registers the lobby, stats
and health HTTP routes plus the live-play websocket endpoint, and the
app stays a :class:`~kaya.core.KayaApp` (both ASGI and RSGI keep
working).
"""
from __future__ import annotations
from dataclasses import dataclass
from kaya.core import KayaApp, KayaMixin
from kaya.oidc import OIDCProviders
from .deadlines import DeadlineScheduler
from .registry import GameRegistry
from .store import GameStore
@dataclass(frozen=True)
class Platform:
"""The collaborators shared by all platform endpoints."""
registry: GameRegistry
game_store: GameStore
scheduler: DeadlineScheduler
oidc: OIDCProviders
class PlatformMixin(KayaMixin):
"""Register the game-independent routes and the websocket endpoint."""
def __init__(self, platform: Platform) -> None:
self.platform = platform
def apply(self, app: KayaApp) -> None:
# Imported here so module import order stays acyclic: the route
# modules reference Platform only for typing.
from . import ws
from .routes import auth, games, health, me, stats
health.register(app, self.platform)
auth.register(app, self.platform)
me.register(app, self.platform)
games.register(app, self.platform)
stats.register(app, self.platform)
ws.register(app, self.platform)