mirror of
https://github.com/azaion/loader.git
synced 2026-04-22 22:16:32 +00:00
4eaf218f09
Made-with: Cursor
100 lines
6.0 KiB
Markdown
100 lines
6.0 KiB
Markdown
# 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.
|