"""Dev-only bypass when ``DEER_FLOW_AUTH_DISABLED`` is set. Never enable in production: all API and LangGraph routes run as an assumed user. """ from __future__ import annotations import os from datetime import UTC from uuid import UUID from sqlalchemy import select from app.gateway.auth.models import User from deerflow.persistence.engine import get_session_factory from deerflow.persistence.user.model import UserRow _FALLBACK_ADMIN_ID = UUID("00000000-0000-4000-8000-000000000001") # Must satisfy pydantic EmailStr (avoid reserved/special-use domains like .local). _FALLBACK_EMAIL = "anonymous@example.com" _cached_assumed_user: User | None = None def is_auth_disabled() -> bool: """Return True when auth gate should be bypassed (development / local tooling).""" return os.environ.get("DEER_FLOW_AUTH_DISABLED", "").strip().lower() in ("1", "true", "yes", "on") def _row_to_user(row: UserRow) -> User: created = row.created_at if created.tzinfo is None: created = created.replace(tzinfo=UTC) return User( id=UUID(row.id), email=row.email, password_hash=row.password_hash, system_role=row.system_role, # type: ignore[arg-type] created_at=created, oauth_provider=row.oauth_provider, oauth_id=row.oauth_id, needs_setup=row.needs_setup, token_version=row.token_version, ) async def get_assumed_user_for_disabled_auth() -> User: """Resolve the user assumed for every request when auth is disabled. Prefer the first admin row in the database so thread ownership matches an existing account. If the DB is empty or unavailable, use a stable synthetic admin (restart the gateway after creating a real admin to pick them up). """ global _cached_assumed_user if _cached_assumed_user is not None: return _cached_assumed_user sf = get_session_factory() if sf is not None: async with sf() as session: stmt = select(UserRow).where(UserRow.system_role == "admin").limit(1) row = (await session.execute(stmt)).scalar_one_or_none() if row is not None: _cached_assumed_user = _row_to_user(row) return _cached_assumed_user _cached_assumed_user = User( id=_FALLBACK_ADMIN_ID, email=_FALLBACK_EMAIL, password_hash=None, system_role="admin", needs_setup=False, token_version=0, ) return _cached_assumed_user