199 lines
6.1 KiB
Python
199 lines
6.1 KiB
Python
"""
|
|
User and Role Seeder
|
|
Creates default roles and an admin user
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
from datetime import datetime, timezone
|
|
import bcrypt
|
|
|
|
# Add parent directory to path to import modules
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from sqlalchemy.orm import Session
|
|
from src.shared.config.database import SessionLocal
|
|
# Import all models to ensure relationships are properly initialized
|
|
from src.models import *
|
|
from src.auth.models.role import Role
|
|
from src.auth.models.user import User
|
|
from src.shared.config.logging_config import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def get_roles_data():
|
|
"""Generate default roles data"""
|
|
return [
|
|
{
|
|
'name': 'admin',
|
|
'description': 'Full system access with all administrative privileges'
|
|
},
|
|
{
|
|
'name': 'staff',
|
|
'description': 'Hotel staff with operational access'
|
|
},
|
|
{
|
|
'name': 'customer',
|
|
'description': 'Regular customer/guest user'
|
|
},
|
|
{
|
|
'name': 'accountant',
|
|
'description': 'Financial management and accounting access'
|
|
},
|
|
|
|
{
|
|
'name': 'housekeeping',
|
|
'description': 'Housekeeping and room management access'
|
|
}
|
|
]
|
|
|
|
|
|
def seed_roles(db: Session):
|
|
"""Seed roles into the database"""
|
|
try:
|
|
roles_data = get_roles_data()
|
|
created_count = 0
|
|
updated_count = 0
|
|
role_map = {}
|
|
|
|
for role_data in roles_data:
|
|
existing = db.query(Role).filter(Role.name == role_data['name']).first()
|
|
|
|
if existing:
|
|
logger.info(f'Role already exists: {role_data["name"]}')
|
|
role_map[role_data['name']] = existing
|
|
else:
|
|
logger.info(f'Creating role: {role_data["name"]}')
|
|
role = Role(**role_data)
|
|
db.add(role)
|
|
db.flush() # Flush to get the ID
|
|
role_map[role_data['name']] = role
|
|
created_count += 1
|
|
|
|
db.commit()
|
|
logger.info(f'Role seeding completed! Created: {created_count}, Existing: {len(roles_data) - created_count}')
|
|
return role_map
|
|
|
|
except Exception as e:
|
|
logger.error(f'Error seeding roles: {str(e)}', exc_info=True)
|
|
db.rollback()
|
|
raise
|
|
|
|
|
|
def seed_admin_user(db: Session, admin_role: Role, email: str = 'admin@hotel.com', password: str = 'admin123', full_name: str = 'Admin User'):
|
|
"""Seed admin user into the database"""
|
|
try:
|
|
# Check if admin user already exists
|
|
existing = db.query(User).filter(User.email == email).first()
|
|
|
|
if existing:
|
|
logger.info(f'Admin user already exists: {email}')
|
|
# Update role if needed
|
|
if existing.role_id != admin_role.id:
|
|
existing.role_id = admin_role.id
|
|
existing.updated_at = datetime.now(timezone.utc)
|
|
db.commit()
|
|
logger.info(f'Updated admin user role: {email}')
|
|
return existing
|
|
|
|
# Create new admin user
|
|
logger.info(f'Creating admin user: {email}')
|
|
password_bytes = password.encode('utf-8')
|
|
salt = bcrypt.gensalt()
|
|
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
|
|
|
|
admin_user = User(
|
|
email=email,
|
|
password=hashed_password,
|
|
full_name=full_name,
|
|
role_id=admin_role.id,
|
|
is_active=True,
|
|
phone=None,
|
|
address=None
|
|
)
|
|
|
|
db.add(admin_user)
|
|
db.commit()
|
|
db.refresh(admin_user)
|
|
logger.info(f'Admin user created successfully: {email}')
|
|
return admin_user
|
|
|
|
except Exception as e:
|
|
logger.error(f'Error seeding admin user: {str(e)}', exc_info=True)
|
|
db.rollback()
|
|
raise
|
|
|
|
|
|
def seed_users_and_roles(db: Session, admin_email: str = 'admin@hotel.com', admin_password: str = 'admin123', admin_name: str = 'Admin User'):
|
|
"""Seed roles and admin user"""
|
|
try:
|
|
# First, seed roles
|
|
role_map = seed_roles(db)
|
|
|
|
# Get admin role
|
|
admin_role = role_map.get('admin')
|
|
if not admin_role:
|
|
raise ValueError('Admin role not found after seeding')
|
|
|
|
# Seed admin user
|
|
admin_user = seed_admin_user(db, admin_role, admin_email, admin_password, admin_name)
|
|
|
|
return role_map, admin_user
|
|
|
|
except Exception as e:
|
|
logger.error(f'Error seeding users and roles: {str(e)}', exc_info=True)
|
|
raise
|
|
|
|
|
|
def main():
|
|
"""Main function to run the seeder"""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description='Seed roles and admin user')
|
|
parser.add_argument(
|
|
'--email',
|
|
default='admin@hotel.com',
|
|
help='Admin user email (default: admin@hotel.com)'
|
|
)
|
|
parser.add_argument(
|
|
'--password',
|
|
default='admin123',
|
|
help='Admin user password (default: admin123)'
|
|
)
|
|
parser.add_argument(
|
|
'--name',
|
|
default='Admin User',
|
|
help='Admin user full name (default: Admin User)'
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
logger.info('Starting user and role seeder...')
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
role_map, admin_user = seed_users_and_roles(
|
|
db,
|
|
admin_email=args.email,
|
|
admin_password=args.password,
|
|
admin_name=args.name
|
|
)
|
|
logger.info(f'User and role seeder completed successfully!')
|
|
logger.info(f'Admin user: {admin_user.email} (ID: {admin_user.id})')
|
|
logger.info(f'Roles created: {len(role_map)}')
|
|
print(f'\n✓ Admin user created successfully!')
|
|
print(f' Email: {admin_user.email}')
|
|
print(f' Password: {args.password}')
|
|
print(f' Role: admin')
|
|
print(f'\n⚠️ IMPORTANT: Change the default password after first login!')
|
|
except Exception as e:
|
|
logger.error(f'Failed to seed users and roles: {str(e)}', exc_info=True)
|
|
sys.exit(1)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|