-
-
- Auto-refresh paused
-
-
-
Loading top processes...
diff --git a/baseTemplate/urls.py b/baseTemplate/urls.py
index 4372548d6..fd30efb2e 100644
--- a/baseTemplate/urls.py
+++ b/baseTemplate/urls.py
@@ -25,10 +25,6 @@ urlpatterns = [
re_path(r'^getSSHUserActivity$', views.getSSHUserActivity, name='getSSHUserActivity'),
re_path(r'^getTopProcesses$', views.getTopProcesses, name='getTopProcesses'),
re_path(r'^analyzeSSHSecurity$', views.analyzeSSHSecurity, name='analyzeSSHSecurity'),
- re_path(r'^sshSecurityWhitelistList$', views.sshSecurityWhitelistList, name='sshSecurityWhitelistList'),
- re_path(r'^sshSecurityWhitelistAdd$', views.sshSecurityWhitelistAdd, name='sshSecurityWhitelistAdd'),
- re_path(r'^sshSecurityWhitelistRemove$', views.sshSecurityWhitelistRemove, name='sshSecurityWhitelistRemove'),
- re_path(r'^sshSecurityWhitelistUpdate$', views.sshSecurityWhitelistUpdate, name='sshSecurityWhitelistUpdate'),
re_path(r'^blockIPAddress$', views.blockIPAddress, name='blockIPAddress'),
re_path(r'^dismiss_backup_notification$', views.dismiss_backup_notification, name='dismiss_backup_notification'),
re_path(r'^dismiss_ai_scanner_notification$', views.dismiss_ai_scanner_notification, name='dismiss_ai_scanner_notification'),
diff --git a/baseTemplate/views.py b/baseTemplate/views.py
index f1d4735fb..871a8551e 100644
--- a/baseTemplate/views.py
+++ b/baseTemplate/views.py
@@ -861,11 +861,6 @@ def getRecentSSHLogins(request):
lines = output.strip().split('\n')
logins = []
ip_cache = {}
- try:
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- ssh_whitelist_ips = SSHSecurityWhitelistUtilities.ip_set()
- except Exception:
- ssh_whitelist_ips = set()
for line in lines:
if not line.strip() or any(x in line for x in ['reboot', 'system boot', 'wtmp begins']):
continue
@@ -933,12 +928,6 @@ def getRecentSSHLogins(request):
country, flag = 'IPv6', ''
elif ip == '127.0.0.1' or ip == '::1':
country, flag = 'Local', ''
- try:
- ip_for_wl = SSHSecurityWhitelistUtilities.normalize_ip(ip)
- if ip_for_wl and ip_for_wl in ssh_whitelist_ips:
- continue
- except Exception:
- pass
logins.append({
'user': user,
'ip': ip,
@@ -997,11 +986,6 @@ def getRecentSSHLogs(request):
output = ProcessUtilities.outputExecutioner(f'tail -n 500 {log_path}')
except Exception as e:
return HttpResponse(json.dumps({'error': f'Failed to read log: {str(e)}'}), content_type='application/json', status=500)
- try:
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- ssh_whitelist_ips = SSHSecurityWhitelistUtilities.ip_set()
- except Exception:
- ssh_whitelist_ips = set()
lines = output.split('\n')
logs = []
# IP address regex patterns (IPv4)
@@ -1031,12 +1015,6 @@ def getRecentSSHLogs(request):
if not ip_address and ip_matches:
ip_address = ip_matches[0]
- try:
- ip_wl = SSHSecurityWhitelistUtilities.normalize_ip(ip_address) if ip_address else ''
- if ip_wl and ip_wl in ssh_whitelist_ips:
- continue
- except Exception:
- pass
logs.append({
'timestamp': timestamp,
'message': message,
@@ -1207,21 +1185,10 @@ def analyzeSSHSecurity(request):
ip = match.group(1)
repeated_connections[ip] += 1
- # Trusted IPs: never show block recommendations / never block via FirewallUtilities
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- try:
- whitelist_entries = SSHSecurityWhitelistUtilities.load_entries()
- wl_set = {e['ip'] for e in whitelist_entries}
- except Exception:
- whitelist_entries = []
- wl_set = set()
-
# Generate alerts based on analysis
-
+
# High severity: Brute force attacks
for ip, count in failed_passwords.items():
- if SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(ip, wl_set):
- continue
if count >= 10:
recommendation = f'Block this IP immediately:\nfirewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address={ip} drop" && firewall-cmd --reload'
@@ -1237,30 +1204,22 @@ def analyzeSSHSecurity(request):
'recommendation': recommendation
})
- # High severity: Root login attempts (exclude trusted IPs)
- root_login_attempts_filtered = [
- r for r in root_login_attempts
- if not SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(r['ip'], wl_set)
- ]
- if root_login_attempts_filtered:
- unique_ips = set(r["ip"] for r in root_login_attempts_filtered)
- top_ip = max(unique_ips, key=lambda x: sum(1 for r in root_login_attempts_filtered if r["ip"] == x))
+ # High severity: Root login attempts
+ if root_login_attempts:
alerts.append({
'title': 'Root Login Attempts Detected',
- 'description': f'Direct root login attempts detected from {len(unique_ips)} IP addresses. Root SSH access should be disabled.',
+ 'description': f'Direct root login attempts detected from {len(set(r["ip"] for r in root_login_attempts))} IP addresses. Root SSH access should be disabled.',
'severity': 'high',
'details': {
- 'Unique IPs': len(unique_ips),
- 'Total Attempts': len(root_login_attempts_filtered),
- 'Top IP': top_ip
+ 'Unique IPs': len(set(r["ip"] for r in root_login_attempts)),
+ 'Total Attempts': len(root_login_attempts),
+ 'Top IP': max(set(r["ip"] for r in root_login_attempts), key=lambda x: sum(1 for r in root_login_attempts if r["ip"] == x))
},
'recommendation': 'Disable root SSH login by setting "PermitRootLogin no" in /etc/ssh/sshd_config'
})
# Medium severity: Dictionary attacks
for ip, count in invalid_users.items():
- if SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(ip, wl_set):
- continue
if count >= 5:
if firewall_cmd == 'csf':
recommendation = f'Consider blocking this IP:\ncsf -d {ip} "Dictionary attack - {count} invalid users"\n\nAlso configure CSF Login Failure Daemon (lfd) for automatic blocking.'
@@ -1281,8 +1240,6 @@ def analyzeSSHSecurity(request):
# Medium severity: Port scanning
for ip, count in port_scan_attempts.items():
- if SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(ip, wl_set):
- continue
if count >= 3:
alerts.append({
'title': 'Port Scan Detected',
@@ -1298,8 +1255,6 @@ def analyzeSSHSecurity(request):
# Low severity: Successful login after failures
for ip, successes in successful_after_failures.items():
- if SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(ip, wl_set):
- continue
if successes:
max_failures = max(s['failures'] for s in successes)
if max_failures >= 3:
@@ -1317,8 +1272,6 @@ def analyzeSSHSecurity(request):
# High severity: Rapid connection attempts (DDoS/flooding)
for ip, count in repeated_connections.items():
- if SSHSecurityWhitelistUtilities.normalized_ip_in_whitelist(ip, wl_set):
- continue
if count >= 50:
if firewall_cmd == 'csf':
recommendation = f'Block this IP immediately to prevent resource exhaustion:\ncsf -d {ip} "SSH flooding - {count} connections"'
@@ -1395,137 +1348,12 @@ def analyzeSSHSecurity(request):
return HttpResponse(json.dumps({
'status': 1,
- 'alerts': alerts,
- 'whitelist_entries': whitelist_entries,
+ 'alerts': alerts
}), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'error': str(e)}), content_type='application/json', status=500)
-
-def _ssh_whitelist_acl(request):
- """Return (user_id, error_response) or (user_id, None)."""
- user_id = request.session.get('userID')
- if not user_id:
- return None, HttpResponse(json.dumps({'error': 'Not logged in'}), content_type='application/json', status=403)
- currentACL = ACLManager.loadedACL(user_id)
- if not currentACL.get('admin', 0):
- return None, HttpResponse(json.dumps({'error': 'Admin only'}), content_type='application/json', status=403)
- if not ACLManager.CheckForPremFeature('all'):
- return None, HttpResponse(json.dumps({
- 'status': 0,
- 'error': 'SSH Security trusted IPs require the same access as SSH Security Analysis (addons).',
- }), content_type='application/json', status=403)
- return user_id, None
-
-
-@csrf_exempt
-@require_POST
-def sshSecurityWhitelistList(request):
- try:
- _, err = _ssh_whitelist_acl(request)
- if err:
- return err
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- try:
- SSHSecurityWhitelistUtilities.ensure_cyberpanel_public_ip_whitelisted()
- except Exception:
- pass
- entries = SSHSecurityWhitelistUtilities.load_entries()
- return HttpResponse(json.dumps({
- 'status': 1,
- 'entries': entries,
- }), content_type='application/json')
- except Exception as e:
- return HttpResponse(json.dumps({'status': 0, 'error': str(e)}), content_type='application/json', status=500)
-
-
-@csrf_exempt
-@require_POST
-def sshSecurityWhitelistAdd(request):
- try:
- _, err = _ssh_whitelist_acl(request)
- if err:
- return err
- try:
- data = json.loads(request.body.decode('utf-8'))
- except (json.JSONDecodeError, UnicodeDecodeError, AttributeError):
- return HttpResponse(json.dumps({'status': 0, 'error': 'Invalid JSON'}), content_type='application/json', status=400)
- ip = (data.get('ip') or '').strip()
- label = (data.get('label') or '').strip()
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- ok, msg = SSHSecurityWhitelistUtilities.add_entry(ip, label)
- if not ok:
- return HttpResponse(json.dumps({'status': 0, 'error': msg}), content_type='application/json', status=400)
- return HttpResponse(json.dumps({
- 'status': 1,
- 'message': 'Trusted IP added',
- 'ip': msg,
- 'entries': SSHSecurityWhitelistUtilities.load_entries(),
- }), content_type='application/json')
- except Exception as e:
- return HttpResponse(json.dumps({'status': 0, 'error': str(e)}), content_type='application/json', status=500)
-
-
-@csrf_exempt
-@require_POST
-def sshSecurityWhitelistRemove(request):
- try:
- _, err = _ssh_whitelist_acl(request)
- if err:
- return err
- try:
- data = json.loads(request.body.decode('utf-8'))
- except (json.JSONDecodeError, UnicodeDecodeError, AttributeError):
- return HttpResponse(json.dumps({'status': 0, 'error': 'Invalid JSON'}), content_type='application/json', status=400)
- ip = (data.get('ip') or '').strip()
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- ok, msg = SSHSecurityWhitelistUtilities.remove_entry(ip)
- if not ok:
- return HttpResponse(json.dumps({'status': 0, 'error': msg}), content_type='application/json', status=400)
- return HttpResponse(json.dumps({
- 'status': 1,
- 'message': 'Trusted IP removed',
- 'entries': SSHSecurityWhitelistUtilities.load_entries(),
- }), content_type='application/json')
- except Exception as e:
- return HttpResponse(json.dumps({'status': 0, 'error': str(e)}), content_type='application/json', status=500)
-
-
-@csrf_exempt
-@require_POST
-def sshSecurityWhitelistUpdate(request):
- try:
- _, err = _ssh_whitelist_acl(request)
- if err:
- return err
- try:
- data = json.loads(request.body.decode('utf-8'))
- except (json.JSONDecodeError, UnicodeDecodeError, AttributeError):
- return HttpResponse(json.dumps({'status': 0, 'error': 'Invalid JSON'}), content_type='application/json', status=400)
- ip = (data.get('ip') or '').strip()
- new_ip = data.get('new_ip')
- if new_ip is not None:
- new_ip = str(new_ip).strip() or None
- label = data.get('label')
- if label is not None:
- label = str(label).strip()
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- ok, msg, unchanged = SSHSecurityWhitelistUtilities.update_entry(ip, new_ip=new_ip, label=label)
- if not ok:
- return HttpResponse(json.dumps({'status': 0, 'error': msg}), content_type='application/json', status=400)
- message = 'No changes to save.' if unchanged else 'Trusted IP updated.'
- return HttpResponse(json.dumps({
- 'status': 1,
- 'message': message,
- 'unchanged': bool(unchanged),
- 'ip': msg,
- 'entries': SSHSecurityWhitelistUtilities.load_entries(),
- }), content_type='application/json')
- except Exception as e:
- return HttpResponse(json.dumps({'status': 0, 'error': str(e)}), content_type='application/json', status=500)
-
-
@csrf_exempt
@require_POST
def blockIPAddress(request):
diff --git a/emailPremium/views.py b/emailPremium/views.py
index a78a2b6fd..8a3be354c 100644
--- a/emailPremium/views.py
+++ b/emailPremium/views.py
@@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
import os
import time
-import http.client
from django.shortcuts import redirect
from django.http import HttpResponse, JsonResponse
-from django.views.decorators.csrf import csrf_exempt
from loginSystem.models import Administrator
from mailServer.models import Domains, EUsers
@@ -1246,153 +1244,18 @@ def Rspamd(request):
checkIfRspamdInstalled = 0
- ipAddress = '127.0.0.1'
- try:
- ipFile = "/etc/cyberpanel/machineIP"
- with open(ipFile, 'r') as f:
- ipData = f.read()
- first_line = ipData.split('\n', 1)[0].strip()
- if first_line:
- ipAddress = first_line
- except (OSError, IOError, IndexError):
- pass
+ ipFile = "/etc/cyberpanel/machineIP"
+ f = open(ipFile)
+ ipData = f.read()
+ ipAddress = ipData.split('\n', 1)[0]
if mailUtilities.checkIfRspamdInstalled() == 1:
checkIfRspamdInstalled = 1
- rspamd_ui_url = request.build_absolute_uri('/emailPremium/Rspamd/ui/')
proc = httpProc(request, 'emailPremium/Rspamd.html',
- {
- 'checkIfRspamdInstalled': checkIfRspamdInstalled,
- 'ipAddress': ipAddress,
- 'rspamd_ui_url': rspamd_ui_url,
- }, 'admin')
+ {'checkIfRspamdInstalled': checkIfRspamdInstalled, 'ipAddress': ipAddress}, 'admin')
return proc.render()
-
-_RSPAMD_UPSTREAM = ('127.0.0.1', 11334)
-_RSPAMD_HOP_RESPONSE = frozenset({
- 'connection', 'transfer-encoding', 'keep-alive', 'proxy-authenticate',
- 'proxy-authorization', 'te', 'trailers', 'upgrade', 'content-encoding',
-})
-
-
-@csrf_exempt
-def rspamd_ui_proxy(request, subpath=None):
- """Reverse-proxy Rspamd controller UI (localhost:11334) for logged-in admins only."""
- try:
- userID = request.session['userID']
- currentACL = ACLManager.loadedACL(userID)
- if currentACL['admin'] != 1:
- return ACLManager.loadError()
- except KeyError:
- return redirect(loadLoginPage)
-
- if mailUtilities.checkIfRspamdInstalled() != 1:
- return HttpResponse(
- 'Rspamd is not installed.',
- status=503,
- content_type='text/plain; charset=utf-8',
- )
-
- proxy_base = request.build_absolute_uri('/emailPremium/Rspamd/ui').rstrip('/')
- path = '/'
- if subpath:
- path = '/' + subpath.lstrip('/')
- q = request.META.get('QUERY_STRING', '')
- if q:
- full_path = path + '?' + q
- else:
- full_path = path
-
- forward_method = request.method
- if forward_method == 'HEAD':
- forward_method = 'GET'
-
- body = None
- if forward_method in ('POST', 'PUT', 'PATCH', 'DELETE'):
- body = request.body
-
- headers = {}
- acc = request.META.get('HTTP_ACCEPT')
- if acc:
- headers['Accept'] = acc
- al = request.META.get('HTTP_ACCEPT_LANGUAGE')
- if al:
- headers['Accept-Language'] = al
- ua = request.META.get('HTTP_USER_AGENT')
- if ua:
- headers['User-Agent'] = ua
- auth = request.META.get('HTTP_AUTHORIZATION')
- if auth:
- headers['Authorization'] = auth
- ct = request.META.get('CONTENT_TYPE')
- if ct and forward_method in ('POST', 'PUT', 'PATCH'):
- headers['Content-Type'] = ct
- cookie = request.META.get('HTTP_COOKIE')
- if cookie:
- headers['Cookie'] = cookie
- xhr = request.META.get('HTTP_X_REQUESTED_WITH')
- if xhr:
- headers['X-Requested-With'] = xhr
-
- conn = None
- try:
- conn = http.client.HTTPConnection(
- _RSPAMD_UPSTREAM[0], _RSPAMD_UPSTREAM[1], timeout=120,
- )
- conn.request(forward_method, full_path, body=body, headers=headers)
- upstream = conn.getresponse()
- data = upstream.read()
- status = upstream.status
- except (ConnectionRefusedError, OSError, http.client.HTTPException) as _e:
- logging.CyberCPLogFileWriter.writeToFile(
- 'rspamd_ui_proxy upstream error: %s' % (type(_e).__name__,),
- )
- return HttpResponse(
- 'Could not reach Rspamd on 127.0.0.1:11334. Is rspamd running?',
- status=502,
- content_type='text/plain; charset=utf-8',
- )
- finally:
- if conn is not None:
- try:
- conn.close()
- except Exception:
- pass
-
- if request.method == 'HEAD':
- out = HttpResponse(status=status)
- data = b''
-
- else:
- out = HttpResponse(data, status=status)
-
- for hdr, val in upstream.getheaders():
- key = hdr.lower()
- if key in _RSPAMD_HOP_RESPONSE:
- continue
- if key == 'location':
- val = _rewrite_rspamd_location(val, proxy_base)
- if request.method == 'HEAD' and key == 'content-length':
- continue
- out[hdr] = val
-
- return out
-
-
-def _rewrite_rspamd_location(location, proxy_base):
- if not location:
- return location
- if location.startswith('http://127.0.0.1:11334'):
- return proxy_base + location[len('http://127.0.0.1:11334'):]
- if location.startswith('http://[::1]:11334'):
- return proxy_base + location[len('http://[::1]:11334'):]
- if location.startswith('/') and not location.startswith('//'):
- return proxy_base + location
- return location
-
-
def installRspamd(request):
try:
userID = request.session['userID']
diff --git a/loginSystem/webauthn_views.py b/loginSystem/webauthn_views.py
index c0c693b24..9b3f3ee69 100644
--- a/loginSystem/webauthn_views.py
+++ b/loginSystem/webauthn_views.py
@@ -162,13 +162,6 @@ class WebAuthnAuthenticationComplete(WebAuthnAPIView):
if ip_addr.find(':') > -1:
ip_addr = ':'.join(ip_addr.split(':')[:3])
request.session['ipAddr'] = ip_addr
- try:
- from loginSystem.models import Administrator
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- adm = Administrator.objects.select_related('acl').get(pk=int(result['user_id']))
- SSHSecurityWhitelistUtilities.on_successful_panel_login(request, adm)
- except Exception:
- pass
redirect_url = data.get('redirect') or request.session.pop('webauthn_redirect', '/') or '/'
if '//' in redirect_url or not redirect_url.startswith('/'):
redirect_url = '/'
@@ -196,13 +189,6 @@ class WebAuthnAuthenticationComplete(WebAuthnAPIView):
if ip_addr.find(':') > -1:
ip_addr = ':'.join(ip_addr.split(':')[:3])
request.session['ipAddr'] = ip_addr
- try:
- from loginSystem.models import Administrator
- from plogical.sshSecurityWhitelistUtilities import SSHSecurityWhitelistUtilities
- adm = Administrator.objects.select_related('acl').get(pk=int(result['user_id']))
- SSHSecurityWhitelistUtilities.on_successful_panel_login(request, adm)
- except Exception:
- pass
logger.info(f"WebAuthn authentication successful for user ID: {result['user_id']}")
return self.json_response(result)
diff --git a/plogical/mailUtilities.py b/plogical/mailUtilities.py
index bcf6062de..ec5f821ef 100644
--- a/plogical/mailUtilities.py
+++ b/plogical/mailUtilities.py
@@ -853,10 +853,6 @@ return custom_keywords
writeToFile.writelines("Configuring RSPAMD repo..\n")
writeToFile.close()
- try:
- os.makedirs('/etc/yum.repos.d', mode=0o755, exist_ok=True)
- except OSError:
- pass
command = 'curl https://rspamd.com/rpm-stable/centos-7/rspamd.repo > /etc/yum.repos.d/rspamd.repo'
ProcessUtilities.normalExecutioner(command, True)
@@ -872,39 +868,20 @@ return custom_keywords
elif ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
- el_major = mailUtilities._rhel_el_major_version()
writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
- writeToFile.writelines(
- "Configuring RSPAMD repo for EL%s (rspamd.com rpm-stable)...\n" % el_major
- )
+ writeToFile.writelines("Configuring RSPAMD repo..\n")
writeToFile.close()
- try:
- os.makedirs('/etc/yum.repos.d', mode=0o755, exist_ok=True)
- except OSError:
- pass
- command = (
- 'curl -fsSL https://rspamd.com/rpm-stable/centos-%s/rspamd.repo '
- '-o /etc/yum.repos.d/rspamd.repo' % el_major
- )
+ command = 'curl https://rspamd.com/rpm-stable/centos-8/rspamd.repo > /etc/yum.repos.d/rspamd.repo'
ProcessUtilities.normalExecutioner(command, True)
command = 'rpm --import https://rspamd.com/rpm-stable/gpg.key'
ProcessUtilities.normalExecutioner(command, True)
- if el_major == '7':
- command = 'yum update -y'
- ProcessUtilities.normalExecutioner(command, True)
- command = (
- 'sudo yum install -y rspamd clamav-server clamav-data clamav-update '
- 'clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib '
- 'clamav-server-systemd'
- )
- else:
- command = 'dnf update -y'
- ProcessUtilities.normalExecutioner(command, True)
+ command = 'dnf update -y'
+ ProcessUtilities.normalExecutioner(command, True)
- command = 'sudo dnf install -y rspamd clamav clamd clamav-update'
+ command = 'sudo dnf install -y rspamd clamav clamd clamav-update'
else:
command = 'DEBIAN_FRONTEND=noninteractive apt-get install rspamd clamav clamav-daemon -y'
@@ -914,24 +891,9 @@ return custom_keywords
f.flush()
res = subprocess.call(command, stdout=f, stderr=f, shell=True)
- if res != 0:
- with open(mailUtilities.RspamdInstallLogPath, 'a') as lf:
- lf.write(
- 'Package install failed (exit code %s). '
- 'On EL9, ensure rspamd.repo matches your OS (EL8 RPMs cause GPG errors on EL9).\n' % res
- )
- lf.write('Can not be installed.[404]\n')
- logging.CyberCPLogFileWriter.writeToFile(
- '[Could not Install Rspamd.] dnf/yum exit %s' % res
- )
- return 0
###### makefile
path = "/etc/rspamd/local.d/antivirus.conf"
- try:
- os.makedirs(os.path.dirname(path), mode=0o755, exist_ok=True)
- except OSError:
- pass
content ="""# ================= DO NOT MODIFY THIS FILE =================
#
# Manual changes will be lost when this file is regenerated.
@@ -995,10 +957,6 @@ clamav {
### disable dkim signing in rspamd in ref to https://github.com/usmannasir/cyberpanel/issues/1176
DKIMPath = '/etc/rspamd/local.d/dkim_signing.conf'
- try:
- os.makedirs(os.path.dirname(DKIMPath), mode=0o755, exist_ok=True)
- except OSError:
- pass
WriteToFile = open(DKIMPath, 'w')
WriteToFile.write('enabled = false;\n')
@@ -1026,10 +984,6 @@ clamav {
wpath = "/etc/rspamd/local.d/redis.conf"
- try:
- os.makedirs(os.path.dirname(wpath), mode=0o755, exist_ok=True)
- except OSError:
- pass
wdata = """
write_servers = "127.0.0.1";
read_servers = "127.0.0.1";
@@ -1040,30 +994,34 @@ read_servers = "127.0.0.1";
wirtedata2.close()
- if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
- command = 'setsebool -P antivirus_can_scan_system 1'
- cmd = shlex.split(command)
+ if res == 1:
+ writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
+ writeToFile.writelines("Can not be installed.[404]\n")
+ writeToFile.close()
+ logging.CyberCPLogFileWriter.writeToFile("[Could not Install Rspamd.]")
+ return 0
+ else:
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8:
+ command = 'setsebool -P antivirus_can_scan_system 1'
+ cmd = shlex.split(command)
- command = 'setsebool -P clamd_use_jit 1'
- cmd = shlex.split(command)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ command = 'setsebool -P clamd_use_jit 1'
+ cmd = shlex.split(command)
- command = 'usermod -a -G clamscan _rspamd'
- cmd = shlex.split(command)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ command = 'usermod -a -G clamscan _rspamd'
+ cmd = shlex.split(command)
- try:
- os.makedirs('/etc/clamd.d', mode=0o755, exist_ok=True)
- except OSError:
- pass
- clamavcontent = """
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
+
+ clamavcontent = """
User clamscan
PidFile /var/run/clamd.scan/clamd.pid
TCPSocket 3310
@@ -1076,60 +1034,49 @@ ScanMail true
ScanArchive true
#LogFile /var/log/clamd.scan/clamav.log
"""
- writeToFile = open('/etc/clamd.d/scan.conf', 'w')
- writeToFile.write(clamavcontent)
- writeToFile.close()
+ writeToFile = open('/etc/clamd.d/scan.conf', 'w')
+ writeToFile.write(clamavcontent)
+ writeToFile.close()
- command = 'touch /var/log/clamd.scan/clamav.log'
- ProcessUtilities.normalExecutioner(command, False, 'clamscan')
+ command = 'touch /var/log/clamd.scan/clamav.log'
+ ProcessUtilities.normalExecutioner(command, False, 'clamscan')
- writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
- writeToFile.writelines("Updating Freshclam database..\n")
- writeToFile.close()
+ writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
+ writeToFile.writelines("Updating Freshclam database..\n")
+ writeToFile.close()
- command = 'freshclam'
- cmd = shlex.split(command)
+ command = 'freshclam'
+ cmd = shlex.split(command)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- command = 'systemctl start clamd@scan'
- cmd = shlex.split(command)
+ command = 'systemctl start clamd@scan'
+ cmd = shlex.split(command)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- command = 'systemctl restart rspamd'
- cmd = shlex.split(command)
+ command = 'systemctl restart rspamd'
+ cmd = shlex.split(command)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
+ elif ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
- time.sleep(5)
+ command = 'usermod -a -G clamav _rspamd'
+ cmd = shlex.split(command)
- writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
- writeToFile.writelines("Rspamd Installed.[200]\n")
- writeToFile.close()
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- elif ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu or ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu20:
+ command = 'chown -R clamav:clamav /var/run/clamav'
+ cmd = shlex.split(command)
- command = 'usermod -a -G clamav _rspamd'
- cmd = shlex.split(command)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
-
- command = 'chown -R clamav:clamav /var/run/clamav'
- cmd = shlex.split(command)
-
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
-
- try:
- os.makedirs('/etc/clamav', mode=0o755, exist_ok=True)
- except OSError:
- pass
- clamavcontent = """
+ clamavcontent = """
User clamav
PidFile /var/run/clamav/clamd.pid
TCPSocket 3310
@@ -1142,31 +1089,32 @@ ScanMail true
ScanArchive true
LogFile /var/log/clamav/clamav.log
"""
- writeToFile = open('/etc/clamav/clamd.conf', 'w')
- writeToFile.write(clamavcontent)
- writeToFile.close()
+ writeToFile = open('/etc/clamav/clamd.conf', 'w')
+ writeToFile.write(clamavcontent)
+ writeToFile.close()
- writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
- writeToFile.writelines("Updating Freshclam database..\n")
- writeToFile.close()
- command = 'freshclam'
- cmd = shlex.split(command)
+ writeToFile = open(mailUtilities.RspamdInstallLogPath, 'a')
+ writeToFile.writelines("Updating Freshclam database..\n")
+ writeToFile.close()
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ command = 'freshclam'
+ cmd = shlex.split(command)
- command = 'systemctl restart clamav-daemon'
- cmd = shlex.split(command)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ command = 'systemctl restart clamav-daemon'
+ cmd = shlex.split(command)
- command = 'systemctl restart rspamd'
- cmd = shlex.split(command)
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
- with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
- res = subprocess.call(cmd, stdout=f)
+ command = 'systemctl restart rspamd'
+ cmd = shlex.split(command)
+
+ with open(mailUtilities.RspamdInstallLogPath, 'a') as f:
+ res = subprocess.call(cmd, stdout=f)
time.sleep(5)
@@ -1704,21 +1652,6 @@ LogFile /var/log/clamav/clamav.log
str(msg) + " [checkIfMailScannerInstalled]")
return 0
- @staticmethod
- def _rhel_el_major_version():
- """Parse PLATFORM_ID from /etc/os-release (e.g. platform:el9 -> '9'). Default '8'."""
- import re
- try:
- with open('/etc/os-release', 'r') as os_release:
- for line in os_release:
- if line.startswith('PLATFORM_ID='):
- m = re.search(r'el(\d+)', line)
- if m:
- return m.group(1)
- except Exception:
- pass
- return '8'
-
@staticmethod
def FetchPostfixHostname():
try:
diff --git a/plogical/processUtilities.py b/plogical/processUtilities.py
index c020180b7..58b270aba 100644
--- a/plogical/processUtilities.py
+++ b/plogical/processUtilities.py
@@ -188,60 +188,17 @@ class ProcessUtilities(multi.Thread):
return ProcessUtilities.ubuntu20
return ProcessUtilities.ubuntu
- # Debian (no Ubuntu): use same apt paths as Ubuntu for CyberPanel mail stack
- for _line in content.splitlines():
- _ls = _line.strip()
- if _ls.startswith('ID='):
- _id = _ls.split('=', 1)[1].strip().strip('"').lower()
- if _id == 'debian':
- return ProcessUtilities.ubuntu
- break
-
# Check for RedHat-based distributions
if os.path.exists(distroPathAlma):
with open(distroPathAlma, 'r') as f:
content = f.read()
- if any(x in content for x in ['CentOS Linux release 7', 'CentOS Linux release 8',
- 'CentOS Stream release 8', 'CentOS Stream release 9',
- 'AlmaLinux release 8', 'Rocky Linux release 8',
- 'Rocky Linux release 9', 'AlmaLinux release 9',
- 'CloudLinux release 9', 'CloudLinux release 8',
- 'AlmaLinux release 10', 'Rocky Linux release 10',
- 'Red Hat Enterprise Linux release 8',
- 'Red Hat Enterprise Linux release 9',
- 'Red Hat Enterprise Linux release 10']):
- if any(x in content for x in ['AlmaLinux release 9', 'Rocky Linux release 9',
- 'AlmaLinux release 10', 'Rocky Linux release 10',
- 'Red Hat Enterprise Linux release 9',
- 'Red Hat Enterprise Linux release 10',
- 'CentOS Stream release 9']):
+ if any(x in content for x in ['CentOS Linux release 8', 'AlmaLinux release 8', 'Rocky Linux release 8',
+ 'Rocky Linux release 9', 'AlmaLinux release 9', 'CloudLinux release 9',
+ 'CloudLinux release 8', 'AlmaLinux release 10']):
+ if any(x in content for x in ['AlmaLinux release 9', 'Rocky Linux release 9', 'AlmaLinux release 10']):
ProcessUtilities.alma9check = 1
return ProcessUtilities.cent8
- # Fallback: /etc/os-release for RHEL family (some minimal images lack redhat-release text we match)
- if os.path.exists('/etc/os-release'):
- try:
- with open('/etc/os-release', 'r') as f:
- os_lines = f.read()
- rid = ''
- for line in os_lines.splitlines():
- if line.startswith('ID='):
- rid = line.split('=', 1)[1].strip().strip('"').lower()
- break
- if rid in ('almalinux', 'rocky', 'centos', 'rhel', 'cloudlinux', 'eurolinux',
- 'miraclelinux', 'openeuler', 'virtuozzo'):
- ver_id = ''
- for line in os_lines.splitlines():
- if line.startswith('VERSION_ID='):
- ver_id = line.split('=', 1)[1].strip().strip('"')
- break
- major = ver_id.split('.')[0] if ver_id else '8'
- if major in ('9', '10'):
- ProcessUtilities.alma9check = 1
- return ProcessUtilities.cent8
- except OSError:
- pass
-
# Default to Ubuntu if no other distribution is detected
return ProcessUtilities.ubuntu
diff --git a/public/static/baseTemplate/custom-js/system-status.js b/public/static/baseTemplate/custom-js/system-status.js
index 64609165b..b4cf11a11 100644
--- a/public/static/baseTemplate/custom-js/system-status.js
+++ b/public/static/baseTemplate/custom-js/system-status.js
@@ -1004,16 +1004,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.topProcesses = [];
$scope.loadingTopProcesses = true;
$scope.errorTopProcesses = '';
- /** When true, automatic Top Process refresh is stopped (user can read the table). */
- $scope.topProcessPaused = false;
- /**
- * @param {boolean} silent If true, refresh rows in place without clearing the table (no loading spinner).
- */
- $scope.refreshTopProcesses = function(silent) {
- silent = !!silent;
- if (!silent) {
- $scope.loadingTopProcesses = true;
- }
+ $scope.refreshTopProcesses = function() {
+ $scope.loadingTopProcesses = true;
var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
$http.get('/base/getTopProcesses', h).then(function (response) {
$scope.loadingTopProcesses = false;
@@ -1022,12 +1014,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
} else {
$scope.topProcesses = [];
}
- $scope.errorTopProcesses = '';
}, function (err) {
$scope.loadingTopProcesses = false;
- if (!silent) {
- $scope.errorTopProcesses = 'Failed to load top processes.';
- }
+ $scope.errorTopProcesses = 'Failed to load top processes.';
});
};
@@ -1035,7 +1024,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogins = [];
$scope.sshLoginsPaginated = [];
$scope.sshLoginsCurrentPage = 1;
- $scope.sshLoginsPerPage = 3;
+ $scope.sshLoginsPerPage = 10;
$scope.sshLoginsGoToPage = 1;
$scope.loadingSSHLogins = true;
$scope.errorSSHLogins = '';
@@ -1065,10 +1054,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
console.log('updateSSHLoginsPaginated: No data, cleared paginated array');
return;
}
- var per = parseInt($scope.sshLoginsPerPage, 10) || 3;
- $scope.sshLoginsPerPage = per;
- var start = ($scope.sshLoginsCurrentPage - 1) * per;
- var end = start + per;
+ var start = ($scope.sshLoginsCurrentPage - 1) * $scope.sshLoginsPerPage;
+ var end = start + $scope.sshLoginsPerPage;
$scope.sshLoginsPaginated = $scope.sshLogins.slice(start, end);
console.log('updateSSHLoginsPaginated: start=', start, 'end=', end, 'total=', $scope.sshLogins.length, 'paginated=', $scope.sshLoginsPaginated.length);
};
@@ -1097,12 +1084,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLoginsGoToPage = $scope.sshLoginsCurrentPage;
}
};
- $scope.sshLoginsChangePerPage = function() {
- $scope.sshLoginsPerPage = parseInt($scope.sshLoginsPerPage, 10) || 3;
- $scope.sshLoginsCurrentPage = 1;
- $scope.sshLoginsGoToPage = 1;
- $scope.updateSSHLoginsPaginated();
- };
$scope.refreshSSHLogins = function() {
$scope.loadingSSHLogins = true;
@@ -1134,7 +1115,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogs = [];
$scope.sshLogsPaginated = [];
$scope.sshLogsCurrentPage = 1;
- $scope.sshLogsPerPage = 3;
+ $scope.sshLogsPerPage = 10;
$scope.sshLogsGoToPage = 1;
$scope.loadingSSHLogs = true;
$scope.errorSSHLogs = '';
@@ -1166,10 +1147,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
console.log('updateSSHLogsPaginated: No data, cleared paginated array');
return;
}
- var per = parseInt($scope.sshLogsPerPage, 10) || 3;
- $scope.sshLogsPerPage = per;
- var start = ($scope.sshLogsCurrentPage - 1) * per;
- var end = start + per;
+ var start = ($scope.sshLogsCurrentPage - 1) * $scope.sshLogsPerPage;
+ var end = start + $scope.sshLogsPerPage;
$scope.sshLogsPaginated = $scope.sshLogs.slice(start, end);
console.log('updateSSHLogsPaginated: start=', start, 'end=', end, 'total=', $scope.sshLogs.length, 'paginated=', $scope.sshLogsPaginated.length);
};
@@ -1198,12 +1177,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogsGoToPage = $scope.sshLogsCurrentPage;
}
};
- $scope.sshLogsChangePerPage = function() {
- $scope.sshLogsPerPage = parseInt($scope.sshLogsPerPage, 10) || 3;
- $scope.sshLogsCurrentPage = 1;
- $scope.sshLogsGoToPage = 1;
- $scope.updateSSHLogsPaginated();
- };
$scope.refreshSSHLogs = function() {
$scope.loadingSSHLogs = true;
@@ -1242,114 +1215,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.blockingIP = null;
$scope.blockedIPs = {};
- // SSH Security: trusted IPs (never blocked, excluded from analysis alerts)
- // Use an object for ng-model: inputs live under ng-if child scopes; primitives would not update parent.
- $scope.sshSecurityWhitelist = [];
- $scope.sshWhitelistMap = {};
- $scope.whitelistUi = { ip: '', label: '' };
-
- $scope._syncWhitelistMap = function () {
- $scope.sshWhitelistMap = {};
- if ($scope.sshSecurityWhitelist && $scope.sshSecurityWhitelist.length) {
- $scope.sshSecurityWhitelist.forEach(function (r) {
- $scope.sshWhitelistMap[r.ip] = true;
- });
- }
- };
-
- $scope._decorateWhitelistEntries = function (entries) {
- $scope.sshSecurityWhitelist = (entries || []).map(function (e) {
- return {
- ip: e.ip,
- label: e.label || '',
- updated: e.updated || 0,
- _l: e.label || '',
- _nip: ''
- };
- });
- $scope._syncWhitelistMap();
- };
-
- $scope.isSshWhitelisted = function (ip) {
- if (!ip) return false;
- return !!$scope.sshWhitelistMap[String(ip).trim()];
- };
-
- $scope.loadSshSecurityWhitelist = function () {
- var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
- $http.post('/base/sshSecurityWhitelistList', {}, h).then(function (res) {
- if (res.data && res.data.status === 1) {
- $scope._decorateWhitelistEntries(res.data.entries);
- }
- });
- };
-
- $scope.addSshSecurityWhitelist = function () {
- var ip = ($scope.whitelistUi && $scope.whitelistUi.ip || '').trim();
- var label = ($scope.whitelistUi && $scope.whitelistUi.label || '').trim();
- if (!ip) {
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Trusted IP', text: 'Enter an IP address', type: 'warning', delay: 4000 }); }
- return;
- }
- var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
- $http.post('/base/sshSecurityWhitelistAdd', { ip: ip, label: label }, h).then(function (res) {
- if (res.data && res.data.status === 1) {
- if ($scope.whitelistUi) {
- $scope.whitelistUi.ip = '';
- $scope.whitelistUi.label = '';
- }
- $scope._decorateWhitelistEntries(res.data.entries);
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Trusted IP', text: 'IP added to trusted list', type: 'success', delay: 4000 }); }
- if ($scope.analyzeSSHSecurity) { $scope.analyzeSSHSecurity(); }
- } else {
- var err = (res.data && (res.data.error || res.data.message)) ? (res.data.error || res.data.message) : 'Failed to add';
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Error', text: err, type: 'error', delay: 6000 }); }
- }
- }, function (err) {
- var msg = 'Request failed';
- if (err.data && err.data.error) msg = err.data.error;
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Error', text: msg, type: 'error', delay: 6000 }); }
- });
- };
-
- $scope.removeSshSecurityWhitelist = function (ip) {
- if (!ip) return;
- var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
- $http.post('/base/sshSecurityWhitelistRemove', { ip: ip }, h).then(function (res) {
- if (res.data && res.data.status === 1) {
- $scope._decorateWhitelistEntries(res.data.entries);
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Trusted IP', text: 'IP removed from trusted list', type: 'success', delay: 4000 }); }
- if ($scope.analyzeSSHSecurity) { $scope.analyzeSSHSecurity(); }
- } else {
- var err2 = (res.data && res.data.error) ? res.data.error : 'Failed to remove';
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Error', text: err2, type: 'error', delay: 6000 }); }
- }
- });
- };
-
- $scope.saveSshSecurityWhitelistRow = function (row) {
- if (!row || !row.ip) return;
- var payload = { ip: row.ip, label: row._l };
- if (row._nip && String(row._nip).trim()) payload.new_ip = String(row._nip).trim();
- var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
- $http.post('/base/sshSecurityWhitelistUpdate', payload, h).then(function (res) {
- var d = res.data || {};
- var st = d.status === 1 || d.status === '1';
- if (st) {
- $scope._decorateWhitelistEntries(d.entries);
- if (typeof PNotify !== 'undefined') {
- var unchanged = d.unchanged === true || d.unchanged === 'true' || d.unchanged === 1;
- var txt = (d.message && String(d.message).length) ? d.message : (unchanged ? 'No changes to save.' : 'Entry updated');
- new PNotify({ title: 'Trusted IP', text: txt, type: unchanged ? 'info' : 'success', delay: 4000 });
- }
- if ($scope.analyzeSSHSecurity) { $scope.analyzeSSHSecurity(); }
- } else {
- var err3 = d.error ? d.error : 'Failed to update';
- if (typeof PNotify !== 'undefined') { new PNotify({ title: 'Error', text: err3, type: 'error', delay: 6000 }); }
- }
- });
- };
-
$scope.analyzeSSHSecurity = function() {
$scope.loadingSecurityAnalysis = true;
$scope.showAddonRequired = false;
@@ -1362,9 +1227,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.securityAlerts = [];
} else if (response.data.status === 1) {
$scope.securityAlerts = response.data.alerts;
- if (response.data.whitelist_entries) {
- $scope._decorateWhitelistEntries(response.data.whitelist_entries);
- }
$scope.showAddonRequired = false;
}
}
@@ -1799,47 +1661,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
// For rate calculation
var lastRx = null, lastTx = null, lastDiskRead = null, lastDiskWrite = null, lastCPU = null;
var lastCPUTimes = null;
- var pollInterval = 2000; // ms (charts / dashboard stats)
- /** Top Process list: slower refresh, silent updates (no table flash). */
- var topProcessPollIntervalMs = 10000;
- var topProcessPollPromise = null;
-
- function cancelTopProcessPoll() {
- if (topProcessPollPromise) {
- $timeout.cancel(topProcessPollPromise);
- topProcessPollPromise = null;
- }
- }
-
- function scheduleTopProcessPoll() {
- cancelTopProcessPoll();
- function tick() {
- if ($scope.topProcessPaused) {
- return;
- }
- topProcessPollPromise = $timeout(function() {
- topProcessPollPromise = null;
- if (!$scope.topProcessPaused) {
- $scope.refreshTopProcesses(true);
- }
- if (!$scope.topProcessPaused) {
- tick();
- }
- }, topProcessPollIntervalMs);
- }
- tick();
- }
-
- $scope.toggleTopProcessPause = function() {
- $scope.topProcessPaused = !$scope.topProcessPaused;
- if ($scope.topProcessPaused) {
- cancelTopProcessPoll();
- } else {
- $scope.refreshTopProcesses(true);
- scheduleTopProcessPoll();
- }
- };
-
+ var pollInterval = 2000; // ms
var maxPoints = 30;
// Expose so switchTab can create charts on first tab click if they weren't created at load
@@ -2362,6 +2184,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
// Initial setup - fetch stats immediately
pollDashboardStats();
+ $scope.refreshTopProcesses();
$scope.refreshSSHLogins();
$scope.refreshSSHLogs();
@@ -2379,17 +2202,16 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.hideSystemCharts = true;
});
- // Start polling for all stats (data feeds charts). Top Process is polled separately (slower, silent).
+ // Start polling for all stats (data feeds charts)
function pollAll() {
pollDashboardStats();
pollTraffic();
pollDiskIO();
pollCPU();
+ $scope.refreshTopProcesses();
$timeout(pollAll, pollInterval);
}
pollAll();
-
- scheduleTopProcessPoll();
}, 800);
// SSH User Activity Modal
diff --git a/static/baseTemplate/custom-js/system-status.js b/static/baseTemplate/custom-js/system-status.js
index c6d928c79..b4cf11a11 100644
--- a/static/baseTemplate/custom-js/system-status.js
+++ b/static/baseTemplate/custom-js/system-status.js
@@ -1004,16 +1004,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.topProcesses = [];
$scope.loadingTopProcesses = true;
$scope.errorTopProcesses = '';
- /** When true, automatic Top Process refresh is stopped (user can read the table). */
- $scope.topProcessPaused = false;
- /**
- * @param {boolean} silent If true, refresh rows in place without clearing the table (no loading spinner).
- */
- $scope.refreshTopProcesses = function(silent) {
- silent = !!silent;
- if (!silent) {
- $scope.loadingTopProcesses = true;
- }
+ $scope.refreshTopProcesses = function() {
+ $scope.loadingTopProcesses = true;
var h = { headers: { 'X-CSRFToken': (typeof getCookie === 'function') ? getCookie('csrftoken') : '' } };
$http.get('/base/getTopProcesses', h).then(function (response) {
$scope.loadingTopProcesses = false;
@@ -1022,12 +1014,9 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
} else {
$scope.topProcesses = [];
}
- $scope.errorTopProcesses = '';
}, function (err) {
$scope.loadingTopProcesses = false;
- if (!silent) {
- $scope.errorTopProcesses = 'Failed to load top processes.';
- }
+ $scope.errorTopProcesses = 'Failed to load top processes.';
});
};
@@ -1035,7 +1024,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogins = [];
$scope.sshLoginsPaginated = [];
$scope.sshLoginsCurrentPage = 1;
- $scope.sshLoginsPerPage = 3;
+ $scope.sshLoginsPerPage = 10;
$scope.sshLoginsGoToPage = 1;
$scope.loadingSSHLogins = true;
$scope.errorSSHLogins = '';
@@ -1065,10 +1054,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
console.log('updateSSHLoginsPaginated: No data, cleared paginated array');
return;
}
- var per = parseInt($scope.sshLoginsPerPage, 10) || 3;
- $scope.sshLoginsPerPage = per;
- var start = ($scope.sshLoginsCurrentPage - 1) * per;
- var end = start + per;
+ var start = ($scope.sshLoginsCurrentPage - 1) * $scope.sshLoginsPerPage;
+ var end = start + $scope.sshLoginsPerPage;
$scope.sshLoginsPaginated = $scope.sshLogins.slice(start, end);
console.log('updateSSHLoginsPaginated: start=', start, 'end=', end, 'total=', $scope.sshLogins.length, 'paginated=', $scope.sshLoginsPaginated.length);
};
@@ -1097,12 +1084,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLoginsGoToPage = $scope.sshLoginsCurrentPage;
}
};
- $scope.sshLoginsChangePerPage = function() {
- $scope.sshLoginsPerPage = parseInt($scope.sshLoginsPerPage, 10) || 3;
- $scope.sshLoginsCurrentPage = 1;
- $scope.sshLoginsGoToPage = 1;
- $scope.updateSSHLoginsPaginated();
- };
$scope.refreshSSHLogins = function() {
$scope.loadingSSHLogins = true;
@@ -1134,7 +1115,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogs = [];
$scope.sshLogsPaginated = [];
$scope.sshLogsCurrentPage = 1;
- $scope.sshLogsPerPage = 3;
+ $scope.sshLogsPerPage = 10;
$scope.sshLogsGoToPage = 1;
$scope.loadingSSHLogs = true;
$scope.errorSSHLogs = '';
@@ -1166,10 +1147,8 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
console.log('updateSSHLogsPaginated: No data, cleared paginated array');
return;
}
- var per = parseInt($scope.sshLogsPerPage, 10) || 3;
- $scope.sshLogsPerPage = per;
- var start = ($scope.sshLogsCurrentPage - 1) * per;
- var end = start + per;
+ var start = ($scope.sshLogsCurrentPage - 1) * $scope.sshLogsPerPage;
+ var end = start + $scope.sshLogsPerPage;
$scope.sshLogsPaginated = $scope.sshLogs.slice(start, end);
console.log('updateSSHLogsPaginated: start=', start, 'end=', end, 'total=', $scope.sshLogs.length, 'paginated=', $scope.sshLogsPaginated.length);
};
@@ -1198,12 +1177,6 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.sshLogsGoToPage = $scope.sshLogsCurrentPage;
}
};
- $scope.sshLogsChangePerPage = function() {
- $scope.sshLogsPerPage = parseInt($scope.sshLogsPerPage, 10) || 3;
- $scope.sshLogsCurrentPage = 1;
- $scope.sshLogsGoToPage = 1;
- $scope.updateSSHLogsPaginated();
- };
$scope.refreshSSHLogs = function() {
$scope.loadingSSHLogs = true;
@@ -1688,47 +1661,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
// For rate calculation
var lastRx = null, lastTx = null, lastDiskRead = null, lastDiskWrite = null, lastCPU = null;
var lastCPUTimes = null;
- var pollInterval = 2000; // ms (charts / dashboard stats)
- /** Top Process list: slower refresh, silent updates (no table flash). */
- var topProcessPollIntervalMs = 10000;
- var topProcessPollPromise = null;
-
- function cancelTopProcessPoll() {
- if (topProcessPollPromise) {
- $timeout.cancel(topProcessPollPromise);
- topProcessPollPromise = null;
- }
- }
-
- function scheduleTopProcessPoll() {
- cancelTopProcessPoll();
- function tick() {
- if ($scope.topProcessPaused) {
- return;
- }
- topProcessPollPromise = $timeout(function() {
- topProcessPollPromise = null;
- if (!$scope.topProcessPaused) {
- $scope.refreshTopProcesses(true);
- }
- if (!$scope.topProcessPaused) {
- tick();
- }
- }, topProcessPollIntervalMs);
- }
- tick();
- }
-
- $scope.toggleTopProcessPause = function() {
- $scope.topProcessPaused = !$scope.topProcessPaused;
- if ($scope.topProcessPaused) {
- cancelTopProcessPoll();
- } else {
- $scope.refreshTopProcesses(true);
- scheduleTopProcessPoll();
- }
- };
-
+ var pollInterval = 2000; // ms
var maxPoints = 30;
// Expose so switchTab can create charts on first tab click if they weren't created at load
@@ -2251,6 +2184,7 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
// Initial setup - fetch stats immediately
pollDashboardStats();
+ $scope.refreshTopProcesses();
$scope.refreshSSHLogins();
$scope.refreshSSHLogs();
@@ -2268,17 +2202,16 @@ var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
$scope.hideSystemCharts = true;
});
- // Start polling for all stats (data feeds charts). Top Process is polled separately (slower, silent).
+ // Start polling for all stats (data feeds charts)
function pollAll() {
pollDashboardStats();
pollTraffic();
pollDiskIO();
pollCPU();
+ $scope.refreshTopProcesses();
$timeout(pollAll, pollInterval);
}
pollAll();
-
- scheduleTopProcessPoll();
}, 800);
// SSH User Activity Modal