diff --git a/baseTemplate/static/baseTemplate/custom-js/system-status.js b/baseTemplate/static/baseTemplate/custom-js/system-status.js index 43cffacf4..39d352c33 100644 --- a/baseTemplate/static/baseTemplate/custom-js/system-status.js +++ b/baseTemplate/static/baseTemplate/custom-js/system-status.js @@ -1196,4 +1196,54 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) { } pollAll(); }, 500); + + // User Session Modal logic + $scope.showSessionModal = false; + $scope.sessionUser = ''; + $scope.sessionTTY = ''; + $scope.sessionWOutput = ''; + $scope.sessionTTYProcesses = ''; + $scope.sessionProcesses = ''; + $scope.sessionLoading = false; + $scope.sessionError = ''; + + $scope.showUserSession = function(login) { + $scope.sessionUser = login.user; + $scope.sessionTTY = login.tty || ''; + $scope.sessionWOutput = ''; + $scope.sessionTTYProcesses = ''; + $scope.sessionProcesses = ''; + $scope.sessionLoading = true; + $scope.sessionError = ''; + $scope.showSessionModal = true; + var postData = { user: login.user }; + // Try to extract tty from login.raw or login.tty if available + if (login.raw) { + var m = login.raw.match(/(pts\/[0-9]+)/); + if (m) postData.tty = m[1]; + } else if (login.tty) { + postData.tty = login.tty; + } + $http.post('/base/getUserSessionInfo', postData).then(function(response) { + $scope.sessionLoading = false; + var data = response.data; + $scope.sessionWOutput = data.w_output || ''; + $scope.sessionTTYProcesses = data.tty_processes || ''; + $scope.sessionProcesses = data.processes || ''; + }, function(err) { + $scope.sessionLoading = false; + $scope.sessionError = (err.data && err.data.error) ? err.data.error : 'Failed to fetch session info.'; + }); + }; + + $scope.closeSessionModal = function() { + $scope.showSessionModal = false; + $scope.sessionUser = ''; + $scope.sessionTTY = ''; + $scope.sessionWOutput = ''; + $scope.sessionTTYProcesses = ''; + $scope.sessionProcesses = ''; + $scope.sessionLoading = false; + $scope.sessionError = ''; + }; }); \ No newline at end of file diff --git a/baseTemplate/templates/baseTemplate/homePage.html b/baseTemplate/templates/baseTemplate/homePage.html index 125214b70..76c3c4a09 100755 --- a/baseTemplate/templates/baseTemplate/homePage.html +++ b/baseTemplate/templates/baseTemplate/homePage.html @@ -64,7 +64,7 @@ Dashboard Stats Section (Enhanced Info Cards) ========================================= --> -
+
-
- - {% if admin %} -
-
- -
-
{% trans "CPU Usage" %}
-
-
- {$ cpuUsage $}% -
-
-
-
-
-
-
- -
-
{% trans "Ram Usage" %}
-
-
- {$ ramUsage $}% -
-
-
-
-
-
-
- -
-
{% trans "Disk Usage '/'" %}
-
-
- {$ diskUsage $}% -
-
-
-
-
-
-
-
-
- {% endif %} + {% if admin %} -
- -
-
-
- 🔐 Recent SSH Logins +
+ +
+
+
+ + Recent SSH Logins
-
-
Loading...
-
{$ errorSSHLogins $}
-
No recent SSH logins found.
-
- +
Loading...
+
{$ errorSSHLogins $}
+
No recent SSH logins found.
+
+
- - - - - - + + + + + + + - - - - + + + + + + - -
UserIPCountryDateSession
UserIPCountryDateSessionActions
{$ login.user $}{$ login.ip $}{$ login.country $}{$ login.date $}{$ login.session $} + {$ login.date $}{$ login.session $}
- -
-
-
- 📋 Recent SSH Logs + +
+
+
+ + Recent SSH Logs
-
-
Loading...
-
{$ errorSSHLogs $}
-
No recent SSH logs found.
-
- +
Loading...
+
{$ errorSSHLogs $}
+
No recent SSH logs found.
+
+
- - - + + + - - - + + +
TimestampMessage
TimestampMessage
{$ log.timestamp $}{$ log.message $}
{$ log.timestamp $}{$ log.message $}
- {% endif %} + {% endif %}
@@ -1083,6 +1033,27 @@ html { scroll-behavior: smooth; } + + /* Add spin animation for refresh icon on hover */ + .refresh-btn:hover .refresh-icon { + transform: rotate(360deg); + } + + /* User Session Modal */ + .view-session-btn:hover { + background: #4c5fad !important; + color: #fff !important; + border-color: #4c5fad !important; + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(76,95,173,0.10); + } + + .modal.fade[ng-show] { + display: block !important; + opacity: 1; + pointer-events: auto; + z-index: 9999; + } @@ -1139,4 +1110,37 @@ });
+ + + {% endblock %} \ No newline at end of file diff --git a/baseTemplate/urls.py b/baseTemplate/urls.py index 713d2909c..1ebaf6845 100755 --- a/baseTemplate/urls.py +++ b/baseTemplate/urls.py @@ -21,4 +21,5 @@ urlpatterns = [ re_path(r'^getCPULoadGraph$', views.getCPULoadGraph, name='getCPULoadGraph'), re_path(r'^getRecentSSHLogins$', views.getRecentSSHLogins, name='getRecentSSHLogins'), re_path(r'^getRecentSSHLogs$', views.getRecentSSHLogs, name='getRecentSSHLogs'), + re_path(r'^getUserSessionInfo$', views.getUserSessionInfo, name='getUserSessionInfo'), ] diff --git a/baseTemplate/views.py b/baseTemplate/views.py index 888c89c44..ed5388300 100755 --- a/baseTemplate/views.py +++ b/baseTemplate/views.py @@ -20,7 +20,7 @@ from plogical.httpProc import httpProc from websiteFunctions.models import Websites, WPSites from databases.models import Databases from mailServer.models import EUsers -from django.views.decorators.http import require_GET +from django.views.decorators.http import require_GET, require_POST # Create your views here. @@ -625,3 +625,37 @@ def getRecentSSHLogs(request): 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) + +@csrf_exempt +@require_POST +def getUserSessionInfo(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 + data = json.loads(request.body.decode('utf-8')) + user = data.get('user') + tty = data.get('tty') + if not user: + return HttpResponse(json.dumps({'error': 'Missing user'}), content_type='application/json', status=400) + result = {} + try: + result['processes'] = ProcessUtilities.outputExecutioner(f'ps -u {user}') + except Exception as e: + result['processes'] = f'Error: {str(e)}' + if tty: + try: + result['tty_processes'] = ProcessUtilities.outputExecutioner(f'ps -ft {tty}') + except Exception as e: + result['tty_processes'] = f'Error: {str(e)}' + try: + result['w_output'] = ProcessUtilities.outputExecutioner(f'w -h {user}') + except Exception as e: + result['w_output'] = f'Error: {str(e)}' + return HttpResponse(json.dumps(result), content_type='application/json') + except Exception as e: + return HttpResponse(json.dumps({'error': str(e)}), content_type='application/json', status=500)