From 0161aba5f55621d4aeda08505c36964c8fe0a86f Mon Sep 17 00:00:00 2001 From: Master3395 Date: Sun, 21 Sep 2025 20:13:15 +0200 Subject: [PATCH] Enhance Imunify installation process: Add checks and fixes for PHP-FPM pool configurations and broken package installations before proceeding with Imunify360 and ImunifyAV installations. Implement auto-fix functionality in the firewall manager for PHP-FPM issues. Update the upgrade module to create missing PHP-FPM pool configurations and restart services as needed. Introduce a new API endpoint to disable two-factor authentication for users, ensuring proper handling and logging of actions. https://github.com/usmannasir/cyberpanel/issues/1114 --- CLManager/CageFS.py | 75 +++++- firewall/firewallManager.py | 24 ++ plogical/upgrade.py | 474 +++++++++++++----------------------- userManagment/urls.py | 1 + userManagment/views.py | 60 +++++ 5 files changed, 319 insertions(+), 315 deletions(-) diff --git a/CLManager/CageFS.py b/CLManager/CageFS.py index 779b63108..f5e2790ca 100644 --- a/CLManager/CageFS.py +++ b/CLManager/CageFS.py @@ -148,25 +148,51 @@ class CageFS: @staticmethod def submitinstallImunify(key): try: - imunifyKeyPath = '/home/cyberpanel/imunifyKeyPath' - ## - writeToFile = open(imunifyKeyPath, 'w') writeToFile.write(key) writeToFile.close() - ## - mailUtilities.checkHome() statusFile = open(ServerStatusUtil.lswsInstallStatusPath, 'w') logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, - "Starting Imunify Installation..\n", 1) + "Starting Imunify360 Installation..\n", 1) - ## + # CRITICAL: Fix PHP-FPM pool configurations before installation + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Fixing PHP-FPM pool configurations for Imunify360 compatibility..\n", 1) + + # Import the upgrade module to access the fix function + from plogical import upgrade + fix_result = upgrade.Upgrade.CreateMissingPoolsforFPM() + + if fix_result == 0: + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "PHP-FPM pool configurations fixed successfully..\n", 1) + else: + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Warning: PHP-FPM pool configuration fix had issues, continuing with installation..\n", 1) + + # Fix broken package installations that might prevent Imunify360 installation + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Fixing broken package installations..\n", 1) + + # Detect OS and fix packages accordingly + if os.path.exists('/etc/redhat-release'): + # CentOS/RHEL/CloudLinux + command = 'yum-complete-transaction --cleanup-only 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + command = 'yum install -y --skip-broken 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + else: + # Ubuntu/Debian + command = 'dpkg --configure -a 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + command = 'apt --fix-broken install -y 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) command = 'mkdir -p /etc/sysconfig/imunify360/generic' ServerStatusUtil.executioner(command, statusFile) @@ -226,8 +252,6 @@ pattern_to_watch = ^/home/.+?/(public_html|public_ftp|private_html)(/.*)?$ @staticmethod def submitinstallImunifyAV(): try: - - mailUtilities.checkHome() statusFile = open(ServerStatusUtil.lswsInstallStatusPath, 'w') @@ -235,7 +259,38 @@ pattern_to_watch = ^/home/.+?/(public_html|public_ftp|private_html)(/.*)?$ logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, "Starting ImunifyAV Installation..\n", 1) - ## + # CRITICAL: Fix PHP-FPM pool configurations before installation + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Fixing PHP-FPM pool configurations for ImunifyAV compatibility..\n", 1) + + # Import the upgrade module to access the fix function + from plogical import upgrade + fix_result = upgrade.Upgrade.CreateMissingPoolsforFPM() + + if fix_result == 0: + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "PHP-FPM pool configurations fixed successfully..\n", 1) + else: + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Warning: PHP-FPM pool configuration fix had issues, continuing with installation..\n", 1) + + # Fix broken package installations that might prevent ImunifyAV installation + logging.CyberCPLogFileWriter.statusWriter(ServerStatusUtil.lswsInstallStatusPath, + "Fixing broken package installations..\n", 1) + + # Detect OS and fix packages accordingly + if os.path.exists('/etc/redhat-release'): + # CentOS/RHEL/CloudLinux + command = 'yum-complete-transaction --cleanup-only 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + command = 'yum install -y --skip-broken 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + else: + # Ubuntu/Debian + command = 'dpkg --configure -a 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) + command = 'apt --fix-broken install -y 2>/dev/null || true' + ServerStatusUtil.executioner(command, statusFile) command = 'mkdir -p /etc/sysconfig/imunify360' ServerStatusUtil.executioner(command, statusFile) diff --git a/firewall/firewallManager.py b/firewall/firewallManager.py index e0d93c922..37519eab5 100644 --- a/firewall/firewallManager.py +++ b/firewall/firewallManager.py @@ -1573,6 +1573,18 @@ class FirewallManager: data['CL'] = 1 + # Auto-fix PHP-FPM issues when accessing Imunify360 page + try: + from plogical import upgrade + logging.CyberCPLogFileWriter.writeToFile("Auto-fixing PHP-FPM pool configurations for Imunify360 compatibility...") + fix_result = upgrade.Upgrade.CreateMissingPoolsforFPM() + if fix_result == 0: + logging.CyberCPLogFileWriter.writeToFile("PHP-FPM pool configurations auto-fixed successfully") + else: + logging.CyberCPLogFileWriter.writeToFile("Warning: PHP-FPM auto-fix had issues") + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error in auto-fix for Imunify360: {str(e)}") + if os.path.exists(FirewallManager.imunifyPath): data['imunify'] = 1 else: @@ -1628,6 +1640,18 @@ class FirewallManager: data = {} data['ipAddress'] = fullAddress + # Auto-fix PHP-FPM issues when accessing ImunifyAV page + try: + from plogical import upgrade + logging.CyberCPLogFileWriter.writeToFile("Auto-fixing PHP-FPM pool configurations for ImunifyAV compatibility...") + fix_result = upgrade.Upgrade.CreateMissingPoolsforFPM() + if fix_result == 0: + logging.CyberCPLogFileWriter.writeToFile("PHP-FPM pool configurations auto-fixed successfully") + else: + logging.CyberCPLogFileWriter.writeToFile("Warning: PHP-FPM auto-fix had issues") + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error in auto-fix for ImunifyAV: {str(e)}") + if os.path.exists(FirewallManager.imunifyAVPath): data['imunify'] = 1 else: diff --git a/plogical/upgrade.py b/plogical/upgrade.py index 3588c5d7a..564037279 100644 --- a/plogical/upgrade.py +++ b/plogical/upgrade.py @@ -4052,317 +4052,181 @@ vmail @staticmethod def CreateMissingPoolsforFPM(): - ##### apache configs + """ + Create missing PHP-FPM pool configurations for all PHP versions. + This function ensures all PHP versions have proper pool configurations + to prevent ImunifyAV/Imunify360 installation failures. + """ + try: + # Detect OS and set paths + CentOSPath = '/etc/redhat-release' + + if os.path.exists(CentOSPath): + # CentOS/RHEL/CloudLinux paths + serverRootPath = '/etc/httpd' + configBasePath = '/etc/httpd/conf.d/' + sockPath = '/var/run/php-fpm/' + runAsUser = 'apache' + group = 'nobody' + + # Define PHP pool paths for CentOS + php_paths = { + '5.4': '/opt/remi/php54/root/etc/php-fpm.d/', + '5.5': '/opt/remi/php55/root/etc/php-fpm.d/', + '5.6': '/etc/opt/remi/php56/php-fpm.d/', + '7.0': '/etc/opt/remi/php70/php-fpm.d/', + '7.1': '/etc/opt/remi/php71/php-fpm.d/', + '7.2': '/etc/opt/remi/php72/php-fpm.d/', + '7.3': '/etc/opt/remi/php73/php-fpm.d/', + '7.4': '/etc/opt/remi/php74/php-fpm.d/', + '8.0': '/etc/opt/remi/php80/php-fpm.d/', + '8.1': '/etc/opt/remi/php81/php-fpm.d/', + '8.2': '/etc/opt/remi/php82/php-fpm.d/', + '8.3': '/etc/opt/remi/php83/php-fpm.d/', + '8.4': '/etc/opt/remi/php84/php-fpm.d/', + '8.5': '/etc/opt/remi/php85/php-fpm.d/' + } + else: + # Ubuntu/Debian paths + serverRootPath = '/etc/apache2' + configBasePath = '/etc/apache2/sites-enabled/' + sockPath = '/var/run/php/' + runAsUser = 'www-data' + group = 'nogroup' + + # Define PHP pool paths for Ubuntu + php_paths = { + '5.4': '/etc/php/5.4/fpm/pool.d/', + '5.5': '/etc/php/5.5/fpm/pool.d/', + '5.6': '/etc/php/5.6/fpm/pool.d/', + '7.0': '/etc/php/7.0/fpm/pool.d/', + '7.1': '/etc/php/7.1/fpm/pool.d/', + '7.2': '/etc/php/7.2/fpm/pool.d/', + '7.3': '/etc/php/7.3/fpm/pool.d/', + '7.4': '/etc/php/7.4/fpm/pool.d/', + '8.0': '/etc/php/8.0/fpm/pool.d/', + '8.1': '/etc/php/8.1/fpm/pool.d/', + '8.2': '/etc/php/8.2/fpm/pool.d/', + '8.3': '/etc/php/8.3/fpm/pool.d/', + '8.4': '/etc/php/8.4/fpm/pool.d/', + '8.5': '/etc/php/8.5/fpm/pool.d/' + } - CentOSPath = '/etc/redhat-release' + # Check if server root exists + if not os.path.exists(serverRootPath): + logging.CyberCPLogFileWriter.writeToFile(f'Server root path not found: {serverRootPath}') + return 1 - if os.path.exists(CentOSPath): + # Create pool configurations for all PHP versions + for version, pool_path in php_paths.items(): + if os.path.exists(pool_path): + www_conf = os.path.join(pool_path, 'www.conf') + + # Skip if www.conf already exists + if os.path.exists(www_conf): + logging.CyberCPLogFileWriter.writeToFile(f'PHP {version} pool config already exists: {www_conf}') + continue + + # Create the pool configuration + pool_name = f'php{version.replace(".", "")}default' + sock_name = f'php{version}-fpm.sock' + + content = f'''[{pool_name}] +user = {runAsUser} +group = {runAsUser} +listen = {sockPath}{sock_name} +listen.owner = {runAsUser} +listen.group = {group} +listen.mode = 0660 +pm = dynamic +pm.max_children = 5 +pm.start_servers = 2 +pm.min_spare_servers = 1 +pm.max_spare_servers = 3 +pm.max_requests = 1000 +pm.status_path = /status +ping.path = /ping +ping.response = pong +request_terminate_timeout = 300 +request_slowlog_timeout = 10 +slowlog = /var/log/php{version}-fpm-slow.log +''' + + try: + # Write the configuration file + with open(www_conf, 'w') as f: + f.write(content) + + # Set proper permissions + os.chown(www_conf, 0, 0) # root:root + os.chmod(www_conf, 0o644) + + logging.CyberCPLogFileWriter.writeToFile(f'Created PHP {version} pool config: {www_conf}') + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f'Error creating PHP {version} pool config: {str(e)}') + else: + logging.CyberCPLogFileWriter.writeToFile(f'PHP {version} pool directory not found: {pool_path}') - serverRootPath = '/etc/httpd' - configBasePath = '/etc/httpd/conf.d/' - php54Path = '/opt/remi/php54/root/etc/php-fpm.d/' - php55Path = '/opt/remi/php55/root/etc/php-fpm.d/' - php56Path = '/etc/opt/remi/php56/php-fpm.d/' - php70Path = '/etc/opt/remi/php70/php-fpm.d/' - php71Path = '/etc/opt/remi/php71/php-fpm.d/' - php72Path = '/etc/opt/remi/php72/php-fpm.d/' - php73Path = '/etc/opt/remi/php73/php-fpm.d/' - - php74Path = '/etc/opt/remi/php74/php-fpm.d/' - - php80Path = '/etc/opt/remi/php80/php-fpm.d/' - php81Path = '/etc/opt/remi/php81/php-fpm.d/' - php82Path = '/etc/opt/remi/php82/php-fpm.d/' - - php83Path = '/etc/opt/remi/php83/php-fpm.d/' - php84Path = '/etc/opt/remi/php84/php-fpm.d/' - php85Path = '/etc/opt/remi/php85/php-fpm.d/' - - serviceName = 'httpd' - sockPath = '/var/run/php-fpm/' - runAsUser = 'apache' - else: - serverRootPath = '/etc/apache2' - configBasePath = '/etc/apache2/sites-enabled/' - - php54Path = '/etc/php/5.4/fpm/pool.d/' - php55Path = '/etc/php/5.5/fpm/pool.d/' - php56Path = '/etc/php/5.6/fpm/pool.d/' - php70Path = '/etc/php/7.0/fpm/pool.d/' - php71Path = '/etc/php/7.1/fpm/pool.d/' - php72Path = '/etc/php/7.2/fpm/pool.d/' - php73Path = '/etc/php/7.3/fpm/pool.d/' - - php74Path = '/etc/php/7.4/fpm/pool.d/' - php80Path = '/etc/php/8.0/fpm/pool.d/' - php81Path = '/etc/php/8.1/fpm/pool.d/' - php82Path = '/etc/php/8.2/fpm/pool.d/' - php83Path = '/etc/php/8.3/fpm/pool.d/' - php84Path = '/etc/php/8.4/fpm/pool.d/' - php85Path = '/etc/php/8.5/fpm/pool.d/' - - serviceName = 'apache2' - sockPath = '/var/run/php/' - runAsUser = 'www-data' - - ##### - - if not os.path.exists(serverRootPath): + # Restart PHP-FPM services to apply configurations + Upgrade.restartPHPFPMServices() + + return 0 + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f'Error in CreateMissingPoolsforFPM: {str(e)}') return 1 - if os.path.exists(php54Path): - content = f""" -[php54default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php5.4-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -""" - WriteToFile = open(f'{php54Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php55Path): - content = f''' -[php55default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php5.5-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php55Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php56Path): - content = f''' -[php56default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php5.6-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php56Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php70Path): - content = f''' -[php70default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php7.0-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php70Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php71Path): - content = f''' -[php71default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php7.1-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php71Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php72Path): - content = f''' -[php72default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php7.2-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php72Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php73Path): - content = f''' -[php73default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php7.3-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php73Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php74Path): - content = f''' -[php74default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php7.4-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php74Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php80Path): - content = f''' -[php80default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.0-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 - -''' - WriteToFile = open(f'{php80Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php81Path): - content = f''' -[php81default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.1-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 - -''' - WriteToFile = open(f'{php81Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - if os.path.exists(php82Path): - content = f''' -[php82default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.2-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 + @staticmethod + def restartPHPFPMServices(): + """ + Restart all PHP-FPM services to apply new pool configurations. + This ensures that ImunifyAV/Imunify360 installation will work properly. + """ + try: + # Define all possible PHP versions + php_versions = ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] -''' - WriteToFile = open(f'{php82Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php83Path): - content = f''' -[php83default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.3-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php83Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php84Path): - content = f''' -[php84default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.4-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php84Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() - - if os.path.exists(php85Path): - content = f''' -[php85default] -user = {runAsUser} -group = {runAsUser} -listen ={sockPath}php8.5-fpm.sock -listen.owner = {runAsUser} -listen.group = {runAsUser} -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -''' - WriteToFile = open(f'{php85Path}www.conf', 'w') - WriteToFile.write(content) - WriteToFile.close() + restarted_count = 0 + total_count = 0 + + for version in php_versions: + service_name = f'php{version}-fpm' + + # Check if service exists + try: + result = subprocess.run(['systemctl', 'list-unit-files', service_name], + capture_output=True, text=True, timeout=10) + if result.returncode == 0 and service_name in result.stdout: + total_count += 1 + + # Restart the service + restart_result = subprocess.run(['systemctl', 'restart', service_name], + capture_output=True, text=True, timeout=30) + + if restart_result.returncode == 0: + # Check if service is actually running + status_result = subprocess.run(['systemctl', 'is-active', service_name], + capture_output=True, text=True, timeout=10) + if status_result.returncode == 0 and 'active' in status_result.stdout: + restarted_count += 1 + logging.CyberCPLogFileWriter.writeToFile(f'Successfully restarted {service_name}') + else: + logging.CyberCPLogFileWriter.writeToFile(f'Warning: {service_name} restarted but not active') + else: + logging.CyberCPLogFileWriter.writeToFile(f'Failed to restart {service_name}: {restart_result.stderr}') + + except subprocess.TimeoutExpired: + logging.CyberCPLogFileWriter.writeToFile(f'Timeout restarting {service_name}') + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f'Error restarting {service_name}: {str(e)}') + + logging.CyberCPLogFileWriter.writeToFile(f'PHP-FPM restart summary: {restarted_count}/{total_count} services restarted successfully') + return restarted_count, total_count + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f'Error in restartPHPFPMServices: {str(e)}') + return 0, 0 @staticmethod def setupPHPSymlink(): diff --git a/userManagment/urls.py b/userManagment/urls.py index 9c4468f9f..fa14ccbcf 100644 --- a/userManagment/urls.py +++ b/userManagment/urls.py @@ -38,4 +38,5 @@ urlpatterns = [ path('getUserHomeDirectories', homeDirectoryViews.getUserHomeDirectories, name='getUserHomeDirectories'), path('migrateUser', homeDirectoryViews.migrateUser, name='migrateUser'), path('userMigration', views.userMigration, name='userMigration'), + path('disable2FA', views.disable2FA, name='disable2FA'), ] diff --git a/userManagment/views.py b/userManagment/views.py index c625d2ed0..cdcaeac3a 100644 --- a/userManagment/views.py +++ b/userManagment/views.py @@ -428,6 +428,10 @@ def saveModifications(request): user.type = 0 user.twoFA = twofa + # If 2FA is being disabled, clear the secret key + if twofa == 0: + user.secretKey = 'None' + if securityLevel == 'LOW': user.securityLevel = secMiddleware.LOW else: @@ -988,3 +992,59 @@ def userMigration(request): except Exception as e: logging.CyberCPLogFileWriter.writeToFile(f"Error loading user migration: {str(e)}") return ACLManager.loadError() + + +def disable2FA(request): + """ + Disable 2FA for a specific user (admin function) + """ + try: + val = request.session['userID'] + currentACL = ACLManager.loadedACL(val) + + if currentACL['admin'] != 1: + data_ret = {'status': 0, 'error_message': 'Unauthorized access. Admin privileges required.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + if request.method == 'POST': + data = json.loads(request.body) + accountUsername = data.get('accountUsername') + + if not accountUsername: + data_ret = {'status': 0, 'error_message': 'Username is required.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + try: + user = Administrator.objects.get(userName=accountUsername) + + # Disable 2FA and clear secret key + user.twoFA = 0 + user.secretKey = 'None' + user.save() + + logging.CyberCPLogFileWriter.writeToFile(f'2FA disabled for user: {accountUsername} by admin: {val}') + + data_ret = { + 'status': 1, + 'error_message': '2FA successfully disabled for user.', + 'message': f'Two-factor authentication has been disabled for user {accountUsername}.' + } + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except Administrator.DoesNotExist: + data_ret = {'status': 0, 'error_message': 'User not found.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + data_ret = {'status': 0, 'error_message': 'Invalid request method.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f'Error in disable2FA: {str(e)}') + data_ret = {'status': 0, 'error_message': str(e)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data)