diff --git a/README.md b/README.md index be90b77..ca1cd50 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,29 @@ Little nodejs + mongodb app that I hack together with ChatGPT and Cursor to keep ![Oscars Pool 2026](https://raw.githubusercontent.com/quoije/oscars-pool/refs/heads/prod/img/preview.png) ## Features -- User accounts: register, login, JWT auth -- 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 (optional) -- Admin movie management: add, edit (optionally refresh from OMDb), delete -- 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 -- App version display (footer) managed from Admin panel (no GitHub dependency) + +### User Features +- **User accounts**: register, login, JWT authentication +- **Optional registration verification**: via `DOG_NAMES` environment variable (if unset, verification is skipped) +- **Movie tracking**: mark nominees/movies as watched (per user), with watched date +- **Movie browsing**: browse movies by Oscar year + API for available years +- **Movie details**: pulled from OMDb (title/plot/rating/poster) via IMDb ID (optional) +- **User statistics**: watched count, points from movies watched and Oscar picks, leaderboard +- **Video player**: 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) +- **Oscar picks**: make picks for each category, auto-save on selection +- **Scores**: view leaderboard with correct/incorrect pick counts, detailed breakdown per user +- **View all picks**: see everyone's picks in a comparison view + +### Admin Features +- **Movie management**: add, edit (optionally refresh from OMDb), delete movies +- **User management**: view users, reset passwords (temp password + forced change on next login) +- **Oscar category management**: create, edit, delete categories with nominees, bulk delete +- **Winner management**: mark winners for each category (can clear winners) +- **Global settings**: active Oscar year, "completion" modal content for checklist +- **Database backup/restore**: create backups and restore from backup files +- **App version control**: manage app version display (footer) from admin panel (no GitHub dependency) +- **Player UI settings**: control player page admin status display ## Setup Create a `.env` file at the project root (same folder as `package.json`). @@ -52,7 +63,13 @@ This app uses **MongoDB** via Mongoose. Provide a connection string in `MONGO_UR - `MONGO_URI` examples: - Atlas: `mongodb+srv://USER:PASS@cluster0.XXXX.mongodb.net/?retryWrites=true&w=majority` - Local: `mongodb://127.0.0.1:27017/` -- Collections are created/managed automatically from the models in `models/` (e.g. `User`, `Movie`, `Setting`, `PlaybackProgress`). +- Collections are created/managed automatically from the models in `models/`: + - `User` - user accounts + - `Movie` - Oscar-nominated movies + - `OscarCategory` - Oscar categories with nominees + - `OscarPick` - user picks for each category + - `Setting` - global settings (active year, etc.) + - `PlaybackProgress` - video playback progress per user ## More `.env` options The app also reads these environment variables (all optional): @@ -70,9 +87,5 @@ Notes: - 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: +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 setup and usage instructions. -```bash -export MONGO_DB_NAME="oscars-pool" # if your MONGO_URI doesn't include a / path -``` diff --git a/python_video_server/README.md b/python_video_server/README.md index c188ba7..8091ee3 100644 --- a/python_video_server/README.md +++ b/python_video_server/README.md @@ -168,10 +168,36 @@ sudo -E python -m python_video_server.letsencrypt renew --production ## Endpoints - `POST /api/video/session` - Sets `video_auth` cookie (send `Authorization: Bearer `). + Sets `video_auth` cookie (send `Authorization: Bearer `). Returns `204 No Content`. - `GET|HEAD /api/video/{movieId}` - Streams the movie file (supports `Range: bytes=...`). + Streams the movie file (supports `Range: bytes=...`). Returns `200` (full file) or `206` (partial content) or `404` (not found). -- `GET /healthz` +- `GET /healthz` + Health check endpoint. Returns JSON with server status, video files directory, MongoDB database name, and OpenSSL version. + +## Functions Reference + +### Public Endpoints +- `create_video_session(request, response, authorization)` - POST `/api/video/session` - Creates video authentication cookie +- `stream_video(movie_id, request, authorization, range)` - GET|HEAD `/api/video/{movie_id}` - Streams video file with Range support +- `healthz()` - GET `/healthz` - Health check endpoint + +### Helper Functions (Internal) +- `_env_str(name, default)` - Get environment variable as string +- `_jwt_secret()` - Get JWT secret from environment +- `_mongo_uri()` - Get MongoDB connection URI from environment +- `_mongo_db_name()` - Get MongoDB database name (from env or parsed from URI) +- `_env_int(name, default)` - Get environment variable as integer +- `_video_files_dir()` - Get video files directory path (default: `./public/video`) +- `_parse_bearer(authorization)` - Parse Bearer token from Authorization header +- `_is_safe_relative_file(path)` - Security check: validates file path is safe (no directory traversal) +- `_guess_content_type(file_path)` - Guess MIME content type from file extension +- `_parse_range(range_header, file_size)` - Parse HTTP Range header into start/end tuple +- `_file_iter(path, start, end, chunk_size)` - Generator that yields file chunks for streaming +- `_get_token(request, authorization)` - Get authentication token from cookie, header, or query string (priority order) +- `_verify_token(token)` - Verify JWT token and return decoded payload +- `_mongo_client()` - Create MongoDB client with TLS/connection timeout configuration +- `_mongo_client_cached()` - Cached MongoDB client (LRU cache, reused across requests) +- `_shutdown()` - Event handler for graceful MongoDB client shutdown