Files
orion/scripts/seed_database.py

320 lines
9.7 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Seed the database with initial development data.
Creates:
- Admin user (admin/admin123)
- Test vendors (TESTVENDOR, WIZAMART)
Usage:
python scripts/seed_database.py
This script is idempotent - safe to run multiple times.
"""
import sys
from pathlib import Path
# Add project root to path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from sqlalchemy.orm import Session
from sqlalchemy import select
from app.core.database import SessionLocal, engine
from models.database.user import User
from models.database.vendor import Vendor
from middleware.auth import AuthManager
from datetime import datetime, timezone
# Default credentials
DEFAULT_ADMIN_EMAIL = "admin@wizamart.com"
DEFAULT_ADMIN_USERNAME = "admin"
DEFAULT_ADMIN_PASSWORD = "admin123" # Change in production!
def verify_database_ready() -> bool:
"""
Verify that database tables exist.
Returns:
bool: True if database is ready, False otherwise
"""
try:
with engine.connect() as conn:
from sqlalchemy import text
# Check for users table
result = conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table' AND name='users'")
)
users_table = result.fetchall()
# Check for vendors table
result = conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table' AND name='vendors'")
)
vendors_table = result.fetchall()
return len(users_table) > 0 and len(vendors_table) > 0
except Exception as e:
print(f"❌ Error checking database: {e}")
return False
def create_admin_user(db: Session, auth_manager: AuthManager) -> tuple[User, bool]:
"""
Create admin user if it doesn't exist.
Args:
db: Database session
auth_manager: AuthManager instance for password hashing
Returns:
tuple: (User object, was_created boolean)
"""
# Check if admin already exists
existing_admin = db.execute(
select(User).where(User.username == DEFAULT_ADMIN_USERNAME)
).scalar_one_or_none()
if existing_admin:
return existing_admin, False
# Create new admin user
admin = User(
email=DEFAULT_ADMIN_EMAIL,
username=DEFAULT_ADMIN_USERNAME,
hashed_password=auth_manager.hash_password(DEFAULT_ADMIN_PASSWORD),
role="admin",
is_active=True,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
db.add(admin)
db.flush() # Get the ID
return admin, True
def create_vendor(
db: Session,
vendor_code: str,
name: str,
subdomain: str,
owner_user_id: int,
description: str = None
) -> tuple[Vendor, bool]:
"""
Create vendor if it doesn't exist.
Args:
db: Database session
vendor_code: Unique vendor code
name: Vendor name
subdomain: Subdomain for the vendor
owner_user_id: ID of the owner user
description: Optional description
Returns:
tuple: (Vendor object, was_created boolean)
"""
# Check if vendor already exists
existing_vendor = db.execute(
select(Vendor).where(Vendor.vendor_code == vendor_code)
).scalar_one_or_none()
if existing_vendor:
return existing_vendor, False
# Create new vendor
vendor = Vendor(
vendor_code=vendor_code,
subdomain=subdomain,
name=name,
description=description or f"{name} - Development vendor",
owner_user_id=owner_user_id,
contact_email=f"contact@{subdomain}.com",
contact_phone="+352 123 456 789",
website=f"https://{subdomain}.com",
is_active=True,
is_verified=True,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
db.add(vendor)
db.flush()
return vendor, True
def seed_database():
"""Main seeding function."""
print("\n" + "" + "" * 68 + "")
print("" + " " * 18 + "DATABASE SEEDING SCRIPT" + " " * 27 + "")
print("" + "" * 68 + "\n")
# ========================================================================
# STEP 1: VERIFY DATABASE
# ========================================================================
print("STEP 1: Verifying database...")
if not verify_database_ready():
print("\n❌ ERROR: Database not ready!")
print("\n Required tables don't exist yet.")
print(" Please run database migrations first:\n")
print(" alembic upgrade head\n")
sys.exit(1)
print(" ✓ Database tables verified\n")
# ========================================================================
# STEP 2: CREATE ADMIN USER
# ========================================================================
db = SessionLocal()
auth_manager = AuthManager()
try:
print("STEP 2: Creating admin user...")
admin, admin_created = create_admin_user(db, auth_manager)
if admin_created:
print(f" ✓ Admin user created (ID: {admin.id})")
print(f" Username: {admin.username}")
print(f" Email: {admin.email}")
else:
print(f" Admin user already exists (ID: {admin.id})")
print(f" Username: {admin.username}")
print(f" Email: {admin.email}")
# ====================================================================
# STEP 3: CREATE VENDORS
# ====================================================================
print("\nSTEP 3: Creating vendors...")
# Create TESTVENDOR
test_vendor, test_created = create_vendor(
db,
vendor_code="TESTVENDOR",
name="Test Vendor",
subdomain="testvendor",
owner_user_id=admin.id,
description="Development test vendor for general testing"
)
if test_created:
print(f" ✓ TESTVENDOR created (ID: {test_vendor.id})")
else:
print(f" TESTVENDOR already exists (ID: {test_vendor.id})")
# Create WIZAMART
wizamart, wizamart_created = create_vendor(
db,
vendor_code="WIZAMART",
name="WizaMart",
subdomain="wizamart",
owner_user_id=admin.id,
description="Primary development vendor for theme customization"
)
if wizamart_created:
print(f" ✓ WIZAMART created (ID: {wizamart.id})")
else:
print(f" WIZAMART already exists (ID: {wizamart.id})")
# Commit all changes
db.commit()
# ====================================================================
# SUMMARY
# ====================================================================
print("\n" + "" + "" * 68 + "")
print("" + " " * 22 + "SEEDING COMPLETE!" + " " * 28 + "")
print("" + "" * 68 + "\n")
if admin_created or test_created or wizamart_created:
print("✅ New items created:")
if admin_created:
print(" • Admin user")
if test_created:
print(" • TESTVENDOR")
if wizamart_created:
print(" • WIZAMART")
else:
print(" All items already existed - no changes made")
print("\n" + "" * 70)
print("📝 ADMIN LOGIN CREDENTIALS")
print("" * 70)
print(f" URL: http://localhost:8000/admin/login")
print(f" Username: {DEFAULT_ADMIN_USERNAME}")
print(f" Password: {DEFAULT_ADMIN_PASSWORD}")
print("" * 70)
print("\n" + "" * 70)
print("🏪 VENDORS")
print("" * 70)
vendors = db.execute(select(Vendor)).scalars().all()
for v in vendors:
print(f"\n {v.vendor_code}")
print(f" Name: {v.name}")
print(f" Subdomain: {v.subdomain}.wizamart.com")
print(f" Theme URL: http://localhost:8000/admin/vendors/{v.vendor_code}/theme")
print(f" Verified: {'' if v.is_verified else ''}")
print(f" Active: {'' if v.is_active else ''}")
print("\n" + "" * 70)
print("🚀 NEXT STEPS")
print("" * 70)
print(" 1. Start the server:")
print(" python -m uvicorn app.main:app --reload\n")
print(" 2. Login to admin panel:")
print(" http://localhost:8000/admin/login\n")
print(" 3. Test theme editor:")
print(" http://localhost:8000/admin/vendors/WIZAMART/theme\n")
if admin_created:
print("⚠️ SECURITY: Change the default admin password after first login!")
print()
except Exception as e:
db.rollback()
print("\n" + "" + "" * 68 + "")
print("" + " " * 28 + "ERROR" + " " * 35 + "")
print("" + "" * 68 + "\n")
print(f"❌ Failed to seed database: {e}")
print(f"\nError type: {type(e).__name__}")
print("\nCommon issues:")
print(" - Database migrations not run (run: alembic upgrade head)")
print(" - Database connection issues")
print(" - Foreign key constraint violations")
print()
import traceback
traceback.print_exc()
sys.exit(1)
finally:
db.close()
if __name__ == "__main__":
try:
seed_database()
except KeyboardInterrupt:
print("\n\n⚠️ Seeding interrupted by user")
sys.exit(1)
except Exception as e:
print(f"\n❌ Fatal error: {e}")
sys.exit(1)