diff --git a/backend/migrations/init_db.py b/backend/migrations/init_db.py new file mode 100644 index 0000000..a44a30f --- /dev/null +++ b/backend/migrations/init_db.py @@ -0,0 +1,100 @@ +"""Initialize database with all tables and seed data.""" +import sqlite3 +from datetime import datetime +from passlib.context import CryptContext + +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + +def get_password_hash(password: str) -> str: + return pwd_context.hash(password) + +def init_db(): + """Create all tables and seed with initial users.""" + conn = sqlite3.connect('/app/data/family_hub.db') + cursor = conn.cursor() + + # Create users table with ALL fields + cursor.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username VARCHAR(50) UNIQUE NOT NULL, + email VARCHAR(100) UNIQUE NOT NULL, + full_name VARCHAR(100) NOT NULL, + hashed_password VARCHAR(255) NOT NULL, + discord_id VARCHAR(100), + profile_picture VARCHAR(500), + is_active BOOLEAN DEFAULT 1, + is_admin BOOLEAN DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # Create chores table + cursor.execute(""" + CREATE TABLE IF NOT EXISTS chores ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title VARCHAR(200) NOT NULL, + description TEXT, + assigned_to INTEGER, + created_by INTEGER NOT NULL, + due_date DATE, + frequency VARCHAR(20) DEFAULT 'ON_TRIGGER', + status VARCHAR(20) DEFAULT 'pending', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (assigned_to) REFERENCES users(id), + FOREIGN KEY (created_by) REFERENCES users(id) + ) + """) + + # Check if users already exist + cursor.execute("SELECT COUNT(*) FROM users") + user_count = cursor.fetchone()[0] + + if user_count == 0: + print("Seeding database with initial users...") + + # Create family members with default password + default_password_hash = get_password_hash("password123") + + users = [ + ("lou", "lou@family.local", "Lou", default_password_hash, False), + ("jess", "jess@family.local", "Jess", default_password_hash, True), + ("william", "william@family.local", "William", default_password_hash, False), + ("xander", "xander@family.local", "Xander", default_password_hash, False), + ("bella", "bella@family.local", "Bella", default_password_hash, False), + ] + + for username, email, full_name, password_hash, is_admin in users: + cursor.execute(""" + INSERT INTO users (username, email, full_name, hashed_password, is_active, is_admin) + VALUES (?, ?, ?, ?, 1, ?) + """, (username, email, full_name, password_hash, 1 if is_admin else 0)) + print(f" Created user: {username} (Admin: {is_admin})") + else: + print(f"Users table already contains {user_count} users, skipping seed.") + + conn.commit() + + # Verify tables + cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") + tables = cursor.fetchall() + print(f"\nDatabase tables created: {[t[0] for t in tables]}") + + # Verify columns in users table + cursor.execute("PRAGMA table_info(users)") + columns = cursor.fetchall() + print("\nColumns in 'users' table:") + for col in columns: + print(f" - {col[1]} ({col[2]})") + + cursor.execute("SELECT COUNT(*) FROM users") + user_count = cursor.fetchone()[0] + print(f"\nTotal users in database: {user_count}") + + conn.close() + print("\nDatabase initialization complete!") + +if __name__ == "__main__": + init_db()