Critical fixes for database compatibility issues:
INSERT operations:
- Fix all INSERT queries to use .returning('id')
- Handle both PostgreSQL (returns objects) and SQLite (returns IDs)
- Fixed in: events.js, adminArchives.js, adminEvents-enhanced.js, create-test-event.js
Date operations:
- Replace SQLite-specific db.raw("datetime('now', '+30 days')")
- Use JavaScript Date objects for cross-database compatibility
- Fixed in: adminArchives.js
Database utilities:
- Add dbCompat.js utility for handling database differences
- Provides consistent API for inserts, dates, booleans, and DB-specific operations
- Centralized database compatibility logic
Migration:
- Add migration 023 documenting PostgreSQL compatibility requirements
- Ensures future developers are aware of compatibility needs
This resolves all 'not iterable' errors and ensures the application
works correctly with both PostgreSQL (production) and SQLite (development).
- Set Express to trust proxy headers for proper IP detection with Traefik
- Add safe JSON parsing for email template variables and activity log metadata
- Create migration to fix invalid JSON data in database
- Add error handling to prevent JSON.parse crashes
This fixes the 500 errors caused by invalid JSON data and the trust proxy
warning from express-rate-limit when running behind Traefik.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix email templates list endpoint to handle both schema variations
- Add migration for default CMS pages with language-specific columns
- Create debug script to identify 500 error causes
- Update CMS migration to use correct column names (title_en/de, content_en/de)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add migration to fix email_templates column structure after language migration
- Add migration to ensure default email templates exist
- Create diagnostic script to check database issues
- Fix docker-compose configuration for proper routing without path stripping
The backend expects routes with /api prefix, so removing the stripprefix
middleware allows proper routing to work.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change from bcryptjs to bcrypt to match installed dependency
- Fixes "Cannot find module 'bcryptjs'" error when creating admin user
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix database configuration to use PostgreSQL in production
- Add knexfile.js to support both SQLite (dev) and PostgreSQL (prod)
- Create admin user creation script (scripts/create-admin.js)
- Clean up docker-compose files:
- Remove redundant docker-compose.yml and docker-compose.local.yml
- Create docker-compose.dev.yml for development
- Update docker-compose.prod.yml with proper DB configuration
- Clean up environment files:
- Update .env.example for development
- Update .env.production.example with proper settings
- Remove redundant .env.local
- Update backend .env.example with database configuration options
- Create comprehensive DEPLOYMENT.md with admin setup instructions
- Fix production database name consistency (picpeak instead of photoapp)
Security Enhancements:
- Fix SQL injection vulnerabilities by replacing whereRaw queries with parameterized queries
- Add LIKE pattern escaping to prevent SQL injection in search functionality
- Implement account lockout protection (5 failed attempts = 30 min lockout)
- Add comprehensive login attempt tracking and audit trail
- Enhance JWT tokens with issuer validation, IP tracking, and password change detection
- Add logout endpoint and session management
- Prevent user enumeration with generic error messages
Database Changes:
- Add login_attempts table for authentication tracking
- Add security columns to admin_users (password_changed_at, last_login_ip, two_factor_enabled)
New Security Features:
- Brute force protection with configurable lockout duration
- Automatic cleanup of old login attempts
- Enhanced authentication middleware with stricter validation
- Monitoring scripts for security health checks
All fixes are backward compatible and production-ready with rollback plans included.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
BREAKING CHANGE: Admin password is now auto-generated on first setup
Security improvements:
- Remove hardcoded 'admin123' password completely
- Generate secure random password on first installation
- Save credentials to ADMIN_CREDENTIALS.txt (git-ignored)
- Force password change on first login
- Implement strong password requirements (12+ chars, mixed case, numbers, special)
- Add password strength validation
- Increase bcrypt rounds from 10 to 12
New features:
- Password generator utility with secure random generation
- Human-readable password format (e.g., SwiftEagle3847\!)
- Password reset script for existing installations
- Comprehensive admin setup documentation
- Must-change-password flag in database
Migration guide:
- New installations: Check ADMIN_CREDENTIALS.txt for generated password
- Existing installations: Run scripts/reset-admin-password.js
- All users must change password on first login after update
This fixes a critical vulnerability where all installations used the same
default admin password, allowing unauthorized access.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
BREAKING CHANGE: Server now requires JWT_SECRET environment variable to be set
Security fixes:
- Remove hardcoded JWT secret fallback 'your-secret-key' from protectedImages.js
- Add startup validation to ensure JWT_SECRET is properly configured
- Reject insecure default values and short secrets
- Server will refuse to start without proper JWT_SECRET
This fixes a critical vulnerability where the application would use a publicly
known secret if JWT_SECRET was not set, completely compromising authentication.
Migration guide: docs/JWT_SECRET_MIGRATION.md
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added default_language field to general settings state in SettingsPage
- Replaced LanguageSelector component with simple select dropdown on settings page
- Fixed public settings endpoint to read general_default_language from database
- Language setting now properly saved when clicking Save Settings button
- Setting is correctly used by gallery login page and legal pages
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>