""" Auth-lag for TeeCup. Selve innloggingen er en STUB her (erstattes med ekte sesjon/JWT senere). Det som IKKE er en stub, og som er sikkerhetskritisk, er `get_authorized_org`: den verifiserer at den innloggede brukeren faktisk er medlem av organisasjonen før org-konteksten settes. Hvorfor det er kritisk: RLS stoler blindt på `app.current_org`. Setter appen den til en organisasjon brukeren ikke tilhører, gir RLS lydig tilgang til den organisasjonens data. Isolasjonen står og faller altså på at denne sjekken skjer FØR org_connection kalles — aldri sett konteksten fra en uverifisert kilde (som en klient-oppgitt header). """ from dataclasses import dataclass from fastapi import Depends, Header, HTTPException, status from .db import plain_connection @dataclass(frozen=True) class CurrentUser: user_id: str async def get_current_user( x_debug_user_id: str | None = Header(default=None), ) -> CurrentUser: """STUB: hent brukeren fra en verifisert sesjon. Midlertidig leses bruker-id fra en header for at skjelettet skal kunne kjøres. ERSTATT dette med validering av sesjonscookie/JWT (signert med settings.SESSION_SECRET) før noe settes i produksjon. En header er IKKE en autentisert kilde. """ if not x_debug_user_id: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Ikke autentisert (stub forventer X-Debug-User-Id).", ) return CurrentUser(user_id=x_debug_user_id) async def get_authorized_org( organization_id: str, user: CurrentUser = Depends(get_current_user), ) -> str: """Returnerer organization_id KUN hvis brukeren er medlem — ellers 403. Medlemskapstabellen er ikke organisasjonsavgrenset, så oppslaget gjøres på en tilkobling uten org-kontekst. """ async with plain_connection() as conn: is_member = await conn.fetchval( """ SELECT EXISTS ( SELECT 1 FROM organization_membership WHERE user_id = $1 AND organization_id = $2 ) """, user.user_id, organization_id, ) if not is_member: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Brukeren er ikke medlem av denne organisasjonen.", ) return organization_id