Files
mono/shared/infrastructure/user_loader.py
giles 580f551700 Split databases and Redis — prepare infrastructure for per-domain isolation
Redis: per-app DB index (0-5) with shared auth DB 15 for SSO keys;
flushdb replaces flushall so deploys don't wipe cross-app auth state.

Postgres: drop 13 cross-domain FK constraints (migration v2t0p8q9r0),
remove dead ORM relationships, add explicit joins for 4 live ones.
Multi-engine sessions (account + federation) ready for per-domain DBs
via DATABASE_URL_ACCOUNT / DATABASE_URL_FEDERATION env vars.

All URLs initially point to the same appdb — zero behaviour change
until split-databases.sh is run to migrate data to per-domain DBs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 02:20:34 +00:00

48 lines
1.5 KiB
Python

from __future__ import annotations
from quart import session as qsession, g
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from shared.models.user import User
from shared.models.ghost_membership_entities import UserNewsletter
async def load_user_by_id(session, user_id: int):
"""Load a user by ID with labels and newsletters eagerly loaded."""
stmt = (
select(User)
.options(
selectinload(User.labels),
selectinload(User.user_newsletters).selectinload(
UserNewsletter.newsletter
),
)
.where(User.id == user_id)
)
result = await session.execute(stmt)
return result.scalar_one_or_none()
async def load_current_user():
uid = qsession.get("uid")
if not uid:
g.user = None
g.rights = {"admin": False}
return
# User table lives in the account DB — use account session when
# the per-request session (g.s) targets a different database.
from shared.db.session import DATABASE_URL, DATABASE_URL_ACCOUNT
if DATABASE_URL_ACCOUNT != DATABASE_URL:
from shared.db.session import get_account_session
async with get_account_session() as s:
g.user = await load_user_by_id(s, uid)
# Expunge so the object is usable outside this session
if g.user:
s.expunge(g.user)
else:
g.user = await load_user_by_id(g.s, uid)
g.rights = {l.name: True for l in g.user.labels} if g.user else {}