a548266461
- Add backend/ai/utils.py — parse_classification, parse_suggestions, strip_code_fences shared by all AI providers; removes duplicated private functions from anthropic_provider.py and openai_provider.py - Add backend/deps/utils.py — get_client_ip, parse_uuid request-parsing helpers; removes local _ip() variants from admin.py, auth.py, shares.py, folders.py - Add backend/storage/exceptions.py — canonical CloudConnectionError definition; all routers and backends import from here instead of redefining - Move validate_password_strength to backend/services/auth.py; removes duplicated _validate_password_strength from admin.py and auth.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
35 lines
1.3 KiB
Python
35 lines
1.3 KiB
Python
"""Shared dependency utilities — request parsing helpers used across all API routers."""
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from typing import Optional
|
|
|
|
from fastapi import HTTPException, Request
|
|
|
|
|
|
def get_client_ip(request: Request) -> Optional[str]:
|
|
"""Extract best-effort client IP from request for audit logging.
|
|
|
|
TRUST BOUNDARY: X-Forwarded-For is a client-controlled header and can be
|
|
forged by any caller. This value is used for forensic audit logging only —
|
|
not for authentication or access control decisions. In production, deploy
|
|
behind a trusted reverse proxy (e.g. nginx with
|
|
``proxy_set_header X-Forwarded-For $remote_addr;``) which overwrites this
|
|
header with the real remote IP before it reaches FastAPI.
|
|
"""
|
|
return request.headers.get("X-Forwarded-For") or (
|
|
request.client.host if request.client else None
|
|
)
|
|
|
|
|
|
def parse_uuid(value: str, detail: str = "Not found") -> uuid.UUID:
|
|
"""Parse *value* as a UUID, raising HTTP 404 with *detail* on failure.
|
|
|
|
Use at API boundaries to convert path/body string IDs to UUID objects.
|
|
Returns the parsed UUID so callers can use it directly without a try/except.
|
|
"""
|
|
try:
|
|
return uuid.UUID(value)
|
|
except ValueError:
|
|
raise HTTPException(status_code=404, detail=detail)
|