forked from andika/membership-be
Donation Tracking\ Validation Rejection\ Subscription Data Export\ Admin Dashboard Logo\ Admin Navbar Reorganization
204 lines
6.9 KiB
Python
204 lines
6.9 KiB
Python
"""
|
|
Create a superadmin user interactively.
|
|
Run this script to add a superadmin account to your database.
|
|
"""
|
|
|
|
import getpass
|
|
import re
|
|
from database import SessionLocal
|
|
from models import User, UserStatus, UserRole, Role
|
|
from auth import get_password_hash
|
|
from datetime import datetime, timezone
|
|
import sys
|
|
|
|
def validate_email(email):
|
|
"""Validate email format"""
|
|
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
|
return re.match(pattern, email) is not None
|
|
|
|
def validate_phone(phone):
|
|
"""Validate phone format (simple check)"""
|
|
# Remove common separators
|
|
cleaned = phone.replace('-', '').replace('(', '').replace(')', '').replace(' ', '').replace('.', '')
|
|
return len(cleaned) >= 10 and cleaned.isdigit()
|
|
|
|
def validate_zipcode(zipcode):
|
|
"""Validate US zipcode format"""
|
|
return len(zipcode) == 5 and zipcode.isdigit()
|
|
|
|
def get_input(prompt, validator=None, required=True, default=None):
|
|
"""Get user input with optional validation"""
|
|
while True:
|
|
if default:
|
|
user_input = input(f"{prompt} [{default}]: ").strip()
|
|
if not user_input:
|
|
return default
|
|
else:
|
|
user_input = input(f"{prompt}: ").strip()
|
|
|
|
if not user_input and not required:
|
|
return None
|
|
|
|
if not user_input and required:
|
|
print("❌ This field is required. Please try again.")
|
|
continue
|
|
|
|
if validator and not validator(user_input):
|
|
print("❌ Invalid format. Please try again.")
|
|
continue
|
|
|
|
return user_input
|
|
|
|
def get_password():
|
|
"""Get password with confirmation and validation"""
|
|
while True:
|
|
password = getpass.getpass("Password (min 8 characters): ")
|
|
|
|
if len(password) < 8:
|
|
print("❌ Password must be at least 8 characters long.")
|
|
continue
|
|
|
|
confirm = getpass.getpass("Confirm password: ")
|
|
|
|
if password != confirm:
|
|
print("❌ Passwords do not match. Please try again.")
|
|
continue
|
|
|
|
return password
|
|
|
|
def create_superadmin():
|
|
"""Create a superadmin user interactively"""
|
|
db = SessionLocal()
|
|
|
|
try:
|
|
print("\n" + "="*60)
|
|
print("🔧 LOAF Membership Platform - Superadmin Creation")
|
|
print("="*60 + "\n")
|
|
|
|
# Get user information interactively
|
|
print("📝 Please provide the superadmin account details:\n")
|
|
|
|
email = get_input(
|
|
"Email address",
|
|
validator=validate_email,
|
|
required=True
|
|
)
|
|
|
|
# Check if user already exists
|
|
existing_user = db.query(User).filter(User.email == email).first()
|
|
|
|
if existing_user:
|
|
print(f"\n⚠️ User with email '{email}' already exists!")
|
|
print(f" Current Role: {existing_user.role.value}")
|
|
print(f" Current Status: {existing_user.status.value}")
|
|
|
|
update = input("\n❓ Would you like to update this user to superadmin? (yes/no): ").strip().lower()
|
|
|
|
if update in ['yes', 'y']:
|
|
existing_user.role = UserRole.superadmin
|
|
existing_user.status = UserStatus.active
|
|
existing_user.email_verified = True
|
|
|
|
# Assign superadmin role in dynamic RBAC if roles table exists
|
|
try:
|
|
superadmin_role = db.query(Role).filter(Role.code == 'superadmin').first()
|
|
if superadmin_role and not existing_user.role_id:
|
|
existing_user.role_id = superadmin_role.id
|
|
except Exception:
|
|
pass # Roles table might not exist yet
|
|
|
|
db.commit()
|
|
print("✅ User updated to superadmin successfully!")
|
|
print(f" Email: {existing_user.email}")
|
|
print(f" Role: {existing_user.role.value}")
|
|
print(f" User ID: {existing_user.id}")
|
|
else:
|
|
print("❌ Operation cancelled.")
|
|
return
|
|
|
|
password = get_password()
|
|
|
|
print("\n👤 Personal Information:\n")
|
|
|
|
first_name = get_input("First name", required=True)
|
|
last_name = get_input("Last name", required=True)
|
|
phone = get_input("Phone number", validator=validate_phone, required=True)
|
|
|
|
print("\n📍 Address Information:\n")
|
|
|
|
address = get_input("Street address", required=True)
|
|
city = get_input("City", required=True)
|
|
state = get_input("State (2-letter code)", required=True, default="CA")
|
|
zipcode = get_input("ZIP code", validator=validate_zipcode, required=True)
|
|
|
|
print("\n📅 Date of Birth (YYYY-MM-DD format):\n")
|
|
|
|
while True:
|
|
dob_str = get_input("Date of birth (e.g., 1990-01-15)", required=True)
|
|
try:
|
|
date_of_birth = datetime.strptime(dob_str, "%Y-%m-%d")
|
|
break
|
|
except ValueError:
|
|
print("❌ Invalid date format. Please use YYYY-MM-DD format.")
|
|
|
|
# Create superadmin user
|
|
print("\n⏳ Creating superadmin user...")
|
|
|
|
superadmin_user = User(
|
|
email=email,
|
|
password_hash=get_password_hash(password),
|
|
first_name=first_name,
|
|
last_name=last_name,
|
|
phone=phone,
|
|
address=address,
|
|
city=city,
|
|
state=state.upper(),
|
|
zipcode=zipcode,
|
|
date_of_birth=date_of_birth,
|
|
status=UserStatus.active,
|
|
role=UserRole.superadmin,
|
|
email_verified=True,
|
|
newsletter_subscribed=False
|
|
)
|
|
|
|
db.add(superadmin_user)
|
|
db.flush() # Flush to get the user ID before looking up roles
|
|
|
|
# Assign superadmin role in dynamic RBAC if roles table exists
|
|
try:
|
|
superadmin_role = db.query(Role).filter(Role.code == 'superadmin').first()
|
|
if superadmin_role:
|
|
superadmin_user.role_id = superadmin_role.id
|
|
print(" ✓ Assigned dynamic superadmin role")
|
|
except Exception as e:
|
|
print(f" ⚠️ Dynamic roles not yet set up (this is normal for fresh installs)")
|
|
|
|
db.commit()
|
|
db.refresh(superadmin_user)
|
|
|
|
print("\n" + "="*60)
|
|
print("✅ Superadmin user created successfully!")
|
|
print("="*60)
|
|
print(f"\n📧 Email: {superadmin_user.email}")
|
|
print(f"👤 Name: {superadmin_user.first_name} {superadmin_user.last_name}")
|
|
print(f"🔑 Role: {superadmin_user.role.value}")
|
|
print(f"🆔 User ID: {superadmin_user.id}")
|
|
print(f"\n✨ You can now log in to the admin panel at /admin/login")
|
|
print("\n" + "="*60 + "\n")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n\n❌ Operation cancelled by user.")
|
|
db.rollback()
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"\n❌ Error creating superadmin user: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
db.rollback()
|
|
sys.exit(1)
|
|
finally:
|
|
db.close()
|
|
|
|
if __name__ == "__main__":
|
|
create_superadmin()
|