# Module: api_client ## Purpose Central API client that orchestrates authentication, encrypted resource download/upload (using a big/small binary-split scheme), and CDN integration for the Azaion resource API. ## Public Interface ### Classes #### `ApiClient` (cdef class) | Attribute | Type | Description | |-------------|-------------|------------------------------------| | credentials | Credentials | User email/password | | user | User | Authenticated user (from JWT) | | token | str | JWT bearer token | | cdn_manager | CDNManager | CDN upload/download client | | api_url | str | Base URL for the resource API | #### Methods | Method | Visibility | Signature | Description | |------------------------------|------------|-------------------------------------------------------------------|--------------------------------------------------------------| | `__init__` | def | `(self, str api_url)` | Initialize with API base URL | | `set_credentials_from_dict` | cpdef | `(self, str email, str password)` | Set credentials + initialize CDN from `cdn.yaml` | | `set_credentials` | cdef | `(self, Credentials credentials)` | Internal: set credentials, lazy-init CDN manager | | `login` | cdef | `(self)` | POST `/login`, store JWT token | | `set_token` | cdef | `(self, str token)` | Decode JWT claims → create `User` with role mapping | | `request` | cdef | `(self, str method, str url, object payload, bint is_stream)` | Authenticated HTTP request with auto-retry on 401/403 | | `load_bytes` | cdef | `(self, str filename, str folder) -> bytes` | Download + decrypt resource using per-user+hw key | | `upload_file` | cdef | `(self, str filename, bytes resource, str folder)` | POST multipart upload to `/resources/{folder}`; raises on HTTP error | | `load_big_file_cdn` | cdef | `(self, str folder, str big_part) -> bytes` | Download large file part from CDN | | `load_big_small_resource` | cpdef | `(self, str resource_name, str folder) -> bytes` | Reassemble resource from small (API) + big (CDN/local) parts | | `upload_big_small_resource` | cpdef | `(self, bytes resource, str resource_name, str folder)` | Split-encrypt; CDN upload must succeed or raises; then small part via `upload_file` | ## Internal Logic ### Authentication Flow 1. `set_credentials_from_dict()` → stores credentials, downloads `cdn.yaml` via `load_bytes()` (encrypted), parses YAML, initializes `CDNManager` 2. `login()` → POST `/login` with email/password → receives JWT token → `set_token()` decodes claims (nameid, unique_name, role) → creates `User` 3. `request()` → wraps all authenticated HTTP calls; on 401/403 auto-retries with fresh login ### Big/Small Resource Split (download) 1. Downloads the "small" encrypted part via API (`load_bytes()` with per-user+hw key) 2. Checks if "big" part exists locally (cached file) 3. If local: concatenates small + big, decrypts with shared resource key 4. If decrypt fails (version mismatch): falls through to CDN download 5. If no local: downloads big part from CDN 6. Concatenates small + big, decrypts with shared resource key ### Big/Small Resource Split (upload) 1. Encrypts entire resource with shared resource key 2. Splits: small part = `min(SMALL_SIZE_KB * 1024, 30% of encrypted)`, big part = remainder 3. Calls `cdn_manager.upload` for the big part; raises if upload fails 4. Writes big part to local cache, then uploads small part to API via `upload_file` (non-2xx responses propagate) ### JWT Role Mapping Maps `role` claim string to `RoleEnum`: ApiAdmin, Admin, ResourceUploader, Validator, Operator, or NONE (default). ## Dependencies - **Internal**: `constants`, `credentials`, `cdn_manager`, `hardware_service`, `security`, `user` - **External**: `json`, `os` (stdlib), `jwt` (pyjwt 2.10.1), `requests` (2.32.4), `yaml` (pyyaml 6.0.2) ## Consumers - `main` — creates `ApiClient` instance; calls `set_credentials_from_dict`, `login`, `load_big_small_resource`, `upload_big_small_resource`; reads `.token` ## Data Models Uses `Credentials`, `User`, `RoleEnum`, `CDNCredentials`, `CDNManager` from other modules. ## Configuration | Source | Key | Usage | |-------------|--------------------|-----------------------------------------| | `cdn.yaml` | host | CDN endpoint URL | | `cdn.yaml` | downloader_access_key/secret | CDN read credentials | | `cdn.yaml` | uploader_access_key/secret | CDN write credentials | The CDN config file is itself downloaded encrypted from the API on first credential setup. ## External Integrations - **Azaion Resource API**: `/login`, `/resources/get/{folder}`, `/resources/{folder}` (upload) - **S3 CDN**: via `CDNManager` for large file parts ## Security - JWT token stored in memory, decoded without signature verification (`options={"verify_signature": False}`) - Per-download encryption: resources encrypted with AES-256-CBC using a key derived from user credentials + hardware fingerprint - Shared resource encryption: big/small split uses a fixed shared key - Auto-retry on 401/403 re-authenticates transparently - CDN config is downloaded encrypted, decrypted locally ## Tests No tests found.