mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
- Create `docs/storage-tab-design.md` covering StorageService architecture - Update `docs/storage-r2.md` to reflect the new provider pattern - Expand Kind 22242 details in `docs/nostr-event-schemas.md`
92 lines
4.5 KiB
Markdown
92 lines
4.5 KiB
Markdown
# Cloudflare R2 integration (r2Service)
|
|
|
|
## Purpose and scope
|
|
|
|
`js/services/r2Service.js` is the specialized provider handler for Cloudflare R2 uploads. While the new **Storage Tab** (powered by `StorageService`) manages the secure storage of credentials, `r2Service` is responsible for:
|
|
|
|
- Uploading the selected video/HLS asset via multipart S3 uploads.
|
|
- Verifying public access via the configured Public Bucket URL.
|
|
- Publishing the resulting public URL into the video note payload.
|
|
|
|
> **Architecture Note:** For the high-level design of credential storage, encryption, and the provider adapter pattern, please refer to [`docs/storage-tab-design.md`](./storage-tab-design.md).
|
|
|
|
## Assets stored in R2
|
|
R2 is used as the URL-first playback source. The upload path supports a single file per upload, but
|
|
file types include:
|
|
|
|
- Video files (MP4/WebM/MOV/MKV/MPG/MPEG).
|
|
- HLS/DASH assets (manifest `.m3u8`/`.mpd` and segment files like `.ts`/`.m4s`).
|
|
- Related static media if the operator chooses to upload them separately (images, subtitles such as
|
|
`.vtt`/`.srt`), which benefit from cache-friendly headers set in the upload flow.
|
|
|
|
The object key format is generated by `buildR2Key()` in `js/r2.js` and looks like:
|
|
`u/<npub>/<YYYY>/<MM>/<slug>.<ext>`, which keeps uploads scoped by user and month.
|
|
|
|
## Setup Guide: Getting your Cloudflare Credentials
|
|
|
|
To enable R2 uploads, you must provide Cloudflare S3-compatible credentials and configure your bucket for public access and CORS.
|
|
|
|
### Step 1: Create Bucket & Enable Public Access
|
|
1. Log in to the **Cloudflare Dashboard**.
|
|
2. Navigate to **R2** -> **Create Bucket**.
|
|
3. In the bucket settings, enable **Public Access** (R2.dev subdomain) or connect a custom domain.
|
|
4. Copy the **Public Bucket URL** (e.g., `https://pub-xxxxxx.r2.dev`).
|
|
|
|
### Step 2: Configure CORS
|
|
Manually add a CORS policy in the bucket settings to allow uploads from your app's origin (or `*`).
|
|
(See `content/upload-content.md` for the recommended JSON configuration).
|
|
|
|
### Step 3: Create S3 Credentials
|
|
1. In the R2 dashboard, click **Manage R2 API Tokens**.
|
|
2. Click **Create API Token**.
|
|
3. Select **Object Read & Write** permissions (Minimal).
|
|
4. Copy the **Account ID**, **Access Key ID**, and **Secret Access Key**.
|
|
|
|
### Step 4: Configure the App
|
|
1. Open the **Storage Tab** (in Profile or Upload modal).
|
|
2. Add a new connection and select **Cloudflare R2**.
|
|
3. Enter the **Account ID**, **Access Key ID**, **Secret Access Key**, and **Public Bucket URL**.
|
|
4. Click **Verify & Save**.
|
|
|
|
The app will attempt to upload a small test file to verify the credentials and public access configuration.
|
|
|
|
## Upload lifecycle
|
|
|
|
1. **Credential Retrieval:**
|
|
- When an upload starts, `UploadModal` retrieves the decrypted credentials from `StorageService`.
|
|
- `StorageService` handles the NIP-44/04 decryption of the Master Key and subsequent decryption of the R2 connection payload.
|
|
|
|
2. **Upload Execution:**
|
|
- `r2Service.multipartUpload()` uses the standard AWS SDK commands (`CreateMultipartUpload`, `UploadPart`, etc.) via the generic `makeR2Client` adapter.
|
|
- The adapter automatically constructs the R2 endpoint (`https://<accountId>.r2.cloudflarestorage.com`) using the stored `accountId`.
|
|
|
|
3. **Publish:**
|
|
- On success, `publishVideoNote()` is called with the hosted URL, enabling URL-first playback.
|
|
|
|
## Configuration keys
|
|
|
|
R2 credentials are no longer stored in plain `bitvidSettings`. They are encapsulated within the `StorageService` data model.
|
|
|
|
**R2 Connection Profile (Encrypted):**
|
|
- `provider`: `cloudflare_r2`
|
|
- `accountId`: Cloudflare account ID.
|
|
- `accessKeyId`: S3 access key ID.
|
|
- `secretAccessKey`: S3 secret access key.
|
|
- `bucket`: The target bucket name.
|
|
|
|
**Metadata (Plaintext):**
|
|
- `baseDomain`: The Public Bucket URL (e.g., `https://pub-xxxx.r2.dev`).
|
|
- `defaultForUploads`: Boolean flag indicating if this is the active upload target.
|
|
|
|
## Environment / global flags
|
|
- `globalThis.__BITVID_DISABLE_NETWORK_IMPORTS__`: disables the AWS SDK network import used by the
|
|
R2 S3 client loader (`js/storage/r2-s3.js`). When true, uploads will fail with a load error until
|
|
the SDK is bundled or otherwise provided.
|
|
|
|
## Security considerations
|
|
|
|
- **Encrypted Storage:** All sensitive keys (`accessKeyId`, `secretAccessKey`) are encrypted at rest using the user's Nostr signer.
|
|
- **Session Security:** Decrypted keys exist in memory only during the active session.
|
|
- **Public Exposure:** The generated playback URLs are public. Ensure your bucket permissions match your intent.
|
|
- **Least Privilege:** Always use "Object Read & Write" tokens rather than Admin tokens.
|