Security Improvements: - Auto-generate AUTH_SECRET and admin credentials on first launch - Cryptographically secure random generation - Stored in database for persistence - Logged once to container logs for admin retrieval - Implement CSRF protection with double-submit cookie pattern - Three-way validation: cookie, header, and session database - Automatic client-side injection via plugin - Server middleware for automatic validation - Zero frontend code changes required - Add session fixation prevention with automatic invalidation - Regenerate sessions on password changes - Keep current session active, invalidate others on profile password change - Invalidate ALL sessions on forgot-password reset - Invalidate ALL sessions on admin password reset - Upgrade password reset codes to 8-char alphanumeric - Increased from 1M to 1.8 trillion combinations - Uses crypto.randomInt() for cryptographic randomness - Excluded confusing characters (I, O) for better UX - Case-insensitive verification - Implement dual-layer account lockout - IP-based rate limiting (existing) - Per-account lockout: 10 attempts = 30 min lock - Automatic unlock after expiration - Admin manual unlock via UI - Visual status indicators in users table Database Changes: - Add csrf_token column to sessions table - Add failed_login_attempts and locked_until columns to users table - Add settings table for persistent AUTH_SECRET storage - All migrations backward-compatible with try-catch New Files: - server/utils/csrf.ts - CSRF protection utilities - server/middleware/csrf.ts - Automatic CSRF validation middleware - plugins/csrf.client.ts - Automatic CSRF header injection - server/api/users/unlock/[id].post.ts - Admin unlock endpoint Modified Files: - server/utils/database.ts - Core security functions and schema updates - server/utils/email.ts - Enhanced reset code generation - server/api/auth/login.post.ts - CSRF + account lockout logic - server/api/auth/register.post.ts - CSRF token generation - server/api/auth/logout.post.ts - CSRF cookie cleanup - server/api/auth/reset-password.post.ts - Session invalidation - server/api/auth/verify-reset-code.post.ts - Case-insensitive codes - server/api/profile/update.put.ts - Session invalidation on password change - server/api/users/password/[id].put.ts - Session invalidation on admin reset - pages/users.vue - Lock status display and unlock functionality - docker-compose.yml - Removed default credentials - nuxt.config.ts - Support auto-generation All changes follow OWASP best practices and are production-ready. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
New Life Christian Church - Sermon Itinerary
A web application for managing and displaying weekly sermons for New Life Christian Church.
Features
- 📝 Sermon Management: Create and manage sermon content with a user-friendly form
- 🔐 Authentication: Secure admin access with login system
- 📱 QR Codes: Generate QR codes for easy sermon sharing
- 📅 Date-based URLs: Sermons accessible via
sermon-MMDDYYYYformat - 🎨 Modern UI: Clean, responsive design using Tailwind CSS and Inter font
- 📊 Three Sections: Bible References, Personal Appliance, and Pastor's Challenge
- 🗂️ Smart Organization: Recent sermons (last 3 months) displayed by default, older sermons in dropdown
- 🐳 Docker Ready: Fully containerized for easy deployment
Technology Stack
- Frontend: Nuxt 3 (Vue.js)
- Styling: Tailwind CSS with Inter font from Google Fonts
- Database: SQLite
- QR Codes: qrcode library
- Deployment: Docker & Docker Compose
Configuration
This application uses environment variables configured directly in docker-compose.yml. Edit the file to customize your deployment settings.
Environment Variables
| Variable | Description | Default |
|---|---|---|
SITE_URL |
Public URL where the app is hosted (used for QR codes) | https://nlcc.rydertech.us |
AUTH_SECRET |
Secret key for authentication sessions | change-this-secret-in-production-please |
ADMIN_USERNAME |
Initial admin login username | admin |
ADMIN_PASSWORD |
Initial admin login password | Admin123! |
EMAIL_HOST |
SMTP server hostname | smtp.example.com |
EMAIL_PORT |
SMTP server port | 587 |
EMAIL_USER |
SMTP authentication username | noreply@example.com |
EMAIL_PASSWORD |
SMTP authentication password | your-email-password |
EMAIL_FROM |
Email sender address and name | New Life Christian Church <noreply@example.com> |
Customizing Configuration
Edit docker-compose.yml and update the values in both the build.args and environment sections:
services:
nlcc-itinerary:
build:
args:
- SITE_URL=https://your-church-domain.com
- AUTH_SECRET=your-secure-random-secret-here
- ADMIN_USERNAME=your-admin-username
- ADMIN_PASSWORD=your-secure-password
- EMAIL_HOST=smtp.gmail.com
- EMAIL_PORT=587
- EMAIL_USER=your-email@gmail.com
- EMAIL_PASSWORD=your-app-password
- EMAIL_FROM=Your Church Name <your-email@gmail.com>
environment:
- SITE_URL=https://your-church-domain.com
- AUTH_SECRET=your-secure-random-secret-here
- ADMIN_USERNAME=your-admin-username
- ADMIN_PASSWORD=your-secure-password
- EMAIL_HOST=smtp.gmail.com
- EMAIL_PORT=587
- EMAIL_USER=your-email@gmail.com
- EMAIL_PASSWORD=your-app-password
- EMAIL_FROM=Your Church Name <your-email@gmail.com>
Generate a secure AUTH_SECRET:
openssl rand -hex 32
Getting Started
Prerequisites
- Docker and Docker Compose installed on your system
Installation & Deployment
- Clone the repository:
git clone <repository-url>
cd nlcc-itinerary
-
Edit
docker-compose.ymland configure your settings:- Update
SITE_URLto your public domain - Generate and set a secure
AUTH_SECRET(useopenssl rand -hex 32) - Set your desired
ADMIN_USERNAMEandADMIN_PASSWORD - Make sure to update values in BOTH
build.argsANDenvironmentsections
- Update
-
Build and run with Docker Compose:
docker-compose up -d --build
The application will be available at http://localhost:3002 (or your configured port)
Important: The SITE_URL must be set correctly for QR codes to work. This should be the public URL where your application is accessible (e.g., https://church.example.com).
Initial Admin Account
The initial admin account is created automatically on first run using the credentials specified in docker-compose.yml:
Default values:
- Username: admin
- Password: Admin123!
⚠️ Important:
- Change these credentials in
docker-compose.ymlbefore deploying to production - After the first build, you can change the admin password through the user management interface
- Additional users can be created through the registration page
Project Structure
nlcc-itinerary/
├── assets/css/ # Global styles
├── components/ # Vue components
│ ├── SermonCard.vue
│ ├── QRCodeButton.vue
│ └── QRCodeModal.vue
├── middleware/ # Route middleware
│ └── auth.ts
├── pages/ # Application pages
│ ├── index.vue # Main sermon listing
│ ├── login.vue # Admin login
│ ├── admin.vue # Sermon creation form
│ └── [slug].vue # Individual sermon page
├── server/
│ ├── api/ # API endpoints
│ │ ├── auth/ # Authentication endpoints
│ │ └── sermons/ # Sermon CRUD endpoints
│ └── utils/ # Server utilities
│ ├── database.ts # SQLite database functions
│ └── auth.ts # Authentication helpers
├── logos/ # Church logos
├── Dockerfile # Docker configuration
├── docker-compose.yml # Docker Compose configuration
└── nuxt.config.ts # Nuxt configuration
Usage
Creating a Sermon
- Navigate to
/loginand sign in with admin credentials - You'll be redirected to
/admin - Fill in the sermon details:
- Date: Select the sermon date (URL will be auto-generated as
sermon-MMDDYYYY) - Title: Enter the sermon title
- Bible References: Add one or more Bible verses (use +/- buttons)
- Personal Appliance: Enter personal application content
- Pastor's Challenge: Enter the pastor's challenge content
- Date: Select the sermon date (URL will be auto-generated as
- Click "Create Sermon"
Viewing Sermons
- Main Page (
/): Shows recent sermons (last 3 months) with option to view older ones - Individual Sermon (
/sermon-MMDDYYYY): Full sermon details with QR code - QR Code: Click the QR code button on any sermon card or page to generate a scannable code
Database
The application uses SQLite with the following schema:
Sermons Table
id: Primary keyslug: Unique sermon identifier (e.g., sermon-09282025)title: Sermon titledate: Sermon datebible_references: Newline-separated Bible versespersonal_appliance: Personal application contentpastors_challenge: Pastor's challenge contentcreated_at: Timestamp
Users Table
id: Primary keyusername: User's usernamepassword: User's password (plain text - should be hashed in production)
Security Notes
⚠️ For Production Use:
- Change the default admin credentials in your
.envfile - ✅ Password hashing is implemented using bcrypt
- Use a strong
AUTH_SECRETin environment variables (generate withopenssl rand -hex 32) - Enable HTTPS
- Consider implementing rate limiting
- Add CSRF protection
Note: Passwords are now securely hashed using bcrypt with 10 salt rounds before being stored in the database.
Docker Commands
# Build and start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop containers
docker-compose down
# Rebuild after changes
docker-compose up -d --build
# Access container shell
docker exec -it nlcc-itinerary sh
Data Persistence
The SQLite database is stored in the ./data directory, which is mounted as a volume in Docker. This ensures sermon data persists across container restarts.
License
This project is created for New Life Christian Church.
Support
For issues or questions, please contact the development team.