ilia df865dca41
All checks were successful
CI / skip-ci-check (push) Successful in 1m25s
CI / lint-and-type-check (push) Successful in 1m50s
CI / test (push) Successful in 1m54s
CI / build (push) Successful in 1m54s
CI / secret-scanning (push) Successful in 1m26s
CI / dependency-scan (push) Successful in 1m31s
CI / sast-scan (push) Successful in 2m34s
CI / workflow-summary (push) Successful in 1m23s
This MR fixes critical authentication issues that prevented login on localhost and improves the developer experience with consolidated rebuild scripts and a working help modal keyboard shortcut. (#5)
# Fix authentication issues and improve developer experience

## Summary

This MR fixes critical authentication issues that prevented login on localhost and improves the developer experience with consolidated rebuild scripts and a working help modal keyboard shortcut.

## Problems Fixed

### 1. Authentication Issues
- **UntrustedHost Error**: NextAuth v5 was rejecting localhost requests with "UntrustedHost: Host must be trusted" error
- **Cookie Prefix Errors**: Cookies were being set with `__Host-` and `__Secure-` prefixes on HTTP (localhost), causing browser rejection
- **MissingCSRF Error**: CSRF token cookies were not being set correctly due to cookie configuration issues

### 2. Help Modal Keyboard Shortcut
- **Shift+? not working**: The help modal keyboard shortcut was not detecting the question mark key correctly

### 3. Developer Experience
- **Multiple rebuild scripts**: Had several overlapping rebuild scripts that were confusing
- **Unused code**: Removed unused `useSecureCookies` variable and misleading comments

## Changes Made

### Authentication Fixes (`lib/auth.ts`)
- Set `trustHost: true` to fix UntrustedHost error (required for NextAuth v5)
- Added explicit cookie configuration for HTTP (localhost) to prevent prefix errors:
  - Cookies use `secure: false` for HTTP
  - Cookie names without prefixes for HTTP
  - Let Auth.js defaults handle HTTPS (with prefixes and Secure flag)
- Removed unused `useSecureCookies` variable
- Simplified debug logging

### Help Modal Fix (`components/HelpModal.tsx`)
- Fixed keyboard shortcut detection to properly handle Shift+? (Shift+/)
- Updated help text to show correct shortcut (Shift+? instead of Ctrl+?)

### Developer Scripts
- **Consolidated rebuild scripts**: Merged `CLEAN_REBUILD.sh`, `FIX_AND_RESTART.sh`, and `start-server.sh` into single `rebuild.sh`
- **Added REBUILD.md**: Documentation for rebuild process
- Removed redundant script files

### Code Cleanup
- Removed unused `useSecureCookies` variable from `lib/auth.ts`
- Removed misleading comment from `app/api/auth/[...nextauth]/route.ts`
- Cleaned up verbose debug logging

## Technical Details

### Cookie Configuration
The fix works by explicitly configuring cookies for HTTP environments:
- **HTTP (localhost)**: Cookies without prefixes, `secure: false`
- **HTTPS (production)**: Let Auth.js defaults handle (prefixes + Secure flag)

This prevents NextAuth v5 from auto-detecting HTTPS from proxy headers and incorrectly adding cookie prefixes.

### Keyboard Shortcut
The question mark key requires Shift+/ on most keyboards. The fix now properly detects:
- `event.shiftKey && event.key === "/"`
- `event.key === "?"` (fallback)
- `event.code === "Slash" && event.shiftKey` (additional fallback)

## Testing

-  Login works on localhost (http://localhost:3000)
-  No cookie prefix errors in browser console
-  No UntrustedHost errors in server logs
-  Help modal opens/closes with Shift+?
-  Rebuild script works in both dev and prod modes

## Files Changed

### Modified
- `lib/auth.ts` - Authentication configuration fixes
- `components/HelpModal.tsx` - Keyboard shortcut fix
- `app/api/auth/[...nextauth]/route.ts` - Removed misleading comment

### Added
- `rebuild.sh` - Consolidated rebuild script
- `REBUILD.md` - Rebuild documentation

## Migration Notes

No database migrations or environment variable changes required. The fix works with existing configuration.

## Related Issues

Fixes authentication issues preventing local development and testing.

Reviewed-on: #5
2026-01-05 19:42:46 -05:00

MirrorMatch

A photo guessing game where users upload photos and other users guess who is in the picture to earn points. Built with Next.js, PostgreSQL, and NextAuth.

📚 Important: Read Documentation First

Before making code changes, please read:

  • .cursor/rules/mirrormatch.mdc - Project rules and guidelines
  • ARCHITECTURE.md - System design and data flows
  • CONTRIBUTING.md - Coding conventions and workflow
  • SECURITY.md - Security practices
  • This README - Setup and usage

Keep documentation updated: When you modify code that changes behavior or architecture, update the relevant documentation files to keep them in sync.

Features

  • User Management: Admin can create users with email/password authentication
  • Photo Upload: Users can upload photos with answer names
  • Guessing Game: Users guess who is in photos to earn points
  • Email Notifications: Users receive emails when new photos are uploaded
  • Leaderboard: Track user points and rankings
  • Profile Management: Users can view their points and change passwords

Tech Stack

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript
  • Database: PostgreSQL
  • ORM: Prisma
  • Authentication: NextAuth.js (Credentials Provider)
  • Styling: Tailwind CSS
  • Email: Nodemailer (Ethereal in dev, SMTP in production)

Prerequisites

  • Node.js 18+ and npm
  • PostgreSQL database (local or remote)
  • For production: SMTP email server credentials

Installation

  1. Clone the repository (if applicable) or navigate to the project directory:

    cd mirrormatch
    
  2. Install dependencies:

    npm install
    
  3. Set up environment variables: Create a .env file in the root directory with the following variables:

    # Database
    DATABASE_URL="postgresql://user:password@localhost:5432/mirrormatch?schema=public"
    
    # NextAuth
    NEXTAUTH_URL="http://localhost:3000"
    NEXTAUTH_SECRET="your-secret-key-here-generate-with-openssl-rand-base64-32"
    
    # Email Configuration (for production)
    SMTP_HOST="smtp.example.com"
    SMTP_PORT="587"
    SMTP_USER="your-email@example.com"
    SMTP_PASSWORD="your-email-password"
    SMTP_FROM="MirrorMatch <noreply@mirrormatch.com>"
    

    Generate NEXTAUTH_SECRET:

    openssl rand -base64 32
    

    Note: In development, emails will use Ethereal (test emails) or console logging. No SMTP config is needed for dev mode.

  4. Set up the database:

    # Generate Prisma Client
    npm run db:generate
    
    # Run migrations
    npm run db:migrate
    
    # Or push schema directly (for development)
    npm run db:push
    
  5. Seed the database (creates default admin user):

    npm run db:seed
    

    This creates an admin user with:

    • Email: admin@mirrormatch.com
    • Password: admin123
    • ⚠️ Important: Change this password after first login!

Basic Usage

Workflow Overview

  1. Admin creates users:

    • Admin logs in and navigates to /admin
    • Creates new users with email, password, and role
    • Users receive temporary passwords
  2. Users log in:

    • Users navigate to /login
    • Enter email and password
    • Access the main application
  3. Users upload photos:

    • Navigate to /upload
    • Enter photo URL and answer name (the correct name to guess)
    • Photo is saved and emails are sent to all other users
  4. Users guess photos:

    • View photos on /photos page
    • Click a photo to view details
    • Submit guesses for who is in the photo
    • Earn points for correct guesses (case-insensitive matching)
  5. Leaderboard:

    • View rankings on /leaderboard page
    • See all users sorted by points
    • Track your own position

Key Features

  • Admin Panel: Create and manage users, reset passwords
  • Photo Upload: Upload photos with answer names
  • Guessing System: Submit guesses and earn points
  • Email Notifications: Get notified when new photos are uploaded
  • Leaderboard: Track user rankings by points
  • Profile Management: View points and change password

Running the Application

Development

npm run dev

Open http://localhost:3000 in your browser.

Production

npm run build
npm start

Deployment Notes

Important Configuration:

  • Ensure NODE_ENV=production is set in production
  • Set NEXTAUTH_URL to your production domain (e.g., https://yourdomain.com)
  • Set AUTH_TRUST_HOST=true if using reverse proxy
  • Ensure DATABASE_URL points to your production database
  • Files are stored in public/uploads/ directory - ensure this directory persists across deployments

File Uploads:

  • Photos are uploaded to public/uploads/ directory
  • Files are served via /api/uploads/[filename] API route
  • Ensure the uploads directory has proper write permissions

Upload Endpoints:

  • POST /api/photos/upload - Single photo upload (supports both file and URL uploads)
  • POST /api/photos/upload-multiple - Multiple photo uploads in batch (used by upload page)
  • Files are stored on the filesystem (not in database)

Monitoring Activity:

  • User activity is logged to console/systemd logs
  • Watch logs in real-time: sudo journalctl -u app-backend -f | grep -E "\[ACTIVITY\]|\[PHOTO_UPLOAD\]|\[GUESS_SUBMIT\]"
  • Activity logs include: page visits, photo uploads, guess submissions
  • Note: For local development, use ./watch-activity.sh script (if systemd/journalctl is not available, check application logs directly)

Database Commands

  • npm run db:generate - Generate Prisma Client
  • npm run db:migrate - Run database migrations
  • npm run db:push - Push schema changes to database (dev only)
  • npm run db:studio - Open Prisma Studio (database GUI)
  • npm run db:seed - Seed database with initial admin user

Querying the Database

Get all photo answers:

psql "postgresql://user:password@host:5432/database" -c "SELECT \"answerName\" FROM \"Photo\" ORDER BY \"createdAt\" DESC;"

Get answers with uploader info:

psql "postgresql://user:password@host:5432/database" -c "SELECT p.\"answerName\", p.url, u.name as uploader, p.\"createdAt\" FROM \"Photo\" p JOIN \"User\" u ON p.\"uploaderId\" = u.id ORDER BY p.\"createdAt\" DESC;"

Creating the First Admin User

The seed script automatically creates an admin user. If you need to create one manually:

  1. Run the seed script: npm run db:seed
  2. Or use Prisma Studio: npm run db:studio and create a user with role: "ADMIN"

Project Structure

mirrormatch/
├── app/                    # Next.js App Router pages
│   ├── api/               # API routes
│   │   ├── admin/        # Admin API routes
│   │   ├── auth/         # NextAuth routes
│   │   ├── photos/       # Photo-related API routes
│   │   └── profile/      # Profile API routes
│   ├── admin/            # Admin panel page
│   ├── leaderboard/      # Leaderboard page
│   ├── login/            # Login page
│   ├── photos/           # Photos listing and detail pages
│   ├── profile/          # User profile page
│   └── upload/           # Photo upload page
├── components/            # React components
├── lib/                   # Utility libraries
│   ├── auth.ts           # NextAuth configuration
│   ├── email.ts          # Email sending utilities
│   ├── prisma.ts         # Prisma client instance
│   └── utils.ts          # Helper functions
├── prisma/                # Prisma schema and migrations
│   ├── schema.prisma     # Database schema
│   └── seed.ts           # Database seed script
└── types/                 # TypeScript type definitions

Features Overview

Authentication

  • Email/password login via NextAuth
  • Protected routes with middleware
  • Role-based access control (ADMIN/USER)

Admin Panel (/admin)

  • View all users
  • Create new users
  • Reset user passwords
  • View user points and roles

Photo Upload (/upload)

  • Upload photos via file upload or URL
  • Files are stored in public/uploads/ directory
  • Files are served via /api/uploads/[filename] API route
  • Set answer name for guessing
  • Automatically sends email notifications to all other users
  • Duplicate file detection (SHA256 hash)

Photo Guessing (/photos/[id])

  • View photo and uploader info
  • Submit guesses
  • Get instant feedback (correct/wrong)
  • Earn points for correct guesses
  • Case-insensitive matching

Leaderboard (/leaderboard)

  • View all users ranked by points
  • See your own ranking highlighted

Profile (/profile)

  • View your points and account info
  • Change password (requires current password)

Email Configuration

Development

In development mode, the app uses:

  • Ethereal Email (if available) - provides test email accounts with preview URLs
  • Console transport (fallback) - logs emails to console

Check the console for email preview URLs when using Ethereal.

Production

Set up SMTP credentials in .env:

  • SMTP_HOST - Your SMTP server hostname
  • SMTP_PORT - SMTP port (usually 587 for TLS, 465 for SSL)
  • SMTP_USER - SMTP username
  • SMTP_PASSWORD - SMTP password
  • SMTP_FROM - From address for emails

Security Notes

  • Passwords are hashed using bcrypt
  • NextAuth handles session management
  • Middleware protects routes
  • Admin routes are restricted to ADMIN role
  • SQL injection protection via Prisma

Troubleshooting

Database Connection Issues

  • Verify DATABASE_URL is correct
  • Ensure PostgreSQL is running
  • Check database exists and user has permissions

Email Not Sending

  • In dev: Check console for Ethereal preview URLs
  • In production: Verify SMTP credentials
  • Check email service logs

Authentication Issues

  • Verify NEXTAUTH_SECRET is set
  • Check NEXTAUTH_URL matches your app URL
  • Set AUTH_TRUST_HOST=true if using reverse proxy
  • Clear browser cookies if needed
  • Check middleware logs: sudo journalctl -u app-backend | grep "Middleware"

Photo Upload Issues

  • Verify public/uploads/ directory exists and has write permissions
  • Check file upload logs: sudo journalctl -u app-backend | grep "UPLOAD"
  • Ensure files are being saved: check public/uploads/ directory
  • Files are served via /api/uploads/[filename] - verify API route is accessible

Build Issues

  • If build fails with DATABASE_URL not set, this is expected - Prisma initialization is lazy
  • Ensure all environment variables are set in production
  • Check for TypeScript errors: npm run type-check

Documentation

This project maintains comprehensive documentation:

  • README.md (this file) - Setup, installation, and basic usage
  • ARCHITECTURE.md - System architecture, data models, and application flows
  • CONTRIBUTING.md - Coding conventions and development workflow
  • SECURITY.md - Security practices and vulnerability reporting
  • .cursor/rules/mirrormatch.mdc - Project rules for AI tools and developers

For Developers and AI Tools:

⚠️ Important: Before making code changes, read .cursor/rules/mirrormatch.mdc, ARCHITECTURE.md, CONTRIBUTING.md, SECURITY.md, and this README. Keep them updated when behavior or architecture changes.

  • Always read the relevant documentation before making changes
  • Update documentation when behavior or architecture changes
  • Keep all documentation files in sync with code changes
  • Follow the guidelines in each document

License

MIT

Description
No description provided
Readme 2.6 MiB
Languages
TypeScript 93%
Shell 5.1%
JavaScript 1.6%
CSS 0.3%