Huge refactor, submission system addition & security improvements. +Implementation of moderation cmds.
This commit is contained in:
134
docs/API.md
Normal file
134
docs/API.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# HTTP API Reference
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/health
|
||||
- **Description:** Health check endpoint.
|
||||
- **Auth:** None
|
||||
- **Query params:** None
|
||||
- **Response:** `{"status":"ok"}`
|
||||
|
||||
---
|
||||
|
||||
### GET /api/content/:cxid
|
||||
- **Description:** Get content metadata (files, view limits, password status, etc.).
|
||||
- **Auth:**
|
||||
- None if the content has no password.
|
||||
- Password required if the content has a password. Provide via query param `sc` **or** cookie `cgcx_pw`.
|
||||
- **Path params:**
|
||||
- `cxid` — Content ID string.
|
||||
- **Query params:**
|
||||
- `sc` (optional) — Password as a query string parameter.
|
||||
- **Response formats:**
|
||||
- `200 OK` — JSON metadata object:
|
||||
```json
|
||||
{
|
||||
"cxid": "string",
|
||||
"files": [
|
||||
{
|
||||
"idx": 0,
|
||||
"name": "string",
|
||||
"mime": "string",
|
||||
"size": 12345,
|
||||
"render_flags": 0
|
||||
}
|
||||
],
|
||||
"has_password": true,
|
||||
"max_views": 10,
|
||||
"current_views": 3,
|
||||
"allow_download": true,
|
||||
"created_at": "2024-01-01T00:00:00+00:00"
|
||||
}
|
||||
```
|
||||
- `401 Unauthorized` — Password required but missing or invalid.
|
||||
- `404 Not Found` — Content does not exist or has been deleted/blacklisted.
|
||||
- `410 Gone` — Content has reached its maximum view count.
|
||||
- **Notes:**
|
||||
- If authentication succeeds via the `sc` query parameter, the server sets an HMAC-signed `cgcx_pw` cookie on the response (`Max-Age=3600; SameSite=Strict; HttpOnly; Path=/`).
|
||||
|
||||
---
|
||||
|
||||
### GET /api/content/:cxid/file/:file_idx
|
||||
- **Description:** Serve a decrypted file. Supports HTTP Range requests for video/audio streaming. Returns the file with `Content-Disposition: inline` by default, or `attachment` when downloading.
|
||||
- **Auth:**
|
||||
- None if the content has no password.
|
||||
- Password required if the content has a password. Provide via query param `sc` **or** cookie `cgcx_pw`.
|
||||
- **Path params:**
|
||||
- `cxid` — Content ID string.
|
||||
- `file_idx` — Zero-based file index within the content bundle.
|
||||
- **Query params:**
|
||||
- `sc` (optional) — Password as a query string parameter.
|
||||
- `download` (optional) — If truthy (`1`, `true`, `yes`), requests a download (`Content-Disposition: attachment`). Ignored if `allow_download` is `false` for the content.
|
||||
- **Response formats:**
|
||||
- `200 OK` — File stream with appropriate `Content-Type`.
|
||||
- `206 Partial Content` — Byte-range response (if `Range` header is present and valid).
|
||||
- `401 Unauthorized` — Password required but missing or invalid.
|
||||
- `403 Forbidden` — Download requested but not allowed, or path traversal blocked.
|
||||
- `404 Not Found` — Content or file index does not exist, or content deleted/blacklisted.
|
||||
- `410 Gone` — Content has reached its maximum view count.
|
||||
- `416 Range Not Satisfiable` — Invalid `Range` header.
|
||||
- **Notes:**
|
||||
- The server increments the view counter on successful full-file responses. Range requests and `If-None-Match` (ETag) matches do **not** increment the counter.
|
||||
- If the incremented view count reaches `max_views`, the server may delete content files (depending on `keep_content` config) and mark the content as `Deleted`, returning `410 Gone`.
|
||||
- `Accept-Ranges: bytes` is included for `video/*` and `audio/*` MIME types.
|
||||
- Cache-Control is `private, max-age=60` for unprotected content and `private, no-store, max-age=0` for password-protected content.
|
||||
- If authentication succeeds via the `sc` query parameter, the server sets an HMAC-signed `cgcx_pw` cookie on the response.
|
||||
|
||||
---
|
||||
|
||||
### GET /api/content/:cxid/file/:file_idx/raw
|
||||
- **Description:** Serve the fully decrypted file as raw plain text (`text/plain; charset=utf-8`). The entire file is decrypted into memory before being returned. No Range support.
|
||||
- **Auth:**
|
||||
- None if the content has no password.
|
||||
- Password required if the content has a password. Provide via query param `sc` **or** cookie `cgcx_pw`.
|
||||
- **Path params:**
|
||||
- `cxid` — Content ID string.
|
||||
- `file_idx` — Zero-based file index within the content bundle.
|
||||
- **Query params:**
|
||||
- `sc` (optional) — Password as a query string parameter.
|
||||
- **Response formats:**
|
||||
- `200 OK` — Plain text body.
|
||||
- `401 Unauthorized` — Password required but missing or invalid.
|
||||
- `403 Forbidden` — Path traversal blocked.
|
||||
- `404 Not Found` — Content or file index does not exist, or content deleted/blacklisted.
|
||||
- `410 Gone` — Content has reached its maximum view count.
|
||||
- **Notes:**
|
||||
- The server performs BLAKE3 integrity verification after full decryption.
|
||||
- If authentication succeeds via the `sc` query parameter, the server sets an HMAC-signed `cgcx_pw` cookie on the response.
|
||||
|
||||
---
|
||||
|
||||
### POST /api/content/:cxid/verify-password
|
||||
- **Description:** Explicitly verify a password for password-protected content and receive an authentication cookie.
|
||||
- **Auth:** None (this is the endpoint used to *obtain* auth).
|
||||
- **Path params:**
|
||||
- `cxid` — Content ID string.
|
||||
- **Body:** JSON object:
|
||||
```json
|
||||
{
|
||||
"password": "string"
|
||||
}
|
||||
```
|
||||
- **Response formats:**
|
||||
- `204 No Content` — Password is correct. The response includes a `Set-Cookie` header with `cgcx_pw`.
|
||||
- `401 Unauthorized` — Password is incorrect.
|
||||
- `404 Not Found` — Content does not exist.
|
||||
- **Notes:**
|
||||
- If the content has no password, the endpoint returns `204 No Content` without setting a cookie.
|
||||
- This endpoint has a separate, stricter rate limit than the general API.
|
||||
|
||||
---
|
||||
|
||||
## General Behavior
|
||||
|
||||
### CORS
|
||||
The server allows cross-origin requests from its configured `base_url` and common local development origins (`http://127.0.0.1:5173`, `http://localhost:5173`, `http://127.0.0.1:8090`, `http://localhost:8090`).
|
||||
|
||||
### Rate Limiting
|
||||
- General API routes (`/api/health`, `/api/content/...`) share a per-IP rate limit configured by `requests_per_minute` and `burst`.
|
||||
- `POST /api/content/:cxid/verify-password` has its own rate limit with a burst of 3 and a separate `password_attempts_per_minute` setting.
|
||||
|
||||
### Fallback / Static Assets
|
||||
- `/assets/*` — Serves static files from `frontend/dist/assets`.
|
||||
- All other non-`/api` paths — Serves `frontend/dist/index.html` (SPA fallback).
|
||||
- `/api/*` paths with no matching route — Return `404 Not Found` JSON.
|
||||
Reference in New Issue
Block a user