from fastapi import Depends, Header, HTTPException, Query, Response, status from typing import Optional, Union import logging import asyncio from app.models.auth_models import AccountContext log = logging.getLogger(__name__) # --- Account Context Dependencies --- def get_account_context_optional( x_account_id: Optional[str] = Header(None, min_length=11, max_length=22), x_no_account_id: Optional[str] = Header(None, min_length=3, max_length=100), x_no_account_id_token: Optional[str] = Query(None, min_length=11, max_length=22), ) -> AccountContext: """ Resolves the account context but does not raise 403 on failure. Uses DEFERRED imports to prevent circular dependency at startup. """ from app.db_sql import redis_lookup_id_random resolved_account_id = None resolved_account_id_random = None auth_method = 'guest' if x_account_id: resolved_account_id_random = x_account_id if looked_up_id := redis_lookup_id_random(table_name='account', record_id_random=x_account_id): resolved_account_id = looked_up_id auth_method = 'legacy_header' elif x_no_account_id_token: resolved_account_id_random = x_no_account_id_token if looked_up_id := redis_lookup_id_random(table_name='account', record_id_random=x_no_account_id_token): resolved_account_id = looked_up_id auth_method = 'token_query' elif x_no_account_id: resolved_account_id = None resolved_account_id_random = '--- NO ACCOUNT ---' auth_method = 'bypass' return AccountContext( account_id=resolved_account_id, account_id_random=resolved_account_id_random, auth_method=auth_method, administrator=(auth_method == 'bypass'), manager=(auth_method == 'bypass'), super=(auth_method == 'bypass') ) def get_account_context( x_account_id: Optional[str] = Header(None, min_length=11, max_length=22), x_no_account_id: Optional[str] = Header(None, min_length=3, max_length=100), x_no_account_id_token: Optional[str] = Query(None, min_length=11, max_length=22), ) -> AccountContext: """Strict version of account context resolution.""" ctx = get_account_context_optional(x_account_id, x_no_account_id, x_no_account_id_token) if ctx.auth_method == 'guest': raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='Account context required.') return ctx # --- Shared Pagination & Status Dependencies --- class PaginationParams: def __init__( self, limit: int = Query(100, ge=0), offset: int = Query(0, ge=0), ): self.limit = limit self.offset = offset class StatusFilterParams: def __init__( self, enabled: str = Query('enabled'), hidden: str = Query('not_hidden'), ): self.enabled = enabled self.hidden = hidden class SerializationParams: def __init__( self, by_alias: bool = Query(True), exclude_unset: bool = Query(False), exclude_defaults: bool = Query(False), exclude_none: bool = Query(False), ): self.by_alias = by_alias self.exclude_unset = exclude_unset self.exclude_defaults = exclude_defaults self.exclude_none = exclude_none class DelayParams: def __init__( self, x_delay_ms: Optional[int] = Header(0, alias='X-Delay-ms'), delay_ms: Optional[int] = Query(0), ): val = max(x_delay_ms or 0, delay_ms or 0) self.sleep_time_ms = val self.sleep_time_s = val / 1000.0