From 8d1aada3777be0f2dff5de3664f6c8eec8c4dfa0 Mon Sep 17 00:00:00 2001 From: usmannasir Date: Mon, 2 Jun 2025 16:11:00 +0500 Subject: [PATCH] ssh logs --- .../baseTemplate/custom-js/system-status.js | 21 + .../templates/baseTemplate/homePage.html | 680 +++++++++--------- baseTemplate/urls.py | 1 + baseTemplate/views.py | 37 + 4 files changed, 406 insertions(+), 333 deletions(-) diff --git a/baseTemplate/static/baseTemplate/custom-js/system-status.js b/baseTemplate/static/baseTemplate/custom-js/system-status.js index 390cc9018..88a4e5bb5 100644 --- a/baseTemplate/static/baseTemplate/custom-js/system-status.js +++ b/baseTemplate/static/baseTemplate/custom-js/system-status.js @@ -875,6 +875,27 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) { $scope.totalDBs = 0; $scope.totalEmails = 0; + // SSH Logs + $scope.sshLogs = []; + $scope.loadingSSHLogs = true; + $scope.errorSSHLogs = ''; + function fetchSSHLogs() { + $scope.loadingSSHLogs = true; + $http.get('/base/getRecentSSHLogs').then(function (response) { + $scope.loadingSSHLogs = false; + if (response.data && response.data.logs) { + $scope.sshLogs = response.data.logs; + } else { + $scope.sshLogs = []; + } + }, function (err) { + $scope.loadingSSHLogs = false; + $scope.errorSSHLogs = 'Failed to load SSH logs.'; + }); + } + fetchSSHLogs(); + setInterval(fetchSSHLogs, 10000); + // SSH Logins $scope.sshLogins = []; $scope.loadingSSHLogins = true; diff --git a/baseTemplate/templates/baseTemplate/homePage.html b/baseTemplate/templates/baseTemplate/homePage.html index 81c8d2d96..1a906562b 100755 --- a/baseTemplate/templates/baseTemplate/homePage.html +++ b/baseTemplate/templates/baseTemplate/homePage.html @@ -6,10 +6,6 @@ {% get_current_language as LANGUAGE_CODE %} -
-
+
-
-
- {% trans "CPU Usage" %} -
-
- - {$ cpuUsage $}% - -
-
-
+
+
{% trans "CPU Usage" %}
+
+
+ {$ cpuUsage $}% +
+
+
+
- -
-
- {% trans "Ram Usage" %} -
-
- - {$ ramUsage $}% - -
-
-
+
+
{% trans "Ram Usage" %}
+
+
+ {$ ramUsage $}% +
+
+
+
- -
-
- {% trans "Disk Usage '/'" %} -
-
- - {$ diskUsage $}% - -
-
-
+
+
{% trans "Disk Usage '/'" %}
+
+
+ {$ diskUsage $}% +
+
+
+
@@ -604,180 +486,66 @@
- -
-
-
- - Recent SSH Logins - -
- - -
- Loading recent SSH logins... -
- - -
- No recent SSH logins found. -
- - -
- + + {% if admin %} +
+ +
+
Recent SSH Logins
+
Loading recent SSH logins...
+
No recent SSH logins found.
+
+
- - - - - - + + + + + + - - - + + + - - + + + + +
- User - - IP - - Country - - Date/Time - - Session -
UserIPCountryDate/TimeSession
+
+
+ +
+
Recent SSH Logs
+
Loading recent SSH logs...
+
{$ errorSSHLogs $}
+
No recent SSH logs found.
+
+ + + + + + + + + + +
TimestampMessage
{$ log.timestamp $}{$ log.message $}
+ {% endif %}
@@ -831,54 +599,294 @@ color: #4c5fad !important; } - /* CSS for circular progress bars - ensuring they display correctly */ + /* CSS for circular progress bars */ .c100 { position: relative; - width: 100px; - height: 100px; + font-size: 100px; + width: 1em; + height: 1em; border-radius: 50%; - background: #f0f0f0; margin: 0 auto; + background-color: #f3f3f3; + display: inline-block; + } + + .c100 *, + .c100 *:before, + .c100 *:after { + box-sizing: content-box; + } + + .c100 > span { + position: absolute; + width: 100%; + z-index: 1; + left: 0; + top: 0; + line-height: 1em; + font-size: 0.2em; + color: #333; + display: block; + text-align: center; + white-space: nowrap; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + } + + .c100:after { + position: absolute; + top: 0.08em; + left: 0.08em; + display: block; + content: " "; + border-radius: 50%; + background-color: #fff; + width: 0.84em; + height: 0.84em; } .c100 .slice { position: absolute; - width: 100px; - height: 100px; - clip: rect(0px, 100px, 100px, 50px); + width: 1em; + height: 1em; + clip: rect(0em, 1em, 1em, 0.5em); + } + + .c100.p50 .slice { + clip: rect(auto, auto, auto, auto); } .c100 .bar { position: absolute; - border: 8px solid transparent; - width: 84px; - height: 84px; + border: 0.08em solid #307bbb; + width: 0.84em; + height: 0.84em; + clip: rect(0em, 0.5em, 1em, 0em); border-radius: 50%; - clip: rect(0px, 50px, 100px, 0px); + transform: rotate(0deg); } .c100 .fill { position: absolute; - border: 8px solid transparent; - width: 84px; - height: 84px; + border: 0.08em solid #307bbb; + width: 0.84em; + height: 0.84em; + clip: rect(0em, 0.5em, 1em, 0em); border-radius: 50%; - clip: rect(0px, 50px, 100px, 0px); transform: rotate(180deg); } - .c100 span { - position: absolute; - width: 100px; - z-index: 1; - left: 0; - top: 0; - line-height: 100px; - text-align: center; - font-size: 20px; - color: #333; + /* Generate rotation classes for percentages 0-49 */ + .c100.p0 .bar { transform: rotate(0deg); } + .c100.p1 .bar { transform: rotate(3.6deg); } + .c100.p2 .bar { transform: rotate(7.2deg); } + .c100.p3 .bar { transform: rotate(10.8deg); } + .c100.p4 .bar { transform: rotate(14.4deg); } + .c100.p5 .bar { transform: rotate(18deg); } + .c100.p6 .bar { transform: rotate(21.6deg); } + .c100.p7 .bar { transform: rotate(25.2deg); } + .c100.p8 .bar { transform: rotate(28.8deg); } + .c100.p9 .bar { transform: rotate(32.4deg); } + .c100.p10 .bar { transform: rotate(36deg); } + .c100.p11 .bar { transform: rotate(39.6deg); } + .c100.p12 .bar { transform: rotate(43.2deg); } + .c100.p13 .bar { transform: rotate(46.8deg); } + .c100.p14 .bar { transform: rotate(50.4deg); } + .c100.p15 .bar { transform: rotate(54deg); } + .c100.p16 .bar { transform: rotate(57.6deg); } + .c100.p17 .bar { transform: rotate(61.2deg); } + .c100.p18 .bar { transform: rotate(64.8deg); } + .c100.p19 .bar { transform: rotate(68.4deg); } + .c100.p20 .bar { transform: rotate(72deg); } + .c100.p21 .bar { transform: rotate(75.6deg); } + .c100.p22 .bar { transform: rotate(79.2deg); } + .c100.p23 .bar { transform: rotate(82.8deg); } + .c100.p24 .bar { transform: rotate(86.4deg); } + .c100.p25 .bar { transform: rotate(90deg); } + .c100.p26 .bar { transform: rotate(93.6deg); } + .c100.p27 .bar { transform: rotate(97.2deg); } + .c100.p28 .bar { transform: rotate(100.8deg); } + .c100.p29 .bar { transform: rotate(104.4deg); } + .c100.p30 .bar { transform: rotate(108deg); } + .c100.p31 .bar { transform: rotate(111.6deg); } + .c100.p32 .bar { transform: rotate(115.2deg); } + .c100.p33 .bar { transform: rotate(118.8deg); } + .c100.p34 .bar { transform: rotate(122.4deg); } + .c100.p35 .bar { transform: rotate(126deg); } + .c100.p36 .bar { transform: rotate(129.6deg); } + .c100.p37 .bar { transform: rotate(133.2deg); } + .c100.p38 .bar { transform: rotate(136.8deg); } + .c100.p39 .bar { transform: rotate(140.4deg); } + .c100.p40 .bar { transform: rotate(144deg); } + .c100.p41 .bar { transform: rotate(147.6deg); } + .c100.p42 .bar { transform: rotate(151.2deg); } + .c100.p43 .bar { transform: rotate(154.8deg); } + .c100.p44 .bar { transform: rotate(158.4deg); } + .c100.p45 .bar { transform: rotate(162deg); } + .c100.p46 .bar { transform: rotate(165.6deg); } + .c100.p47 .bar { transform: rotate(169.2deg); } + .c100.p48 .bar { transform: rotate(172.8deg); } + .c100.p49 .bar { transform: rotate(176.4deg); } + .c100.p50 .bar { transform: rotate(180deg); } + + /* For values > 50%, show the fill */ + .c100.p51 .slice, + .c100.p52 .slice, + .c100.p53 .slice, + .c100.p54 .slice, + .c100.p55 .slice, + .c100.p56 .slice, + .c100.p57 .slice, + .c100.p58 .slice, + .c100.p59 .slice, + .c100.p60 .slice, + .c100.p61 .slice, + .c100.p62 .slice, + .c100.p63 .slice, + .c100.p64 .slice, + .c100.p65 .slice, + .c100.p66 .slice, + .c100.p67 .slice, + .c100.p68 .slice, + .c100.p69 .slice, + .c100.p70 .slice, + .c100.p71 .slice, + .c100.p72 .slice, + .c100.p73 .slice, + .c100.p74 .slice, + .c100.p75 .slice, + .c100.p76 .slice, + .c100.p77 .slice, + .c100.p78 .slice, + .c100.p79 .slice, + .c100.p80 .slice, + .c100.p81 .slice, + .c100.p82 .slice, + .c100.p83 .slice, + .c100.p84 .slice, + .c100.p85 .slice, + .c100.p86 .slice, + .c100.p87 .slice, + .c100.p88 .slice, + .c100.p89 .slice, + .c100.p90 .slice, + .c100.p91 .slice, + .c100.p92 .slice, + .c100.p93 .slice, + .c100.p94 .slice, + .c100.p95 .slice, + .c100.p96 .slice, + .c100.p97 .slice, + .c100.p98 .slice, + .c100.p99 .slice, + .c100.p100 .slice { + clip: rect(auto, auto, auto, auto); } + .c100.p51 .bar { transform: rotate(180deg); } + .c100.p52 .bar { transform: rotate(180deg); } + .c100.p53 .bar { transform: rotate(180deg); } + .c100.p54 .bar { transform: rotate(180deg); } + .c100.p55 .bar { transform: rotate(180deg); } + .c100.p56 .bar { transform: rotate(180deg); } + .c100.p57 .bar { transform: rotate(180deg); } + .c100.p58 .bar { transform: rotate(180deg); } + .c100.p59 .bar { transform: rotate(180deg); } + .c100.p60 .bar { transform: rotate(180deg); } + .c100.p61 .bar { transform: rotate(180deg); } + .c100.p62 .bar { transform: rotate(180deg); } + .c100.p63 .bar { transform: rotate(180deg); } + .c100.p64 .bar { transform: rotate(180deg); } + .c100.p65 .bar { transform: rotate(180deg); } + .c100.p66 .bar { transform: rotate(180deg); } + .c100.p67 .bar { transform: rotate(180deg); } + .c100.p68 .bar { transform: rotate(180deg); } + .c100.p69 .bar { transform: rotate(180deg); } + .c100.p70 .bar { transform: rotate(180deg); } + .c100.p71 .bar { transform: rotate(180deg); } + .c100.p72 .bar { transform: rotate(180deg); } + .c100.p73 .bar { transform: rotate(180deg); } + .c100.p74 .bar { transform: rotate(180deg); } + .c100.p75 .bar { transform: rotate(180deg); } + .c100.p76 .bar { transform: rotate(180deg); } + .c100.p77 .bar { transform: rotate(180deg); } + .c100.p78 .bar { transform: rotate(180deg); } + .c100.p79 .bar { transform: rotate(180deg); } + .c100.p80 .bar { transform: rotate(180deg); } + .c100.p81 .bar { transform: rotate(180deg); } + .c100.p82 .bar { transform: rotate(180deg); } + .c100.p83 .bar { transform: rotate(180deg); } + .c100.p84 .bar { transform: rotate(180deg); } + .c100.p85 .bar { transform: rotate(180deg); } + .c100.p86 .bar { transform: rotate(180deg); } + .c100.p87 .bar { transform: rotate(180deg); } + .c100.p88 .bar { transform: rotate(180deg); } + .c100.p89 .bar { transform: rotate(180deg); } + .c100.p90 .bar { transform: rotate(180deg); } + .c100.p91 .bar { transform: rotate(180deg); } + .c100.p92 .bar { transform: rotate(180deg); } + .c100.p93 .bar { transform: rotate(180deg); } + .c100.p94 .bar { transform: rotate(180deg); } + .c100.p95 .bar { transform: rotate(180deg); } + .c100.p96 .bar { transform: rotate(180deg); } + .c100.p97 .bar { transform: rotate(180deg); } + .c100.p98 .bar { transform: rotate(180deg); } + .c100.p99 .bar { transform: rotate(180deg); } + .c100.p100 .bar { transform: rotate(180deg); } + + .c100.p51 .fill { transform: rotate(183.6deg); } + .c100.p52 .fill { transform: rotate(187.2deg); } + .c100.p53 .fill { transform: rotate(190.8deg); } + .c100.p54 .fill { transform: rotate(194.4deg); } + .c100.p55 .fill { transform: rotate(198deg); } + .c100.p56 .fill { transform: rotate(201.6deg); } + .c100.p57 .fill { transform: rotate(205.2deg); } + .c100.p58 .fill { transform: rotate(208.8deg); } + .c100.p59 .fill { transform: rotate(212.4deg); } + .c100.p60 .fill { transform: rotate(216deg); } + .c100.p61 .fill { transform: rotate(219.6deg); } + .c100.p62 .fill { transform: rotate(223.2deg); } + .c100.p63 .fill { transform: rotate(226.8deg); } + .c100.p64 .fill { transform: rotate(230.4deg); } + .c100.p65 .fill { transform: rotate(234deg); } + .c100.p66 .fill { transform: rotate(237.6deg); } + .c100.p67 .fill { transform: rotate(241.2deg); } + .c100.p68 .fill { transform: rotate(244.8deg); } + .c100.p69 .fill { transform: rotate(248.4deg); } + .c100.p70 .fill { transform: rotate(252deg); } + .c100.p71 .fill { transform: rotate(255.6deg); } + .c100.p72 .fill { transform: rotate(259.2deg); } + .c100.p73 .fill { transform: rotate(262.8deg); } + .c100.p74 .fill { transform: rotate(266.4deg); } + .c100.p75 .fill { transform: rotate(270deg); } + .c100.p76 .fill { transform: rotate(273.6deg); } + .c100.p77 .fill { transform: rotate(277.2deg); } + .c100.p78 .fill { transform: rotate(280.8deg); } + .c100.p79 .fill { transform: rotate(284.4deg); } + .c100.p80 .fill { transform: rotate(288deg); } + .c100.p81 .fill { transform: rotate(291.6deg); } + .c100.p82 .fill { transform: rotate(295.2deg); } + .c100.p83 .fill { transform: rotate(298.8deg); } + .c100.p84 .fill { transform: rotate(302.4deg); } + .c100.p85 .fill { transform: rotate(306deg); } + .c100.p86 .fill { transform: rotate(309.6deg); } + .c100.p87 .fill { transform: rotate(313.2deg); } + .c100.p88 .fill { transform: rotate(316.8deg); } + .c100.p89 .fill { transform: rotate(320.4deg); } + .c100.p90 .fill { transform: rotate(324deg); } + .c100.p91 .fill { transform: rotate(327.6deg); } + .c100.p92 .fill { transform: rotate(331.2deg); } + .c100.p93 .fill { transform: rotate(334.8deg); } + .c100.p94 .fill { transform: rotate(338.4deg); } + .c100.p95 .fill { transform: rotate(342deg); } + .c100.p96 .fill { transform: rotate(345.6deg); } + .c100.p97 .fill { transform: rotate(349.2deg); } + .c100.p98 .fill { transform: rotate(352.8deg); } + .c100.p99 .fill { transform: rotate(356.4deg); } + .c100.p100 .fill { transform: rotate(360deg); } + /* Color variants for progress circles */ .c100.red .bar, .c100.red .fill { border-color: #e53935; @@ -896,6 +904,12 @@ canvas { transition: none !important; } + + @media (min-width: 900px) { + .system-stats-row { + flex-wrap: nowrap !important; + } + } diff --git a/baseTemplate/urls.py b/baseTemplate/urls.py index b20d275b2..713d2909c 100755 --- a/baseTemplate/urls.py +++ b/baseTemplate/urls.py @@ -20,4 +20,5 @@ urlpatterns = [ re_path(r'^getDiskIOStats$', views.getDiskIOStats, name='getDiskIOStats'), re_path(r'^getCPULoadGraph$', views.getCPULoadGraph, name='getCPULoadGraph'), re_path(r'^getRecentSSHLogins$', views.getRecentSSHLogins, name='getRecentSSHLogins'), + re_path(r'^getRecentSSHLogs$', views.getRecentSSHLogs, name='getRecentSSHLogs'), ] diff --git a/baseTemplate/views.py b/baseTemplate/views.py index 2397ef63e..39709ee57 100755 --- a/baseTemplate/views.py +++ b/baseTemplate/views.py @@ -588,3 +588,40 @@ def getRecentSSHLogins(request): return HttpResponse(json.dumps({'logins': logins}), content_type='application/json') except Exception as e: return HttpResponse(json.dumps({'error': str(e)}), content_type='application/json', status=500) + +@csrf_exempt +@require_GET +def getRecentSSHLogs(request): + try: + user_id = request.session.get('userID') + if not user_id: + return 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 HttpResponse(json.dumps({'error': 'Admin only'}), content_type='application/json', status=403) + from plogical.processUtilities import ProcessUtilities + distro = ProcessUtilities.decideDistro() + if distro in [ProcessUtilities.ubuntu, ProcessUtilities.ubuntu20]: + log_path = '/var/log/auth.log' + else: + log_path = '/var/log/secure' + try: + output = ProcessUtilities.outputExecutioner(f'tail -n 100 {log_path}') + except Exception as e: + return HttpResponse(json.dumps({'error': f'Failed to read log: {str(e)}'}), content_type='application/json', status=500) + lines = output.split('\n') + logs = [] + for line in lines: + if 'sshd' in line: + # Try to split into timestamp and message + parts = line.split() + if len(parts) > 4: + timestamp = ' '.join(parts[:3]) + message = ' '.join(parts[4:]) + else: + timestamp = '' + message = line + logs.append({'timestamp': timestamp, 'message': message, 'raw': line}) + return HttpResponse(json.dumps({'logs': logs}), content_type='application/json') + except Exception as e: + return HttpResponse(json.dumps({'error': str(e)}), content_type='application/json', status=500)