docs: reorganize documentation structure for better context efficiency
Reorganization changes: 1. Moved from root → docs/: - QUICKSTART.md - QUICK_TEST.md - WEBRTC_TESTING_GUIDE.md 2. Created docs/archive/ and moved archival files: - COMPLETED.md (completed tasks archive) - PHASE_1.5.md (historical phase documentation) - RESOURCES.md (learning resources) - SECURITY_AUDIT.md (security audit) - ADMIN_CLI.md (CLI documentation) 3. Updated all references in: - README.md - docs/CONTEXT.md - docs/TODO.md - docs/SESSION_CONTEXT.md - docs/DEPLOYMENT.md - docs/QUICK_TEST.md Active docs/ now contains only essential files: - SESSION_CONTEXT.md (primary for context restoration) - TODO.md - CONTEXT.md - ARCHITECTURE.md - DEPLOYMENT.md - MONITORING.md - QUICKSTART.md - QUICK_TEST.md - WEBRTC_TESTING_GUIDE.md Benefits: - Reduced token usage when reading docs/ for context - Clear separation between active and archived documentation - Better organization for future maintenance
This commit is contained in:
179
docs/archive/ADMIN_CLI.md
Normal file
179
docs/archive/ADMIN_CLI.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Admin CLI & REPL — spotlight.cam
|
||||
|
||||
Administrative console for maintenance tasks inside the backend container. Provides both one‑shot commands and an interactive REPL with app context.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
- Development REPL: `docker compose exec backend npm run cli`
|
||||
- Production REPL: `docker compose exec backend-prod npm run cli`
|
||||
- One-shot examples:
|
||||
- `docker compose exec backend npm run cli -- users:list --limit 20`
|
||||
- `docker compose exec backend npm run cli -- events:checkin --username john_doe --slug warsaw-dance-2025`
|
||||
|
||||
With Makefile shortcuts:
|
||||
- `make dev-cli` / `make prod-cli`
|
||||
- `make dev-up`, `make dev-down`, `make prod-up`, `make prod-down`, rebuild variants also available
|
||||
|
||||
---
|
||||
|
||||
## REPL Features
|
||||
|
||||
- Default entry: running `npm run cli` starts a Node.js REPL with:
|
||||
- `prisma` client and `bcrypt` in context
|
||||
- Aliases: `u = prisma.user`, `e = prisma.event`, `m = prisma.match`, `ep = prisma.eventParticipant`, `r = prisma.rating`
|
||||
- Top‑level await: `await u.findMany({ take: 5 })`
|
||||
- Autocomplete (TAB) from Node REPL
|
||||
- Persistent history in `.repl_history` (best‑effort)
|
||||
- Run CLI subcommands from inside REPL:
|
||||
- `.cli users:list --limit 20`
|
||||
- `run('events:checkin --username john_doe --slug warsaw-dance-2025')`
|
||||
- Error handling: CLI errors (e.g., missing flags) do not exit the REPL; the error is printed and you can correct the command and retry.
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
### Cheatsheet
|
||||
- `repl`
|
||||
- `users:list [--limit <n>]`
|
||||
- `users:create --email <e> --username <u> --password <p> [--first <f>] [--last <l>]`
|
||||
- `users:verify --email <e>`
|
||||
- `events:list [--limit <n>]`
|
||||
- `events:details --slug <slug>`
|
||||
- `events:participants --slug <slug> [--limit <n>] [--csv]`
|
||||
- `events:import:wsdc [--dry-run] [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--limit <n>]`
|
||||
- `matches:list [--limit <n>] [--status pending|accepted|completed]`
|
||||
- `events:checkin --username <u> --slug <s>`
|
||||
- `logs:app [--lines <n>]`
|
||||
- `logs:messages [--limit <n>]`
|
||||
|
||||
### users:list
|
||||
- Description: List users
|
||||
- Options:
|
||||
- `--limit <n>`: number of rows (default: 50)
|
||||
- Examples:
|
||||
- CLI: `npm run cli -- users:list --limit 20`
|
||||
- REPL: `.cli users:list --limit 20`
|
||||
|
||||
### users:create
|
||||
- Description: Create a user
|
||||
- Required:
|
||||
- `--email <email>`
|
||||
- `--username <username>`
|
||||
- `--password <password>` (hashed with bcrypt)
|
||||
- Optional:
|
||||
- `--first <firstName>`
|
||||
- `--last <lastName>`
|
||||
- Examples:
|
||||
- CLI: `npm run cli -- users:create --email admin@example.com --username admin --password 'Secret123!'`
|
||||
- REPL: `run("users:create --email a@b.c --username admin --password 'Secret123!'")`
|
||||
|
||||
### users:verify
|
||||
- Description: Mark user email as verified and clear verification fields
|
||||
- Required:
|
||||
- `--email <email>`
|
||||
- Example: `npm run cli -- users:verify --email admin@example.com`
|
||||
|
||||
### events:list
|
||||
- Description: List events
|
||||
- Options:
|
||||
- `--limit <n>` (default: 50)
|
||||
- Example: `npm run cli -- events:list --limit 10`
|
||||
|
||||
### events:details
|
||||
- Description: Show details for a specific event by slug
|
||||
- Required:
|
||||
- `--slug <event-slug>`
|
||||
- Options:
|
||||
- `--participants <n>`: number of recent participants to show (default: 10)
|
||||
- Output: basic fields (id, slug, name, start/end, location, worldsdcId), participantsCount, optional check-in token, relation counts, event chat room id and message count, and up to N recent participants
|
||||
- Examples:
|
||||
- `npm run cli -- events:details --slug warsaw-dance-2025`
|
||||
- `npm run cli -- events:details --slug warsaw-dance-2025 --participants 25`
|
||||
|
||||
### matches:list
|
||||
- Description: List matches
|
||||
- Options:
|
||||
- `--limit <n>` (default: 50)
|
||||
- `--status <pending|accepted|completed>` filter
|
||||
- Example: `npm run cli -- matches:list --status accepted --limit 20`
|
||||
|
||||
### events:checkin
|
||||
- Description: Attach user to event by username and event slug (simulate QR check-in)
|
||||
- Required:
|
||||
- `--username <username>`
|
||||
- `--slug <event-slug>`
|
||||
- Behavior: Upserts into `event_participants` (idempotent)
|
||||
- Example: `npm run cli -- events:checkin --username john_doe --slug warsaw-dance-2025`
|
||||
|
||||
### events:participants
|
||||
- Description: List participants for an event by slug
|
||||
- Required:
|
||||
- `--slug <event-slug>`
|
||||
- Options:
|
||||
- `--limit <n>`: number of rows (default: 100)
|
||||
- `--csv`: output as CSV (stdout)
|
||||
- Output: eventId, slug, userId, username, email, firstName, lastName, country, city, joinedAt
|
||||
- Examples:
|
||||
- `npm run cli -- events:participants --slug warsaw-dance-2025 --limit 50`
|
||||
- `npm run cli -- events:participants --slug warsaw-dance-2025 --limit 200 --csv > participants.csv`
|
||||
|
||||
### events:import:wsdc
|
||||
- Description: Import events from worldsdc.com.
|
||||
- Sources:
|
||||
- `--source list`: parse Event List page (includes Event Location + Country)
|
||||
- `--source calendar`: parse Events Calendar page (title/start/end/url)
|
||||
- `--source auto` (default): try calendar first, then list if calendar parsing yields no events
|
||||
- Options:
|
||||
- `--dry-run`: show what would be created without writing to DB
|
||||
- `--since YYYY-MM-DD`: only events on/after date
|
||||
- `--until YYYY-MM-DD`: only events on/before date
|
||||
- `--limit <n>`: limit considered items after filtering
|
||||
- `--update-missing-location`: when an event already exists and its `location` is empty/"Unknown", update it from the imported source (list recommended)
|
||||
- Examples:
|
||||
- `npm run cli -- events:import:wsdc --dry-run --since 2024-01-01 --until 2024-12-31`
|
||||
- `npm run cli -- events:import:wsdc --source list --limit 50`
|
||||
- `npm run cli -- events:import:wsdc --source list --update-missing-location`
|
||||
- Field mapping: `name`, `startDate`, `endDate`, `sourceUrl`, `location` (from list) or `Unknown` (from calendar). No updates to `participantsCount`.
|
||||
- Dedup strategy: skip when `(name, startDate)` already exists.
|
||||
- Alias: `events:import:worldsdc` (kept for backwards compatibility).
|
||||
|
||||
### logs:app
|
||||
- Description: Tail application log file (if configured)
|
||||
- Options:
|
||||
- `--lines <n>` number of lines from end (default: 200)
|
||||
- Env:
|
||||
- `LOG_FILE` — absolute/relative path inside backend container (default: `./app.log` in working dir)
|
||||
- Note: For container logs prefer `docker compose logs -f backend`
|
||||
|
||||
### logs:messages
|
||||
- Description: Recent chat messages from DB
|
||||
- Options:
|
||||
- `--limit <n>` (default: 50)
|
||||
- Output: message id, time, user, room (event/private), type, first 100 chars
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- REPL not interactive: ensure TTY: `docker compose exec -it backend npm run cli`
|
||||
- DB access errors: verify backend container env and DB service are running
|
||||
- `events:checkin` says not found: confirm `username` and `slug` exist in DB
|
||||
- Autocomplete: works with Node REPL; press TAB after `prisma.` to see model methods
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- CLI has full DB access; restrict usage to SSH + container exec
|
||||
- Do not expose CLI via HTTP endpoints
|
||||
- Consider audit logs for sensitive actions if needed
|
||||
|
||||
---
|
||||
|
||||
## Domain Notes
|
||||
|
||||
- In spotlight.cam, `participantsCount` reflects local check‑ins (EventParticipants), not official WSDC participant metrics.
|
||||
- The WSDC calendar source does not provide reliable location or participant counts; importer intentionally does not set `worldsdcId` or `participantsCount`.
|
||||
576
docs/archive/COMPLETED.md
Normal file
576
docs/archive/COMPLETED.md
Normal file
@@ -0,0 +1,576 @@
|
||||
# Completed Tasks - spotlight.cam
|
||||
|
||||
**Archive of completed tasks - for reference only**
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 0: Frontend Mockup (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-12
|
||||
**Status:** Ready for presentation and UX testing
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 1: Backend Foundation (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-12
|
||||
**Time Spent:** ~14 hours
|
||||
**Status:** Production-ready backend with 81%+ test coverage
|
||||
|
||||
### Step 1: Backend Setup
|
||||
- [x] Docker backend container (Node.js 20 Alpine)
|
||||
- [x] Express 4.18.2 server setup
|
||||
- [x] Folder structure (controllers, routes, middleware, utils, __tests__)
|
||||
- [x] Health check endpoint `GET /api/health`
|
||||
- [x] nginx proxy for `/api/*`
|
||||
- [x] GET `/api/events` endpoint with Prisma
|
||||
- [x] Unit tests: 7 tests passing
|
||||
- [x] CORS configuration
|
||||
|
||||
### Step 2: PostgreSQL Setup
|
||||
- [x] PostgreSQL 15 Alpine container
|
||||
- [x] Prisma ORM 5.8.0 integration
|
||||
- [x] Database schema with 6 tables:
|
||||
- users (id, username, email, password_hash, avatar, created_at)
|
||||
- events (id, name, location, start_date, end_date, description, worldsdc_id)
|
||||
- chat_rooms (id, event_id, match_id, type, created_at)
|
||||
- messages (id, room_id, user_id, content, type, created_at)
|
||||
- matches (id, user1_id, user2_id, event_id, room_id, status, created_at)
|
||||
- ratings (id, match_id, rater_id, rated_id, score, comment, created_at)
|
||||
- [x] Relations and indexes
|
||||
- [x] Migrations (prisma migrate)
|
||||
- [x] Seed data (3 events, 2 users, chat rooms)
|
||||
- [x] Volume persistence for database
|
||||
- [x] **Bug fix:** OpenSSL compatibility for Prisma (added `apk add openssl` to Dockerfile)
|
||||
|
||||
### Step 3: Authentication API
|
||||
- [x] Dependencies: bcryptjs 2.4.3, jsonwebtoken 9.0.2, express-validator 7.3.0
|
||||
- [x] Password hashing with bcrypt (10 salt rounds)
|
||||
- [x] JWT token generation (24h expiry)
|
||||
- [x] Endpoints:
|
||||
- `POST /api/auth/register` - Create account
|
||||
- `POST /api/auth/login` - Login with JWT
|
||||
- `GET /api/users/me` - Get current user (protected)
|
||||
- [x] Auth middleware for protected routes
|
||||
- [x] Input validation and sanitization
|
||||
- [x] Frontend integration (AuthContext + API service layer)
|
||||
- [x] Unit tests: 30 tests passing, 78.26% coverage
|
||||
|
||||
### Step 4: WebSocket Chat (Socket.IO)
|
||||
- [x] Socket.IO 4.8.1 server installation
|
||||
- [x] HTTP server integration with Express
|
||||
- [x] JWT authentication for socket connections
|
||||
- [x] Event rooms implementation:
|
||||
- `join_event_room` - Join event chat
|
||||
- `leave_event_room` - Leave event chat
|
||||
- `send_event_message` - Send message to event room
|
||||
- `event_message` - Receive messages
|
||||
- `active_users` - Active users list
|
||||
- `user_joined` / `user_left` - Notifications
|
||||
- [x] Match rooms implementation:
|
||||
- `join_match_room` - Join private 1:1 chat
|
||||
- `send_match_message` - Send private message
|
||||
- `match_message` - Receive private messages
|
||||
- [x] Message persistence to PostgreSQL
|
||||
- [x] Active users tracking with Map data structure
|
||||
- [x] Automatic cleanup on disconnect
|
||||
- [x] nginx WebSocket proxy for `/socket.io` (7d timeout)
|
||||
- [x] Frontend integration:
|
||||
- socket.io-client installation
|
||||
- Socket service layer (connectSocket, getSocket, disconnectSocket)
|
||||
- EventChatPage with real-time messaging
|
||||
- MatchChatPage with real-time private chat
|
||||
- Connection status indicators
|
||||
- [x] Unit tests: 12 tests passing, 89.13% coverage for Socket.IO module
|
||||
- [x] Overall test coverage: 81.19%
|
||||
|
||||
### Infrastructure Updates
|
||||
- [x] docker-compose.yml with 4 services (nginx, frontend, backend, db)
|
||||
- [x] nginx config for API proxy and WebSocket support
|
||||
- [x] Backend Dockerfile with OpenSSL for Prisma
|
||||
- [x] Environment variables (.env) for database and JWT
|
||||
|
||||
### Git Commits (Phase 1)
|
||||
1. `docs: optimize documentation structure for token efficiency`
|
||||
2. `feat: add backend setup with Express and unit tests`
|
||||
3. `feat: add PostgreSQL database with Prisma ORM`
|
||||
4. `feat: add JWT authentication with complete test coverage`
|
||||
5. `feat: implement real-time chat with Socket.IO`
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 1.5 Continuation: QR Code Check-in System (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-14
|
||||
**Time Spent:** ~4 hours
|
||||
**Status:** Production-ready with security fixes
|
||||
|
||||
### QR Code Event Check-in Implementation
|
||||
- [x] Database schema extension:
|
||||
- EventCheckinToken model (id, event_id unique, token cuid unique, created_at)
|
||||
- Migration: `20251114125544_add_event_checkin_tokens`
|
||||
- One token per event (on-demand generation)
|
||||
- [x] Backend endpoints:
|
||||
- `GET /api/events/:slug/details` - Get event details with QR code token and participants
|
||||
- `POST /api/events/checkin/:token` - Check-in to event via QR code scan
|
||||
- `DELETE /api/events/:slug/leave` - Leave event (remove participation)
|
||||
- Date validation (startDate - 1 day to endDate + 1 day, disabled in dev mode)
|
||||
- Participant count updates (increment/decrement)
|
||||
- [x] Frontend pages:
|
||||
- EventDetailsPage.jsx - QR code display (qrcode.react), participant list, stats
|
||||
- EventCheckinPage.jsx - Check-in confirmation screen with event info
|
||||
- EventChatPage.jsx - Access control (verify participation before showing chat)
|
||||
- EventsPage.jsx - Check-in requirement notice, dev-only details link
|
||||
- [x] Security implementation:
|
||||
- Frontend access control (check participation status)
|
||||
- Socket.IO handler verification (prevent auto-participation)
|
||||
- Dev-only QR code access (import.meta.env.DEV)
|
||||
- Leave Event button with confirmation modal
|
||||
- [x] UX improvements:
|
||||
- Real participant counts using `_count.participants`
|
||||
- Joined events shown first in events list
|
||||
- Check-in required screen for non-participants
|
||||
- Dev mode shortcuts for testing
|
||||
- [x] Security fixes:
|
||||
- Fixed bypass vulnerability (page refresh granting unauthorized access)
|
||||
- Removed auto-participation from Socket.IO handler
|
||||
- Added participant verification before room join
|
||||
|
||||
### Git Commits (QR Code Check-in)
|
||||
1. `feat: add QR code event check-in system`
|
||||
2. `fix: improve event check-in UX and participant counting`
|
||||
3. `fix: prevent bypassing event check-in via page refresh`
|
||||
|
||||
### Key Features
|
||||
- Physical presence requirement (QR code must be scanned at venue)
|
||||
- On-demand token generation (created when admin views /details)
|
||||
- Development mode bypass for date validation
|
||||
- Secure token generation (CUID)
|
||||
- Complete access control (frontend + backend + socket)
|
||||
- Leave event functionality with confirmation
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 2: Matches & Ratings API (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-14
|
||||
**Time Spent:** ~10 hours
|
||||
**Status:** Production-ready with full CRUD operations and real-time updates
|
||||
|
||||
### Step 1: Matches API Implementation
|
||||
- [x] Database schema:
|
||||
- Added `slug` field to Match model (CUID for security)
|
||||
- Migration: `20251114183814_add_match_slug`
|
||||
- Unique constraint on slug
|
||||
- [x] Backend endpoints:
|
||||
- `POST /api/matches` - Create match request (with event slug, target user)
|
||||
- `GET /api/matches` - List matches with filters (eventSlug, status)
|
||||
- `GET /api/matches/:slug` - Get match details with hasRated flag
|
||||
- `GET /api/matches/:slug/messages` - Get match message history
|
||||
- `PUT /api/matches/:slug/accept` - Accept match request
|
||||
- `DELETE /api/matches/:slug` - Reject/cancel match
|
||||
- Real-time notifications via Socket.IO (match_request_received, match_accepted, match_cancelled)
|
||||
- [x] Frontend pages:
|
||||
- MatchesPage.jsx - List and manage matches with filter tabs (all/pending/active)
|
||||
- MatchChatPage.jsx - Private 1:1 chat with message history loading
|
||||
- Updated EventChatPage - UserPlus button creates match requests
|
||||
- [x] Security:
|
||||
- CUID slugs prevent ID enumeration
|
||||
- URLs: `/matches/{slug}/chat` instead of `/matches/{id}/chat`
|
||||
- Partner-based access control
|
||||
|
||||
### Step 2: Ratings API Implementation
|
||||
- [x] Database schema:
|
||||
- Rating model with unique constraint (match_id, rater_id, rated_id)
|
||||
- Fields: score (1-5), comment, would_collaborate_again
|
||||
- [x] Backend endpoints:
|
||||
- `POST /api/matches/:slug/ratings` - Create rating
|
||||
- `GET /api/users/:username/ratings` - Get user ratings (last 50)
|
||||
- hasRated flag in match response
|
||||
- Auto-complete match when both users rate
|
||||
- [x] Frontend integration:
|
||||
- RatePartnerPage.jsx - Real API integration with validation
|
||||
- Duplicate rating prevention (redirect if already rated)
|
||||
- "✓ Rated" badge in MatchChatPage when user has rated
|
||||
- PublicProfilePage.jsx - Display ratings with stars, comments, and collaboration preferences
|
||||
- [x] Validation:
|
||||
- Score 1-5 required
|
||||
- Comment optional
|
||||
- One rating per user per match (database constraint)
|
||||
|
||||
### Step 3: Public Profile Ratings Display
|
||||
- [x] PublicProfilePage enhancements:
|
||||
- Fetch and display user ratings using ratingsAPI.getUserRatings()
|
||||
- Summary section: average rating with star visualization, total count
|
||||
- Individual ratings section:
|
||||
- Rater avatar and name (clickable links to their profiles)
|
||||
- Star rating (1-5 filled stars)
|
||||
- Comment text
|
||||
- "Would collaborate again" indicator with thumbs up icon
|
||||
- Event context (clickable link) and date
|
||||
- Loading states and empty states
|
||||
- [x] Profile navigation:
|
||||
- MatchesPage: Partner avatar and name link to profile
|
||||
- MatchChatPage: Header avatar and name link to profile
|
||||
- Hover effects on all profile links
|
||||
|
||||
### Git Commits (Phase 2)
|
||||
1. `feat: implement Phase 2 - Matches API with real-time notifications`
|
||||
2. `feat: add match slugs for security and fix message history loading`
|
||||
3. `feat: implement Ratings API (Phase 2.5)`
|
||||
4. `feat: prevent duplicate ratings and show rated status in chat`
|
||||
5. `feat: display user ratings on public profiles and add profile links`
|
||||
|
||||
### Key Features
|
||||
- Secure match URLs with CUID slugs
|
||||
- Real-time match notifications via Socket.IO
|
||||
- Message history persistence and loading
|
||||
- Complete ratings system with duplicate prevention
|
||||
- Auto-match completion when both users rate
|
||||
- Public profile ratings display with detailed reviews
|
||||
- Clickable profile links throughout the app
|
||||
- Comprehensive validation and error handling
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 2.5: WebRTC P2P File Transfer (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-15
|
||||
**Time Spent:** ~10 hours
|
||||
**Status:** Production-ready P2P file transfer with E2E encryption
|
||||
|
||||
### Step 1: WebRTC Signaling
|
||||
- [x] Socket.IO signaling events:
|
||||
- `webrtc_offer` - Send SDP offer
|
||||
- `webrtc_answer` - Send SDP answer
|
||||
- `webrtc_ice_candidate` - Exchange ICE candidates
|
||||
- [x] Frontend WebRTC setup:
|
||||
- RTCPeerConnection initialization
|
||||
- STUN server configuration (Google STUN servers)
|
||||
- Signaling flow implementation
|
||||
- [x] Connection state monitoring (disconnected, connecting, connected, failed)
|
||||
- [x] Backend tests: 7 WebRTC tests passing
|
||||
|
||||
### Step 2: WebRTC File Transfer
|
||||
- [x] RTCDataChannel setup (ordered, reliable)
|
||||
- [x] File metadata exchange (name, size, type)
|
||||
- [x] File chunking implementation (16KB chunks)
|
||||
- [x] Progress monitoring (sender & receiver with percentage)
|
||||
- [x] Error handling & reconnection logic
|
||||
- [x] Complete P2P video transfer flow:
|
||||
- Select video file from device
|
||||
- Establish P2P connection via WebRTC
|
||||
- Transfer file via DataChannel
|
||||
- Save file on receiver side (automatic download)
|
||||
- [x] Tested with various file sizes (up to 700MB successfully)
|
||||
- [x] Fallback: Link sharing UI (Google Drive, Dropbox)
|
||||
- [x] NAT traversal with STUN servers
|
||||
- [x] E2E encryption (DTLS for DataChannel)
|
||||
|
||||
### Git Commits (Phase 2.5)
|
||||
1. `feat: implement WebRTC P2P file transfer with signaling`
|
||||
2. `test: add WebRTC backend tests (7 tests passing)`
|
||||
3. `fix: improve WebRTC connection handling and error recovery`
|
||||
|
||||
### Key Features
|
||||
- True peer-to-peer file transfer (no server storage)
|
||||
- Automatic chunking for large files (16KB per chunk)
|
||||
- Real-time progress tracking
|
||||
- Connection state visualization
|
||||
- NAT traversal support via STUN
|
||||
- E2E encryption by default (DTLS)
|
||||
- Tested up to 700MB video files
|
||||
- Graceful fallback to link sharing if WebRTC fails
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 3: MVP Finalization (COMPLETED)
|
||||
|
||||
**Completed:** 2025-11-20
|
||||
**Time Spent:** ~20 hours
|
||||
**Status:** Production-ready MVP with full security hardening
|
||||
|
||||
### Security Hardening
|
||||
- [x] CSRF protection (csurf middleware with cookie-based tokens)
|
||||
- [x] Rate limiting (express-rate-limit):
|
||||
- Auth endpoints: 5 attempts per 15 minutes
|
||||
- Email endpoints: 3 attempts per 15 minutes
|
||||
- Account lockout after failed attempts
|
||||
- [x] Input validation & sanitization (express-validator)
|
||||
- [x] CORS configuration (strict origin checking)
|
||||
- [x] SQL injection prevention (Prisma ORM with parameterized queries)
|
||||
- [x] XSS protection (Content Security Policy headers)
|
||||
- [x] Environment variables security (.env.production with strong secrets)
|
||||
- [x] Helmet.js security headers
|
||||
|
||||
### Testing & Quality
|
||||
- [x] Backend integration tests (Jest + Supertest)
|
||||
- [x] WebRTC connection tests (7 backend tests)
|
||||
- [x] Socket.IO tests (complete coverage)
|
||||
- [x] Security tests (CSRF, rate limiting, auth)
|
||||
- [x] Test isolation (unique test data per suite)
|
||||
- [x] **Final result:** 223/223 tests passing (100%)
|
||||
- [x] Code coverage: 71.31% (up from ~43%)
|
||||
|
||||
### PWA Features
|
||||
- [x] Web app manifest (vite-plugin-pwa)
|
||||
- [x] Service worker (Workbox for offline support)
|
||||
- [x] App icons & splash screens (all sizes for iOS/Android)
|
||||
- [x] Install prompts (BeforeInstallPrompt event handling)
|
||||
- [x] iOS support (apple-touch-icon, standalone mode)
|
||||
- [x] Offline page fallback
|
||||
|
||||
### Production Deployment Preparation
|
||||
- [x] Production Docker images:
|
||||
- `frontend/Dockerfile.prod` (multi-stage build)
|
||||
- `backend/Dockerfile.prod` (multi-stage build)
|
||||
- [x] Docker Compose profiles (dev/prod separation)
|
||||
- [x] Environment configuration:
|
||||
- `.env.development` with relaxed security
|
||||
- `.env.production` with strict security settings
|
||||
- [x] Operations scripts:
|
||||
- `scripts/backup-db.sh` - Automated backups with 7-day retention
|
||||
- `scripts/restore-db.sh` - Safe restore with confirmation
|
||||
- `scripts/health-check.sh` - Complete service monitoring
|
||||
- [x] Monitoring documentation (`docs/MONITORING.md`):
|
||||
- Application health monitoring
|
||||
- Docker container monitoring
|
||||
- External monitoring setup (UptimeRobot, Pingdom)
|
||||
- Log monitoring & rotation
|
||||
- Alerting configuration
|
||||
- Incident response procedures
|
||||
- [x] Production nginx config (`nginx/conf.d.prod/`)
|
||||
|
||||
### Git Commits (Phase 3)
|
||||
1. `feat: add CSRF protection and security hardening`
|
||||
2. `feat: implement account lockout and rate limiting`
|
||||
3. `feat: add PWA features (manifest, service worker, iOS support)`
|
||||
4. `test: fix socket.test.js cleanup and event room parameters`
|
||||
5. `test: improve test cleanup - selective deletion instead of wiping tables`
|
||||
6. `test: fix test isolation by using unique test data per suite`
|
||||
7. `feat: add production operations scripts and monitoring guide`
|
||||
8. `docs: mark Phase 3 (MVP Finalization) as completed`
|
||||
|
||||
### Key Achievements
|
||||
- **Security:** Production-grade security with CSRF, rate limiting, account lockout
|
||||
- **Testing:** 100% test pass rate (223/223), 71% code coverage
|
||||
- **PWA:** Full offline support, installable on iOS/Android
|
||||
- **DevOps:** Complete deployment infrastructure (Docker, scripts, monitoring)
|
||||
- **Documentation:** Comprehensive guides for deployment and monitoring
|
||||
|
||||
---
|
||||
|
||||
## 🐳 1. Setup projektu i infrastruktura
|
||||
|
||||
### Docker Compose
|
||||
- [x] ✅ Utworzenie `docker-compose.yml` z serwisem nginx
|
||||
- [x] ✅ Konfiguracja kontenera frontend (React/Vite)
|
||||
- [x] ✅ Konfiguracja sieci między kontenerami
|
||||
- [x] ✅ nginx proxy config (port 8080, WebSocket support)
|
||||
|
||||
### Struktura projektu
|
||||
- [x] ✅ Inicjalizacja projektu frontend (React + Vite + Tailwind)
|
||||
- [x] ✅ Utworzenie `.gitignore`
|
||||
- [x] ✅ Konfiguracja ESLint (frontend)
|
||||
- [x] ✅ Fix Tailwind CSS v4 compatibility issue (downgraded to v3.4.0)
|
||||
|
||||
---
|
||||
|
||||
## 🎨 6. Frontend - PWA (React + Vite + Tailwind)
|
||||
|
||||
### Setup PWA
|
||||
- [x] ✅ Konfiguracja Vite
|
||||
- [x] ✅ Konfiguracja Tailwind CSS v3.4.0
|
||||
- [x] ✅ Konfiguracja custom color scheme (primary-600, etc.)
|
||||
|
||||
### Routing
|
||||
- [x] ✅ Setup React Router
|
||||
- [x] ✅ Ochrona tras (require authentication)
|
||||
- [x] ✅ Redirect logic (logged in → /events, logged out → /login)
|
||||
|
||||
### Widoki/Komponenty
|
||||
- [x] ✅ **Logowanie** (`/login`) - Formularz email + hasło, link do rejestracji
|
||||
- [x] ✅ **Rejestracja** (`/register`) - Formularz username, email, hasło, walidacja
|
||||
- [x] ✅ **Wybór eventu** (`/events`) - Lista eventów, informacje (location, dates, participants), przycisk "Join chat"
|
||||
- [x] ✅ **Czat eventowy** (`/events/:id/chat`) - Lista wiadomości, aktywni użytkownicy (sidebar), matchmaking (UserPlus button), auto-scroll
|
||||
- [x] ✅ **Czat 1:1** (`/matches/:id/chat`) - Profil partnera (header), czat, **mockup WebRTC transfer** (file select, progress bar, status indicator), link sharing fallback, "End & rate" button
|
||||
- [x] ✅ **Ocena partnera** (`/matches/:id/rate`) - Gwiazdki 1-5 (interactive), komentarz (textarea), checkbox "Would collaborate again", submit button
|
||||
- [x] ✅ **Historia współprac** (`/history`) - Lista matchów (cards), partner info, rating stars, date, status badge, "View details" buttons
|
||||
|
||||
### Komponenty reużywalne
|
||||
- [x] ✅ `<Navbar>` - nawigacja (logo, links: Events, History, Logout), responsive, active link styling
|
||||
- [x] ✅ `<Layout>` - wrapper dla stron (container max-w-7xl, padding, Navbar integration)
|
||||
|
||||
### Stylowanie (Tailwind)
|
||||
- [x] ✅ Konfiguracja motywu kolorystycznego (primary, secondary, gray scale)
|
||||
- [x] ✅ Responsive design (mobile-first)
|
||||
- [x] ✅ Hover states, transitions, shadows
|
||||
- [x] ✅ Form styling (inputs, buttons, focus states)
|
||||
|
||||
### State Management
|
||||
- [x] ✅ Auth state (Context API - current user, mock login/logout)
|
||||
- [x] ✅ Mock authentication with localStorage persistence
|
||||
- [x] ✅ Protected routes based on auth state
|
||||
|
||||
---
|
||||
|
||||
## 🎥 5. WebRTC - Peer-to-Peer Transfer Filmów (MOCKUP)
|
||||
|
||||
### Fallback - wymiana linków
|
||||
- [x] ✅ UI do wklejenia linku do filmu (Google Drive, Dropbox, itp.)
|
||||
- [x] ✅ Walidacja URL (type="url" in input)
|
||||
- [x] ✅ Wysłanie linku przez czat (mockup)
|
||||
|
||||
### WebRTC UI Mockup
|
||||
- [x] ✅ File input for video selection (`accept="video/*"`)
|
||||
- [x] ✅ File validation (video type check)
|
||||
- [x] ✅ WebRTC connection status indicator (disconnected, connecting, connected, failed)
|
||||
- [x] ✅ Transfer progress bar (simulated 0-100%)
|
||||
- [x] ✅ File metadata display (name, size in MB)
|
||||
- [x] ✅ Cancel transfer button
|
||||
- [x] ✅ Send video button (P2P)
|
||||
- [x] ✅ Status messages ("Connected (P2P)", "E2E Encrypted (DTLS/SRTP)")
|
||||
- [x] ✅ Info box explaining WebRTC functionality
|
||||
|
||||
---
|
||||
|
||||
## 📚 9. Dokumentacja
|
||||
|
||||
- [x] ✅ README.md - instrukcja uruchomienia projektu (Docker commands, ports, mock login)
|
||||
- [x] ✅ QUICKSTART.md - szybki start (2 minuty, step-by-step)
|
||||
- [x] ✅ CONTEXT.md - architektura i założenia projektu (full description, user flow, tech stack, dev guidelines)
|
||||
- [x] ✅ TODO.md - roadmap projektu (11 sections, phase breakdown, next steps)
|
||||
- [x] ✅ Development Guidelines in CONTEXT.md (English code, Polish communication, Git commit format)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Mock Data
|
||||
|
||||
### Mock Users
|
||||
- [x] ✅ john_doe (current user)
|
||||
- [x] ✅ sarah_swing
|
||||
- [x] ✅ mike_blues
|
||||
- [x] ✅ anna_balboa
|
||||
- [x] ✅ tom_lindy
|
||||
- [x] ✅ All users have: id, username, email, avatar, rating, matches_count
|
||||
|
||||
### Mock Events
|
||||
- [x] ✅ Warsaw Dance Festival 2025
|
||||
- [x] ✅ Swing Camp Barcelona 2025
|
||||
- [x] ✅ Blues Week Herräng 2025
|
||||
- [x] ✅ All events have: id, name, location, dates, worldsdc_id, participants, description
|
||||
|
||||
### Mock Messages
|
||||
- [x] ✅ Event messages (public chat)
|
||||
- [x] ✅ Private messages (1:1 chat)
|
||||
- [x] ✅ All messages have: id, room_id, user_id, username, avatar, content, type, created_at
|
||||
|
||||
### Mock Matches
|
||||
- [x] ✅ Match history with different statuses
|
||||
- [x] ✅ Partner info, event, date, status
|
||||
|
||||
### Mock Ratings
|
||||
- [x] ✅ Ratings with scores, comments, would_collaborate_again flag
|
||||
- [x] ✅ Linked to matches and users
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
### Tailwind CSS v4 Compatibility Issue
|
||||
**Problem:**
|
||||
- Error: "It looks like you're trying to use `tailwindcss` directly as a PostCSS plugin"
|
||||
- Tailwind v4 has breaking changes with Vite setup
|
||||
|
||||
**Solution:**
|
||||
- Downgraded to Tailwind CSS v3.4.0
|
||||
- Command: `npm install -D tailwindcss@^3.4.0`
|
||||
- Rebuilt Docker container without cache
|
||||
- Verified working at http://localhost:8080
|
||||
|
||||
**Date:** 2025-11-12
|
||||
|
||||
### Port 80 Already Allocated
|
||||
**Problem:**
|
||||
- Docker error: "Bind for 0.0.0.0:80 failed: port is already allocated"
|
||||
|
||||
**Solution:**
|
||||
- Changed nginx port from 80 to 8080 in docker-compose.yml
|
||||
- Updated all documentation to reference port 8080
|
||||
- Access: http://localhost:8080
|
||||
|
||||
**Date:** 2025-11-12
|
||||
|
||||
---
|
||||
|
||||
## 🌍 Localization
|
||||
|
||||
- [x] ✅ Changed all UI text from Polish to English
|
||||
- [x] ✅ Updated placeholders in forms
|
||||
- [x] ✅ Updated button labels
|
||||
- [x] ✅ Updated page titles and headers
|
||||
- [x] ✅ Updated error messages and alerts
|
||||
- [x] ✅ Updated mock data content
|
||||
- [x] ✅ Changed date formatting locale from 'pl-PL' to 'en-US'
|
||||
- [x] ✅ Restarted frontend container to apply changes
|
||||
|
||||
**Date:** 2025-11-12
|
||||
|
||||
---
|
||||
|
||||
## 📝 Git Commits
|
||||
|
||||
### Commit 1: Initial project setup
|
||||
```
|
||||
feat: initial project setup with frontend mockup
|
||||
|
||||
- Add Docker Compose with nginx and frontend services
|
||||
- Initialize React + Vite + Tailwind CSS frontend
|
||||
- Implement all pages: Login, Register, Events, Event Chat, Match Chat, Rate, History
|
||||
- Add mock authentication with Context API
|
||||
- Add mock data for users, events, messages, matches, ratings
|
||||
- Create WebRTC P2P video transfer UI mockup
|
||||
- Add project documentation (README, QUICKSTART, CONTEXT, TODO)
|
||||
```
|
||||
**Date:** 2025-11-12
|
||||
|
||||
### Commit 2: Update TODO.md
|
||||
```
|
||||
docs: update TODO.md with completed tasks and next steps
|
||||
|
||||
- Mark Phase 0 (Frontend Mockup) as completed
|
||||
- Add current project status section (25% complete)
|
||||
- Add detailed next steps for Phase 1 (Backend Foundation)
|
||||
- Add time estimates for each step
|
||||
- Add learning resources section
|
||||
```
|
||||
**Date:** 2025-11-12
|
||||
|
||||
---
|
||||
|
||||
## 📊 Statistics
|
||||
|
||||
**Frontend:**
|
||||
- 7 pages implemented
|
||||
- 2 layout components
|
||||
- 1 context (AuthContext)
|
||||
- 5 mock data files
|
||||
- ~1,500 lines of React code
|
||||
|
||||
**Docker:**
|
||||
- 2 services (nginx, frontend)
|
||||
- 1 network
|
||||
- 2 volume mounts
|
||||
|
||||
**Documentation:**
|
||||
- 4 markdown files (README, QUICKSTART, CONTEXT, TODO)
|
||||
- ~1,200 lines of documentation
|
||||
|
||||
**Total Development Time:** ~8-10 hours
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-20 (Phase 3 completed - MVP finalized)
|
||||
**Note:** This file is an archive of completed phases. For current status, see SESSION_CONTEXT.md or TODO.md
|
||||
|
||||
**MVP Status:** ✅ 100% Complete - All core features implemented, tested, and production-ready
|
||||
524
docs/archive/PHASE_1.5.md
Normal file
524
docs/archive/PHASE_1.5.md
Normal file
@@ -0,0 +1,524 @@
|
||||
# Phase 1.5: Email Verification & WSDC Integration
|
||||
|
||||
**Status:** ✅ COMPLETED
|
||||
**Date:** 2025-11-13
|
||||
**Duration:** ~8 hours
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Phase 1.5 implements a complete email verification system with AWS SES, password reset functionality, and WSDC ID integration for dancer registration. This phase enhances user account security and provides a streamlined registration experience for the dance community.
|
||||
|
||||
---
|
||||
|
||||
## Features Implemented
|
||||
|
||||
### 1. Email Verification System (AWS SES)
|
||||
- **Dual Verification Methods:**
|
||||
- Verification link (token-based)
|
||||
- 6-digit PIN code
|
||||
- User can choose either method
|
||||
- **Email Templates:**
|
||||
- Professional HTML templates with gradient design
|
||||
- Verification email (link + code)
|
||||
- Welcome email (post-verification)
|
||||
- Password reset email
|
||||
- **Token Management:**
|
||||
- Secure token generation (crypto)
|
||||
- 24-hour expiry for verification
|
||||
- 1-hour expiry for password reset
|
||||
- **Resend Functionality:**
|
||||
- Users can request new verification emails
|
||||
- Prevents spam with proper validation
|
||||
|
||||
### 2. Password Reset Workflow
|
||||
- **Request Reset:**
|
||||
- Email-based reset request
|
||||
- Security: No user enumeration (same response for existing/non-existing emails)
|
||||
- **Reset Flow:**
|
||||
- Secure token sent via email
|
||||
- Token validation with expiry
|
||||
- Password strength validation
|
||||
- New password hashing with bcrypt
|
||||
|
||||
### 3. WSDC Integration
|
||||
- **Two-Step Registration:**
|
||||
- Step 1: "Do you have a WSDC ID?" choice
|
||||
- Step 2: Registration form (auto-filled if WSDC ID provided)
|
||||
- **WSDC API Proxy:**
|
||||
- Backend proxy endpoint: `GET /api/wsdc/lookup?id=<wsdcId>`
|
||||
- Fetches dancer data from points.worldsdc.com
|
||||
- Auto-fills: first name, last name, WSDC ID
|
||||
- **Security:**
|
||||
- Input validation (numeric, max 10 digits)
|
||||
- Error handling for invalid IDs
|
||||
- User-friendly error messages
|
||||
|
||||
### 4. Enhanced Registration
|
||||
- **Password Strength Indicator:**
|
||||
- Real-time visual feedback
|
||||
- Color-coded strength levels (weak/medium/strong)
|
||||
- Criteria checklist (length, uppercase, numbers)
|
||||
- **Improved UX:**
|
||||
- Multi-step registration flow
|
||||
- Loading states and error handling
|
||||
- Responsive design
|
||||
|
||||
### 5. Verification Banner
|
||||
- **Persistent Reminder:**
|
||||
- Yellow banner for unverified users
|
||||
- Appears on all protected routes
|
||||
- Dismissible but persists across sessions
|
||||
- **Quick Actions:**
|
||||
- "Verify Now" button → verification page
|
||||
- "Resend Email" button with loading state
|
||||
- Dismiss button (session-only)
|
||||
|
||||
---
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Database Schema Changes
|
||||
|
||||
**New Migration:** `20251113151534_add_wsdc_and_email_verification`
|
||||
|
||||
```sql
|
||||
ALTER TABLE "users" ADD COLUMN:
|
||||
-- WSDC Integration
|
||||
"first_name" VARCHAR(100),
|
||||
"last_name" VARCHAR(100),
|
||||
"wsdc_id" VARCHAR(20) UNIQUE,
|
||||
|
||||
-- Email Verification
|
||||
"email_verified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"verification_token" VARCHAR(255) UNIQUE,
|
||||
"verification_code" VARCHAR(6),
|
||||
"verification_token_expiry" TIMESTAMP(3),
|
||||
|
||||
-- Password Reset
|
||||
"reset_token" VARCHAR(255) UNIQUE,
|
||||
"reset_token_expiry" TIMESTAMP(3);
|
||||
```
|
||||
|
||||
### Backend API Endpoints
|
||||
|
||||
#### Authentication Endpoints (Extended)
|
||||
- `POST /api/auth/register` - **Updated:** Now accepts firstName, lastName, wsdcId
|
||||
- `POST /api/auth/login` - Unchanged
|
||||
- `GET /api/auth/verify-email?token=xxx` - **NEW:** Verify by link
|
||||
- `POST /api/auth/verify-code` - **NEW:** Verify by PIN code
|
||||
- `POST /api/auth/resend-verification` - **NEW:** Resend verification email
|
||||
- `POST /api/auth/request-password-reset` - **NEW:** Request password reset
|
||||
- `POST /api/auth/reset-password` - **NEW:** Reset password with token
|
||||
|
||||
#### WSDC Endpoints
|
||||
- `GET /api/wsdc/lookup?id=<wsdcId>` - **NEW:** Lookup dancer by WSDC ID
|
||||
|
||||
### Backend Files
|
||||
|
||||
**New Files:**
|
||||
- `backend/src/controllers/wsdc.js` - WSDC API proxy controller
|
||||
- `backend/src/routes/wsdc.js` - WSDC routes
|
||||
- `backend/src/utils/email.js` - AWS SES email service with templates
|
||||
- `backend/prisma/migrations/20251113151534_add_wsdc_and_email_verification/` - Database migration
|
||||
|
||||
**Updated Files:**
|
||||
- `backend/src/controllers/auth.js` - Extended with verification & reset functions
|
||||
- `backend/src/utils/auth.js` - Added token/code generation utilities
|
||||
- `backend/src/middleware/auth.js` - Added `requireEmailVerification()` middleware
|
||||
- `backend/src/routes/auth.js` - Added new routes
|
||||
- `backend/src/app.js` - Registered WSDC routes
|
||||
- `backend/.env` - Added AWS SES configuration
|
||||
- `backend/package.json` - Added @aws-sdk/client-ses
|
||||
|
||||
### Frontend Files
|
||||
|
||||
**New Pages:**
|
||||
- `frontend/src/pages/RegisterPage.jsx` - Two-step registration with WSDC lookup
|
||||
- `frontend/src/pages/VerifyEmailPage.jsx` - Email verification (link + code)
|
||||
- `frontend/src/pages/ForgotPasswordPage.jsx` - Request password reset
|
||||
- `frontend/src/pages/ResetPasswordPage.jsx` - Reset password form
|
||||
|
||||
**New Components:**
|
||||
- `frontend/src/components/common/PasswordStrengthIndicator.jsx` - Password strength indicator
|
||||
- `frontend/src/components/common/VerificationBanner.jsx` - Email verification banner
|
||||
|
||||
**Updated Files:**
|
||||
- `frontend/src/services/api.js` - Added new API methods (wsdcAPI, email verification, password reset)
|
||||
- `frontend/src/contexts/AuthContext.jsx` - Updated register function signature
|
||||
- `frontend/src/pages/LoginPage.jsx` - Added "Forgot password?" link
|
||||
- `frontend/src/App.jsx` - Added new routes, integrated VerificationBanner
|
||||
|
||||
### Frontend Routes (New)
|
||||
- `/verify-email` - Email verification page
|
||||
- `/forgot-password` - Request password reset
|
||||
- `/reset-password` - Reset password with token
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### AWS SES Configuration
|
||||
|
||||
**Environment Variables (backend/.env):**
|
||||
```bash
|
||||
# AWS SES (Phase 1.5)
|
||||
AWS_REGION=us-east-1
|
||||
AWS_ACCESS_KEY_ID=your-aws-access-key-id
|
||||
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
|
||||
SES_FROM_EMAIL=noreply@spotlight.cam
|
||||
SES_FROM_NAME=spotlight.cam
|
||||
|
||||
# Email Settings
|
||||
FRONTEND_URL=http://localhost:8080
|
||||
VERIFICATION_TOKEN_EXPIRY=24h
|
||||
```
|
||||
|
||||
**Setup Required:**
|
||||
1. Create AWS account and configure SES
|
||||
2. Verify email address or domain in SES
|
||||
3. Get AWS access credentials (IAM user with SES permissions)
|
||||
4. Update `.env` with credentials
|
||||
5. Test email sending
|
||||
|
||||
**SES Sandbox Mode:**
|
||||
- By default, SES is in sandbox mode
|
||||
- Can only send to verified email addresses
|
||||
- To send to any email, request production access
|
||||
|
||||
---
|
||||
|
||||
## User Flows
|
||||
|
||||
### Registration Flow (with WSDC ID)
|
||||
1. User arrives at `/register`
|
||||
2. **Step 1:** "Do you have a WSDC ID?"
|
||||
- YES → Enter WSDC ID → Lookup → Auto-fill form
|
||||
- NO → Empty form
|
||||
3. **Step 2:** Complete registration form
|
||||
- First Name (auto-filled if WSDC)
|
||||
- Last Name (auto-filled if WSDC)
|
||||
- Username
|
||||
- Email
|
||||
- Password (with strength indicator)
|
||||
- Confirm Password
|
||||
4. Submit → Account created
|
||||
5. Verification email sent (link + PIN code)
|
||||
6. User logged in but sees verification banner
|
||||
|
||||
### Email Verification Flow
|
||||
1. User receives email with:
|
||||
- Verification link
|
||||
- 6-digit PIN code
|
||||
2. **Option A:** Click link → Auto-verify → Welcome email → Success
|
||||
3. **Option B:** Visit `/verify-email` → Enter email + code → Success
|
||||
4. After verification:
|
||||
- `emailVerified` set to `true`
|
||||
- Welcome email sent
|
||||
- Banner disappears
|
||||
|
||||
### Password Reset Flow
|
||||
1. User clicks "Forgot password?" on login page
|
||||
2. Enter email → Request reset
|
||||
3. Email sent with reset link (1-hour expiry)
|
||||
4. Click link → Redirected to `/reset-password?token=xxx`
|
||||
5. Enter new password (with strength validation)
|
||||
6. Submit → Password updated → Redirect to login
|
||||
|
||||
---
|
||||
|
||||
## Security Features
|
||||
|
||||
### Email Verification
|
||||
- Secure random token generation (32 bytes hex)
|
||||
- 6-digit numeric PIN code
|
||||
- 24-hour token expiry
|
||||
- Tokens cleared after verification
|
||||
- Idempotent verification (already verified = success)
|
||||
|
||||
### Password Reset
|
||||
- No user enumeration (same response for all emails)
|
||||
- 1-hour token expiry
|
||||
- Secure token generation
|
||||
- Single-use tokens (cleared after reset)
|
||||
- Password strength validation
|
||||
|
||||
### WSDC API
|
||||
- Input validation (numeric only, max 10 digits)
|
||||
- Backend proxy (hides WSDC API from frontend)
|
||||
- Error handling for invalid/not found IDs
|
||||
- No sensitive data exposure
|
||||
|
||||
### Authentication
|
||||
- JWT tokens (24-hour expiry)
|
||||
- bcrypt password hashing (10 salt rounds)
|
||||
- Middleware for email verification check
|
||||
- Protected routes require authentication
|
||||
|
||||
---
|
||||
|
||||
## Code Quality
|
||||
|
||||
### Error Handling
|
||||
- Comprehensive try-catch blocks
|
||||
- User-friendly error messages
|
||||
- Backend logging for debugging
|
||||
- Fallback handling (e.g., email send failures)
|
||||
|
||||
### Validation
|
||||
- Backend input validation
|
||||
- Frontend form validation
|
||||
- Password strength requirements
|
||||
- Email format validation
|
||||
- WSDC ID format validation
|
||||
|
||||
### UX/UI
|
||||
- Loading states for all async operations
|
||||
- Error feedback with visual cues
|
||||
- Success confirmations
|
||||
- Responsive design
|
||||
- Accessible components
|
||||
|
||||
---
|
||||
|
||||
## Email Templates
|
||||
|
||||
### Verification Email
|
||||
- Gradient header with logo
|
||||
- Personalized greeting (first name)
|
||||
- Two verification options (link + code)
|
||||
- Clear call-to-action buttons
|
||||
- Expiry information (24 hours)
|
||||
- Security note ("Didn't create an account?")
|
||||
- Plain text fallback
|
||||
|
||||
### Password Reset Email
|
||||
- Security-focused design
|
||||
- Warning banner
|
||||
- Single reset link (1-hour expiry)
|
||||
- Plain text fallback
|
||||
- "Ignore if not requested" message
|
||||
|
||||
### Welcome Email
|
||||
- Celebratory design
|
||||
- Feature highlights
|
||||
- Call-to-action (explore events)
|
||||
- Personalized greeting
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Manual Testing Checklist
|
||||
|
||||
**Registration:**
|
||||
- [x] Register with WSDC ID
|
||||
- [x] Register without WSDC ID
|
||||
- [x] Invalid WSDC ID error handling
|
||||
- [x] Password strength indicator
|
||||
- [x] Password mismatch validation
|
||||
- [x] Duplicate email/username error
|
||||
- [x] Verification email sent
|
||||
|
||||
**Email Verification:**
|
||||
- [x] Verify by link
|
||||
- [x] Verify by code
|
||||
- [x] Invalid token/code error
|
||||
- [x] Expired token error
|
||||
- [x] Already verified handling
|
||||
- [x] Resend verification
|
||||
- [x] Welcome email sent
|
||||
|
||||
**Password Reset:**
|
||||
- [x] Request reset (existing email)
|
||||
- [x] Request reset (non-existing email - same response)
|
||||
- [x] Reset email sent
|
||||
- [x] Reset with valid token
|
||||
- [x] Reset with expired token
|
||||
- [x] Password strength validation
|
||||
- [x] Password mismatch validation
|
||||
|
||||
**Verification Banner:**
|
||||
- [x] Shows for unverified users
|
||||
- [x] Hides for verified users
|
||||
- [x] "Verify Now" button works
|
||||
- [x] "Resend Email" works
|
||||
- [x] Dismiss button works
|
||||
|
||||
**WSDC Lookup:**
|
||||
- [x] Valid WSDC ID lookup
|
||||
- [x] Invalid WSDC ID error
|
||||
- [x] Auto-fill form fields
|
||||
- [x] Loading state
|
||||
- [x] Error handling
|
||||
|
||||
### Unit Tests
|
||||
**Status:** ✅ COMPLETED
|
||||
|
||||
**Test Coverage Achieved:**
|
||||
- ✅ **Auth Utils Tests** - 18 tests (100% coverage)
|
||||
- Token generation (verification token, PIN code, expiry)
|
||||
- Password hashing and comparison
|
||||
- JWT token generation and verification
|
||||
- ✅ **Email Service Tests** - 22 tests (100% coverage)
|
||||
- Send email functionality
|
||||
- Verification email (link + code)
|
||||
- Password reset email
|
||||
- Welcome email
|
||||
- Error handling
|
||||
- ✅ **WSDC Controller Tests** - 13 tests (100% coverage)
|
||||
- Dancer lookup by ID
|
||||
- Input validation
|
||||
- Error handling
|
||||
- API integration
|
||||
- ✅ **Auth Middleware Tests** - 11 tests (coverage of requireEmailVerification)
|
||||
- Email verification checks
|
||||
- Error handling
|
||||
- User authorization
|
||||
|
||||
**Total:** 65 unit tests - All passing ✅
|
||||
|
||||
**Test Files:**
|
||||
- `backend/src/__tests__/utils/auth.test.js` - Auth utilities
|
||||
- `backend/src/__tests__/utils/email.test.js` - Email service
|
||||
- `backend/src/__tests__/wsdc.test.js` - WSDC controller
|
||||
- `backend/src/__tests__/middleware/auth.test.js` - Auth middleware
|
||||
- `backend/src/__tests__/auth-phase1.5.test.js` - Integration tests (require database)
|
||||
|
||||
**Running Tests:**
|
||||
```bash
|
||||
# Unit tests only (no database required)
|
||||
npm test -- --testPathPattern="utils/|wsdc.test|middleware/"
|
||||
|
||||
# All tests including integration (requires database)
|
||||
npm test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Added
|
||||
|
||||
### Backend
|
||||
```json
|
||||
"@aws-sdk/client-ses": "^3.x.x"
|
||||
```
|
||||
|
||||
### Frontend
|
||||
No new dependencies (used existing React, Tailwind, lucide-react)
|
||||
|
||||
---
|
||||
|
||||
## Known Issues & Limitations
|
||||
|
||||
### AWS SES Sandbox
|
||||
- **Issue:** In sandbox mode, can only send emails to verified addresses
|
||||
- **Solution:** Request production access from AWS or verify test email addresses
|
||||
|
||||
### Email Delivery
|
||||
- **Issue:** Emails may go to spam folder
|
||||
- **Solution:**
|
||||
- Verify domain with SES
|
||||
- Configure SPF, DKIM, DMARC records
|
||||
- Use verified sender domain
|
||||
|
||||
### WSDC API
|
||||
- **Issue:** WSDC API is third-party, may be rate-limited or change
|
||||
- **Solution:** Implement caching if needed, monitor API availability
|
||||
|
||||
### Token Cleanup
|
||||
- **Issue:** Expired tokens not automatically cleaned from database
|
||||
- **Solution:** Add cron job to clean expired tokens (future enhancement)
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Short-term (Phase 2)
|
||||
- Unit tests for new features
|
||||
- Integration tests for email workflows
|
||||
- Email template customization via admin panel
|
||||
|
||||
### Long-term (Phase 3+)
|
||||
- SMS verification as alternative
|
||||
- Social OAuth (Google, Facebook)
|
||||
- Two-factor authentication (2FA)
|
||||
- Email preferences (notification settings)
|
||||
- WSDC data sync (automatic profile updates)
|
||||
|
||||
---
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Email Sending
|
||||
- Asynchronous email sending (doesn't block registration)
|
||||
- Error handling (continues even if email fails)
|
||||
- Logging for debugging email issues
|
||||
|
||||
### WSDC API Calls
|
||||
- Frontend loading states
|
||||
- Timeout handling
|
||||
- Error recovery (retry option)
|
||||
|
||||
### Database
|
||||
- Indexed fields: verification_token, reset_token, wsdc_id
|
||||
- Unique constraints prevent duplicates
|
||||
|
||||
---
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Monitoring
|
||||
- Check AWS SES sending limits and bounce rates
|
||||
- Monitor email delivery success rates
|
||||
- Log verification and reset attempts
|
||||
- Track WSDC API errors
|
||||
|
||||
### Regular Tasks
|
||||
- Review and remove expired tokens (manual or automated)
|
||||
- Update email templates as needed
|
||||
- Monitor AWS SES costs
|
||||
|
||||
---
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
**Files Updated:**
|
||||
- `docs/SESSION_CONTEXT.md` - Added Phase 1.5 status and new files
|
||||
- `docs/PHASE_1.5.md` - This file (complete phase documentation)
|
||||
|
||||
**Recommended Reading:**
|
||||
- AWS SES Documentation: https://docs.aws.amazon.com/ses/
|
||||
- WSDC API: https://points.worldsdc.com/lookup2020/find
|
||||
- Prisma Migrations: https://www.prisma.io/docs/concepts/components/prisma-migrate
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- ✅ **Email Verification:** Dual method (link + code) implemented
|
||||
- ✅ **Password Reset:** Complete workflow with security best practices
|
||||
- ✅ **WSDC Integration:** Auto-fill registration from dancer database
|
||||
- ✅ **Password Security:** Strength indicator and validation
|
||||
- ✅ **User Experience:** Verification banner and streamlined flows
|
||||
- ✅ **Code Quality:** Clean, well-documented, error-handled
|
||||
- ✅ **Professional Emails:** HTML templates with branding
|
||||
- ✅ **Unit Tests:** 65 tests with 100% coverage of new features
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 1.5 successfully enhances spotlight.cam with production-ready authentication features:
|
||||
- Professional email system with AWS SES
|
||||
- Secure verification and password reset workflows
|
||||
- Dance community integration with WSDC ID lookup
|
||||
- Improved user experience with strength indicators and banners
|
||||
|
||||
The application is now ready for Phase 2 (Core Features: Matches API, Ratings, and WebRTC signaling).
|
||||
|
||||
---
|
||||
|
||||
**Next Phase:** [Phase 2 - Core Features](TODO.md)
|
||||
**Last Updated:** 2025-11-13
|
||||
**Author:** Claude Code (spotlight.cam development)
|
||||
294
docs/archive/RESOURCES.md
Normal file
294
docs/archive/RESOURCES.md
Normal file
@@ -0,0 +1,294 @@
|
||||
# Resources - spotlight.cam
|
||||
|
||||
**Learning resources, documentation links, and useful references**
|
||||
|
||||
---
|
||||
|
||||
## 📚 Official Documentation
|
||||
|
||||
### Backend (Node.js + Express)
|
||||
- **Express.js** - https://expressjs.com/
|
||||
- Best practices: https://expressjs.com/en/advanced/best-practice-performance.html
|
||||
- Security: https://expressjs.com/en/advanced/best-practice-security.html
|
||||
- **Node.js** - https://nodejs.org/docs/
|
||||
- **Socket.IO** - https://socket.io/docs/v4/
|
||||
- Rooms: https://socket.io/docs/v4/rooms/
|
||||
- Emit cheatsheet: https://socket.io/docs/v4/emit-cheatsheet/
|
||||
|
||||
### Database
|
||||
- **PostgreSQL** - https://www.postgresql.org/docs/
|
||||
- Best practices: https://wiki.postgresql.org/wiki/Don't_Do_This
|
||||
- Performance tips: https://wiki.postgresql.org/wiki/Performance_Optimization
|
||||
- **Prisma** - https://www.prisma.io/docs
|
||||
- Schema reference: https://www.prisma.io/docs/concepts/components/prisma-schema
|
||||
- Migrations: https://www.prisma.io/docs/concepts/components/prisma-migrate
|
||||
- **Knex.js** - https://knexjs.org/
|
||||
- Migrations: https://knexjs.org/guide/migrations.html
|
||||
|
||||
### Frontend
|
||||
- **React** - https://react.dev/
|
||||
- Hooks: https://react.dev/reference/react
|
||||
- Context: https://react.dev/reference/react/useContext
|
||||
- **Vite** - https://vitejs.dev/
|
||||
- Config: https://vitejs.dev/config/
|
||||
- Env variables: https://vitejs.dev/guide/env-and-mode.html
|
||||
- **Tailwind CSS** - https://tailwindcss.com/docs
|
||||
- Configuration: https://tailwindcss.com/docs/configuration
|
||||
- Customization: https://tailwindcss.com/docs/theme
|
||||
- **React Router** - https://reactrouter.com/en/main
|
||||
- Protected routes: https://reactrouter.com/en/main/start/tutorial#adding-a-loader
|
||||
|
||||
### Docker
|
||||
- **Docker Compose** - https://docs.docker.com/compose/
|
||||
- Compose file reference: https://docs.docker.com/compose/compose-file/
|
||||
- Networking: https://docs.docker.com/compose/networking/
|
||||
- **nginx** - https://nginx.org/en/docs/
|
||||
- Reverse proxy: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
|
||||
- WebSocket: https://nginx.org/en/docs/http/websocket.html
|
||||
|
||||
---
|
||||
|
||||
## 🎥 WebRTC Resources
|
||||
|
||||
### Getting Started
|
||||
- **WebRTC.org** - https://webrtc.org/
|
||||
- Getting started: https://webrtc.org/getting-started/overview
|
||||
- Use cases: https://webrtc.org/getting-started/use-cases
|
||||
- **MDN WebRTC API** - https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API
|
||||
- RTCPeerConnection: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection
|
||||
- RTCDataChannel: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel
|
||||
- Simple peer-to-peer data: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample
|
||||
|
||||
### Tutorials
|
||||
- **WebRTC samples** - https://webrtc.github.io/samples/
|
||||
- File transfer sample: https://webrtc.github.io/samples/src/content/datachannel/filetransfer/
|
||||
- Basic RTCDataChannel: https://webrtc.github.io/samples/src/content/datachannel/basic/
|
||||
- **HTML5 Rocks - WebRTC** - https://www.html5rocks.com/en/tutorials/webrtc/basics/
|
||||
|
||||
### Advanced Topics
|
||||
- **STUN/TURN Servers**
|
||||
- Understanding STUN/TURN: https://bloggeek.me/webrtcglossary/stun/
|
||||
- Free STUN servers: https://gist.github.com/mondain/b0ec1cf5f60ae726202e
|
||||
- Coturn (self-hosted TURN): https://github.com/coturn/coturn
|
||||
- **NAT Traversal**
|
||||
- ICE explained: https://bloggeek.me/webrtcglossary/ice/
|
||||
- Trickle ICE: https://webrtc.org/getting-started/trickle-ice
|
||||
- **WebRTC for the Curious** (free book) - https://webrtcforthecurious.com/
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security Resources
|
||||
|
||||
### Authentication
|
||||
- **JWT** - https://jwt.io/
|
||||
- Introduction: https://jwt.io/introduction
|
||||
- Debugger: https://jwt.io/#debugger-io
|
||||
- Best practices: https://curity.io/resources/learn/jwt-best-practices/
|
||||
- **bcrypt** - https://github.com/kelektiv/node.bcrypt.js
|
||||
- How bcrypt works: https://auth0.com/blog/hashing-in-action-understanding-bcrypt/
|
||||
|
||||
### General Security
|
||||
- **OWASP Top 10** - https://owasp.org/www-project-top-ten/
|
||||
- **Helmet.js** - https://helmetjs.github.io/
|
||||
- **express-rate-limit** - https://github.com/express-rate-limit/express-rate-limit
|
||||
- **express-validator** - https://express-validator.github.io/docs/
|
||||
- **CORS** - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
||||
### WebRTC Security
|
||||
- **WebRTC Security** - https://webrtc-security.github.io/
|
||||
- **DTLS/SRTP** - https://webrtc.org/getting-started/security
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Resources
|
||||
|
||||
### Backend Testing
|
||||
- **Jest** - https://jestjs.io/
|
||||
- Getting started: https://jestjs.io/docs/getting-started
|
||||
- API testing: https://jestjs.io/docs/testing-asynchronous-code
|
||||
- **Supertest** - https://github.com/ladjs/supertest
|
||||
- Express testing guide: https://github.com/ladjs/supertest#example
|
||||
|
||||
### Frontend Testing
|
||||
- **Vitest** - https://vitest.dev/
|
||||
- Getting started: https://vitest.dev/guide/
|
||||
- **React Testing Library** - https://testing-library.com/react
|
||||
- Cheatsheet: https://testing-library.com/docs/react-testing-library/cheatsheet/
|
||||
- **Playwright** - https://playwright.dev/
|
||||
- Getting started: https://playwright.dev/docs/intro
|
||||
- **Cypress** - https://www.cypress.io/
|
||||
- Getting started: https://docs.cypress.io/guides/getting-started/installing-cypress
|
||||
|
||||
---
|
||||
|
||||
## 📱 PWA Resources
|
||||
|
||||
### Service Workers
|
||||
- **MDN Service Worker API** - https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
|
||||
- **Workbox** - https://developers.google.com/web/tools/workbox
|
||||
- Getting started: https://developers.google.com/web/tools/workbox/guides/get-started
|
||||
|
||||
### PWA Features
|
||||
- **Vite PWA Plugin** - https://vite-pwa-org.netlify.app/
|
||||
- Guide: https://vite-pwa-org.netlify.app/guide/
|
||||
- **Web App Manifest** - https://developer.mozilla.org/en-US/docs/Web/Manifest
|
||||
- **Web Push Notifications** - https://developer.mozilla.org/en-US/docs/Web/API/Push_API
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment Resources
|
||||
|
||||
### Cloud Platforms
|
||||
- **Vercel** - https://vercel.com/docs
|
||||
- React deployment: https://vercel.com/docs/frameworks/vite
|
||||
- **Netlify** - https://docs.netlify.com/
|
||||
- **Render** - https://render.com/docs
|
||||
- **DigitalOcean** - https://docs.digitalocean.com/
|
||||
- App Platform: https://docs.digitalocean.com/products/app-platform/
|
||||
- Droplets: https://docs.digitalocean.com/products/droplets/
|
||||
- **AWS** - https://aws.amazon.com/getting-started/
|
||||
- EC2: https://docs.aws.amazon.com/ec2/
|
||||
- RDS: https://docs.aws.amazon.com/rds/
|
||||
|
||||
### SSL/TLS
|
||||
- **Let's Encrypt** - https://letsencrypt.org/
|
||||
- Certbot: https://certbot.eff.org/
|
||||
- Documentation: https://letsencrypt.org/docs/
|
||||
|
||||
### Docker Production
|
||||
- **Docker Production Best Practices** - https://docs.docker.com/develop/dev-best-practices/
|
||||
- **Multi-stage builds** - https://docs.docker.com/build/building/multi-stage/
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Video Tutorials
|
||||
|
||||
### WebRTC
|
||||
- **WebRTC Crash Course** - https://www.youtube.com/watch?v=WmR9IMUD_CY (Traversy Media)
|
||||
- **WebRTC File Transfer** - https://www.youtube.com/watch?v=WmR9IMUD_CY
|
||||
- **Build a Video Chat App** - https://www.youtube.com/watch?v=DvlyzDZDEq4 (Fireship)
|
||||
|
||||
### MERN Stack (Similar to our stack)
|
||||
- **MERN Stack Tutorial** - https://www.youtube.com/watch?v=7CqJlxBYj-M (freeCodeCamp)
|
||||
- **Socket.IO Tutorial** - https://www.youtube.com/watch?v=ZKEqqIO7n-k (Web Dev Simplified)
|
||||
|
||||
### React
|
||||
- **React Course for Beginners** - https://www.youtube.com/watch?v=bMknfKXIFA8 (freeCodeCamp)
|
||||
- **React Hooks** - https://www.youtube.com/watch?v=O6P86uwfdR0 (Codevolution)
|
||||
|
||||
---
|
||||
|
||||
## 📦 Useful npm Packages
|
||||
|
||||
### Backend
|
||||
- **express** - Web framework
|
||||
- **socket.io** - WebSocket library
|
||||
- **@prisma/client** / **knex** - Database ORM/query builder
|
||||
- **bcryptjs** - Password hashing
|
||||
- **jsonwebtoken** - JWT authentication
|
||||
- **dotenv** - Environment variables
|
||||
- **helmet** - Security headers
|
||||
- **express-rate-limit** - Rate limiting
|
||||
- **express-validator** - Input validation
|
||||
- **cors** - CORS middleware
|
||||
- **winston** / **pino** - Logging
|
||||
- **nodemon** - Dev server auto-restart
|
||||
|
||||
### Frontend
|
||||
- **react** - UI library
|
||||
- **react-dom** - React DOM renderer
|
||||
- **react-router-dom** - Routing
|
||||
- **socket.io-client** - Socket.IO client
|
||||
- **lucide-react** - Icons (already using)
|
||||
- **react-hook-form** - Form handling
|
||||
- **zod** - Schema validation
|
||||
- **axios** - HTTP client
|
||||
|
||||
### Testing
|
||||
- **jest** - Testing framework
|
||||
- **supertest** - HTTP testing
|
||||
- **vitest** - Vite-native testing
|
||||
- **@testing-library/react** - React component testing
|
||||
- **@testing-library/user-event** - User interaction simulation
|
||||
- **playwright** / **cypress** - E2E testing
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Development Tools
|
||||
|
||||
### API Development
|
||||
- **Postman** - https://www.postman.com/
|
||||
- **Insomnia** - https://insomnia.rest/
|
||||
- **Thunder Client** (VS Code extension) - https://www.thunderclient.com/
|
||||
|
||||
### Database Tools
|
||||
- **pgAdmin** - https://www.pgadmin.org/
|
||||
- **DBeaver** - https://dbeaver.io/
|
||||
- **Prisma Studio** - Built-in with Prisma
|
||||
|
||||
### WebRTC Testing
|
||||
- **Trickle ICE** - https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
|
||||
- **WebRTC Troubleshooter** - https://test.webrtc.org/
|
||||
|
||||
### Performance
|
||||
- **Lighthouse** - Chrome DevTools
|
||||
- **WebPageTest** - https://www.webpagetest.org/
|
||||
|
||||
---
|
||||
|
||||
## 📖 Articles & Guides
|
||||
|
||||
### WebRTC
|
||||
- **WebRTC File Transfer with Progress** - https://bloggeek.me/webrtc-file-transfer/
|
||||
- **Understanding WebRTC Data Channels** - https://bloggeek.me/webrtc-data-channel/
|
||||
- **WebRTC for Real-World Applications** - https://webrtchacks.com/
|
||||
|
||||
### Socket.IO
|
||||
- **Socket.IO Best Practices** - https://socket.io/docs/v4/performance-tuning/
|
||||
- **Scaling Socket.IO** - https://socket.io/docs/v4/using-multiple-nodes/
|
||||
|
||||
### Authentication
|
||||
- **JWT Authentication Best Practices** - https://blog.logrocket.com/jwt-authentication-best-practices/
|
||||
- **Session vs Token Authentication** - https://security.stackexchange.com/questions/81756/session-authentication-vs-token-authentication
|
||||
|
||||
### Docker
|
||||
- **Docker for Node.js Developers** - https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
|
||||
- **Docker Compose for Development** - https://docs.docker.com/compose/gettingstarted/
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Community
|
||||
|
||||
### Forums
|
||||
- **Stack Overflow** - https://stackoverflow.com/
|
||||
- Tag: [webrtc] - https://stackoverflow.com/questions/tagged/webrtc
|
||||
- Tag: [react] - https://stackoverflow.com/questions/tagged/react
|
||||
- Tag: [node.js] - https://stackoverflow.com/questions/tagged/node.js
|
||||
|
||||
### Discord/Slack
|
||||
- **Reactiflux** (React community) - https://www.reactiflux.com/
|
||||
- **Node.js Discord** - https://discord.com/invite/nodejs
|
||||
|
||||
### Reddit
|
||||
- **/r/webdev** - https://www.reddit.com/r/webdev/
|
||||
- **/r/reactjs** - https://www.reddit.com/r/reactjs/
|
||||
- **/r/node** - https://www.reddit.com/r/node/
|
||||
|
||||
---
|
||||
|
||||
## 📚 Recommended Reading
|
||||
|
||||
### Books
|
||||
- **Node.js Design Patterns** - Mario Casciaro
|
||||
- **Learning WebRTC** - Dan Ristic
|
||||
- **React Up & Running** - Stoyan Stefanov
|
||||
|
||||
### Blogs
|
||||
- **webrtcHacks** - https://webrtchacks.com/
|
||||
- **BlogGeek.me** - https://bloggeek.me/ (WebRTC expert)
|
||||
- **Kent C. Dodds** - https://kentcdodds.com/blog (React expert)
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-11-12
|
||||
**Note:** Links verified as of last update. Some may change over time.
|
||||
740
docs/archive/SECURITY_AUDIT.md
Normal file
740
docs/archive/SECURITY_AUDIT.md
Normal file
@@ -0,0 +1,740 @@
|
||||
# Security Audit Report - spotlight.cam Backend
|
||||
|
||||
**Date:** 2025-11-13
|
||||
**Auditor:** Security Review
|
||||
**Scope:** Backend API (Node.js/Express)
|
||||
**Framework:** OWASP Top 10 2021
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This security audit identified **21 security issues** across 4 severity levels:
|
||||
- 🔴 **CRITICAL (P0):** 5 issues - Immediate action required
|
||||
- 🟠 **HIGH (P1):** 6 issues - Fix within 1 week
|
||||
- 🟡 **MEDIUM (P2):** 7 issues - Fix within 2-4 weeks
|
||||
- 🔵 **LOW (P3):** 3 issues - Fix when convenient
|
||||
|
||||
**Overall Security Rating:** ⚠️ **MODERATE RISK**
|
||||
|
||||
---
|
||||
|
||||
## 🔴 CRITICAL Issues (P0) - FIX IMMEDIATELY
|
||||
|
||||
### 1. Secrets Exposed in `.env` File (CWE-798)
|
||||
|
||||
**Severity:** 🔴 CRITICAL
|
||||
**OWASP:** A02:2021 - Cryptographic Failures
|
||||
**File:** `backend/.env`
|
||||
|
||||
**Issue:**
|
||||
```bash
|
||||
JWT_SECRET=dev-secret-key-12345-change-in-production
|
||||
AWS_ACCESS_KEY_ID=your-aws-access-key-id
|
||||
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
|
||||
DATABASE_URL=postgresql://spotlightcam:spotlightcam123@db:5432/spotlightcam
|
||||
```
|
||||
|
||||
**Vulnerabilities:**
|
||||
- Weak JWT secret key
|
||||
- Default placeholder AWS credentials
|
||||
- Database password in plain text
|
||||
- `.env` file may be committed to git
|
||||
|
||||
**Impact:**
|
||||
- Attacker can forge JWT tokens
|
||||
- Potential unauthorized access to AWS services
|
||||
- Database compromise
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
# Use strong random secrets (at least 32 characters)
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
|
||||
# Use AWS IAM roles instead of access keys (in production)
|
||||
# Or use AWS Secrets Manager
|
||||
|
||||
# Use environment variables in production (Kubernetes secrets, Docker secrets, etc.)
|
||||
# Never commit .env to git - add to .gitignore
|
||||
```
|
||||
|
||||
**Action:**
|
||||
1. Generate strong JWT secret: `openssl rand -base64 64`
|
||||
2. Use AWS IAM roles or Secrets Manager
|
||||
3. Verify `.env` is in `.gitignore`
|
||||
4. Rotate all secrets immediately if `.env` was committed
|
||||
|
||||
---
|
||||
|
||||
### 2. Insecure Random Number Generation (CWE-338)
|
||||
|
||||
**Severity:** 🔴 CRITICAL
|
||||
**OWASP:** A02:2021 - Cryptographic Failures
|
||||
**File:** `backend/src/utils/auth.js:38`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
function generateVerificationCode() {
|
||||
return Math.floor(100000 + Math.random() * 900000).toString();
|
||||
}
|
||||
```
|
||||
|
||||
**Vulnerabilities:**
|
||||
- `Math.random()` is NOT cryptographically secure
|
||||
- Predictable verification codes
|
||||
- Can be brute-forced
|
||||
|
||||
**Impact:**
|
||||
- Attacker can predict verification codes
|
||||
- Account takeover possible
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
|
||||
function generateVerificationCode() {
|
||||
// Cryptographically secure random 6-digit code
|
||||
const bytes = crypto.randomBytes(4);
|
||||
const num = bytes.readUInt32BE(0);
|
||||
return String(num % 900000 + 100000);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. No Rate Limiting - Brute Force Vulnerability (CWE-307)
|
||||
|
||||
**Severity:** 🔴 CRITICAL
|
||||
**OWASP:** A07:2021 - Identification and Authentication Failures
|
||||
**File:** `backend/src/app.js`
|
||||
|
||||
**Issue:**
|
||||
No rate limiting on any endpoints.
|
||||
|
||||
**Vulnerabilities:**
|
||||
- Login brute force attacks
|
||||
- Password reset abuse
|
||||
- Verification code brute force (6 digits = 1M combinations)
|
||||
- Email bombing via resend verification
|
||||
|
||||
**Impact:**
|
||||
- Account takeover
|
||||
- Service disruption (DoS)
|
||||
- Email service abuse
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
npm install express-rate-limit
|
||||
```
|
||||
|
||||
```javascript
|
||||
// backend/src/app.js
|
||||
const rateLimit = require('express-rate-limit');
|
||||
|
||||
// General API rate limiter
|
||||
const apiLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 100, // limit each IP to 100 requests per windowMs
|
||||
message: 'Too many requests from this IP, please try again later.',
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
|
||||
// Strict limiter for auth endpoints
|
||||
const authLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 5, // 5 attempts
|
||||
skipSuccessfulRequests: true,
|
||||
message: 'Too many login attempts, please try again later.',
|
||||
});
|
||||
|
||||
// Email limiter
|
||||
const emailLimiter = rateLimit({
|
||||
windowMs: 60 * 60 * 1000, // 1 hour
|
||||
max: 3, // 3 emails per hour
|
||||
message: 'Too many emails sent, please try again later.',
|
||||
});
|
||||
|
||||
app.use('/api/', apiLimiter);
|
||||
app.use('/api/auth/login', authLimiter);
|
||||
app.use('/api/auth/register', authLimiter);
|
||||
app.use('/api/auth/resend-verification', emailLimiter);
|
||||
app.use('/api/auth/request-password-reset', emailLimiter);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. No Request Body Size Limit - DoS Vulnerability (CWE-400)
|
||||
|
||||
**Severity:** 🔴 CRITICAL
|
||||
**OWASP:** A05:2021 - Security Misconfiguration
|
||||
**File:** `backend/src/app.js:11`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
app.use(express.json()); // No limit
|
||||
app.use(express.urlencoded({ extended: true })); // No limit
|
||||
```
|
||||
|
||||
**Vulnerabilities:**
|
||||
- Attacker can send huge JSON payloads
|
||||
- Memory exhaustion (DoS)
|
||||
|
||||
**Impact:**
|
||||
- Server crash
|
||||
- Service unavailability
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
app.use(express.json({ limit: '10kb' }));
|
||||
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. User Enumeration Vulnerability (CWE-204)
|
||||
|
||||
**Severity:** 🔴 CRITICAL
|
||||
**OWASP:** A01:2021 - Broken Access Control
|
||||
**File:** `backend/src/controllers/auth.js:28-46`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
if (existingUser.email === email) {
|
||||
return res.status(400).json({
|
||||
error: 'Email already registered',
|
||||
});
|
||||
}
|
||||
if (existingUser.username === username) {
|
||||
return res.status(400).json({
|
||||
error: 'Username already taken',
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Vulnerabilities:**
|
||||
- Reveals which emails/usernames are registered
|
||||
- Enables targeted attacks
|
||||
|
||||
**Impact:**
|
||||
- Email/username enumeration
|
||||
- Privacy breach
|
||||
- Targeted phishing attacks
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
// Don't reveal which field exists
|
||||
if (existingUser) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'An account with these credentials already exists',
|
||||
});
|
||||
}
|
||||
|
||||
// Or implement verification via email before confirming registration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🟠 HIGH Issues (P1) - Fix Within 1 Week
|
||||
|
||||
### 6. Weak Password Policy (CWE-521)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**File:** `backend/src/middleware/validators.js:30`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
body('password')
|
||||
.isLength({ min: 6 }) // Too weak!
|
||||
```
|
||||
|
||||
And in `auth.js:441`:
|
||||
```javascript
|
||||
if (newPassword.length < 8) // Inconsistent
|
||||
```
|
||||
|
||||
**Vulnerabilities:**
|
||||
- 6 characters is too weak (should be 8+)
|
||||
- No complexity requirements
|
||||
- Inconsistent validation (6 vs 8)
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
body('password')
|
||||
.isLength({ min: 8, max: 128 })
|
||||
.withMessage('Password must be between 8 and 128 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
|
||||
.withMessage('Password must contain at least one uppercase, one lowercase, and one number'),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Missing Security Headers (CWE-693)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**OWASP:** A05:2021 - Security Misconfiguration
|
||||
**File:** `backend/src/app.js`
|
||||
|
||||
**Issue:**
|
||||
No security headers (CSP, HSTS, X-Frame-Options, etc.)
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
npm install helmet
|
||||
```
|
||||
|
||||
```javascript
|
||||
const helmet = require('helmet');
|
||||
|
||||
app.use(helmet({
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
styleSrc: ["'self'", "'unsafe-inline'"],
|
||||
scriptSrc: ["'self'"],
|
||||
imgSrc: ["'self'", "data:", "https:"],
|
||||
},
|
||||
},
|
||||
hsts: {
|
||||
maxAge: 31536000,
|
||||
includeSubDomains: true,
|
||||
preload: true,
|
||||
},
|
||||
}));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8. No Account Lockout After Failed Logins (CWE-307)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**File:** `backend/src/controllers/auth.js:120`
|
||||
|
||||
**Issue:**
|
||||
No account lockout mechanism after multiple failed login attempts.
|
||||
|
||||
**Recommendation:**
|
||||
Add to database schema:
|
||||
```prisma
|
||||
model User {
|
||||
failedLoginAttempts Int @default(0)
|
||||
lockedUntil DateTime?
|
||||
}
|
||||
```
|
||||
|
||||
Implement lockout logic:
|
||||
```javascript
|
||||
// In login controller
|
||||
if (user.lockedUntil && user.lockedUntil > new Date()) {
|
||||
return res.status(423).json({
|
||||
error: 'Account temporarily locked due to too many failed login attempts',
|
||||
lockedUntil: user.lockedUntil,
|
||||
});
|
||||
}
|
||||
|
||||
if (!isPasswordValid) {
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: {
|
||||
failedLoginAttempts: { increment: 1 },
|
||||
...(user.failedLoginAttempts + 1 >= 5 && {
|
||||
lockedUntil: new Date(Date.now() + 15 * 60 * 1000), // 15 minutes
|
||||
}),
|
||||
},
|
||||
});
|
||||
return res.status(401).json({ error: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
// Reset on successful login
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: { failedLoginAttempts: 0, lockedUntil: null },
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. Missing Input Validation for WSDC Data (CWE-20)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**File:** `backend/src/controllers/auth.js:15`
|
||||
|
||||
**Issue:**
|
||||
No validation for `firstName`, `lastName`, `wsdcId` in register.
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
// In validators.js
|
||||
body('firstName')
|
||||
.optional()
|
||||
.trim()
|
||||
.isLength({ max: 100 })
|
||||
.matches(/^[a-zA-Z\s'-]+$/)
|
||||
.withMessage('Invalid first name'),
|
||||
body('lastName')
|
||||
.optional()
|
||||
.trim()
|
||||
.isLength({ max: 100 })
|
||||
.matches(/^[a-zA-Z\s'-]+$/)
|
||||
.withMessage('Invalid last name'),
|
||||
body('wsdcId')
|
||||
.optional()
|
||||
.trim()
|
||||
.matches(/^\d{1,10}$/)
|
||||
.withMessage('WSDC ID must be numeric (max 10 digits)'),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 10. No Email Input Sanitization - XSS Risk (CWE-79)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**OWASP:** A03:2021 - Injection
|
||||
**File:** `backend/src/utils/email.js:98`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
<h2>Hi ${firstName || 'there'}! 👋</h2>
|
||||
```
|
||||
|
||||
If `firstName` contains `<script>alert('XSS')</script>`, it's injected into email.
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
npm install dompurify jsdom
|
||||
```
|
||||
|
||||
```javascript
|
||||
const createDOMPurify = require('dompurify');
|
||||
const { JSDOM } = require('jsdom');
|
||||
const window = new JSDOM('').window;
|
||||
const DOMPurify = createDOMPurify(window);
|
||||
|
||||
// Sanitize before using in email
|
||||
const sanitizedFirstName = DOMPurify.sanitize(firstName || 'there', {
|
||||
ALLOWED_TAGS: [],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 11. Missing CSRF Protection (CWE-352)
|
||||
|
||||
**Severity:** 🟠 HIGH
|
||||
**OWASP:** A01:2021 - Broken Access Control
|
||||
**File:** `backend/src/app.js`
|
||||
|
||||
**Issue:**
|
||||
No CSRF token validation for state-changing operations.
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
npm install csurf cookie-parser
|
||||
```
|
||||
|
||||
```javascript
|
||||
const csrf = require('csurf');
|
||||
const cookieParser = require('cookie-parser');
|
||||
|
||||
app.use(cookieParser());
|
||||
app.use(csrf({ cookie: true }));
|
||||
|
||||
// Add endpoint to get CSRF token
|
||||
app.get('/api/csrf-token', (req, res) => {
|
||||
res.json({ csrfToken: req.csrfToken() });
|
||||
});
|
||||
|
||||
// Frontend must include CSRF token in requests
|
||||
// Headers: { 'X-CSRF-Token': token }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM Issues (P2) - Fix Within 2-4 Weeks
|
||||
|
||||
### 12. Permissive CORS Configuration (CWE-346)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/app.js:7`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
app.use(cors({
|
||||
origin: process.env.CORS_ORIGIN || 'http://localhost:8080',
|
||||
credentials: true
|
||||
}));
|
||||
```
|
||||
|
||||
In production, this could be misconfigured.
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
const allowedOrigins = [
|
||||
'https://spotlight.cam',
|
||||
'https://www.spotlight.cam',
|
||||
...(process.env.NODE_ENV === 'development' ? ['http://localhost:8080'] : []),
|
||||
];
|
||||
|
||||
app.use(cors({
|
||||
origin: (origin, callback) => {
|
||||
if (!origin || allowedOrigins.includes(origin)) {
|
||||
callback(null, true);
|
||||
} else {
|
||||
callback(new Error('Not allowed by CORS'));
|
||||
}
|
||||
},
|
||||
credentials: true,
|
||||
maxAge: 86400, // 24 hours
|
||||
}));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 13. Error Information Disclosure (CWE-209)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/app.js:47`
|
||||
|
||||
**Issue:**
|
||||
```javascript
|
||||
res.status(err.status || 500).json({
|
||||
error: err.message || 'Internal Server Error',
|
||||
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
|
||||
});
|
||||
```
|
||||
|
||||
Stack traces leak in development if `NODE_ENV` not set in production.
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
app.use((err, req, res, next) => {
|
||||
console.error('Error:', err);
|
||||
|
||||
// Log full error internally
|
||||
logger.error(err);
|
||||
|
||||
// Return generic error to client in production
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
|
||||
res.status(err.status || 500).json({
|
||||
error: isDevelopment ? err.message : 'Internal Server Error',
|
||||
...(isDevelopment && { stack: err.stack }),
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 14. No Validation on Email Verification Endpoints
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/controllers/auth.js:233`
|
||||
|
||||
**Issue:**
|
||||
No input validation for `verifyEmailByCode`.
|
||||
|
||||
**Recommendation:**
|
||||
Add validation:
|
||||
```javascript
|
||||
body('email').trim().isEmail().normalizeEmail(),
|
||||
body('code').trim().matches(/^\d{6}$/).withMessage('Code must be 6 digits'),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 15. No Logging for Security Events (CWE-778)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** All controllers
|
||||
|
||||
**Issue:**
|
||||
Only `console.log()` used. No structured logging.
|
||||
|
||||
**Recommendation:**
|
||||
```bash
|
||||
npm install winston
|
||||
```
|
||||
|
||||
```javascript
|
||||
const winston = require('winston');
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.json(),
|
||||
transports: [
|
||||
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
||||
new winston.transports.File({ filename: 'security.log', level: 'warn' }),
|
||||
new winston.transports.File({ filename: 'combined.log' }),
|
||||
],
|
||||
});
|
||||
|
||||
// Log security events
|
||||
logger.warn('Failed login attempt', { email, ip: req.ip });
|
||||
logger.warn('Account locked', { userId, ip: req.ip });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 16. Missing JWT Token Blacklist/Revocation (CWE-613)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/utils/auth.js`
|
||||
|
||||
**Issue:**
|
||||
No way to revoke JWT tokens before expiry.
|
||||
|
||||
**Recommendation:**
|
||||
Implement token blacklist using Redis:
|
||||
```javascript
|
||||
// When user logs out or changes password
|
||||
await redis.setex(`blacklist:${token}`, 86400, '1');
|
||||
|
||||
// In auth middleware
|
||||
const isBlacklisted = await redis.get(`blacklist:${token}`);
|
||||
if (isBlacklisted) {
|
||||
return res.status(401).json({ error: 'Token revoked' });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 17. No Password History Check (CWE-521)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/controllers/auth.js:429`
|
||||
|
||||
**Issue:**
|
||||
Users can reuse old passwords.
|
||||
|
||||
**Recommendation:**
|
||||
Add password history tracking (prevent reuse of last 5 passwords).
|
||||
|
||||
---
|
||||
|
||||
### 18. Timing Attack Vulnerability in Token Comparison (CWE-208)
|
||||
|
||||
**Severity:** 🟡 MEDIUM
|
||||
**File:** `backend/src/controllers/auth.js:178`
|
||||
|
||||
**Issue:**
|
||||
String comparison for tokens may leak timing information.
|
||||
|
||||
**Recommendation:**
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
|
||||
function timingSafeEqual(a, b) {
|
||||
if (typeof a !== 'string' || typeof b !== 'string') return false;
|
||||
if (a.length !== b.length) return false;
|
||||
|
||||
return crypto.timingSafeEqual(
|
||||
Buffer.from(a, 'utf8'),
|
||||
Buffer.from(b, 'utf8')
|
||||
);
|
||||
}
|
||||
|
||||
// Use in comparisons
|
||||
if (!timingSafeEqual(user.verificationToken, token)) {
|
||||
return res.status(404).json({ error: 'Invalid token' });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔵 LOW Issues (P3) - Fix When Convenient
|
||||
|
||||
### 19. No Security Monitoring/Alerts
|
||||
|
||||
**Severity:** 🔵 LOW
|
||||
|
||||
**Recommendation:**
|
||||
Implement monitoring for:
|
||||
- Multiple failed login attempts
|
||||
- Password reset requests
|
||||
- Account lockouts
|
||||
- Unusual API usage patterns
|
||||
|
||||
---
|
||||
|
||||
### 20. Missing HTTP Strict Transport Security (HSTS)
|
||||
|
||||
**Severity:** 🔵 LOW
|
||||
|
||||
**Recommendation:**
|
||||
Add via helmet (see issue #7).
|
||||
|
||||
---
|
||||
|
||||
### 21. No Password Strength Meter Feedback
|
||||
|
||||
**Severity:** 🔵 LOW
|
||||
|
||||
**Recommendation:**
|
||||
Implement server-side password strength validation:
|
||||
```bash
|
||||
npm install zxcvbn
|
||||
```
|
||||
|
||||
```javascript
|
||||
const zxcvbn = require('zxcvbn');
|
||||
|
||||
const result = zxcvbn(password);
|
||||
if (result.score < 3) {
|
||||
return res.status(400).json({
|
||||
error: 'Password too weak',
|
||||
suggestions: result.feedback.suggestions,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Best Practices Checklist
|
||||
|
||||
- [ ] Use environment-specific secrets
|
||||
- [ ] Implement rate limiting on all endpoints
|
||||
- [ ] Use helmet.js for security headers
|
||||
- [ ] Enable CSRF protection
|
||||
- [ ] Add request body size limits
|
||||
- [ ] Implement account lockout mechanism
|
||||
- [ ] Use cryptographically secure random generation
|
||||
- [ ] Add input validation for all endpoints
|
||||
- [ ] Sanitize user inputs (XSS prevention)
|
||||
- [ ] Implement structured logging
|
||||
- [ ] Add security monitoring and alerts
|
||||
- [ ] Use HTTPS in production
|
||||
- [ ] Implement JWT token revocation
|
||||
- [ ] Add password strength requirements
|
||||
- [ ] Use timing-safe comparisons for sensitive data
|
||||
- [ ] Prevent user enumeration
|
||||
- [ ] Implement proper CORS configuration
|
||||
- [ ] Regular security audits
|
||||
- [ ] Dependency vulnerability scanning (`npm audit`)
|
||||
- [ ] Keep dependencies up to date
|
||||
|
||||
---
|
||||
|
||||
## Immediate Action Items (This Week)
|
||||
|
||||
1. **Generate and rotate all secrets**
|
||||
2. **Install and configure rate limiting** (`express-rate-limit`)
|
||||
3. **Install and configure helmet** (`helmet`)
|
||||
4. **Fix cryptographic random generation** in `generateVerificationCode()`
|
||||
5. **Add request body size limits**
|
||||
6. **Strengthen password requirements** (8+ chars, complexity)
|
||||
7. **Fix user enumeration** in registration
|
||||
8. **Add input validation** for all fields
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- OWASP Top 10 2021: https://owasp.org/Top10/
|
||||
- Node.js Security Checklist: https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html
|
||||
- Express Security Best Practices: https://expressjs.com/en/advanced/best-practice-security.html
|
||||
|
||||
---
|
||||
|
||||
**Report Generated:** 2025-11-13
|
||||
**Next Audit Recommended:** 2025-12-13 (or after major changes)
|
||||
Reference in New Issue
Block a user