fix: merge main branch and renumber migration 027→037
Resolve 3 merge conflicts and renumber the automation_hooks migration to follow main's migration chain (036_add_document_translation_fields). Conflicts resolved: - app/api/__init__.py: add automation_router alongside main's new routers - app/utils/settings_service.py: add automation_hooks_enabled alongside compliance_enabled - tests/conftest.py: add AutomationHook alongside AuditLog/ComplianceTemplate imports Migration renumbered: - 027_add_automation_hooks → 037_add_automation_hooks - down_revision: 026_add_scheduled_jobs → 036_add_document_translation_fields Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
+56
-8
@@ -20,13 +20,31 @@ from app.models import FileRecord
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _owner_id_from_user(user: dict) -> str | None:
|
||||
"""Extract the owner identifier from a user dict.
|
||||
|
||||
Priority: ``sub`` (OAuth subject) → ``preferred_username`` → ``email`` → ``id``.
|
||||
"""
|
||||
return user.get("sub") or user.get("preferred_username") or user.get("email") or user.get("id")
|
||||
|
||||
|
||||
def get_current_owner_id(request: Request) -> str | None:
|
||||
"""Extract the owner identifier for the current authenticated user.
|
||||
|
||||
The owner ID is derived from the user's session data. It uses the
|
||||
``sub`` claim (OAuth subject) when available, falling back to
|
||||
``preferred_username`` or ``email``. Returns ``None`` when no user
|
||||
is authenticated.
|
||||
The owner ID is derived from the user's session data or, when no session
|
||||
is present, from a valid Bearer API token in the ``Authorization`` header.
|
||||
This ensures that both browser-based (session cookie) and mobile/API
|
||||
(Bearer token) requests are correctly identified.
|
||||
|
||||
Priority for user resolution:
|
||||
|
||||
1. Session ``user`` dict (set by OAuth or local login).
|
||||
2. ``request.state.api_token_user`` (set by ``require_login`` or an
|
||||
earlier call to this function during the same request).
|
||||
3. Direct Bearer token look-up against the database.
|
||||
|
||||
Within the resolved user dict the owner ID is chosen as:
|
||||
``sub`` → ``preferred_username`` → ``email`` → ``id``.
|
||||
|
||||
Args:
|
||||
request: The current FastAPI request with session data.
|
||||
@@ -34,11 +52,41 @@ def get_current_owner_id(request: Request) -> str | None:
|
||||
Returns:
|
||||
A stable string identifier for the user, or ``None``.
|
||||
"""
|
||||
# 1. Session-based auth (most common for web UI)
|
||||
user = request.session.get("user")
|
||||
if not user or not isinstance(user, dict):
|
||||
return None
|
||||
# Prefer 'sub' (OAuth subject), then 'preferred_username', then 'email', then 'id'
|
||||
return user.get("sub") or user.get("preferred_username") or user.get("email") or user.get("id")
|
||||
if user and isinstance(user, dict):
|
||||
return _owner_id_from_user(user)
|
||||
|
||||
# 2. Already-resolved API token user (cached by require_login or a
|
||||
# prior dependency call during this request)
|
||||
api_user = getattr(request.state, "api_token_user", None)
|
||||
if isinstance(api_user, dict):
|
||||
return _owner_id_from_user(api_user)
|
||||
|
||||
# 3. Direct Bearer token resolution – necessary when this function is
|
||||
# invoked as a FastAPI dependency (via Depends) which runs *before*
|
||||
# the @require_login decorator wrapper has had a chance to resolve
|
||||
# the token and populate request.state.api_token_user.
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if isinstance(auth_header, str) and auth_header.startswith("Bearer "):
|
||||
try:
|
||||
from app.auth import _resolve_bearer_user
|
||||
from app.database import SessionLocal
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
resolved = _resolve_bearer_user(request, db)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if resolved:
|
||||
# Cache so subsequent calls (and require_login) skip the DB
|
||||
request.state.api_token_user = resolved
|
||||
return _owner_id_from_user(resolved)
|
||||
except Exception:
|
||||
logger.debug("Bearer token resolution failed in get_current_owner_id", exc_info=True)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def apply_owner_filter(query: Query, request: Request) -> Query:
|
||||
|
||||
Reference in New Issue
Block a user