Commit 818ead85 authored by ibuler's avatar ibuler

[Feature] 增加上传replay log的api

parent 7f9ce573
......@@ -24,3 +24,4 @@ tags
jumpserver.iml
.python-version
tmp/*
sessions/*
......@@ -2,11 +2,15 @@
#
from collections import OrderedDict
import copy
import logging
import os
from rest_framework import viewsets, serializers
from rest_framework.views import APIView, Response
from rest_framework.permissions import AllowAny
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.conf import settings
from .models import Terminal, TerminalStatus, TerminalSession, TerminalTask
from .serializers import TerminalSerializer, TerminalStatusSerializer, \
......@@ -15,6 +19,8 @@ from .hands import IsSuperUserOrAppUser, IsAppUser, ProxyLog, \
IsSuperUserOrAppUserOrUserReadonly
from common.utils import get_object_or_none
logger = logging.getLogger(__file__)
class TerminalViewSet(viewsets.ModelViewSet):
queryset = Terminal.objects.filter(is_deleted=False)
......@@ -62,20 +68,28 @@ class TerminalStatusViewSet(viewsets.ModelViewSet):
session_serializer_class = TerminalSessionSerializer
def create(self, request, *args, **kwargs):
self.handle_sessions()
return super().create(request, *args, **kwargs)
def handle_sessions(self):
sessions_active = []
for session_data in request.data.get("sessions", []):
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(TerminalSession, id=_id)
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))
if session_data["is_finished"]:
if not session_data["is_finished"]:
sessions_active.append(session_data["id"])
sessions_in_db_active = TerminalSession.objects.filter(
......@@ -83,13 +97,11 @@ class TerminalStatusViewSet(viewsets.ModelViewSet):
)
for session in sessions_in_db_active:
if session.id not in sessions_active:
if str(session.id) not in sessions_active:
session.is_finished = True
session.date_end = timezone.now()
session.save()
return super().create(request, *args, **kwargs)
def get_queryset(self):
terminal_id = self.kwargs.get("terminal", None)
if terminal_id:
......@@ -135,3 +147,29 @@ class TerminalTaskViewSet(viewsets.ModelViewSet):
terminal = self.request.user.terminal
self.queryset = terminal.terminalstatus_set.all()
return self.queryset
class SessionReplayAPI(APIView):
permission_classes = (IsSuperUserOrAppUser,)
def post(self, request, **kwargs):
session_id = kwargs.get("pk", None)
session = get_object_or_404(TerminalSession, id=session_id)
record_dir = settings.CONFIG.SESSION_RECORDE_DIR
date = session.date_start.strftime("%Y-%m-%d")
record_dir = os.path.join(record_dir, date)
record_filename = os.path.join(record_dir, str(session.id))
if not os.path.exists(record_dir):
os.makedirs(record_dir)
archive_stream = request.data.get("archive")
if not archive_stream:
return Response("None file upload", status=400)
with open(record_filename, 'wb') as f:
for chunk in archive_stream.chunks():
f.write(chunk)
session.has_replay = True
session.save()
return Response({"session_id": session.id}, status=201)
......@@ -69,9 +69,6 @@ class TerminalStatus(models.Model):
class Meta:
db_table = 'terminal_status'
# def __str__(self):
# return "<{} status>".format(self.terminal.name)
class TerminalSession(models.Model):
LOGIN_FROM_CHOICES = (
......@@ -85,6 +82,8 @@ class TerminalSession(models.Model):
system_user = models.CharField(max_length=128, verbose_name=_("System User"))
login_from = models.CharField(max_length=2, choices=LOGIN_FROM_CHOICES, default="ST")
is_finished = models.BooleanField(default=False)
has_replay = models.BooleanField(default=False, verbose_name=_("Replay"))
has_command = models.BooleanField(default=False, verbose_name=_("Command"))
terminal = models.IntegerField(null=True, verbose_name=_("Terminal"))
date_start = models.DateTimeField(verbose_name=_("Date Start"))
date_end = models.DateTimeField(verbose_name=_("Date End"), null=True)
......
......@@ -19,11 +19,11 @@ class TerminalSerializer(serializers.ModelSerializer):
@staticmethod
def get_session_connected(obj):
return ProxyLog.objects.filter(terminal=obj.name, is_finished=False).count()
return TerminalSession.objects.filter(terminal=obj.id, is_finished=False)
@staticmethod
def get_is_alive(obj):
log = obj.terminalheatbeat_set.last()
log = obj.terminalstatus_set.last()
if log and timezone.now() - log.date_created < timezone.timedelta(seconds=600):
return True
else:
......
......@@ -79,7 +79,7 @@ $(document).ready(function(){
var reject_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="99991937" data-name="99991938">{% trans "Reject" %}</a>'
.replace('99991937', cellData)
.replace('99991938', rowData.name);
var connect_btn = '<a href="{% url "applications:terminal-connect" pk=99991937 %}"" class="btn btn-xs btn-warning btn-connect" >{% trans "Connect" %}</a> '
var connect_btn = '<a href="" class="btn btn-xs btn-warning btn-connect" >{% trans "Connect" %}</a> '
.replace('99991937', cellData);
if (rowData.is_accepted) {
{% if user.is_superuser %}
......@@ -96,7 +96,7 @@ $(document).ready(function(){
],
ajax_url: '{% url "api-applications:terminal-list" %}',
columns: [{data: function(){return ""}}, {data: "name" }, {data: "remote_addr" }, {data: "ssh_port"}, {data: "http_port"},
{data: "session_connected"}, {data: "is_alive" }, {data: 'is_alive'}, {data: "id"}],
{data: "session_connected"}, {data: "is_accepted" }, {data: 'is_alive'}, {data: "id"}],
op_html: $('#actions').html()
};
jumpserver.initDataTable(options);
......
......@@ -33,8 +33,8 @@
<h3>{% trans 'Info' %}</h3>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.type layout="horizontal" %}
{% bootstrap_field form.url layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
......
......@@ -12,11 +12,12 @@ app_name = 'applications'
router = routers.DefaultRouter()
router.register(r'v1/terminal/(?P<terminal>[0-9]+)?/?status', api.TerminalStatusViewSet, 'terminal-status')
router.register(r'v1/terminal/(?P<terminal>[0-9]+)?/?sessions', api.TerminalSessionViewSet, 'terminal-sessions')
router.register(r'v1/terminal$', api.TerminalViewSet, 'terminal')
router.register(r'v1/terminal', api.TerminalViewSet, 'terminal')
urlpatterns = [
# url(r'^v1/terminate/connection/$', api.TerminateConnectionView.as_view(),
# name='terminate-connection')
url(r'^v1/sessions/(?P<pk>[0-9a-zA-Z\-_]+)/replay/$', api.SessionReplayAPI.as_view(), name='session-replay'),
]
urlpatterns += router.urls
......@@ -123,7 +123,7 @@
window.location.reload()
}, 300)
}
var the_url = "{% url 'api-applications:terminate-connection' %}";
var the_url = "";
APIUpdateAttr({url: the_url, method: 'POST', body: JSON.stringify(data), success: success, success_message: 'Terminate success'});
}
$(document).ready(function() {
......
......@@ -137,7 +137,7 @@
window.location.reload()
}, 300)
}
var the_url = "{% url 'api-applications:terminate-connection' %}";
var the_url = "";
APIUpdateAttr({url: the_url, method: 'POST', body: JSON.stringify(data), success: success, success_message: 'Terminate success'});
}
$(document).ready(function() {
......
......@@ -10,7 +10,6 @@ urlpatterns = [
name='proxy-log-online-list'),
url(r'^proxy-log/(?P<pk>\d+)/$', views.ProxyLogDetailView.as_view(),
name='proxy-log-detail'),
# url(r'^proxy-log/(?P<pk>\d+)/commands$', views.ProxyLogCommandsListView.as_view(), name='proxy-log-commands-list'),
url(r'^command-log/$', views.CommandLogListView.as_view(),
name='command-log-list'),
url(r'^login-log/$', views.LoginLogListView.as_view(),
......
......@@ -1375,7 +1375,7 @@ msgstr "终止所选"
#: audits/views.py:72 audits/views.py:209 audits/views.py:263
#: templates/_nav.html:56
msgid "Audits"
msgstr "审计"
msgstr "审计中心"
#: audits/views.py:73 audits/views.py:264
msgid "Proxy log list"
......
......@@ -6,6 +6,7 @@ import errno
if __name__ == "__main__":
try:
os.makedirs('../logs')
os.makedirs('../sessions')
except:
pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment