# Database Migrations This directory contains SQL migration files for the Rustelo application database setup. ## Overview The migration system sets up a complete database with authentication, content management, and auditing capabilities. **Rustelo now supports both PostgreSQL and SQLite** through a database-agnostic architecture. ## Migration Files Rustelo provides **database-specific migration files** to support both PostgreSQL and SQLite: ### Database-Specific Files - `001_initial_setup_postgres.sql` - PostgreSQL-optimized schema - `001_initial_setup_sqlite.sql` - SQLite-optimized schema - `002_add_2fa_support_postgres.sql` - PostgreSQL 2FA tables - `002_add_2fa_support_sqlite.sql` - SQLite 2FA tables - `003_rbac_system_postgres.sql` - PostgreSQL RBAC system ### Legacy Files - `001_initial_setup.sql` - Legacy unified file (deprecated) - `002_add_2fa_support.sql` - Legacy 2FA file (deprecated) The migration system **automatically detects your database type** from the connection URL and runs the appropriate migration files. ### Schema Features #### Authentication Tables - **users** - Core user accounts and profile information - **user_roles** - User role assignments for RBAC (Role-Based Access Control) - **oauth_accounts** - External OAuth provider account links - **sessions** - User session management - **tokens** - Security tokens for password reset, email verification, etc. - **permissions** - System permissions for fine-grained access control - **role_permissions** - Role to permission mappings - **user_audit_log** - Audit trail for user actions #### Content Management Tables - **page_contents** - Main content management table for pages, posts, and other content #### Key Features - **UUID Primary Keys** - All tables use UUID primary keys for better security - **Comprehensive Indexing** - Optimized indexes for performance - **Full-Text Search** - PostgreSQL full-text search capabilities - **Audit Logging** - Complete audit trail for user actions - **Role-Based Access Control** - Flexible permission system - **Automatic Timestamps** - Automatic created_at/updated_at handling - **Data Validation** - Comprehensive constraints and validation rules ## Database Schema ### User Management ```sql users (id, email, username, password_hash, display_name, ...) user_roles (user_id, role) oauth_accounts (id, user_id, provider, provider_id, ...) sessions (id, user_id, expires_at, ...) tokens (id, user_id, token_type, token_hash, ...) ``` ### Authorization ```sql permissions (id, name, description, resource, action) role_permissions (role, permission_id) user_audit_log (id, user_id, action, resource, ...) ``` ### Content Management ```sql page_contents (id, slug, title, content, author_id, ...) ``` ## Default Data The migration includes default data: ### User Roles - **admin** - Full system access - **moderator** - Content management and user oversight - **user** - Basic content creation - **guest** - Read-only access ### Default Admin User - **Username**: admin - **Email**: admin@example.com - **Password**: admin123 (⚠️ **CHANGE THIS IMMEDIATELY IN PRODUCTION!**) ### Sample Content - Welcome page - About page - Sample blog post ## Functions and Triggers ### Automatic Triggers - `update_updated_at_column()` - Updates timestamps automatically - `assign_default_role()` - Assigns default role to new users ### Utility Functions - `log_user_action()` - Logs user actions for auditing - `cleanup_expired_auth_data()` - Cleans up expired sessions and tokens ## Running Migrations ### Using the Built-in Migration Runner (Recommended) ```bash # The application automatically runs migrations on startup cargo run # Or use the database tool cargo run --bin db_tool -- migrate ``` ### Database Type Detection The migration system automatically detects your database type from the `DATABASE_URL`: ```bash # PostgreSQL - runs *_postgres.sql files DATABASE_URL=postgresql://user:pass@localhost/database_name # SQLite - runs *_sqlite.sql files DATABASE_URL=sqlite:data/app.db ``` ### Using SQLx CLI ```bash # Install sqlx-cli cargo install sqlx-cli # PostgreSQL migrations sqlx migrate run --database-url "postgresql://username:password@localhost/database_name" # SQLite migrations sqlx migrate run --database-url "sqlite:data/app.db" ``` ### Manual Migration ```bash # PostgreSQL psql -U username -d database_name -f 001_initial_setup_postgres.sql # SQLite sqlite3 data/app.db < 001_initial_setup_sqlite.sql ``` ## Environment Setup Configure your database connection using the `DATABASE_URL` environment variable: ### PostgreSQL ```env DATABASE_URL=postgresql://username:password@localhost:5432/database_name ``` ### SQLite ```env DATABASE_URL=sqlite:data/app.db ``` ### Additional Database Configuration ```env # Connection pool settings (optional) DATABASE_MAX_CONNECTIONS=10 DATABASE_MIN_CONNECTIONS=1 DATABASE_CONNECT_TIMEOUT=30 DATABASE_IDLE_TIMEOUT=600 DATABASE_MAX_LIFETIME=3600 ``` ## Security Considerations 1. **Change Default Admin Password** - The default admin password is `admin123` 2. **Review Permissions** - Customize role permissions based on your needs 3. **Configure OAuth** - Set up OAuth providers if using external authentication 4. **Enable SSL** - Use SSL connections in production (PostgreSQL) 5. **Backup Strategy** - Implement regular database backups 6. **File Permissions** - Secure SQLite database files (chmod 600) 7. **Database Location** - Store SQLite files outside web root ## Schema Evolution For future schema changes: 1. Create **database-specific** migration files: - `003_new_feature_postgres.sql` - `003_new_feature_sqlite.sql` 2. Always use `CREATE TABLE IF NOT EXISTS` for safety 3. Add proper indexes for performance 4. Handle database-specific differences (UUID vs TEXT, etc.) 5. Test migrations on both database types 6. Include rollback scripts when possible 7. Test migrations on a copy of production data ### Database Differences to Consider - **UUIDs**: PostgreSQL native vs SQLite TEXT - **Timestamps**: PostgreSQL native vs SQLite TEXT (ISO 8601) - **JSON**: PostgreSQL JSONB vs SQLite TEXT - **Arrays**: PostgreSQL arrays vs SQLite JSON arrays - **Booleans**: PostgreSQL BOOLEAN vs SQLite INTEGER ## Performance Notes ### PostgreSQL - All tables have appropriate indexes for common queries - Full-text search is enabled for content - Partial indexes are used for filtered queries - GIN indexes are used for JSONB and array columns - Connection pooling for high concurrency ### SQLite - Optimized indexes for single-user scenarios - WAL mode enabled for better concurrency - Foreign key constraints enabled - Query planner optimizations - Smaller memory footprint ## Troubleshooting ### Common Issues #### PostgreSQL Issues 1. **Extension Error**: If you get an error about `uuid-ossp` extension, ensure your PostgreSQL user has superuser privileges or the extension is already installed. 2. **Permission Denied**: Ensure your database user has CREATE privileges. 3. **Connection Failed**: Check PostgreSQL service is running and connection details are correct. #### SQLite Issues 1. **File Permission Error**: Ensure the SQLite file and directory have proper write permissions. 2. **Database Locked**: Close other connections to the SQLite file. 3. **Directory Not Found**: Ensure the directory for the SQLite file exists. #### General Issues 1. **Constraint Violations**: Check that your data meets the constraint requirements (email format, username format, etc.). 2. **Migration Version Mismatch**: Ensure all migration files are present and properly numbered. 3. **Database Type Detection Failed**: Verify your `DATABASE_URL` format is correct. ### Verification After running the migration, verify the setup: #### PostgreSQL Verification ```sql -- Check tables were created SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'; -- Check default admin user SELECT username, email, is_active FROM users WHERE username = 'admin'; -- Check permissions setup SELECT COUNT(*) FROM permissions; SELECT COUNT(*) FROM role_permissions; -- Check sample content SELECT slug, title, state FROM page_contents; ``` #### SQLite Verification ```sql -- Check tables were created SELECT name FROM sqlite_master WHERE type='table'; -- Check default admin user SELECT username, email, is_active FROM users WHERE username = 'admin'; -- Check permissions setup SELECT COUNT(*) FROM permissions; SELECT COUNT(*) FROM role_permissions; -- Check sample content SELECT slug, title, state FROM page_contents; ``` ## Backup and Restore ### PostgreSQL ```bash # Create backup pg_dump -U username -d database_name > backup.sql # Restore backup psql -U username -d database_name < backup.sql # Compressed backup pg_dump -U username -d database_name | gzip > backup.sql.gz ``` ### SQLite ```bash # Create backup (simple copy) cp data/app.db data/app_backup.db # Create SQL dump sqlite3 data/app.db .dump > backup.sql # Restore from SQL dump sqlite3 data/app_new.db < backup.sql # Online backup (while app is running) sqlite3 data/app.db ".backup data/app_backup.db" ``` ### Cross-Database Migration ```bash # SQLite to PostgreSQL sqlite3 data/app.db .dump | sed 's/INSERT INTO/INSERT INTO public./g' > backup.sql psql -U username -d database_name < backup.sql # Note: May require manual adjustments for data types ``` ## Support For issues or questions: 1. Check the application logs 2. Verify database connectivity 3. Review the migration file for any custom modifications 4. Consult the PostgreSQL documentation for specific errors