diff --git a/apps/templates/_nav.html b/apps/templates/_nav.html
index 6d125e9c2..9558bb48d 100644
--- a/apps/templates/_nav.html
+++ b/apps/templates/_nav.html
@@ -41,7 +41,7 @@
diff --git a/apps/terminal/api.py b/apps/terminal/api.py
index ca3e5b112..d8b90e734 100644
--- a/apps/terminal/api.py
+++ b/apps/terminal/api.py
@@ -78,19 +78,20 @@ class TerminalStatusViewSet(viewsets.ModelViewSet):
sessions_active = []
for session_data in self.request.data.get("sessions", []):
session_data["terminal"] = self.request.user.terminal.id
- _id = session_data["id"]
- session = get_object_or_none(Session, id=_id)
+ _uuid = session_data["uuid"]
+ session = get_object_or_none(Session, uuid=_uuid)
if session:
- serializer = TerminalSessionSerializer(data=session_data,
- instance=session)
+ serializer = TerminalSessionSerializer(
+ data=session_data, instance=session
+ )
else:
serializer = TerminalSessionSerializer(data=session_data)
if serializer.is_valid():
serializer.save()
else:
- logger.error("session serializer is not valid {}".format(
- serializer.errors))
+ msg = "session data is not valid {}".format(serializer.errors)
+ logger.error(msg)
if not session_data["is_finished"]:
sessions_active.append(session_data["id"])
diff --git a/apps/terminal/models.py b/apps/terminal/models.py
index e7643e5b4..2e0fe98e2 100644
--- a/apps/terminal/models.py
+++ b/apps/terminal/models.py
@@ -74,6 +74,10 @@ class Status(models.Model):
class Meta:
db_table = 'terminal_status'
+ get_latest_by = 'date_created'
+
+ def __str__(self):
+ return self.date_created.strftime("%Y-%m-%d %H:%M:%S")
class Session(models.Model):
@@ -82,7 +86,7 @@ class Session(models.Model):
('WT', 'Web Terminal'),
)
- id = models.UUIDField(default=uuid.uuid4, primary_key=True)
+ uuid = models.UUIDField(default=uuid.uuid4, db_index=True)
user = models.CharField(max_length=128, verbose_name=_("User"))
asset = models.CharField(max_length=1024, verbose_name=_("Asset"))
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
diff --git a/apps/terminal/serializers.py b/apps/terminal/serializers.py
index 7abab05b7..79d1bc03f 100644
--- a/apps/terminal/serializers.py
+++ b/apps/terminal/serializers.py
@@ -23,8 +23,13 @@ class TerminalSerializer(serializers.ModelSerializer):
@staticmethod
def get_is_alive(obj):
- log = obj.status_set.last()
- if log and timezone.now() - log.date_created < timezone.timedelta(seconds=600):
+ status = obj.status_set.latest()
+
+ if not status:
+ return False
+
+ delta = timezone.now() - status.date_created
+ if delta < timezone.timedelta(seconds=600):
return True
else:
return False
diff --git a/apps/terminal/templates/terminal/command_list.html b/apps/terminal/templates/terminal/command_list.html
new file mode 100644
index 000000000..04bb976fb
--- /dev/null
+++ b/apps/terminal/templates/terminal/command_list.html
@@ -0,0 +1,109 @@
+{% extends '_base_list.html' %}
+{% load i18n %}
+{% load static %}
+{% load common_tags %}
+{% block content_left_head %}
+
+
+
+{% endblock %}
+
+{% block table_search %}
+
+{% endblock %}
+{% block table_container %}
+
+{% endblock %}
+
+{% block custom_foot_js %}
+
+
+
+{% endblock %}
+
+
diff --git a/apps/terminal/templates/terminal/session_commands_list_modal.html b/apps/terminal/templates/terminal/session_commands_list_modal.html
new file mode 100644
index 000000000..fca95de6e
--- /dev/null
+++ b/apps/terminal/templates/terminal/session_commands_list_modal.html
@@ -0,0 +1,58 @@
+{% load static %}
+
+
+
+
+
+
+ {% include '_head_css_js.html' %}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/terminal/templates/terminal/session_detail.html b/apps/terminal/templates/terminal/session_detail.html
new file mode 100644
index 000000000..0fa28b517
--- /dev/null
+++ b/apps/terminal/templates/terminal/session_detail.html
@@ -0,0 +1,85 @@
+{% extends 'base.html' %}
+{% load static %}
+{% load i18n %}
+{% load common_tags %}
+
+{% block custom_head_css_js %}
+
+{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+
+
+
{% trans 'Command log list' %} {{ user_object.name }}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+{% block custom_foot_js %}
+
+
+{% endblock %}
diff --git a/apps/terminal/templates/terminal/session_offline.html b/apps/terminal/templates/terminal/session_offline.html
new file mode 100644
index 000000000..7dcac94b7
--- /dev/null
+++ b/apps/terminal/templates/terminal/session_offline.html
@@ -0,0 +1,159 @@
+{% extends '_base_list.html' %}
+{% load i18n %}
+{% load static %}
+{% block content_left_head %}
+
+
+{% endblock %}
+
+
+{% block table_search %}
+
+{% endblock %}
+
+{% block table_head %}
+ |
+ {% trans 'ID' %} |
+ {% trans 'User' %} |
+ {% trans 'Asset' %} |
+ {% trans 'System user' %} |
+ {% trans 'Terminal' %} |
+ {% trans 'Command' %} |
+ {% trans 'Success' %} |
+ {% trans 'Finished' %} |
+ {% trans 'Play' %} |
+ {% trans 'Date start' %} |
+ {% trans 'Time' %} |
+{% endblock %}
+
+{% block table_body %}
+ {% for proxy_log in proxy_log_list %}
+
+ |
+
+ {{ proxy_log.id }}
+ |
+ {{ proxy_log.user }} |
+ {{ proxy_log.asset }} |
+ {{ proxy_log.system_user }} |
+ {{ proxy_log.terminal }} |
+ {{ proxy_log.commands.all|length}} |
+
+ {% if proxy_log.is_failed %}
+
+ {% else %}
+
+ {% endif %}
+ |
+ {% if proxy_log.is_finished %}
+
+
+ |
+
+
+ |
+ {% else %}
+
+
+ |
+
+
+ |
+ {% endif %}
+ {{ proxy_log.date_start }} |
+ {{ proxy_log.date_finished|timeuntil:proxy_log.date_start }} |
+
+ {% endfor %}
+{% endblock %}
+
+
+{% block custom_foot_js %}
+
+
+{% endblock %}
+
diff --git a/apps/terminal/templates/terminal/session_online.html b/apps/terminal/templates/terminal/session_online.html
new file mode 100644
index 000000000..e190a92ad
--- /dev/null
+++ b/apps/terminal/templates/terminal/session_online.html
@@ -0,0 +1,173 @@
+{% extends '_base_list.html' %}
+{% load i18n %}
+{% load static %}
+{% block content_left_head %}
+
+
+{% endblock %}
+
+
+{% block table_search %}
+
+{% endblock %}
+
+{% block table_head %}
+ |
+ {% trans 'ID' %} |
+ {% trans 'User' %} |
+ {% trans 'Asset' %} |
+ {% trans 'System user' %} |
+ {% trans 'Terminal' %} |
+ {% trans 'Command' %} |
+ {% trans 'Success' %} |
+ {% trans 'Finished' %} |
+ {% trans 'Monitor' %} |
+ {% trans 'Date start' %} |
+ {% trans 'Time' %} |
+{% endblock %}
+
+{% block table_body %}
+ {% for session in session_list %}
+
+ |
+
+ {{ session.id }}
+ |
+ {{ session.user }} |
+ {{ session.asset }} |
+ {{ session.system_user }} |
+ {{ session.terminal.name }} |
+ {{ session.commands.all|length}} |
+
+ {% if session.is_failed %}
+
+ {% else %}
+
+ {% endif %}
+ |
+ {% if session.is_finished %}
+
+
+ |
+
+
+ |
+ {% else %}
+
+
+ |
+
+
+ |
+ {% endif %}
+ {{ session.date_start }} |
+ {{ session.date_finished|timeuntil:session.date_start }} |
+
+ {% endfor %}
+{% endblock %}
+
+{% block content_bottom_left %}
+
+{% endblock %}
+
+{% block custom_foot_js %}
+
+
+{% endblock %}
+
diff --git a/apps/terminal/urls/views_urls.py b/apps/terminal/urls/views_urls.py
index 8792f55aa..373385e28 100644
--- a/apps/terminal/urls/views_urls.py
+++ b/apps/terminal/urls/views_urls.py
@@ -9,13 +9,14 @@ from .. import views
app_name = 'terminal'
urlpatterns = [
+ # Terminal view
url(r'^terminal/$', views.TerminalListView.as_view(), name='terminal-list'),
- url(r'^terminal/(?P[0-9a-zA-Z\-]+)/$', views.TerminalDetailView.as_view(),
- name='terminal-detail'),
- url(r'^terminal/(?P[0-9a-zA-Z\-]+)/connect/$', views.TerminalConnectView.as_view(),
- name='terminal-connect'),
- url(r'^terminal/(?P[0-9a-zA-Z\-]+)/update/$', views.TerminalUpdateView.as_view(),
- name='terminal-update'),
- url(r'^(?P[0-9a-zA-Z\-]+)/accept/$', views.TerminalAccept.as_view(),
- name='terminal-accept'),
+ url(r'^terminal/(?P[0-9a-zA-Z\-]+)/$', views.TerminalDetailView.as_view(), name='terminal-detail'),
+ url(r'^terminal/(?P[0-9a-zA-Z\-]+)/connect/$', views.TerminalConnectView.as_view(), name='terminal-connect'),
+ url(r'^terminal/(?P[0-9a-zA-Z\-]+)/update/$', views.TerminalUpdateView.as_view(), name='terminal-update'),
+ url(r'^(?P[0-9a-zA-Z\-]+)/accept/$', views.TerminalAcceptView.as_view(), name='terminal-accept'),
+
+ # Session view
+ url(r'^session/online/$', views.SessionOnlineListView.as_view(), name='session-online-list'),
+ url(r'^session/offline$', views.SessionOfflineListView.as_view(), name='session-offline-list'),
]
diff --git a/apps/terminal/views/__init__.py b/apps/terminal/views/__init__.py
new file mode 100644
index 000000000..69525d808
--- /dev/null
+++ b/apps/terminal/views/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+#
+from .terminal import *
+from .session import *
diff --git a/apps/terminal/views/session.py b/apps/terminal/views/session.py
new file mode 100644
index 000000000..b809a3be2
--- /dev/null
+++ b/apps/terminal/views/session.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+#
+
+import time
+from datetime import datetime
+
+from django.views.generic import ListView, UpdateView, DeleteView, DetailView, TemplateView
+from django.views.generic.edit import SingleObjectMixin
+from django.utils.translation import ugettext as _
+from django.utils import timezone
+from django.utils.module_loading import import_string
+from django.urls import reverse_lazy
+from django.http import HttpResponse
+from django.conf import settings
+from django.db.models import Q
+
+from users.utils import AdminUserRequiredMixin
+from ..models import Session, Command, Terminal
+from ..backends import get_command_store
+
+
+__all__ = [
+ 'SessionOnlineListView', 'SessionOfflineListView',
+]
+
+
+class SessionListView(AdminUserRequiredMixin, ListView):
+ model = Session
+ template_name = 'terminal/session_online.html'
+ context_object_name = 'session_list'
+ paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
+ keyword = username = hostname = system_user = date_from_s = date_to_s = ''
+ ordering = ['is_finished', '-id']
+ date_format = '%m/%d/%Y'
+
+ def get_queryset(self):
+ date_now = timezone.localtime(timezone.now())
+ date_to_default = date_now.strftime(self.date_format)
+ date_from_default = (date_now-timezone.timedelta(7)).strftime(self.date_format)
+
+ self.queryset = super().get_queryset()
+ self.keyword = self.request.GET.get('keyword', '')
+ self.username = self.request.GET.get('username')
+ self.ip = self.request.GET.get('ip')
+ self.system_user = self.request.GET.get('system_user')
+ self.date_from_s = self.request.GET.get('date_from', date_from_default)
+ self.date_to_s = self.request.GET.get('date_to', date_to_default)
+
+ filter_kwargs = {}
+ if self.date_from_s:
+ date_from = datetime.strptime(self.date_from_s, self.date_format)
+ date_from = date_from.replace(tzinfo=timezone.get_current_timezone())
+ filter_kwargs['date_start__gt'] = date_from
+ if self.date_to_s:
+ date_to = timezone.datetime.strptime(
+ self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
+ date_to = date_to.replace(tzinfo=timezone.get_current_timezone())
+ filter_kwargs['date_start__lt'] = date_to
+ if self.username:
+ filter_kwargs['user'] = self.username
+ if self.ip:
+ filter_kwargs['asset'] = self.ip
+ if self.system_user:
+ filter_kwargs['system_user'] = self.system_user
+ if self.keyword:
+ self.queryset = self.queryset.filter(
+ Q(user__icontains=self.keyword) |
+ Q(asset__icontains=self.keyword) |
+ Q(system_user__icontains=self.keyword)).distinct()
+ if filter_kwargs:
+ self.queryset = self.queryset.filter(**filter_kwargs)
+ return self.queryset
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'app': _('Audits'),
+ 'action': _('Proxy log list'),
+ 'user_list': set(
+ list(Session.objects.values_list('user', flat=True))),
+ 'asset_list': set(
+ list(Session.objects.values_list('asset', flat=True))),
+ 'system_user_list': set(
+ list(Session.objects.values_list('system_user', flat=True))),
+ 'keyword': self.keyword,
+ 'date_from': self.date_from_s,
+ 'date_to': self.date_to_s,
+ 'username': self.username,
+ 'ip': self.ip,
+ 'system_user': self.system_user,
+ }
+ kwargs.update(context)
+ return super().get_context_data(**kwargs)
+
+
+class SessionOnlineListView(SessionListView):
+ template_name = 'terminal/session_online.html'
+
+ def get_queryset(self):
+ queryset = super().get_queryset().filter(is_finished=False)
+ return queryset
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'action': _('Session online list'),
+ }
+ kwargs.update(context)
+ return super().get_context_data(**kwargs)
+
+
+class SessionOfflineListView(SessionListView):
+ template_name = 'terminal/session_offline.html'
+
+ def get_queryset(self):
+ queryset = super().get_queryset()
+ queryset = queryset.filter(is_finished=True)
+ return queryset
+
+ def get_context_data(self, **kwargs):
+ context = {
+ 'action': _('Session offline list'),
+ }
+ kwargs.update(context)
+ return super().get_context_data(**kwargs)
+
+
+
diff --git a/apps/terminal/views.py b/apps/terminal/views/terminal.py
similarity index 90%
rename from apps/terminal/views.py
rename to apps/terminal/views/terminal.py
index 357521d1b..673851f94 100644
--- a/apps/terminal/views.py
+++ b/apps/terminal/views/terminal.py
@@ -8,9 +8,15 @@ from django.utils.translation import ugettext as _
from django.urls import reverse_lazy, reverse
from common.mixins import JSONResponseMixin
-from .models import Terminal
-from .forms import TerminalForm
-from .hands import AdminUserRequiredMixin
+from ..models import Terminal
+from ..forms import TerminalForm
+from ..hands import AdminUserRequiredMixin
+
+
+__all__ = [
+ "TerminalListView", "TerminalUpdateView", "TerminalDetailView",
+ "TerminalDeleteView", "TerminalConnectView", "TerminalAcceptView",
+]
class TerminalListView(LoginRequiredMixin, ListView):
@@ -60,7 +66,7 @@ class TerminalDeleteView(AdminUserRequiredMixin, DeleteView):
success_url = reverse_lazy('terminal:terminal-list')
-class TerminalAccept(AdminUserRequiredMixin, JSONResponseMixin, UpdateView):
+class TerminalAcceptView(AdminUserRequiredMixin, JSONResponseMixin, UpdateView):
model = Terminal
form_class = TerminalForm
template_name = 'Terminal/terminal_modal_test.html'