mirror of https://github.com/jumpserver/jumpserver
[Feture] session detail页面,包含命令列表
parent
01558c985a
commit
9b6696bb6e
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.conf import settings
|
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from audits.backends import command_store
|
from audits.backends import command_store
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ class StatusViewSet(viewsets.ModelViewSet):
|
||||||
for session_data in self.request.data.get("sessions", []):
|
for session_data in self.request.data.get("sessions", []):
|
||||||
self.create_or_update_session(session_data)
|
self.create_or_update_session(session_data)
|
||||||
if not session_data["is_finished"]:
|
if not session_data["is_finished"]:
|
||||||
sessions_active.append(session_data["uuid"])
|
sessions_active.append(session_data["id"])
|
||||||
|
|
||||||
sessions_in_db_active = Session.objects.filter(
|
sessions_in_db_active = Session.objects.filter(
|
||||||
is_finished=False,
|
is_finished=False,
|
||||||
|
@ -92,15 +92,15 @@ class StatusViewSet(viewsets.ModelViewSet):
|
||||||
)
|
)
|
||||||
|
|
||||||
for session in sessions_in_db_active:
|
for session in sessions_in_db_active:
|
||||||
if str(session.uuid) not in sessions_active:
|
if str(session.id) not in sessions_active:
|
||||||
session.is_finished = True
|
session.is_finished = True
|
||||||
session.date_end = timezone.now()
|
session.date_end = timezone.now()
|
||||||
session.save()
|
session.save()
|
||||||
|
|
||||||
def create_or_update_session(self, session_data):
|
def create_or_update_session(self, session_data):
|
||||||
session_data["terminal"] = self.request.user.terminal.id
|
session_data["terminal"] = self.request.user.terminal.id
|
||||||
_uuid = session_data["uuid"]
|
_id = session_data["id"]
|
||||||
session = get_object_or_none(Session, uuid=_uuid)
|
session = get_object_or_none(Session, id=_id)
|
||||||
if session:
|
if session:
|
||||||
serializer = SessionSerializer(
|
serializer = SessionSerializer(
|
||||||
data=session_data, instance=session
|
data=session_data, instance=session
|
||||||
|
@ -210,7 +210,7 @@ class CommandViewSet(viewsets.ViewSet):
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
self.command_store.all()
|
self.command_store.filter(**dict(self.request.data))
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
serializer = self.serializer_class(data=request.data, many=True)
|
serializer = self.serializer_class(data=request.data, many=True)
|
||||||
|
@ -221,7 +221,6 @@ class CommandViewSet(viewsets.ViewSet):
|
||||||
else:
|
else:
|
||||||
return Response("save error", status=500)
|
return Response("save error", status=500)
|
||||||
else:
|
else:
|
||||||
print(serializer.errors)
|
|
||||||
return Response({"msg": "Not valid: {}".format(serializer.errors)}, status=401)
|
return Response({"msg": "Not valid: {}".format(serializer.errors)}, status=401)
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -14,9 +14,8 @@ class CommandBase(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def filter(self, date_from=None, date_to=None, user=None,
|
def filter(self, date_from=None, date_to=None,
|
||||||
asset=None, system_user=None, command=None, session=None):
|
user=None, asset=None, system_user=None,
|
||||||
|
input=None, session=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,27 +37,26 @@ class CommandStore(CommandBase):
|
||||||
))
|
))
|
||||||
return self.model.objects.bulk_create(_commands)
|
return self.model.objects.bulk_create(_commands)
|
||||||
|
|
||||||
def filter(self, date_from=None, date_to=None, user=None,
|
def filter(self, date_from=None, date_to=None,
|
||||||
asset=None, system_user=None, _input=None, session=None):
|
user=None, asset=None, system_user=None,
|
||||||
|
input=None, session=None):
|
||||||
filter_kwargs = {}
|
filter_kwargs = {}
|
||||||
|
date_from_default = timezone.now() - datetime.timedelta(days=7)
|
||||||
|
date_to_default = timezone.now()
|
||||||
|
|
||||||
|
date_from = date_from if date_from else date_from_default
|
||||||
|
date_to = date_to if date_to else date_to_default
|
||||||
|
filter_kwargs['timestamp__gte'] = int(date_from.timestamp())
|
||||||
|
filter_kwargs['timestamp__lte'] = int(date_to.timestamp())
|
||||||
|
|
||||||
if date_from:
|
|
||||||
filter_kwargs['timestamp__gte'] = int(date_from.timestamp())
|
|
||||||
else:
|
|
||||||
week_ago = timezone.now() - datetime.timedelta(days=7)
|
|
||||||
filter_kwargs['timestamp__gte'] = int(week_ago.timestamp())
|
|
||||||
if date_to:
|
|
||||||
filter_kwargs['timestamp__lte'] = int(date_to.timestamp())
|
|
||||||
else:
|
|
||||||
filter_kwargs['timestamp__lte'] = int(timezone.now().timestamp())
|
|
||||||
if user:
|
if user:
|
||||||
filter_kwargs['user'] = user
|
filter_kwargs["user"] = user
|
||||||
if asset:
|
if asset:
|
||||||
filter_kwargs['asset'] = asset
|
filter_kwargs['asset'] = asset
|
||||||
if system_user:
|
if system_user:
|
||||||
filter_kwargs['system_user'] = system_user
|
filter_kwargs['system_user'] = system_user
|
||||||
if _input:
|
if input:
|
||||||
filter_kwargs['input__icontains'] = _input
|
filter_kwargs['input__icontains'] = input
|
||||||
if session:
|
if session:
|
||||||
filter_kwargs['session'] = session
|
filter_kwargs['session'] = session
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class AbstractSessionCommand(models.Model):
|
||||||
asset = models.CharField(max_length=128, verbose_name=_("Asset"))
|
asset = models.CharField(max_length=128, verbose_name=_("Asset"))
|
||||||
system_user = models.CharField(max_length=64, verbose_name=_("System user"))
|
system_user = models.CharField(max_length=64, verbose_name=_("System user"))
|
||||||
input = models.CharField(max_length=128, db_index=True, verbose_name=_("Input"))
|
input = models.CharField(max_length=128, db_index=True, verbose_name=_("Input"))
|
||||||
output = models.CharField(max_length=1024, verbose_name=_("Output"))
|
output = models.CharField(max_length=1024, blank=True, verbose_name=_("Output"))
|
||||||
session = models.CharField(max_length=36, db_index=True, verbose_name=_("Session"))
|
session = models.CharField(max_length=36, db_index=True, verbose_name=_("Session"))
|
||||||
timestamp = models.IntegerField(db_index=True)
|
timestamp = models.IntegerField(db_index=True)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ class SessionCommandSerializer(serializers.Serializer):
|
||||||
asset = serializers.CharField(max_length=128)
|
asset = serializers.CharField(max_length=128)
|
||||||
system_user = serializers.CharField(max_length=64)
|
system_user = serializers.CharField(max_length=64)
|
||||||
input = serializers.CharField(max_length=128)
|
input = serializers.CharField(max_length=128)
|
||||||
output = serializers.CharField(max_length=1024)
|
output = serializers.CharField(max_length=1024, allow_blank=True)
|
||||||
session = serializers.CharField(max_length=36)
|
session = serializers.CharField(max_length=36)
|
||||||
timestamp = serializers.IntegerField()
|
timestamp = serializers.IntegerField()
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ class Session(models.Model):
|
||||||
('WT', 'Web Terminal'),
|
('WT', 'Web Terminal'),
|
||||||
)
|
)
|
||||||
|
|
||||||
uuid = models.UUIDField(default=uuid.uuid4, db_index=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
user = models.CharField(max_length=128, verbose_name=_("User"))
|
user = models.CharField(max_length=128, verbose_name=_("User"))
|
||||||
asset = models.CharField(max_length=1024, verbose_name=_("Asset"))
|
asset = models.CharField(max_length=1024, verbose_name=_("Asset"))
|
||||||
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
|
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
|
||||||
|
@ -126,3 +126,4 @@ class Command(AbstractSessionCommand):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "terminal_command"
|
db_table = "terminal_command"
|
||||||
|
ordering = ('timestamp',)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils import timezone
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from .models import Terminal, Status, Session, Task
|
from .models import Terminal, Status, Session, Task
|
||||||
from .hands import ProxyLog
|
from .backends import get_command_store
|
||||||
|
|
||||||
|
|
||||||
class TerminalSerializer(serializers.ModelSerializer):
|
class TerminalSerializer(serializers.ModelSerializer):
|
||||||
|
@ -36,11 +36,16 @@ class TerminalSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SessionSerializer(serializers.ModelSerializer):
|
class SessionSerializer(serializers.ModelSerializer):
|
||||||
|
command_amount = serializers.SerializerMethodField()
|
||||||
|
command_store = get_command_store()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Session
|
model = Session
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
def get_command_amount(self, obj):
|
||||||
|
return len(self.command_store.filter(session=obj.session))
|
||||||
|
|
||||||
|
|
||||||
class StatusSerializer(serializers.ModelSerializer):
|
class StatusSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="col-sm-11" style="padding-left: 0;">
|
<div class="col-sm-11" style="padding-left: 0;">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<span style="float: left">{% trans 'Command log list' %} <b>{{ user_object.name }}</b></span>
|
<span style="float: left">{% trans 'Command list' %} <b></b></span>
|
||||||
<div class="ibox-tools">
|
<div class="ibox-tools">
|
||||||
<a class="collapse-link">
|
<a class="collapse-link">
|
||||||
<i class="fa fa-chevron-up"></i>
|
<i class="fa fa-chevron-up"></i>
|
||||||
|
@ -43,18 +43,22 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th data-toggle="true">ID</th>
|
<th data-toggle="true">ID</th>
|
||||||
<th>Command</th>
|
<th>Command</th>
|
||||||
<th data-hide="all">Output</th>
|
<th data-hide="all"></th>
|
||||||
<th>Datetime</th>
|
<th>Datetime</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for command in object_list %}
|
{% for command in object_list %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ command.command_no }}</td>
|
<td>{{ forloop.counter }}</td>
|
||||||
<td>{{ command.command }}</td>
|
<td>{{ command.input }}</td>
|
||||||
<td><pre style="border: none;background: none">{{ command.output|to_html|safe}}</pre></td>
|
<td><pre style="border: none;background: none">{{ command.output }}</pre></td>
|
||||||
<td>{{ command.timestamp|ts_to_date}}</td>
|
<td>{{ command.timestamp|ts_to_date}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">{% trans "There is no command about this session" %}</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{% extends '_base_list.html' %}
|
{% extends '_base_list.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load terminal_tags %}
|
||||||
{% block content_left_head %}
|
{% block content_left_head %}
|
||||||
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
|
@ -77,13 +78,13 @@
|
||||||
<tr class="gradeX">
|
<tr class="gradeX">
|
||||||
<td class="text-center"><input type="checkbox" class="cbx-term" value="{{ session.id }}"></td>
|
<td class="text-center"><input type="checkbox" class="cbx-term" value="{{ session.id }}"></td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="">{{ session.id }}</a>
|
<a href="{% url 'terminal:session-detail' pk=session.id %}">{{ forloop.counter }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">{{ session.user }}</td>
|
<td class="text-center">{{ session.user }}</td>
|
||||||
<td class="text-center">{{ session.asset }}</td>
|
<td class="text-center">{{ session.asset }}</td>
|
||||||
<td class="text-center">{{ session.system_user }}</td>
|
<td class="text-center">{{ session.system_user }}</td>
|
||||||
<td class="text-center">{{ session.terminal.name }}</td>
|
<td class="text-center">{{ session.terminal.name }}</td>
|
||||||
<td class="text-center">{{ session.commands.all|length}}</td>
|
<td class="text-center">{{ session.id | get_session_command_amount }}</td>
|
||||||
{% if session.is_finished %}
|
{% if session.is_finished %}
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<i class="fa fa-check text-navy"></i>
|
<i class="fa fa-check text-navy"></i>
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
|
@ -0,0 +1,14 @@
|
||||||
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from ..backends import get_command_store
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
command_store = get_command_store()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def get_session_command_amount(session_id):
|
||||||
|
print(session_id)
|
||||||
|
return len(command_store.filter(session=str(session_id)))
|
||||||
|
|
|
@ -19,4 +19,5 @@ urlpatterns = [
|
||||||
# Session view
|
# Session view
|
||||||
url(r'^session/online/$', views.SessionOnlineListView.as_view(), name='session-online-list'),
|
url(r'^session/online/$', views.SessionOnlineListView.as_view(), name='session-online-list'),
|
||||||
url(r'^session/offline$', views.SessionOfflineListView.as_view(), name='session-offline-list'),
|
url(r'^session/offline$', views.SessionOfflineListView.as_view(), name='session-offline-list'),
|
||||||
|
url(r'^session/(?P<pk>[0-9a-zA-Z\-]+)/$', views.SessionDetailView.as_view(), name='session-detail'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,8 +21,11 @@ from ..backends import get_command_store
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'SessionOnlineListView', 'SessionOfflineListView',
|
'SessionOnlineListView', 'SessionOfflineListView',
|
||||||
|
'SessionDetailView',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
command_store = get_command_store()
|
||||||
|
|
||||||
|
|
||||||
class SessionListView(AdminUserRequiredMixin, ListView):
|
class SessionListView(AdminUserRequiredMixin, ListView):
|
||||||
model = Session
|
model = Session
|
||||||
|
@ -101,6 +104,7 @@ class SessionOnlineListView(SessionListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
|
'app': _('Terminal'),
|
||||||
'action': _('Session online list'),
|
'action': _('Session online list'),
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
|
@ -117,10 +121,26 @@ class SessionOfflineListView(SessionListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
|
'app': _('Terminal'),
|
||||||
'action': _('Session offline list'),
|
'action': _('Session offline list'),
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class SessionDetailView(SingleObjectMixin, ListView):
|
||||||
|
template_name = 'terminal/session_detail.html'
|
||||||
|
model = Session
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
self.object = self.get_object(self.model.objects.all())
|
||||||
|
return command_store.filter(session=self.object.id)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'app': _('Terminal'),
|
||||||
|
'action': _('Session detail'),
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue