diff --git a/py_app/app/__pycache__/routes.cpython-312.pyc b/py_app/app/__pycache__/routes.cpython-312.pyc index 31ec46b..f3b6de2 100644 Binary files a/py_app/app/__pycache__/routes.cpython-312.pyc and b/py_app/app/__pycache__/routes.cpython-312.pyc differ diff --git a/py_app/app/__pycache__/settings.cpython-312.pyc b/py_app/app/__pycache__/settings.cpython-312.pyc index b5f7fbf..1865883 100644 Binary files a/py_app/app/__pycache__/settings.cpython-312.pyc and b/py_app/app/__pycache__/settings.cpython-312.pyc differ diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 69cd6f6..d72e5fb 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -9,14 +9,16 @@ from reportlab.pdfgen import canvas from flask import Blueprint, render_template, request, redirect, url_for, flash import csv from .warehouse import add_location -from .settings import ( - settings_handler, +from app.settings import ( + settings_handler, role_permissions_handler, save_role_permissions_handler, reset_role_permissions_handler, - create_user_handler, - edit_user_handler, - delete_user_handler, + save_all_role_permissions_handler, + reset_all_role_permissions_handler, + edit_user_handler, + create_user_handler, + delete_user_handler, save_external_db_handler ) @@ -278,6 +280,107 @@ def save_external_db(): def role_permissions(): return role_permissions_handler() +@bp.route('/test_permissions') +def test_permissions(): + from app.settings import role_permissions_handler + from flask import render_template, session, redirect, url_for, flash + from app.permissions import APP_PERMISSIONS, ACTIONS + + # Check if superadmin + if not session.get('role') == 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.dashboard')) + + try: + # Get the same data as role_permissions_handler + from app.settings import get_external_db_connection + + conn = get_external_db_connection() + cursor = conn.cursor() + + # Get roles from role_hierarchy table + cursor.execute("SELECT role_name, display_name, description, level FROM role_hierarchy ORDER BY level DESC") + role_data = cursor.fetchall() + + roles = {} + for role_name, display_name, description, level in role_data: + roles[role_name] = { + 'display_name': display_name, + 'description': description, + 'level': level + } + + conn.close() + + return render_template('test_permissions.html', + roles=roles, + pages=APP_PERMISSIONS, + action_names=ACTIONS) + + except Exception as e: + return f"Error: {e}" + +@bp.route('/role_permissions_simple') +def role_permissions_simple(): + # Use the same handler but different template + from app.settings import get_external_db_connection + from flask import render_template, session, redirect, url_for, flash + from app.permissions import APP_PERMISSIONS, ACTIONS + import json + + # Check if superadmin + if not session.get('role') == 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.dashboard')) + + try: + # Get roles and their current permissions + conn = get_external_db_connection() + cursor = conn.cursor() + + # Get roles from role_hierarchy table + cursor.execute("SELECT role_name, display_name, description, level FROM role_hierarchy ORDER BY level DESC") + role_data = cursor.fetchall() + + roles = {} + for role_name, display_name, description, level in role_data: + roles[role_name] = { + 'display_name': display_name, + 'description': description, + 'level': level + } + + # Get current role permissions + cursor.execute(""" + SELECT role, permission_key + FROM role_permissions + WHERE granted = TRUE + """) + permission_data = cursor.fetchall() + + role_permissions = {} + for role, permission_key in permission_data: + if role not in role_permissions: + role_permissions[role] = [] + role_permissions[role].append(permission_key) + + conn.close() + + # Convert to JSON for JavaScript + permissions_json = json.dumps(APP_PERMISSIONS) + role_permissions_json = json.dumps(role_permissions) + + return render_template('role_permissions_simple.html', + roles=roles, + pages=APP_PERMISSIONS, + action_names=ACTIONS, + permissions_json=permissions_json, + role_permissions_json=role_permissions_json) + + except Exception as e: + flash(f'Error loading role permissions: {e}') + return redirect(url_for('main.dashboard')) + @bp.route('/settings/save_role_permissions', methods=['POST']) def save_role_permissions(): return save_role_permissions_handler() @@ -286,6 +389,14 @@ def save_role_permissions(): def reset_role_permissions(): return reset_role_permissions_handler() +@bp.route('/settings/save_all_role_permissions', methods=['POST']) +def save_all_role_permissions(): + return save_all_role_permissions_handler() + +@bp.route('/settings/reset_all_role_permissions', methods=['POST']) +def reset_all_role_permissions(): + return reset_all_role_permissions_handler() + @bp.route('/get_report_data', methods=['GET']) def get_report_data(): report = request.args.get('report') @@ -683,6 +794,13 @@ def debug_dates(): @bp.route('/test_database', methods=['GET']) def test_database(): """Test database connection and query the scan1_orders table""" + # Check if user has superadmin permissions + if 'role' not in session or session['role'] != 'superadmin': + return jsonify({ + "success": False, + "error": "Access denied: Superadmin permissions required for database testing." + }), 403 + try: print("DEBUG: Testing database connection...") conn = get_db_connection() diff --git a/py_app/app/settings.py b/py_app/app/settings.py index 5ade332..73d92e8 100644 --- a/py_app/app/settings.py +++ b/py_app/app/settings.py @@ -491,3 +491,116 @@ def reset_role_permissions_handler(): except Exception as e: return jsonify({'success': False, 'error': str(e)}) + + +def save_all_role_permissions_handler(): + """Save all role permissions at once""" + if not is_superadmin(): + return jsonify({'success': False, 'error': 'Access denied: Superadmin only.'}) + + try: + data = request.get_json() + permissions_data = data.get('permissions', {}) + + if not permissions_data: + return jsonify({'success': False, 'error': 'No permissions data provided'}) + + conn = get_external_db_connection() + cursor = conn.cursor() + + current_user = session.get('username', 'system') + total_updated = 0 + + # Process each role's permissions + for role, role_permissions in permissions_data.items(): + # Clear existing permissions for this role + cursor.execute("DELETE FROM role_permissions WHERE role = %s", (role,)) + + # Convert nested permissions to flat permission keys + permission_keys = [] + for page_key, page_perms in role_permissions.items(): + for section_key, actions in page_perms.items(): + for action in actions: + permission_key = f"{page_key}.{section_key}.{action}" + permission_keys.append(permission_key) + + # Insert new permissions + for permission_key in permission_keys: + cursor.execute(""" + INSERT INTO role_permissions (role, permission_key, granted, granted_by) + VALUES (%s, %s, TRUE, %s) + """, (role, permission_key, current_user)) + total_updated += 1 + + # Log the change + cursor.execute(""" + INSERT INTO permission_audit_log (role, permission_key, action, changed_by, reason) + VALUES (%s, %s, 'bulk_update', %s, %s) + """, (role, f"Updated {len(permission_keys)} permissions", current_user, "Bulk permission update")) + + conn.commit() + conn.close() + + # Clear permission cache since permissions changed + clear_permission_cache() + + return jsonify({ + 'success': True, + 'message': f'Successfully updated {total_updated} permissions across {len(permissions_data)} roles' + }) + + except Exception as e: + return jsonify({'success': False, 'error': str(e)}) + + +def reset_all_role_permissions_handler(): + """Reset all role permissions to defaults""" + if not is_superadmin(): + return jsonify({'success': False, 'error': 'Access denied: Superadmin only.'}) + + try: + # Get all roles + conn = get_external_db_connection() + cursor = conn.cursor() + + cursor.execute("SELECT role_name FROM role_hierarchy") + roles = [row[0] for row in cursor.fetchall()] + + current_user = session.get('username', 'system') + total_reset = 0 + + # Reset each role to defaults + for role in roles: + # Clear existing permissions + cursor.execute("DELETE FROM role_permissions WHERE role = %s", (role,)) + + # Get default permissions for the role + default_permissions = get_default_permissions_for_role(role) + + # Add default permissions + for permission_key in default_permissions: + cursor.execute(""" + INSERT INTO role_permissions (role, permission_key, granted, granted_by) + VALUES (%s, %s, TRUE, %s) + """, (role, permission_key, current_user)) + total_reset += 1 + + # Log the change + cursor.execute(""" + INSERT INTO permission_audit_log (role, permission_key, action, changed_by, reason) + VALUES (%s, %s, 'reset_all_defaults', %s, %s) + """, (role, f"Reset {len(default_permissions)} permissions", current_user, "Reset all to default permissions")) + + conn.commit() + conn.close() + + # Clear permission cache since permissions changed + clear_permission_cache() + + return jsonify({ + 'success': True, + 'message': f'Successfully reset {total_reset} permissions across {len(roles)} roles to defaults' + }) + + except Exception as e: + return jsonify({'success': False, 'error': str(e)}) diff --git a/py_app/app/templates/quality.html b/py_app/app/templates/quality.html index fd25d82..eea0503 100644 --- a/py_app/app/templates/quality.html +++ b/py_app/app/templates/quality.html @@ -56,7 +56,9 @@
diff --git a/py_app/app/templates/role_permissions.html b/py_app/app/templates/role_permissions.html index 735880d..5d03e90 100644 --- a/py_app/app/templates/role_permissions.html +++ b/py_app/app/templates/role_permissions.html @@ -5,345 +5,178 @@ {% block head %} {% endblock %} {% block content %}