-
Notifications
You must be signed in to change notification settings - Fork 159
Description
Summary
The admin seeder has a design flaw where it assumes existing admin users are correctly configured, leading to authentication failures when environment variables don't match the database state.
Bug Description
In scripts/seeders/admin_seeder.py (also applicable for scripts/seeders/client_seeder.py), the seeder uses overly simplistic logic for existing users:
# PROBLEMATIC CODE (lines ~74-77)
existing_admin = session.query(User).filter(User.email == admin_email).first()
if existing_admin:
logger.info(f"Admin with email {admin_email} already exists")
return True # Assumes everything is fine!The Issue: The seeder assumes that if an admin user exists, it's correctly configured. This creates problems when:
- Environment Variables Change:
ADMIN_INITIAL_PASSWORDis updated but existing admin still has old password - Manual Database Changes: Admin user exists but has wrong settings (inactive, unverified, non-admin)
- Configuration Drift: Initial setup used different credentials than current environment
Expected Behavior
- Seeders should ensure existing users match current environment configuration
- Admin users should be authenticatable with environment-defined credentials
- Seeder should update existing users to match environment settings
Actual Behavior
- Seeder reports "Admin already exists" but doesn't verify configuration
- Admin users may be unconfigured, inactive, or have mismatched passwords
- Authentication fails with environment-defined credentials
- Users must manually fix database inconsistencies
Real-World Scenario
- Initial setup creates admin with password "oldpassword"
- Later,
ADMIN_INITIAL_PASSWORDenvironment variable is changed to "newpassword" - Seeder runs and says "Admin exists, all good!"
- Authentication fails because admin still has "oldpassword" hash
- Logs show no errors, but admin cannot log in with environment credentials
Environment
- Version: Latest (as of current commit)
- Component:
scripts/seeders/admin_seeder.py - Related Files: Potentially other seeders with similar patterns
Root Cause
Seeder design assumes database state always matches environment configuration, which is not guaranteed in real deployments.
Proposed Fix
Replace the simplistic check with configuration validation:
# Check if the admin already exists
existing_admin = session.query(User).filter(User.email == admin_email).first()
if existing_admin:
logger.info(f"Admin with email {admin_email} already exists")
# Ensure the admin configuration matches environment settings
needs_update = False
# Verify password matches environment
if not verify_password(admin_password, existing_admin.password_hash):
logger.info("Admin password doesn't match environment, updating...")
existing_admin.password_hash = get_password_hash(admin_password)
needs_update = True
# Ensure admin privileges
if not existing_admin.is_admin:
existing_admin.is_admin = True
needs_update = True
# Ensure user is active
if not existing_admin.is_active:
existing_admin.is_active = True
needs_update = True
# Ensure email is verified
if not existing_admin.email_verified:
existing_admin.email_verified = True
needs_update = True
if needs_update:
session.commit()
logger.info("Admin configuration updated to match environment")
else:
logger.info("Admin configuration already matches environment")
return TrueRequired Import Addition:
from src.utils.security import get_password_hash, verify_password # Add verify_passwordAlternative Approach
Add a --force-update flag to seeders that always synchronizes existing users with environment configuration.
Testing Steps to Reproduce
- Create admin user with password "test123"
- Change
ADMIN_INITIAL_PASSWORDenvironment variable to "newpassword" - Run seeder - it reports success
- Try to authenticate with "newpassword" - fails
- Original password "test123" still works, proving configuration drift