feat(upload): add resumable chunk configuration and file validation
Some checks failed
Build and Publish Docker Image / deploy (push) Failing after 56s
Some checks failed
Build and Publish Docker Image / deploy (push) Failing after 56s
- Add `WARPBOX_RESUMABLE_CHUNK_MODE` and `WARPBOX_RESUMABLE_CHUNK_PATH` environment variables to configure temporary chunk storage. - Implement strict file validation for resuming uploads to ensure selected files match the pending session's metadata. - Add `PLANS.md` to document development stages, roadmap, and API specifications (including batching and resumable flows).
This commit is contained in:
368
README.md
368
README.md
@@ -1,6 +1,20 @@
|
||||
# Warpbox.dev
|
||||
|
||||
This repository contains the Go backend base for `warpbox.dev`, a self-hosted transfer-first file sharing application.
|
||||
Warpbox is a self-hosted, transfer first file sharing application written in Go. It renders
|
||||
server side templates and serves static assets directly.
|
||||
|
||||
## Features
|
||||
|
||||
- Anonymous and authenticated uploads from the browser, `curl`, or ShareX.
|
||||
- Warpbox-native resumable uploads with a JSON API for large files.
|
||||
- Upload boxes with expiry, optional download limits, password protection, and one time delete tokens.
|
||||
- User accounts with personal dashboards, collections, storage quotas, and invite based registration.
|
||||
- Admin tooling for metrics, file management, storage backends, upload policy, and IP bans.
|
||||
- Local and S3 compatible storage backends.
|
||||
- Background jobs for cleanup and thumbnail generation.
|
||||
- Emoji reaction packs loaded from the runtime data directory.
|
||||
|
||||
> Looking for the roadmap and the staged development history? See [PLANS.md](./PLANS.md).
|
||||
|
||||
## Run
|
||||
|
||||
@@ -10,11 +24,25 @@ This repository contains the Go backend base for `warpbox.dev`, a self-hosted tr
|
||||
|
||||
The default server listens on `:8080`.
|
||||
|
||||
Upload size limits are configured in megabytes through `WARPBOX_MAX_UPLOAD_SIZE_MB`.
|
||||
Fractions are supported, so `0.5Mb` is 512 KiB and `1.5Mb` is 1536 KiB.
|
||||
For one off Go commands, run them from the backend module:
|
||||
|
||||
Upload policy defaults are also configured in megabytes and can later be changed from
|
||||
`/admin/settings`:
|
||||
```bash
|
||||
cd backend
|
||||
go run ./cmd/warpbox
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
All configuration comes from environment variables. The dev script sources `scripts/env/dev.env`.
|
||||
|
||||
### Upload size
|
||||
|
||||
Upload size limits are configured in megabytes through `WARPBOX_MAX_UPLOAD_SIZE_MB`. Fractions are
|
||||
supported, so `0.5Mb` is 512 KiB and `1.5Mb` is 1536 KiB.
|
||||
|
||||
### Upload policy defaults
|
||||
|
||||
These defaults can later be changed from `/admin/settings`:
|
||||
|
||||
- `WARPBOX_ANONYMOUS_UPLOADS_ENABLED=true`
|
||||
- `WARPBOX_ANONYMOUS_MAX_UPLOAD_MB=512`
|
||||
@@ -36,36 +64,147 @@ Upload policy defaults are also configured in megabytes and can later be changed
|
||||
- `WARPBOX_RESUMABLE_UPLOADS_ENABLED=true`
|
||||
- `WARPBOX_RESUMABLE_CHUNK_MB=8`
|
||||
- `WARPBOX_RESUMABLE_RETENTION_HOURS=24`
|
||||
- `WARPBOX_TRUSTED_PROXIES=` controls whether forwarded client IP headers are accepted only from specific proxy IPs/CIDRs. See [SECURITY_PROXY.md](./SECURITY_PROXY.md).
|
||||
- `WARPBOX_RESUMABLE_CHUNK_MODE=same`
|
||||
- `WARPBOX_RESUMABLE_CHUNK_PATH=`
|
||||
- `WARPBOX_TRUSTED_PROXIES=` controls whether forwarded client IP headers are accepted only from
|
||||
specific proxy IPs/CIDRs. See [SECURITY_PROXY.md](./SECURITY_PROXY.md).
|
||||
|
||||
Resumable settings are seeded from the environment and can then be edited from `/admin/settings`.
|
||||
Saved admin settings override these env defaults. `WARPBOX_RESUMABLE_CHUNK_MODE=same` stores draft
|
||||
chunks in the normal local temp path, `data/tmp/uploads/{session_id}` under `WARPBOX_DATA_DIR`.
|
||||
`WARPBOX_RESUMABLE_CHUNK_MODE=custom` uses `WARPBOX_RESUMABLE_CHUNK_PATH` instead, for example a
|
||||
mounted fast SSD path. Chunk storage is always local temporary staging; completed files are finalized
|
||||
into the selected storage backend after all chunks arrive.
|
||||
|
||||
### Timeouts
|
||||
|
||||
Large uploads are expected to take minutes on normal home/server connections. Keep
|
||||
`WARPBOX_READ_TIMEOUT=0s` and `WARPBOX_WRITE_TIMEOUT=0s` so Go does not close the connection
|
||||
mid upload; `WARPBOX_READ_HEADER_TIMEOUT=15s` still protects header reads from slowloris style
|
||||
connections.
|
||||
|
||||
### Data directory
|
||||
|
||||
Runtime data is configured with `WARPBOX_DATA_DIR` and defaults to `./data` in the dev environment.
|
||||
The dev script resolves that path from the repository root.
|
||||
|
||||
Large uploads are expected to take minutes on normal home/server connections. Keep
|
||||
`WARPBOX_READ_TIMEOUT=0s` and `WARPBOX_WRITE_TIMEOUT=0s` so Go does not close the connection
|
||||
mid-upload; `WARPBOX_READ_HEADER_TIMEOUT=15s` still protects header reads from slowloris-style
|
||||
connections.
|
||||
|
||||
Browser uploads use Warpbox-native resumable uploads by default. Chunks are stored temporarily under
|
||||
`data/tmp/uploads/{session_id}` and then streamed into the selected storage backend when the upload
|
||||
is completed. Stale sessions are cleaned by the cleanup job after `WARPBOX_RESUMABLE_RETENTION_HOURS`.
|
||||
### Background jobs
|
||||
|
||||
Background jobs are enabled with `WARPBOX_JOBS_ENABLED=true`. Individual jobs can be toggled with
|
||||
`WARPBOX_CLEANUP_ENABLED` and `WARPBOX_THUMBNAIL_ENABLED`, and their schedules are configured with
|
||||
`WARPBOX_CLEANUP_EVERY` and `WARPBOX_THUMBNAIL_EVERY`.
|
||||
|
||||
- **Cleanup**: expired boxes and boxes that have reached their download limit are cleaned on startup
|
||||
and then on schedule. Stale resumable sessions are removed after `WARPBOX_RESUMABLE_RETENTION_HOURS`.
|
||||
- **Thumbnails**: missing image/video thumbnails are generated in a background worker.
|
||||
|
||||
## First run bootstrap
|
||||
|
||||
On a fresh data directory, visit `/register` to create the first account. That first user becomes
|
||||
the instance admin and normal registration closes after bootstrap. Admins can create copyable invite
|
||||
links from `/admin/users`.
|
||||
|
||||
The env admin token still exists as emergency fallback access. Set `WARPBOX_ADMIN_TOKEN` and use it
|
||||
at `/admin/login` if you need to recover access without a user session.
|
||||
The env admin token exists as emergency fallback access. Set `WARPBOX_ADMIN_TOKEN` and use it at
|
||||
`/admin/login` if you need to recover access without a user session.
|
||||
|
||||
## Uploads
|
||||
|
||||
Browser uploads use Warpbox native resumable uploads by default. Resumable behavior is configurable
|
||||
from `/admin/settings`, including enable/disable, chunk size, retention, and whether chunks use the
|
||||
default local temp path or a custom local path such as a fast SSD. When all chunks arrive, Warpbox
|
||||
returns the share link immediately and marks files as `Processing` until the background finalizer
|
||||
streams them into the selected storage backend. Draft chunks are deleted once finalization succeeds.
|
||||
Expired uploading drafts are cleaned after the configured retention window; sessions already in
|
||||
`Processing` are protected from cleanup while finalization is running.
|
||||
|
||||
### Anonymous uploads
|
||||
|
||||
Anonymous uploads return a private management link at creation time. Keep that link secret: anyone
|
||||
with it can delete the entire upload box. The raw delete token is not stored and cannot be recovered
|
||||
later. Browser uploads show `Open box` and `Copy URL` as the primary actions, with a smaller
|
||||
`Manage or delete this upload` link in the completion panel.
|
||||
|
||||
### `curl` and ShareX
|
||||
|
||||
```bash
|
||||
# Terminal-friendly output: one plain box URL.
|
||||
curl -F file=@./report.pdf http://localhost:8080/api/v1/upload
|
||||
|
||||
# JSON output with boxUrl, thumbnailUrl, manageUrl, deleteUrl, zipUrl, and file entries.
|
||||
curl -F sharex=@./screenshot.png \
|
||||
-H 'Accept: application/json' \
|
||||
http://localhost:8080/api/v1/upload
|
||||
```
|
||||
|
||||
The upload endpoint accepts multipart fields named `file` and `sharex`. ShareX users can start from
|
||||
`examples/sharex/warpbox-anonymous.sxcu`; update `RequestURL` to match your instance URL.
|
||||
Authenticated uploads (your account's limits) add an `Authorization: Bearer <token>` header mint a
|
||||
token under **Account → Access tokens**. The JSON response uses ShareX placeholders `{json:boxUrl}`
|
||||
(URL), `{json:thumbnailUrl}` (thumbnail), `{json:deleteUrl}` (deletion), and `{json:error}` (error
|
||||
message).
|
||||
|
||||
### Grouping multiple files into one box (`X-Warpbox-Batch`)
|
||||
|
||||
By default every uploaded file becomes its own box. To put several files in a **single** box, send
|
||||
the opt-in `X-Warpbox-Batch` header: requests that share the same header value (scoped per account,
|
||||
or per IP for anonymous uploads) within 20s are appended to the same box. This lets a multi-file
|
||||
ShareX selection which ShareX sends as separate back-to-back requests land as one shareable link.
|
||||
The shipped `.sxcu` sets `X-Warpbox-Batch: sharex`; remove that header for one box per file. Requests
|
||||
without the header behave exactly as before.
|
||||
|
||||
### Resumable API flow
|
||||
|
||||
Custom clients can use the resumable JSON API for large files:
|
||||
|
||||
```bash
|
||||
# 1. Create a resumable session from file metadata.
|
||||
curl -s http://localhost:8080/api/v1/uploads/resumable \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"files":[{"name":"large.bin","size":1048576,"contentType":"application/octet-stream"}],"expiresMinutes":1440}'
|
||||
|
||||
# 2. Upload exact-sized chunks using the returned sessionId, file id, and chunkSize.
|
||||
dd if=./large.bin bs=8388608 count=1 skip=0 2>/dev/null | \
|
||||
curl -X PUT --data-binary @- \
|
||||
http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/files/FILE_ID/chunks/0
|
||||
|
||||
# 3. Complete the session after all chunks are present.
|
||||
curl -X POST -H 'Accept: application/json' \
|
||||
http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/complete
|
||||
```
|
||||
|
||||
The complete response is the same JSON shape as `POST /api/v1/upload`, including `boxUrl`,
|
||||
`manageUrl`, `deleteUrl`, and file URLs. Send `Authorization: Bearer <token>` on every resumable
|
||||
request to upload as an account.
|
||||
|
||||
## Accounts and admin
|
||||
|
||||
- `/register` bootstraps the first admin account only when no users exist.
|
||||
- `/login` and `/logout` provide cookie-based web sessions.
|
||||
- `/app` is the personal dashboard for logged-in users, showing owned boxes, storage usage, upload
|
||||
history, and flat collections. Uploading still happens from the homepage.
|
||||
- `/admin` shows overview metrics: boxes, files, storage, recent uploads, protected/expired boxes.
|
||||
- `/admin/files` is a recent upload table with view and delete actions.
|
||||
- `/admin/users` lets admins create invite links, disable/reactivate users, generate reset links,
|
||||
view storage/daily usage, and set per-user storage quota overrides.
|
||||
- `/admin/settings` controls anonymous uploads, anonymous max upload size, daily upload caps, default
|
||||
user storage quota, and usage retention.
|
||||
- `/admin/storage` manages the built-in local file backend and S3-compatible bucket backends.
|
||||
- `/admin/bans` manages manual IP/CIDR bans and optional automatic bans for suspicious probes and
|
||||
repeated login failures. Auto-ban is off by default and configured from the admin UI.
|
||||
|
||||
Logged-in browser uploads from `/` use `POST /api/v1/upload`, and the resulting box is stored with
|
||||
owner and optional collection metadata. Admin users are exempt from the global max upload size on the
|
||||
homepage upload flow.
|
||||
|
||||
Email delivery is intentionally deferred. Invite and reset links are copyable today; future SMTP
|
||||
support will power public forgot-password and optional email delivery.
|
||||
|
||||
## Emoji reaction packs
|
||||
|
||||
File reactions use emoji packs from the runtime data directory, not from the application code. By
|
||||
default that means `./data/emoji`; if you change `WARPBOX_DATA_DIR`, use
|
||||
`$WARPBOX_DATA_DIR/emoji` instead.
|
||||
default that means `./data/emoji`; if you change `WARPBOX_DATA_DIR`, use `$WARPBOX_DATA_DIR/emoji`
|
||||
instead.
|
||||
|
||||
Each folder under `./data/emoji` becomes one emoji tab in the reaction picker. Put image files
|
||||
directly inside the pack folder:
|
||||
@@ -76,35 +215,30 @@ data/
|
||||
├── files/
|
||||
├── logs/
|
||||
└── emoji/
|
||||
├── openmoji/
|
||||
│ ├── 1F600.svg
|
||||
│ ├── 1F44D.svg
|
||||
│ └── 2764.svg
|
||||
├── pixel-pack/
|
||||
│ ├── happy.webp
|
||||
│ ├── fire.webp
|
||||
│ └── star.webp
|
||||
└── custom-work/
|
||||
├── approved.png
|
||||
└── shipped.png
|
||||
├── openmoji/
|
||||
│ ├── 1F600.svg
|
||||
│ ├── 1F44D.svg
|
||||
│ └── 2764.svg
|
||||
├── pixel-pack/
|
||||
│ ├── happy.webp
|
||||
│ ├── fire.webp
|
||||
│ └── star.webp
|
||||
└── custom-work/
|
||||
├── approved.png
|
||||
└── shipped.png
|
||||
```
|
||||
|
||||
In this example, the picker shows tabs named `Openmoji`, `Pixel pack`, and `Custom work`.
|
||||
Supported emoji image extensions are `.svg`, `.webp`, `.png`, `.jpg`, `.jpeg`, and `.gif`.
|
||||
In this example, the picker shows tabs named `Openmoji`, `Pixel pack`, and `Custom work`. Supported
|
||||
emoji image extensions are `.svg`, `.webp`, `.png`, `.jpg`, `.jpeg`, and `.gif`.
|
||||
|
||||
For one-off Go commands, run them from the backend module:
|
||||
## Deployment
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
go run ./cmd/warpbox
|
||||
```
|
||||
|
||||
## Docker / Podman
|
||||
### Docker / Podman
|
||||
|
||||
Copy the example environment file and adjust values such as `WARPBOX_BASE_URL` and
|
||||
`WARPBOX_ADMIN_TOKEN` before running the container:
|
||||
|
||||
Copy the example [docker-compose.example.yml](./docker-compose.example.yml) to [docker-compose.yml](./docker-compose.yml), modify as need-be
|
||||
`WARPBOX_ADMIN_TOKEN` before running the container. Copy the example
|
||||
[docker-compose.example.yml](./docker-compose.example.yml) to
|
||||
[docker-compose.yml](./docker-compose.yml), modify as need-be:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
@@ -112,20 +246,19 @@ docker compose -f docker-compose.yml up --build
|
||||
```
|
||||
|
||||
The compose example also works with Podman compatible compose tools. Its data volume uses
|
||||
`./data:/data:Z` for SELinux relabeling, and the container overrides runtime paths to use
|
||||
`/data`, `/app/static`, and `/app/templates`.
|
||||
`./data:/data:Z` for SELinux relabeling, and the container overrides runtime paths to use `/data`,
|
||||
`/app/static`, and `/app/templates`. The image exposes the health endpoint `/health`, which Docker
|
||||
and compose healthchecks use.
|
||||
|
||||
The image exposes the health endpoint: `/health`. Docker and compose healthchecks use it.
|
||||
|
||||
## Reverse Proxy Security
|
||||
### Reverse proxy security
|
||||
|
||||
Warpbox uses the resolved client IP for anonymous limits, manual bans, and automatic bans. The
|
||||
default behavior trusts `X-Forwarded-For` and `X-Real-IP` so a normal Caddy reverse proxy works
|
||||
without extra setup. For hardened deployments where the app port might be reachable from more than
|
||||
one network, set `WARPBOX_TRUSTED_PROXIES` to trusted proxy IPs/CIDRs. See
|
||||
without extra setup. For hardened deployments where the app port might be reachable from more than one
|
||||
network, set `WARPBOX_TRUSTED_PROXIES` to trusted proxy IPs/CIDRs. See
|
||||
[SECURITY_PROXY.md](./SECURITY_PROXY.md) for Caddy examples and Docker/systemd notes.
|
||||
|
||||
## Systemd
|
||||
### Systemd
|
||||
|
||||
Build the binary on the server, create a dedicated user, and keep runtime data outside the repo:
|
||||
|
||||
@@ -187,7 +320,23 @@ sudo systemctl status warpbox
|
||||
|
||||
Put Caddy in front of `127.0.0.1:6070` and keep the Warpbox port closed to the public internet.
|
||||
|
||||
## Layout
|
||||
## Runtime data
|
||||
|
||||
Warpbox keeps local runtime data under the configured data directory:
|
||||
|
||||
- `data/files/{box_id}/@each@{file_id}.ext` - uploaded file contents when the local backend is selected.
|
||||
- `data/files/{box_id}/@thumb@{file_id}.jpg` - generated previews when the local backend is selected.
|
||||
- `data/tmp/uploads/{session_id}` - temporary local chunks for unfinished resumable uploads when
|
||||
the default chunk mode is selected.
|
||||
- `data/db/warpbox.bbolt` - bbolt metadata database for boxes, file records, users, sessions,
|
||||
invites, collections, upload policy settings, daily usage records, manual bans, automatic ban
|
||||
settings, abuse counters, and malicious path rules.
|
||||
- `data/logs/{YYYY-MM-DD}.log` - JSONL logs, one event per line.
|
||||
|
||||
Uploaded file content, thumbnails, and private box metadata use the selected storage backend. The
|
||||
bbolt database and JSON logs always remain local under `./data/db` and `./data/logs`.
|
||||
|
||||
## Project layout
|
||||
|
||||
- `backend/cmd/warpbox` - main application entry point.
|
||||
- `backend/libs/config` - environment-backed configuration.
|
||||
@@ -195,7 +344,7 @@ Put Caddy in front of `127.0.0.1:6070` and keep the Warpbox port closed to the p
|
||||
- `backend/libs/handlers` - HTTP handlers for pages, API, health, static files.
|
||||
- `backend/libs/jobs` - background job registration and job loop definitions.
|
||||
- `backend/libs/middleware` - request logging, recovery, security headers, gzip, request IDs.
|
||||
- `backend/libs/services` - business logic boundaries, starting with upload limits.
|
||||
- `backend/libs/services` - business logic boundaries.
|
||||
- `backend/libs/helpers` - small reusable helpers.
|
||||
- `backend/libs/web` - Go template renderer.
|
||||
- `backend/templates` - server-rendered Go templates.
|
||||
@@ -204,118 +353,7 @@ Put Caddy in front of `127.0.0.1:6070` and keep the Warpbox port closed to the p
|
||||
- `scripts/env/dev.env.example` - tracked development environment template.
|
||||
- `scripts/env/dev.env` - local development environment, ignored by git.
|
||||
|
||||
## Stage 2 Operator Tools
|
||||
## Static asset policy
|
||||
|
||||
- `/admin/login` - token-based admin login.
|
||||
- `/admin` - overview metrics: boxes, files, storage, recent uploads, protected/expired boxes.
|
||||
- `/admin/files` - recent upload table with view and delete actions.
|
||||
- Expired boxes and boxes that have reached their download limit are cleaned on startup and then every `WARPBOX_CLEANUP_EVERY` when `WARPBOX_CLEANUP_ENABLED=true`.
|
||||
- Missing image/video thumbnails are generated in a background worker every `WARPBOX_THUMBNAIL_EVERY` when `WARPBOX_THUMBNAIL_ENABLED=true`.
|
||||
|
||||
## Stage 3 Anonymous Integrations
|
||||
|
||||
Anonymous uploads now return a private management link at creation time. Keep that link secret:
|
||||
anyone with it can delete the entire upload box. The raw delete token is not stored and cannot be
|
||||
recovered later.
|
||||
|
||||
Browser uploads still show `Open box` and `Copy URL` as the primary actions, with a smaller
|
||||
`Manage or delete this upload` link in the completion panel.
|
||||
|
||||
Curl and custom uploaders can use the same endpoint:
|
||||
|
||||
```bash
|
||||
# Terminal-friendly output: one plain box URL.
|
||||
curl -F file=@./report.pdf http://localhost:8080/api/v1/upload
|
||||
|
||||
# JSON output with boxUrl, thumbnailUrl, manageUrl, deleteUrl, zipUrl, and file entries.
|
||||
curl -F sharex=@./screenshot.png \
|
||||
-H 'Accept: application/json' \
|
||||
http://localhost:8080/api/v1/upload
|
||||
```
|
||||
|
||||
The upload endpoint accepts multipart fields named `file` and `sharex`. ShareX users can start
|
||||
from `examples/sharex/warpbox-anonymous.sxcu`; update `RequestURL` to match your instance URL.
|
||||
Authenticated uploads (your account's limits) add an `Authorization: Bearer <token>` header — mint
|
||||
a token under **Account → Access tokens**. The JSON response uses ShareX placeholders
|
||||
`{json:boxUrl}` (URL), `{json:thumbnailUrl}` (thumbnail), `{json:deleteUrl}` (deletion), and
|
||||
`{json:error}` (error message).
|
||||
|
||||
### Grouping multiple files into one box (`X-Warpbox-Batch`)
|
||||
|
||||
By default every uploaded file becomes its own box. To put several files in a **single** box, send
|
||||
the opt-in `X-Warpbox-Batch` header: requests that share the same header value (scoped per account,
|
||||
or per IP for anonymous uploads) within 20s are appended to the same box. This lets a multi-file
|
||||
ShareX selection — which ShareX sends as separate back-to-back requests — land as one shareable
|
||||
link. The shipped `.sxcu` sets `X-Warpbox-Batch: sharex`; remove that header for one box per file.
|
||||
Requests without the header behave exactly as before.
|
||||
|
||||
### Resumable API flow
|
||||
|
||||
Custom clients can use the resumable JSON API for large files:
|
||||
|
||||
```bash
|
||||
# 1. Create a resumable session from file metadata.
|
||||
curl -s http://localhost:8080/api/v1/uploads/resumable \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"files":[{"name":"large.bin","size":1048576,"contentType":"application/octet-stream"}],"expiresMinutes":1440}'
|
||||
|
||||
# 2. Upload exact-sized chunks using the returned sessionId, file id, and chunkSize.
|
||||
dd if=./large.bin bs=8388608 count=1 skip=0 2>/dev/null | \
|
||||
curl -X PUT --data-binary @- \
|
||||
http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/files/FILE_ID/chunks/0
|
||||
|
||||
# 3. Complete the session after all chunks are present.
|
||||
curl -X POST -H 'Accept: application/json' \
|
||||
http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/complete
|
||||
```
|
||||
|
||||
The complete response is the same JSON shape as `POST /api/v1/upload`, including `boxUrl`,
|
||||
`manageUrl`, `deleteUrl`, and file URLs. Send `Authorization: Bearer <token>` on every resumable
|
||||
request to upload as an account.
|
||||
|
||||
## Stage 4 Accounts + Personal Boxes
|
||||
|
||||
- `/register` bootstraps the first admin account only when no users exist.
|
||||
- `/login` and `/logout` provide cookie-based web sessions.
|
||||
- `/app` is the personal dashboard for logged-in users, showing owned boxes, storage usage, upload
|
||||
history, and flat collections. Uploading still happens from the homepage.
|
||||
- `/admin/users` lets admins create invite links, disable/reactivate users, and generate reset links.
|
||||
- Logged-in browser uploads from `/` still use `POST /api/v1/upload`, but the resulting box is
|
||||
stored with owner and optional collection metadata.
|
||||
- Admin users are exempt from the global max upload size on the homepage upload flow. Future
|
||||
per-user quotas should apply to this same upload path rather than creating a second uploader.
|
||||
- `/admin/settings` controls anonymous uploads, anonymous max upload size, daily upload caps, default
|
||||
user storage quota, and usage retention.
|
||||
- `/admin/users` shows storage/daily usage and lets admins set per-user storage quota overrides.
|
||||
- `/admin/storage` manages the built-in local file backend and S3-compatible bucket backends.
|
||||
- `/admin/bans` manages manual IP/CIDR bans and optional automatic bans for suspicious probes and
|
||||
repeated login failures. Auto-ban is off by default and configured from the admin UI.
|
||||
- Upload limits now include daily bytes, daily box counts, active box counts, short-window request
|
||||
limits, max expiration days, local storage capacity in GB, and per-user policy overrides.
|
||||
- Uploaded file content, thumbnails, and private box metadata use the selected storage backend.
|
||||
The bbolt database and JSON logs remain local under `./data/db` and `./data/logs`.
|
||||
- Anonymous uploads, ShareX uploads, unlisted public box links, password protection, expiry, delete
|
||||
tokens, thumbnails, and cleanup continue to work as before.
|
||||
|
||||
Email delivery is intentionally deferred. Invite and reset links are copyable today; future SMTP
|
||||
support will power public forgot-password and optional email delivery.
|
||||
|
||||
## Runtime Data
|
||||
|
||||
Warpbox keeps local runtime data under the configured data directory:
|
||||
|
||||
- `data/files/{box_id}/@each@{file_id}.ext` - uploaded file contents when the local backend is selected.
|
||||
- `data/files/{box_id}/@thumb@{file_id}.jpg` - generated previews when the local backend is selected.
|
||||
- `data/tmp/uploads/{session_id}` - temporary chunks for unfinished resumable uploads.
|
||||
- `data/db/warpbox.bbolt` - bbolt metadata database for boxes and file records.
|
||||
- `data/db/warpbox.bbolt` also stores users, sessions, invites, and collections.
|
||||
- `data/db/warpbox.bbolt` stores upload policy settings and daily usage records keyed by plain IP
|
||||
for anonymous uploads and user ID for signed-in uploads.
|
||||
- `data/db/warpbox.bbolt` stores manual bans, automatic ban settings, abuse counters, and malicious
|
||||
path rules.
|
||||
- `data/logs/{YYYY-MM-DD}.log` - JSONL logs, one event per line.
|
||||
|
||||
## Static Asset Policy
|
||||
|
||||
The static handler sets long-lived immutable caching for images, video, audio, and fonts, shorter caching for CSS/JS, and gzip compression for compressible responses.
|
||||
The static handler sets long-lived immutable caching for images, video, audio, and fonts, shorter
|
||||
caching for CSS/JS, and gzip compression for compressible responses.
|
||||
|
||||
Reference in New Issue
Block a user