From 9936940c9e129b3f214b70fd60a5b749382f52cf Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 22 Dec 2025 21:27:50 +0000 Subject: [PATCH 1/2] Refactor READMEs and clarify optional features Co-authored-by: mathieumoran1 --- README.md | 12 ++++-- python_video_server/README.md | 80 ++++------------------------------- 2 files changed, 16 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 151b7a3..821ff58 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ Little nodejs + mongodb app that I hack together with ChatGPT and Cursor to keep ## Features - User accounts: register, login, JWT auth -- Simple registration verification via `DOG_NAMES` +- Optional registration "verification" via `DOG_NAMES` (if unset, verification is skipped) - Mark nominees as watched (per user), with watched date - Browse movies by Oscar year + API for available years - User stats: watched count/ratio and watched titles -- Movie details pulled from OMDb (title/plot/rating/poster) via IMDb ID +- Movie details pulled from OMDb (title/plot/rating/poster) via IMDb ID (optional) - Admin movie management: add, edit (optionally refresh from OMDb), delete -- Built-in player page with multiple source options (VOD link, direct video file, embed) +- Built-in player page with multiple source options (VOD link, direct video URL, embed, or server file) - Resume playback: per-user playback progress saving (time/duration) - Global settings: active Oscar year, “completion” modal content for checklist - Password flows: admin temp password reset + forced change on next login @@ -35,7 +35,7 @@ MONGO_URI=mongodb://127.0.0.1:27017/oscars-pool # MongoDB connection string JWT_SECRET=replace-with-a-random-string # JWT signing secret (auth) # optional -DOG_NAMES=woof,WOOF,Woof # simple registration "verification" +DOG_NAMES=woof,WOOF,Woof # registration verification answers (comma-separated) OMDB_API=your_omdb_key # OMDb API key (movie info) ``` @@ -65,6 +65,10 @@ VIDEO_SESSION_MAX_AGE_SECONDS=28800 # video_auth cookie max-age (default: 8h) MOVIES_CACHE_TTL_MS=30000 # movies route cache TTL (default: 30000ms) ``` +Notes: +- The server serves the UI from `public/` (open `http://localhost:5000` by default). +- If you use `video_file` in a movie record, it must be a **relative path** under `VIDEO_FILES_DIR` (the backend blocks traversal/absolute paths). + ## Python video server (optional) There is also a standalone Python server in `python_video_server/` that mirrors `/api/video/:id` (Range streaming + JWT + Mongo). See `python_video_server/README.md` for full instructions. In addition to `MONGO_URI` and `JWT_SECRET`, you may need: diff --git a/python_video_server/README.md b/python_video_server/README.md index cf6151f..7288307 100644 --- a/python_video_server/README.md +++ b/python_video_server/README.md @@ -27,7 +27,7 @@ export CORS_ALLOW_ORIGINS="https://your-app.example.com" # default: "*" # Cookie behavior for /api/video/session export VIDEO_COOKIE_SAMESITE="Lax" # Lax|Strict|None (default: Lax) -# Mongo TLS / connectivity troubleshooting (Atlas, weird hosts, etc.) +# Mongo TLS / connectivity troubleshooting (Atlas, odd hosts, etc.) export MONGO_TLS_CA_FILE="/path/to/ca.pem" # prefer a valid CA bundle export MONGO_TLS_FORCE_TLS12="1" # force TLS 1.2 if TLS 1.3 breaks export MONGO_TLS_INSECURE="1" # NOT recommended; debug only @@ -36,83 +36,19 @@ export MONGO_CONNECT_TIMEOUT_MS="8000" export MONGO_SOCKET_TIMEOUT_MS="20000" ``` -## HTTPS (Let’s Encrypt, Python-only) +## HTTPS (optional) -This server can be served over HTTPS by running `uvicorn` with `--ssl-certfile` and `--ssl-keyfile`. -To obtain/renew a trusted cert from Let’s Encrypt **without installing system certbot**, this repo includes a small wrapper that uses the **`certbot` Python package**. - -### 1) Issue a certificate (HTTP-01 standalone) - -Requirements: -- Your domain’s DNS `A/AAAA` records must point to this machine. -- Port **80** must be reachable from the internet for the ACME challenge. +You can run behind a reverse proxy/ingress, or run `uvicorn` with TLS directly: ```bash -python3 -m pip install -r python_video_server/requirements.txt - -# Staging by default (recommended first). Add --production when it works. -sudo -E python3 -m python_video_server.letsencrypt certonly \ - --email you@example.com \ - --domains example.com,www.example.com -``` - -### 1b) Issue a certificate (DNS-01 manual TXT record — no port 80, no root) - -If your host already uses port **80** (or you don't have permission to bind it), use DNS-01. -This does **not** require any inbound ports on the machine, but you must be able to edit DNS for the domain. - -```bash -python3 -m pip install -r python_video_server/requirements.txt - -# Add --production when staging works. -python3 -m python_video_server.letsencrypt certonly \ - --challenge dns \ - --email you@example.com \ - --domains example.com,www.example.com -``` - -During issuance, certbot will prompt you to create a TXT record like: -- Name: `_acme-challenge.example.com` -- Type: `TXT` -- Value: (a token certbot prints) - -After it propagates, press Enter and certbot will continue. - -If you run into a situation where the prompt/token only shows up in logs, you can try the hook-based mode: - -```bash -python3 -m python_video_server.letsencrypt certonly \ - --challenge dns \ - --dns-hooks \ - --email you@example.com \ - --domains example.com,www.example.com -``` - -Certificates will be written under: -- `python_video_server/certs/config/live//fullchain.pem` -- `python_video_server/certs/config/live//privkey.pem` - -### 2) Run the video server on 443 with TLS - -```bash -sudo -E uvicorn python_video_server.server:app --host 0.0.0.0 --port 443 \ - --ssl-certfile python_video_server/certs/config/live/example.com/fullchain.pem \ - --ssl-keyfile python_video_server/certs/config/live/example.com/privkey.pem +uvicorn python_video_server.server:app --host 0.0.0.0 --port 443 \ + --ssl-certfile /path/to/fullchain.pem \ + --ssl-keyfile /path/to/privkey.pem ``` Notes: -- Binding to ports **80/443** usually requires `sudo` (or a reverse proxy / port forwarding). -- If you’re behind a proxy/ingress, keep sending `X-Forwarded-Proto: https` so `/api/video/session` sets `Secure` cookies correctly. - -### 3) Renew certificates - -```bash -# Dry-run renewal (safe) -sudo -E python3 -m python_video_server.letsencrypt renew --dry-run - -# Actual renew (typically run via cron/systemd timer) -sudo -E python3 -m python_video_server.letsencrypt renew --production -``` +- If you’re behind a proxy, forward `X-Forwarded-Proto: https` so `/api/video/session` can set `Secure` cookies correctly. +- This repo includes `python_video_server/letsencrypt.py` as an optional helper for cert issuance/renewal (kept intentionally lightweight here). ## Endpoints -- 2.54.0 From a441fc9e651b3e940c4a1937fd61ab6ecce92061 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 22 Dec 2025 21:30:20 +0000 Subject: [PATCH 2/2] Add video auth details and Let's Encrypt helper Co-authored-by: mathieumoran1 --- python_video_server/README.md | 117 +++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/python_video_server/README.md b/python_video_server/README.md index 7288307..c188ba7 100644 --- a/python_video_server/README.md +++ b/python_video_server/README.md @@ -36,6 +36,58 @@ export MONGO_CONNECT_TIMEOUT_MS="8000" export MONGO_SOCKET_TIMEOUT_MS="20000" ``` +## Video auth / usage + +`GET /api/video/{movieId}` accepts auth in three ways (in priority order): + +1) `video_auth` cookie (best for browser `