Fix: Resolve newly created users unable to login - Add modules column support to user creation and login flow
Changes: 1. Fixed create_user_handler to properly initialize modules JSON for new users 2. Fixed edit_user_handler to manage module assignments instead of non-existent email field 3. Updated settings_handler to select modules column instead of email from users table 4. Added validate_and_repair_user_modules function in setup_complete_database.py to ensure all users have correct module assignments 5. Added create_app_license function to create development license file during database setup 6. Added ensure_app_license function to docker-entrypoint.sh for license creation on container startup 7. Added user modules validation on Flask app startup to repair any malformed modules 8. License file is automatically created with 1-year validity on deployment This ensures: - New users created via UI get proper module assignments - Existing users are validated/repaired on app startup - Non-superadmin users can login after license check passes - All deployments have a valid development license by default
This commit is contained in:
@@ -423,14 +423,40 @@ def create_users_table_mariadb():
|
||||
# Insert superadmin user if not exists
|
||||
cursor.execute("SELECT COUNT(*) FROM users WHERE username = %s", ('superadmin',))
|
||||
if cursor.fetchone()[0] == 0:
|
||||
# Superadmin doesn't need explicit modules (handled at login)
|
||||
cursor.execute("""
|
||||
INSERT INTO users (username, password, role)
|
||||
VALUES (%s, %s, %s)
|
||||
""", ('superadmin', 'superadmin123', 'superadmin'))
|
||||
INSERT INTO users (username, password, role, modules)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
""", ('superadmin', 'superadmin123', 'superadmin', None))
|
||||
print_success("Superadmin user created (username: superadmin, password: superadmin123)")
|
||||
else:
|
||||
print_success("Superadmin user already exists")
|
||||
|
||||
# Create additional role examples (if they don't exist)
|
||||
cursor.execute("SELECT COUNT(*) FROM roles WHERE name = %s", ('admin',))
|
||||
if cursor.fetchone()[0] == 0:
|
||||
cursor.execute("""
|
||||
INSERT INTO roles (name, access_level, description)
|
||||
VALUES (%s, %s, %s)
|
||||
""", ('admin', 'high', 'Administrator with access to all modules'))
|
||||
print_success("Admin role created")
|
||||
|
||||
cursor.execute("SELECT COUNT(*) FROM roles WHERE name = %s", ('manager',))
|
||||
if cursor.fetchone()[0] == 0:
|
||||
cursor.execute("""
|
||||
INSERT INTO roles (name, access_level, description)
|
||||
VALUES (%s, %s, %s)
|
||||
""", ('manager', 'medium', 'Manager with access to assigned modules'))
|
||||
print_success("Manager role created")
|
||||
|
||||
cursor.execute("SELECT COUNT(*) FROM roles WHERE name = %s", ('worker',))
|
||||
if cursor.fetchone()[0] == 0:
|
||||
cursor.execute("""
|
||||
INSERT INTO roles (name, access_level, description)
|
||||
VALUES (%s, %s, %s)
|
||||
""", ('worker', 'low', 'Worker with limited module access'))
|
||||
print_success("Worker role created")
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
@@ -740,9 +766,103 @@ password={db_password}
|
||||
print_error(f"Failed to update external config: {e}")
|
||||
return False
|
||||
|
||||
def validate_and_repair_user_modules():
|
||||
"""Validate and repair user modules - ensure all users have proper module assignments"""
|
||||
print_step(11, "Validating and Repairing User Module Assignments")
|
||||
|
||||
try:
|
||||
conn = mariadb.connect(**DB_CONFIG)
|
||||
cursor = conn.cursor()
|
||||
|
||||
import json
|
||||
|
||||
# Get all users
|
||||
cursor.execute("SELECT id, username, role, modules FROM users")
|
||||
users = cursor.fetchall()
|
||||
|
||||
users_updated = 0
|
||||
users_checked = 0
|
||||
|
||||
for user_id, username, role, modules in users:
|
||||
users_checked += 1
|
||||
|
||||
# Determine what modules should be assigned
|
||||
if role == 'superadmin':
|
||||
# Superadmin doesn't need explicit modules (set to NULL)
|
||||
correct_modules = None
|
||||
elif role == 'admin':
|
||||
# Admin gets all modules
|
||||
correct_modules = json.dumps(['quality', 'warehouse', 'labels', 'daily_mirror'])
|
||||
elif role in ['manager', 'quality_manager', 'warehouse_manager']:
|
||||
# These roles get quality and warehouse by default
|
||||
correct_modules = json.dumps(['quality', 'warehouse'])
|
||||
else:
|
||||
# worker and others get empty array
|
||||
correct_modules = json.dumps([])
|
||||
|
||||
# Check if modules need to be updated
|
||||
current_modules = modules
|
||||
if current_modules != correct_modules:
|
||||
cursor.execute("""
|
||||
UPDATE users SET modules = %s WHERE id = %s
|
||||
""", (correct_modules, user_id))
|
||||
users_updated += 1
|
||||
action = "assigned" if correct_modules else "cleared"
|
||||
print(f" ✓ User '{username}' ({role}): modules {action}")
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
print_success(f"User modules validation complete: {users_checked} users checked, {users_updated} updated")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print_error(f"Failed to validate/repair user modules: {e}")
|
||||
return False
|
||||
|
||||
def create_app_license():
|
||||
"""Create a default app license file for the application"""
|
||||
print_step(12, "Creating Application License File")
|
||||
|
||||
try:
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Get instance path
|
||||
instance_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../instance'))
|
||||
os.makedirs(instance_path, exist_ok=True)
|
||||
|
||||
license_path = os.path.join(instance_path, 'app_license.json')
|
||||
|
||||
# Check if license already exists
|
||||
if os.path.exists(license_path):
|
||||
print_success("License file already exists")
|
||||
return True
|
||||
|
||||
# Create a default license valid for 1 year from today
|
||||
valid_until = (datetime.utcnow() + timedelta(days=365)).strftime('%Y-%m-%d')
|
||||
|
||||
license_data = {
|
||||
"valid_until": valid_until,
|
||||
"customer": "Development",
|
||||
"license_type": "development",
|
||||
"created_at": datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
with open(license_path, 'w') as f:
|
||||
json.dump(license_data, f, indent=2)
|
||||
|
||||
print_success(f"Application license created (valid until: {valid_until})")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print_error(f"Failed to create application license: {e}")
|
||||
return False
|
||||
|
||||
def verify_database_setup():
|
||||
"""Verify that all tables were created successfully"""
|
||||
print_step(11, "Verifying Database Setup")
|
||||
print_step(13, "Verifying Database Setup")
|
||||
|
||||
try:
|
||||
conn = mariadb.connect(**DB_CONFIG)
|
||||
@@ -825,6 +945,8 @@ def main():
|
||||
create_database_triggers,
|
||||
populate_permissions_data,
|
||||
update_external_config,
|
||||
validate_and_repair_user_modules, # Validate/repair user modules after all setup
|
||||
create_app_license, # Create app license file
|
||||
verify_database_setup
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user