Replace sequential event IDs in URLs with unique alphanumeric slugs to prevent enumeration attacks. Event URLs now use format /events/{slug}/chat instead of /events/{id}/chat.
Backend changes:
- Add slug field (VARCHAR 50, unique) to Event model
- Create migration with auto-generated 12-char MD5-based slugs for existing events
- Update GET /api/events/:slug endpoint (changed from :id)
- Update GET /api/events/:slug/messages endpoint (changed from :eventId)
- Modify Socket.IO join_event_room to accept slug parameter
- Update send_event_message to use stored event context instead of passing eventId
Frontend changes:
- Update eventsAPI.getBySlug() method (changed from getById)
- Update eventsAPI.getMessages() to use slug parameter
- Change route from /events/:eventId/chat to /events/:slug/chat
- Update EventsPage to navigate using event.slug
- Update EventChatPage to fetch event data via slug and use slug in socket events
Security impact: Prevents attackers from discovering all events by iterating sequential IDs.
Backend:
- Add EventParticipant model to track user-event participation
- Create database migration for event_participants table
- Record participation when user joins event chat via Socket.IO
- Update GET /api/events to include isJoined flag for current user
- Sort events: joined events first, then by start date
- Add authenticate middleware to GET /api/events
Frontend:
- Replace mock events with real API data from backend
- Add loading and error states to EventsPage
- Display "Joined" badge on events user has joined
- Highlight joined events with colored border
- Show "Open chat" vs "Join chat" button text
- Auto-refresh events list when navigating back
When users join an event chat, this is now recorded in the database.
Joined events appear at the top of the list with visual indicators.
- Add GET /api/users/:username endpoint for public profiles
- Create PublicProfilePage component with user stats and info
- Add getUserByUsername function to API service
- Add /:username route to App.jsx
- Display user info: name, location, stats, WSDC ID, social links
- Only show public data (no email or sensitive information)
- Accessible only to authenticated users
Users can now view public profiles of other users by visiting
/<username>. The profile displays stats, location, WSDC ID, and
social media links.
- Add country and city fields to User model
- Create database migration for location fields
- Add validation for country and city (max 100 characters)
- Create countries.js with complete list of 195 countries
- Add country dropdown select and city text input to profile page
- Include country and city in GET /api/users/me response
- Update profile form to support location data
Users can now select their country from a dropdown list of all
countries and enter their city name.
- Add YouTube, Instagram, Facebook, and TikTok URL fields to User model
- Create database migration for social media link columns
- Add custom validators to ensure URLs contain correct domains
- Update profile page with social media input fields
- Include social media URLs in GET /api/users/me response
- Add icons for each social platform in the UI
Users can now add links to their social media profiles. Each field
validates that the URL contains the appropriate domain (e.g.,
instagram.com for Instagram, youtube.com/youtu.be for YouTube).
- Add useEffect to pre-fill profile form with current user data
- Add WSDC ID field to profile edit form with numeric validation
- Update backend to accept wsdcId in profile updates with null handling
- Add wsdcId validation to updateProfileValidation middleware
- Include firstName, lastName, wsdcId in GET /api/users/me response
Fixes issue where profile inputs were empty on page load and allows
users to update their WSDC ID.
Backend changes:
- Add PATCH /api/users/me endpoint for profile updates (firstName, lastName, email)
- Add PATCH /api/users/me/password endpoint for password change
- Email change triggers re-verification flow (emailVerified=false, new verification token/code)
- Send verification email automatically on email change
- Return new JWT token when email changes (to update emailVerified status)
- Add validation for profile update and password change
- Create user controller with updateProfile and changePassword functions
Frontend changes:
- Add ProfilePage with tabbed interface (Profile & Password tabs)
- Profile tab: Edit firstName, lastName, email
- Password tab: Change password (requires current password)
- Add Profile link to navigation bar
- Add authAPI.updateProfile() and authAPI.changePassword() functions
- Update AuthContext user data when profile is updated
- Display success/error messages for profile and password updates
Security:
- Username cannot be changed (permanent identifier)
- Email uniqueness validation
- Password change requires current password
- Email change forces re-verification to prevent hijacking
User flow:
1. User edits profile and changes email
2. Backend sets emailVerified=false and generates new verification tokens
3. Verification email sent to new address
4. User must verify new email to access all features
5. Banner appears until email is verified
Backend changes:
- Socket.IO: Send last 20 messages on join_event_room
- REST API: Add GET /api/events/:eventId/messages endpoint with pagination
- Support for 'before' cursor-based pagination for loading older messages
Frontend changes:
- Load initial 20 messages when joining event chat
- Implement infinite scroll to load older messages on scroll to top
- Add loading indicator for older messages
- Preserve scroll position when loading older messages
- Add eventsAPI.getMessages() function for pagination
User experience:
- New users see last 20 messages immediately
- Scrolling up automatically loads older messages in batches of 20
- Smooth scrolling experience with position restoration
Note: Messages are encrypted in transit via HTTPS/WSS but stored
as plain text in database (no E2E encryption).
The verification banner was reappearing after login/refresh because
the /api/users/me endpoint was not returning the emailVerified field.
This ensures the frontend always has access to the current email
verification status when loading user data.
Changes:
- Updated AWS_REGION to eu-central-1 in env examples
- Fixed email verification to return new JWT token with updated emailVerified status
- Added updateUser function to AuthContext for token refresh
- Updated frontend to save new token after email verification
- Fixed variable naming conflict (token vs jwtToken) in verification endpoints
- Changed WSDC ID placeholder from 26997 to 12345
This ensures the verification banner disappears immediately after
email verification without requiring re-login.
Simplified Docker Compose configuration by using native profiles
instead of override files, following best practices.
Changes:
- Consolidated docker-compose.yml with --profile dev/prod support
- Removed docker-compose.dev.yml and docker-compose.prod.yml
- Updated all documentation for new usage pattern
- Created comprehensive README.md and DEPLOYMENT.md
- Simplified commands: 'docker compose --profile dev up'
Environment-specific configurations:
- Development: relaxed security, hot reload, exposed ports
- Production: strict security, optimized builds, restricted access
This approach is cleaner, more maintainable, and follows Docker
Compose best practices.
Enhanced WSDC registration flow with auto-lookup and account validation:
Backend changes:
- Add accountExists flag to WSDC lookup endpoint
- Check database for existing users with WSDC ID
- Fix Prisma binary target for Alpine Linux Docker containers
Frontend changes:
- Auto-lookup WSDC data after entering 4+ digits (500ms debounce)
- Show live preview dropdown with dancer information
- Display warning if account with WSDC ID already exists
- Block registration and suggest login for existing accounts
- Improve UX with real-time validation feedback
- Add CheckCircle, XCircle, AlertCircle icons for visual feedback
This prevents duplicate WSDC ID registrations and provides immediate
feedback to users, improving the registration experience.
Tested with:
- ID 26111 (Vince Yap) - new account allowed
- ID 26997 (Radoslaw) - existing account blocked
Backend features:
- AWS SES email service with HTML templates
- Email verification with dual method (link + 6-digit PIN code)
- Password reset workflow with secure tokens
- WSDC API proxy for dancer lookup and auto-fill registration
- Extended User model with verification and WSDC fields
- Email verification middleware for protected routes
Frontend features:
- Two-step registration with WSDC ID lookup
- Password strength indicator component
- Email verification page with code input
- Password reset flow (request + reset pages)
- Verification banner for unverified users
- Updated authentication context and API service
Testing:
- 65 unit tests with 100% coverage of new features
- Tests for auth utils, email service, WSDC controller, and middleware
- Integration tests for full authentication flows
- Comprehensive mocking of AWS SES and external APIs
Database:
- Migration: add WSDC fields (firstName, lastName, wsdcId)
- Migration: add email verification fields (token, code, expiry)
- Migration: add password reset fields (token, expiry)
Documentation:
- Complete Phase 1.5 documentation
- Test suite documentation and best practices
- Updated session context with new features
Implemented WebSocket-based real-time messaging for both event rooms and private match chats using Socket.IO with comprehensive test coverage.
Backend changes:
- Installed socket.io@4.8.1 for WebSocket server
- Created Socket.IO server with JWT authentication middleware
- Implemented event room management (join/leave/messages)
- Added active users tracking with real-time updates
- Implemented private match room messaging
- Integrated Socket.IO with Express HTTP server
- Messages are persisted to PostgreSQL via Prisma
- Added 12 comprehensive unit tests (89.13% coverage)
Frontend changes:
- Installed socket.io-client for WebSocket connections
- Created socket service layer for connection management
- Updated EventChatPage with real-time messaging
- Updated MatchChatPage with real-time private chat
- Added connection status indicators (● Connected/Disconnected)
- Disabled message input when not connected
Infrastructure:
- Updated nginx config to proxy WebSocket connections at /socket.io
- Added Upgrade and Connection headers for WebSocket support
- Set long timeouts (7d) for persistent WebSocket connections
Key features:
- JWT-authenticated socket connections
- Room-based architecture for events and matches
- Real-time message broadcasting
- Active users list with automatic updates
- Automatic cleanup on disconnect
- Message persistence in database
Test coverage:
- 12 tests passing (authentication, event rooms, match rooms, disconnect, errors)
- Socket.IO module: 89.13% statements, 81.81% branches, 91.66% functions
- Overall coverage: 81.19%
Phase 1, Step 4 completed. Ready for Phase 2 (Core Features).
Phase 1 - Step 2: PostgreSQL Setup
**Infrastructure:**
- Add PostgreSQL 15 Alpine container to docker-compose.yml
- Configure persistent volume for database data
- Update backend Dockerfile with OpenSSL for Prisma compatibility
**Database Schema (Prisma):**
- 6 tables: users, events, chat_rooms, messages, matches, ratings
- Foreign key relationships and cascading deletes
- Performance indexes on frequently queried columns
- Unique constraints for data integrity
**Prisma Setup:**
- Prisma Client for database queries
- Migration system with initial migration
- Seed script with 4 test events and chat rooms
- Database connection utility with singleton pattern
**API Implementation:**
- GET /api/events - List all events (with filtering and sorting)
- GET /api/events/:id - Get single event with relations
- Database connection test on server startup
- Graceful database disconnect on shutdown
**Seed Data:**
- Warsaw Dance Festival 2025
- Swing Camp Barcelona 2025
- Blues Week Herräng 2025
- Krakow Swing Connection 2025
**Testing:**
- Database connection verified ✅
- API endpoints returning data from PostgreSQL ✅
- Migrations applied successfully ✅
All systems operational 🚀