feat(api-v3): implement temporary ?key= access pattern and update guide
- Added ?key= query param support for unauthenticated direct downloads. - Fixed site table column bug (auth_key -> access_key). - Updated GUIDE__V3_FRONTEND_API.md with temporary auth documentation. - Ensured valid keys bypass the 403 Machine Auth requirement.
This commit is contained in:
@@ -185,6 +185,7 @@ async def download_file_action(
|
|||||||
response: Response,
|
response: Response,
|
||||||
hosted_file_id: str = Path(min_length=11, max_length=22),
|
hosted_file_id: str = Path(min_length=11, max_length=22),
|
||||||
filename: Optional[str] = Query(None, min_length=4, max_length=255),
|
filename: Optional[str] = Query(None, min_length=4, max_length=255),
|
||||||
|
key: Optional[str] = Query(None), # Simplified unauthenticated access (Account ID)
|
||||||
site_key: Optional[str] = Query(None), # Bypass API Key/JWT if valid site key provided
|
site_key: Optional[str] = Query(None), # Bypass API Key/JWT if valid site key provided
|
||||||
range: Optional[str] = Header(None),
|
range: Optional[str] = Header(None),
|
||||||
account: AccountContext = Depends(get_account_context_optional),
|
account: AccountContext = Depends(get_account_context_optional),
|
||||||
@@ -192,23 +193,35 @@ async def download_file_action(
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Enhanced download/streaming logic.
|
Enhanced download/streaming logic.
|
||||||
Supports byte-range seeking, delay simulation, and site_key bypass.
|
Supports byte-range seeking, delay simulation, and site_key/key bypass.
|
||||||
"""
|
"""
|
||||||
if delay.sleep_time_s > 0: await asyncio.sleep(delay.sleep_time_s)
|
if delay.sleep_time_s > 0: await asyncio.sleep(delay.sleep_time_s)
|
||||||
|
|
||||||
# 1. Auth Bypass Logic (site_key)
|
# 1. Auth Bypass Logic (site_key and simplified key)
|
||||||
is_authorized = False
|
is_authorized = False
|
||||||
|
|
||||||
|
# Priority A: Standard Auth (JWT or API Key)
|
||||||
if account.auth_method != 'guest':
|
if account.auth_method != 'guest':
|
||||||
is_authorized = True
|
is_authorized = True
|
||||||
|
|
||||||
|
# Priority B: Simplified Access Pattern (?key=ANY_VALID_ACCOUNT_ID)
|
||||||
|
elif key:
|
||||||
|
# For now, to unblock the frontend, any valid account_id_random is sufficient.
|
||||||
|
# Ideally, we would match it to the file's account, but that requires a DB lookup.
|
||||||
|
if redis_lookup_id_random(record_id_random=key, table_name='account'):
|
||||||
|
is_authorized = True
|
||||||
|
log.info(f"Auth Bypass: Download authorized via simplified account key.")
|
||||||
|
|
||||||
|
# Priority C: Site Key (?site_key=SITE_ACCESS_KEY)
|
||||||
elif site_key:
|
elif site_key:
|
||||||
# Verify site key existence and status
|
# FIX: site table uses 'access_key', not 'auth_key'
|
||||||
sql = "SELECT id FROM site WHERE auth_key = :key AND enable = true LIMIT 1"
|
sql = "SELECT id FROM site WHERE access_key = :key AND enable = true LIMIT 1"
|
||||||
if site_res := sql_select(sql=sql, data={'key': site_key}):
|
if site_res := sql_select(sql=sql, data={'key': site_key}):
|
||||||
is_authorized = True
|
is_authorized = True
|
||||||
log.info(f"Auth Bypass: Download authorized via site_key.")
|
log.info(f"Auth Bypass: Download authorized via site_key.")
|
||||||
|
|
||||||
if not is_authorized:
|
if not is_authorized:
|
||||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Authentication required or invalid site_key.")
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Authentication required or invalid access key.")
|
||||||
|
|
||||||
# 2. Resolve File Record
|
# 2. Resolve File Record
|
||||||
# ID Vision: Attempt to resolve the ID.
|
# ID Vision: Attempt to resolve the ID.
|
||||||
|
|||||||
@@ -88,12 +88,21 @@ V3 uses specialized **"Action"** routes for binary operations to separate proces
|
|||||||
### B. Download & Streaming Action
|
### B. Download & Streaming Action
|
||||||
**Path**: `GET /v3/action/hosted_file/{id}/download`
|
**Path**: `GET /v3/action/hosted_file/{id}/download`
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `key` | String | **Temporary V3.0 Auth:** Pass any valid `account_id_random` to bypass headers. |
|
||||||
|
| `site_key` | String | Bypass headers via `access_key` from the `site` table. |
|
||||||
|
| `filename` | String | Override the response filename. |
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
- **ID Vision:** Automatically resolves `{id}` if it belongs to a container object (e.g., `event_file`) instead of a direct `hosted_file`.
|
- **ID Vision:** Automatically resolves `{id}` if it belongs to a container object (e.g., `event_file`) instead of a direct `hosted_file`.
|
||||||
- **Streaming:** Supports standard `Range` headers for large files and video seeking.
|
- **Streaming:** Supports standard `Range` headers for large files and video seeking.
|
||||||
- **Auth Bypass:** Use `?site_key=<auth_key>` to download without an API Key header or JWT (useful for public kiosks).
|
|
||||||
- **Testing:** Supports `delay_ms` query parameter.
|
- **Testing:** Supports `delay_ms` query parameter.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> **TEMPORARY SOLUTION (V3.0):** The `?key=` and `?site_key=` unauthenticated access patterns are intended to unblock the frontend for inline images and direct links where custom headers are not possible. This will be replaced by a standardized Signed URL or Read-Token system in **Version 3.1**. Please do not rely on this pattern for long-term security architecture.
|
||||||
|
|
||||||
### C. Hash-Based Download (Content-Addressable)
|
### C. Hash-Based Download (Content-Addressable)
|
||||||
**Path**: `GET /v3/action/hosted_file/hash/{sha256}/download`
|
**Path**: `GET /v3/action/hosted_file/hash/{sha256}/download`
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user