c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
111 lines
4.4 KiB
Python
111 lines
4.4 KiB
Python
import os
|
|
from typing import Optional
|
|
from fastapi import Depends, HTTPException
|
|
from ..models import User
|
|
from ..get_fastapi_users import get_fastapi_users
|
|
from .get_default_user import get_default_user
|
|
from .get_user import get_user
|
|
from cognee.shared.logging_utils import get_logger
|
|
|
|
|
|
logger = get_logger("get_authenticated_user")
|
|
|
|
|
|
def _resolve_auth_posture() -> tuple[bool, bool, str]:
|
|
"""Resolve authentication + access-control posture from env vars.
|
|
|
|
Returns ``(require_authentication, enable_backend_access_control, reason)``.
|
|
|
|
Semantics:
|
|
* ``ENABLE_BACKEND_ACCESS_CONTROL`` is the canonical posture switch
|
|
(multi-tenant on/off, default on).
|
|
* ``REQUIRE_AUTHENTICATION`` controls whether endpoints demand a user.
|
|
If unset, it inherits from ``ENABLE_BACKEND_ACCESS_CONTROL`` — turning
|
|
off backend access control disables the auth requirement, matching
|
|
single-user / internal-deployment expectations.
|
|
* Invariant: multi-tenant mode requires authentication. Setting
|
|
``REQUIRE_AUTHENTICATION=false`` together with
|
|
``ENABLE_BACKEND_ACCESS_CONTROL=true`` is a misconfiguration; we log
|
|
a warning and force auth on to keep per-user data isolated.
|
|
"""
|
|
|
|
def _read_bool(name: str) -> tuple[Optional[bool], bool]:
|
|
raw = os.environ.get(name)
|
|
if raw is None or raw == "":
|
|
return None, False
|
|
return raw.lower() == "true", True
|
|
|
|
access_value, access_explicit = _read_bool("ENABLE_BACKEND_ACCESS_CONTROL")
|
|
require_value, require_explicit = _read_bool("REQUIRE_AUTHENTICATION")
|
|
|
|
enable_access_control = True if access_value is None else access_value
|
|
|
|
if require_explicit:
|
|
assert require_value is not None # require_explicit implies a parsed value
|
|
require_authentication = require_value
|
|
if enable_access_control and not require_authentication:
|
|
logger.warning(
|
|
"REQUIRE_AUTHENTICATION=false is incompatible with "
|
|
"ENABLE_BACKEND_ACCESS_CONTROL=true: multi-tenant mode requires "
|
|
"authentication. Forcing REQUIRE_AUTHENTICATION=true. "
|
|
"To disable auth for a single-user deployment, also set "
|
|
"ENABLE_BACKEND_ACCESS_CONTROL=false."
|
|
)
|
|
require_authentication = True
|
|
reason = "forced on by multi-tenant mode (REQUIRE_AUTHENTICATION=false was ignored)"
|
|
else:
|
|
reason = "explicit REQUIRE_AUTHENTICATION"
|
|
else:
|
|
require_authentication = enable_access_control
|
|
reason = (
|
|
"inherited from ENABLE_BACKEND_ACCESS_CONTROL"
|
|
if access_explicit
|
|
else "default (no env vars set)"
|
|
)
|
|
|
|
return require_authentication, enable_access_control, reason
|
|
|
|
|
|
REQUIRE_AUTHENTICATION, ENABLE_BACKEND_ACCESS_CONTROL, _AUTH_REASON = _resolve_auth_posture()
|
|
|
|
logger.info(
|
|
"auth posture: authentication=%s, multi_tenant=%s (%s)",
|
|
"required" if REQUIRE_AUTHENTICATION else "disabled",
|
|
"enabled" if ENABLE_BACKEND_ACCESS_CONTROL else "disabled",
|
|
_AUTH_REASON,
|
|
)
|
|
|
|
fastapi_users = get_fastapi_users()
|
|
|
|
_auth_dependency = fastapi_users.current_user(active=True, optional=not REQUIRE_AUTHENTICATION)
|
|
|
|
|
|
async def get_authenticated_user(
|
|
user: Optional[User] = Depends(_auth_dependency),
|
|
) -> User:
|
|
"""
|
|
Get authenticated user with environment-controlled behavior:
|
|
- If REQUIRE_AUTHENTICATION=true: Enforces authentication (raises 401 if not authenticated)
|
|
- If REQUIRE_AUTHENTICATION=false: Falls back to default user if not authenticated
|
|
|
|
Always returns a User object for consistent typing.
|
|
"""
|
|
if user is None:
|
|
# When authentication is optional and user is None, use default user
|
|
try:
|
|
user = await get_default_user()
|
|
except Exception as e:
|
|
# Convert any get_default_user failure into a proper HTTP 500 error
|
|
logger.error(f"Failed to create default user: {str(e)}")
|
|
raise HTTPException(
|
|
status_code=500, detail=f"Failed to create default user: {str(e)}"
|
|
) from e
|
|
else:
|
|
# FastAPI Users returns a session-bound instance without eager-loaded
|
|
# relationships. Re-fetch so callers (including background tasks that
|
|
# outlive the request) can access user.tenants / user.roles without
|
|
# DetachedInstanceError.
|
|
user = await get_user(user.id)
|
|
|
|
return user
|