feat: Implement warehouse module roles with auto-schema repair and remove module access section
- Add SchemaVerifier class for automatic database schema verification and repair - Implement warehouse_manager (Level 75) and warehouse_worker (Level 35) roles - Add zone-based access control for warehouse workers - Implement worker-manager binding system with zone filtering - Add comprehensive database auto-repair on Docker initialization - Remove Module Access section from user form (role-based access only) - Add autocomplete attributes to password fields for better UX - Include detailed documentation for warehouse implementation - Update initialize_db.py with schema verification as Step 0
This commit is contained in:
@@ -185,7 +185,6 @@ def create_user():
|
||||
password = request.form.get('password', '').strip()
|
||||
confirm_password = request.form.get('confirm_password', '').strip()
|
||||
is_active = request.form.get('is_active') == 'on'
|
||||
modules = request.form.getlist('modules')
|
||||
|
||||
# Validation
|
||||
errors = []
|
||||
@@ -202,8 +201,6 @@ def create_user():
|
||||
errors.append("Passwords do not match")
|
||||
if len(password) < 8:
|
||||
errors.append("Password must be at least 8 characters")
|
||||
if not modules:
|
||||
errors.append("Select at least one module")
|
||||
|
||||
if errors:
|
||||
conn = get_db()
|
||||
@@ -251,13 +248,6 @@ def create_user():
|
||||
(user_id, password_hash)
|
||||
)
|
||||
|
||||
# Grant module access
|
||||
for module in modules:
|
||||
cursor.execute(
|
||||
"INSERT IGNORE INTO user_modules (user_id, module_name) VALUES (%s, %s)",
|
||||
(user_id, module)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
|
||||
@@ -311,11 +301,10 @@ def edit_user(user_id):
|
||||
|
||||
if request.method == 'GET':
|
||||
cursor.close()
|
||||
available_modules = ['quality', 'settings']
|
||||
return render_template('modules/settings/user_form.html',
|
||||
user=user,
|
||||
roles=roles,
|
||||
available_modules=available_modules,
|
||||
available_modules=['quality', 'settings'],
|
||||
user_modules=user_modules)
|
||||
|
||||
# Handle POST - Update user
|
||||
@@ -326,7 +315,6 @@ def edit_user(user_id):
|
||||
password = request.form.get('password', '').strip()
|
||||
confirm_password = request.form.get('confirm_password', '').strip()
|
||||
is_active = request.form.get('is_active') == 'on'
|
||||
modules = request.form.getlist('modules')
|
||||
|
||||
# Validation
|
||||
errors = []
|
||||
@@ -339,16 +327,13 @@ def edit_user(user_id):
|
||||
errors.append("Passwords do not match")
|
||||
if password and len(password) < 8:
|
||||
errors.append("Password must be at least 8 characters")
|
||||
if not modules:
|
||||
errors.append("Select at least one module")
|
||||
|
||||
if errors:
|
||||
cursor.close()
|
||||
available_modules = ['quality', 'settings']
|
||||
return render_template('modules/settings/user_form.html',
|
||||
user=user,
|
||||
roles=roles,
|
||||
available_modules=available_modules,
|
||||
available_modules=['quality', 'settings'],
|
||||
user_modules=user_modules,
|
||||
error="; ".join(errors))
|
||||
|
||||
@@ -366,14 +351,6 @@ def edit_user(user_id):
|
||||
(password_hash, user_id)
|
||||
)
|
||||
|
||||
# Update module access
|
||||
cursor.execute("DELETE FROM user_modules WHERE user_id = %s", (user_id,))
|
||||
for module in modules:
|
||||
cursor.execute(
|
||||
"INSERT INTO user_modules (user_id, module_name) VALUES (%s, %s)",
|
||||
(user_id, module)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
|
||||
@@ -381,11 +358,10 @@ def edit_user(user_id):
|
||||
|
||||
except Exception as e:
|
||||
cursor.close()
|
||||
available_modules = ['quality', 'settings']
|
||||
return render_template('modules/settings/user_form.html',
|
||||
user=user,
|
||||
roles=roles,
|
||||
available_modules=available_modules,
|
||||
available_modules=['quality', 'settings'],
|
||||
user_modules=user_modules,
|
||||
error=f"Error updating user: {str(e)}")
|
||||
|
||||
@@ -862,6 +838,40 @@ def restore_database():
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@settings_bp.route('/api/database/tables', methods=['GET'])
|
||||
def get_database_tables():
|
||||
"""Get list of all database tables (dynamically fetched)"""
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'error': 'Unauthorized'}), 401
|
||||
|
||||
try:
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Get list of all tables with their row counts
|
||||
cursor.execute("""
|
||||
SELECT TABLE_NAME, TABLE_ROWS
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
ORDER BY TABLE_NAME
|
||||
""")
|
||||
|
||||
tables = [{'name': row[0], 'rows': row[1] or 0} for row in cursor.fetchall()]
|
||||
cursor.close()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'tables': tables,
|
||||
'count': len(tables)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}), 500
|
||||
|
||||
|
||||
@settings_bp.route('/api/database/truncate', methods=['POST'])
|
||||
def truncate_table():
|
||||
"""Truncate (clear) a database table"""
|
||||
|
||||
Reference in New Issue
Block a user