4 Commits

Author SHA1 Message Date
df865dca41 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)
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
# 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
dfc2ee978d Production Deployment Fixes and Enhancements (#3)
All checks were successful
CI / skip-ci-check (push) Successful in 1m23s
CI / lint-and-type-check (push) Successful in 1m46s
CI / test (push) Successful in 1m51s
CI / build (push) Successful in 1m54s
CI / secret-scanning (push) Successful in 1m24s
CI / dependency-scan (push) Successful in 1m28s
CI / sast-scan (push) Successful in 2m32s
CI / workflow-summary (push) Successful in 1m21s
# Merge Request: Production Deployment Fixes and Enhancements

## Summary

This MR includes critical fixes for production deployment, authentication improvements, file upload serving, and monitoring capabilities. All changes have been tested and are ready for production.

## 🐛 Critical Fixes

### 1. Authentication & Session Management
- **Fixed TypeScript error in session callback** (`lib/auth.ts`)
  - Removed `return null` that caused build failures
  - Session callback now always returns a valid session object
- **Fixed login redirect loop** (`app/login/page.tsx`)
  - Changed from `router.push()` to `window.location.href` for full page reload
  - Ensures session cookie is available before middleware checks
- **Created proper middleware** (`proxy.ts`)
  - Next.js 16 requires `proxy.ts` instead of `middleware.ts`
  - Fixed authentication checks in Edge runtime
  - Explicitly specifies cookie name for `getToken`

### 2. Build & Deployment
- **Fixed Prisma initialization** (`lib/prisma.ts`)
  - Made Prisma client initialization lazy to fix build without DATABASE_URL
  - Uses Proxy pattern for on-demand initialization
  - Prevents build failures when DATABASE_URL not set

### 3. File Upload & Serving
- **Fixed photo upload serving** (`app/api/uploads/[filename]/route.ts`)
  - Created dedicated API route to serve uploaded files
  - Files now served via `/api/uploads/[filename]` instead of static `/uploads/`
  - Ensures files are accessible regardless of filesystem location
  - Added file existence verification and proper error handling
- **Updated upload routes** to use new API endpoint
  - `app/api/photos/upload/route.ts` - Updated to use `/api/uploads/` URLs
  - `app/api/photos/upload-multiple/route.ts` - Updated to use `/api/uploads/` URLs
- **Fixed photo display components**
  - `components/PhotoThumbnail.tsx` - Uses regular `img` tag for uploads
  - `components/PhotoImage.tsx` - Uses regular `img` tag for uploads
  - Avoids Next.js Image component issues with dynamically uploaded files

### 4. Middleware & Route Protection
- **Updated proxy middleware** (`proxy.ts`)
  - Added `/uploads` and `/api/uploads` to public routes
  - Added comprehensive activity logging
  - Improved error handling and logging

##  New Features

### Activity Logging
- **Created activity logging utility** (`lib/activity-log.ts`)
  - Structured logging for user actions
  - Tracks: page visits, photo uploads, guess submissions
  - Includes user info, IP, timestamps, and action details
- **Added activity logging to key routes**
  - `proxy.ts` - Logs all page visits and API calls
  - `app/api/photos/upload/route.ts` - Logs photo uploads
  - `app/api/photos/[photoId]/guess/route.ts` - Logs guess submissions

### Monitoring
- **Activity monitoring commands**
  - Watch logs: `sudo journalctl -u app-backend -f | grep -E "\[ACTIVITY\]|\[PHOTO_UPLOAD\]|\[GUESS_SUBMIT\]"`
  - Filter by user, action type, or time range

## 📝 Documentation Updates

- **README.md**
  - Added deployment notes section
  - Added file upload details and troubleshooting
  - Added activity monitoring commands
  - Added database query examples
  - Updated troubleshooting section

- **ARCHITECTURE.md**
  - Updated middleware references (proxy.ts instead of middleware.ts)
  - Added activity logging documentation
  - Updated photo upload flow with file upload details
  - Added file serving architecture
  - Updated guess submission flow

- **CLEANUP.md** (new)
  - Created cleanup checklist for future improvements
  - Documents debug code and verbose logging
  - Provides recommendations for optimization

## 🔧 Technical Changes

### Files Modified
- `lib/auth.ts` - Fixed session callback return type
- `app/login/page.tsx` - Fixed redirect to use full page reload
- `proxy.ts` - Created/updated middleware with activity logging
- `lib/prisma.ts` - Made initialization lazy
- `app/api/photos/upload/route.ts` - Updated file serving, added logging
- `app/api/photos/upload-multiple/route.ts` - Updated file serving
- `components/PhotoThumbnail.tsx` - Fixed image display
- `components/PhotoImage.tsx` - Fixed image display

### Files Created
- `app/api/uploads/[filename]/route.ts` - File serving API route
- `lib/activity-log.ts` - Activity logging utility
- `CLEANUP.md` - Cleanup checklist

##  Testing

- [x] Authentication flow tested (login, session persistence)
- [x] Photo upload tested (file and URL uploads)
- [x] Photo display tested (uploaded files visible to all users)
- [x] Guess submission tested
- [x] Build tested (no TypeScript errors)
- [x] Middleware tested (route protection working)
- [x] Activity logging verified

## 🚀 Deployment Notes

### Environment Variables Required
- `NODE_ENV=production`
- `NEXTAUTH_URL` - Production domain
- `NEXTAUTH_SECRET` - Secret key
- `AUTH_TRUST_HOST=true` (if using reverse proxy)
- `DATABASE_URL` - Production database connection

### Post-Deployment
1. Verify `public/uploads/` directory exists and has write permissions
2. Test photo upload and verify files are accessible
3. Monitor activity logs to ensure logging is working
4. Verify authentication flow works correctly

### Monitoring
- Watch activity logs: `sudo journalctl -u app-backend -f | grep -E "\[ACTIVITY\]|\[PHOTO_UPLOAD\]|\[GUESS_SUBMIT\]"`
- Check for errors: `sudo journalctl -u app-backend --since "1 hour ago" | grep -i error`

## 🔄 Breaking Changes

**None** - All changes are backward compatible. Existing photos with `/uploads/` URLs may need to be updated to `/api/uploads/` if files are not accessible, but the system will continue to work.

## 📋 Migration Notes

### For Existing Photos
- Photos uploaded before this change use `/uploads/` URLs
- New photos use `/api/uploads/` URLs
- Old photos will continue to work if files exist in `public/uploads/`
- Consider migrating old photo URLs if needed (optional)

## 🎯 Next Steps (Future)

See `CLEANUP.md` for recommended cleanup tasks:
- Reduce verbose logging in production
- Add log levels (DEBUG, INFO, WARN, ERROR)
- Protect debug endpoints
- Optimize activity logging

---

**Ready for Production:**  Yes
**Breaking Changes:**  No
**Requires Migration:** ⚠️ Optional (old photo URLs)

Reviewed-on: #3
2026-01-04 16:37:34 -05:00
a8548bddcf This PR adds comprehensive photo management features, duplicate detection, attempt limits, penalty system improvements, and admin photo deletion capabilities to the MirrorMatch application. (#1)
All checks were successful
CI / skip-ci-check (push) Successful in 1m21s
CI / lint-and-type-check (push) Successful in 1m45s
CI / test (push) Successful in 1m49s
CI / build (push) Successful in 1m50s
CI / secret-scanning (push) Successful in 1m22s
CI / dependency-scan (push) Successful in 1m27s
CI / sast-scan (push) Successful in 2m27s
CI / workflow-summary (push) Successful in 1m19s
# Photo Management and Game Features

## Summary
This PR adds comprehensive photo management features, duplicate detection, attempt limits, penalty system improvements, and admin photo deletion capabilities to the MirrorMatch application.

## Features Added

### 1. Duplicate Photo Detection
- **File-based duplicates**: Calculates SHA256 hash of uploaded files to detect duplicate content
- **URL-based duplicates**: Checks for duplicate photo URLs
- Prevents users from uploading the same photo multiple times
- Returns HTTP 409 (Conflict) with clear error messages

### 2. Maximum Attempts Per Photo
- Uploaders can set a maximum number of guesses allowed per user for each photo
- Default: unlimited (null or 0)
- UI displays remaining attempts counter
- API enforces attempt limits before allowing guesses
- Shows warning message when max attempts reached

### 3. Penalty System Improvements
- **Simplified UI**: Removed checkbox - penalty automatically enabled when penalty points > 0
- **Score protection**: Scores cannot go below 0, even with large penalties
- If penalty would result in negative score, only deducts available points and sets to 0

### 4. Admin Photo Deletion
- Admins can delete photos from:
  - Photos list page (hover to reveal delete icon)
  - Individual photo detail page (delete button in header)
- Deletes associated guesses automatically
- Deletes local uploaded files from filesystem
- Confirmation dialog before deletion
- Proper error handling and user feedback

### 5. Navigation Improvements
- Logout button always visible in side menu (hamburger menu)
- Improved side menu layout with fixed footer for logout button
- Better mobile responsiveness

### 6. Self-Guess Prevention
- Users cannot guess on their own uploaded photos
- Shows informative message with answer for photo owners

## Technical Changes

### Database Schema
- Added `fileHash` field (String?) to Photo model for duplicate detection
- Added `maxAttempts` field (Int?) to Photo model for attempt limits
- Added indexes on `url` and `fileHash` for performance

### API Routes
- `POST /api/photos/upload-multiple`: Enhanced with duplicate checking and maxAttempts
- `POST /api/photos/[photoId]/guess`: Added maxAttempts enforcement and score floor protection
- `DELETE /api/photos/[photoId]`: New route for admin photo deletion

### Components
- `DeletePhotoButton`: New reusable component for photo deletion
- Updated upload form to remove penalty checkbox
- Enhanced photo display pages with attempt counters and admin controls

## Database Migrations
- Run `npm run db:push` to apply schema changes
- Run `npm run db:generate` to regenerate Prisma client

## Testing
- Test duplicate detection with same file and different filenames
- Test duplicate detection with same URL
- Test max attempts enforcement
- Test penalty system with various point values
- Test score floor (cannot go below 0)
- Test admin photo deletion
- Test self-guess prevention

## Breaking Changes
None - all changes are backward compatible. Existing photos will have `null` for `maxAttempts` (unlimited) and `fileHash` (for URL uploads).

Reviewed-on: #1
2026-01-03 10:19:59 -05:00
9640627972 feat: Add photo management features, duplicate detection, attempt limits, and admin deletion
Some checks failed
CI / skip-ci-check (pull_request) Successful in 1m19s
CI / lint-and-type-check (pull_request) Failing after 1m37s
CI / test (pull_request) Successful in 2m16s
CI / build (pull_request) Failing after 1m46s
CI / secret-scanning (pull_request) Successful in 1m20s
CI / dependency-scan (pull_request) Successful in 1m27s
CI / sast-scan (pull_request) Successful in 2m29s
CI / workflow-summary (pull_request) Successful in 1m18s
- Add duplicate photo detection (file hash and URL checking)
- Add max attempts per photo with UI counter
- Simplify penalty system (auto-enable when points > 0)
- Prevent scores from going below 0
- Add admin photo deletion functionality
- Improve navigation with always-visible logout
- Prevent users from guessing their own photos
2026-01-02 14:57:30 -05:00