mirror of https://github.com/jumpserver/jumpserver
Add command list
parent
c2aab50c7b
commit
5d3f9b4a03
|
@ -3,6 +3,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
import functools
|
||||
from django.db import models
|
||||
from django.core import serializers
|
||||
import logging
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
@ -336,6 +337,9 @@ class Asset(models.Model):
|
|||
return True, ''
|
||||
return False, warning
|
||||
|
||||
def json(self):
|
||||
pass
|
||||
|
||||
class Meta:
|
||||
db_table = 'asset'
|
||||
unique_together = ('ip', 'port')
|
||||
|
|
|
@ -63,7 +63,6 @@ class AssetCreateView(AdminUserRequiredMixin,CreateAssetTagsMiXin,CreateView):
|
|||
print(form.errors)
|
||||
return super(AssetCreateView, self).form_invalid(form)
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': 'Assets',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from rest_framework import generics
|
||||
from rest_framework.views import APIView, Response
|
||||
|
||||
from . import models, serializers
|
||||
from .hands import IsSuperUserOrTerminalUser, Terminal
|
||||
|
@ -44,7 +45,18 @@ class ProxyLogDetailApi(generics.RetrieveUpdateDestroyAPIView):
|
|||
permission_classes = (IsSuperUserOrTerminalUser,)
|
||||
|
||||
|
||||
class CommandLogCreateApi(generics.ListCreateAPIView):
|
||||
class CommandLogListCreateApi(generics.ListCreateAPIView):
|
||||
queryset = models.CommandLog.objects.all()
|
||||
serializer_class = serializers.CommandLogSerializer
|
||||
permission_classes = (IsSuperUserOrTerminalUser,)
|
||||
|
||||
|
||||
# class CommandLogTitleApi(APIView):
|
||||
# def get(self, request):
|
||||
# response = [
|
||||
# {"name": "command_no", "title": "ID", "type": "number"},
|
||||
# {"name": "command", "title": "Title", "visible": True, "filterable": True},
|
||||
# {"name": "datetime", "title": "Datetime", "type"},
|
||||
# {"name": "output", "title": "Output", "filterable": True},
|
||||
# ]
|
||||
#
|
|
@ -2,6 +2,7 @@
|
|||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import base64
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -68,6 +69,10 @@ class CommandLog(models.Model):
|
|||
def __unicode__(self):
|
||||
return '%s: %s' % (self.id, self.command)
|
||||
|
||||
@property
|
||||
def output_decode(self):
|
||||
return base64.b64decode(self.output).replace('\n', '<br />')
|
||||
|
||||
class Meta:
|
||||
db_table = 'command_log'
|
||||
ordering = ['command_no', 'command']
|
||||
|
|
|
@ -3,14 +3,26 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.utils import timesince
|
||||
from . import models
|
||||
|
||||
|
||||
class ProxyLogSerializer(serializers.ModelSerializer):
|
||||
time = serializers.SerializerMethodField()
|
||||
command_length = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = models.ProxyLog
|
||||
fields = ['id', 'name', 'username', 'hostname', 'ip', 'system_user', 'login_type', 'terminal',
|
||||
'log_file', 'was_failed', 'is_finished', 'date_start', 'date_finished', 'get_login_type_display']
|
||||
'log_file', 'was_failed', 'is_finished', 'date_start', 'time', 'command_length']
|
||||
|
||||
@staticmethod
|
||||
def get_time(obj):
|
||||
return timesince(obj.date_start, since=obj.date_finished)
|
||||
|
||||
@staticmethod
|
||||
def get_command_length(obj):
|
||||
return len(obj.command_log.all())
|
||||
|
||||
|
||||
class CommandLogSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load common_tags %}
|
||||
{% load users_tags %}
|
||||
{% load bootstrap %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block custom_head_css_js %}
|
||||
<script src="{% static "css/plugins/footable/footable.core.css" %}"></script>
|
||||
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
|
@ -40,16 +38,25 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<table class="footable table table-stripped toggle-arrow-tiny command" data-page-size="8">
|
||||
{# <thead>#}
|
||||
{# <tr>#}
|
||||
{# <th data-toggle="true">No</th>#}
|
||||
{# <th>Command</th>#}
|
||||
{# <th>Datetime</th>#}
|
||||
{# </tr>#}
|
||||
{# </thead>#}
|
||||
{# <tbody>#}
|
||||
{# </tbody>#}
|
||||
<table id="command-log" class="footable table table-stripped toggle-arrow-tiny" data-page-size="10">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-toggle="true">ID</th>
|
||||
<th>Command</th>
|
||||
<th data-hide="all">Output</th>
|
||||
<th>Datetime</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for command in object_list %}
|
||||
<tr>
|
||||
<td>{{ command.command_no }}</td>
|
||||
<td>{{ command.command }}</td>
|
||||
<td>{{ command.output_decode |safe }}</td>
|
||||
<td>{{ command.datetime }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,31 +80,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'Asset count' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for asset_group, system_users in asset_groups %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center">
|
||||
<a href="{% url 'assets:asset-group-detail' pk=asset_group.id %}">
|
||||
{{ asset_group.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">{{ asset_group.assets.count }}</td>
|
||||
<td class="text-center">{{ system_users|join_attr:"name" }}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger btn-xs btn_delete_user_group {% if not asset_group.is_inherit_from_user_groups %} disabled {% endif %}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<table class="table2 table-stripped toggle-arrow-tiny" data-page-size="8">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -110,11 +93,10 @@
|
|||
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.command').footable({
|
||||
"rows": $.get({% url 'audits:command-log-create-list-api' %})
|
||||
})
|
||||
$('.footable').footable();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
<th class="text-center">{% trans 'Username' %}</th>
|
||||
<th class="text-center">{% trans 'IP' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</th>
|
||||
<th class="text-center">{% trans 'Login type' %}</th>
|
||||
{# <th class="text-center">{% trans 'Terminal' %}</th>#}
|
||||
{# <th class="text-center">{% trans 'Login type' %}</th>#}
|
||||
<th class="text-center">{% trans 'Command' %}</th>
|
||||
<th class="text-center">{% trans 'Success' %}</th>
|
||||
<th class="text-center">{% trans 'Finished' %}</th>
|
||||
<th class="text-center">{% trans 'Date start' %}</th>
|
||||
<th class="text-center">{% trans 'Date finished' %}</th>
|
||||
<th class="text-center">{% trans 'Time' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -76,8 +76,8 @@ $(document).ready(function(){
|
|||
],
|
||||
ajax_url: '{% url "audits:proxy-log-list-create-api" %}',
|
||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "ip"},
|
||||
{data: "system_user"}, {data: "terminal"}, {data: 'was_failed'},
|
||||
{data: "is_finished"}, {data: "date_start"}, {data: 'date_finished'}, {data: 'id'}],
|
||||
{data: "system_user"}, {data: "command_length"}, {data: 'was_failed'},
|
||||
{data: "is_finished"}, {data: "date_start"}, {data: 'time'}, {data: 'id'}],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
jumpserver.initDataTable(options);
|
||||
|
|
|
@ -15,5 +15,5 @@ urlpatterns = [
|
|||
urlpatterns += [
|
||||
url(r'^v1/proxy-log/$', api.ProxyLogListCreateApi.as_view(), name='proxy-log-list-create-api'),
|
||||
url(r'^v1/proxy-log/(?P<pk>\d+)/$', api.ProxyLogDetailApi.as_view(), name='proxy-log-detail-api'),
|
||||
url(r'^v1/command-log/$', api.CommandLogCreateApi.as_view(), name='command-log-create-list-api'),
|
||||
url(r'^v1/command-log/$', api.CommandLogListCreateApi.as_view(), name='command-log-create-list-api'),
|
||||
]
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
|
||||
from users.utils import AdminUserRequiredMixin
|
||||
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
#
|
||||
|
||||
from django.views.generic import ListView, UpdateView, DeleteView, DetailView
|
||||
from django.views.generic.edit import SingleObjectMixin
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.urls import reverse_lazy
|
||||
from django.conf import settings
|
||||
|
||||
from .models import ProxyLog, CommandLog
|
||||
from .utils import AdminUserRequiredMixin
|
||||
|
||||
|
||||
class ProxyLogListView(ListView):
|
||||
|
@ -18,11 +21,21 @@ class ProxyLogListView(ListView):
|
|||
return context
|
||||
|
||||
|
||||
class ProxyLogDetailView(DetailView):
|
||||
model = ProxyLog
|
||||
class ProxyLogDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
|
||||
template_name = 'audits/proxy_log_detail.html'
|
||||
context_object_name = 'proxy_log'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object(queryset=ProxyLog.objects.all())
|
||||
return super(ProxyLogDetailView, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return list(self.object.command_log.all())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ProxyLogDetailView, self).get_context_data(**kwargs)
|
||||
context.update({'app': _('Audits'), 'action': _('Proxy log detail')})
|
||||
|
||||
context = {
|
||||
'app': 'Audits',
|
||||
'action': 'Proxy log detail',
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ProxyLogDetailView, self).get_context_data(**kwargs)
|
||||
|
|
|
@ -6,6 +6,7 @@ from six import string_types
|
|||
from itertools import chain
|
||||
import string
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from itsdangerous import Signer, TimedJSONWebSignatureSerializer, JSONWebSignatureSerializer, TimestampSigner, \
|
||||
BadSignature, SignatureExpired
|
||||
|
@ -133,3 +134,34 @@ def int_seq(seq):
|
|||
return map(int, seq)
|
||||
except ValueError:
|
||||
return seq
|
||||
|
||||
|
||||
def timesince(dt, since='', default="just now"):
|
||||
"""
|
||||
Returns string representing "time since" e.g.
|
||||
3 days, 5 hours.
|
||||
"""
|
||||
|
||||
if since is '':
|
||||
since = datetime.datetime.utcnow()
|
||||
|
||||
if since is None:
|
||||
return default
|
||||
|
||||
diff = since - dt
|
||||
|
||||
periods = (
|
||||
(diff.days / 365, "year", "years"),
|
||||
(diff.days / 30, "month", "months"),
|
||||
(diff.days / 7, "week", "weeks"),
|
||||
(diff.days, "day", "days"),
|
||||
(diff.seconds / 3600, "hour", "hours"),
|
||||
(diff.seconds / 60, "minute", "minutes"),
|
||||
(diff.seconds, "second", "seconds"),
|
||||
)
|
||||
|
||||
for period, singular, plural in periods:
|
||||
if period:
|
||||
return "%d %s" % (period, singular if period == 1 else plural)
|
||||
return default
|
||||
|
||||
|
|
|
@ -22,7 +22,13 @@ class UserAssetsGrantedApi(APIView):
|
|||
'hostname': asset.hostname,
|
||||
'ip': asset.ip,
|
||||
'port': asset.port,
|
||||
'system_users': [system_user.name for system_user in system_users],
|
||||
'system_users': [
|
||||
{
|
||||
'id': system_user.id,
|
||||
'name': system_user.name,
|
||||
'username': system_user.username,
|
||||
} for system_user in system_users
|
||||
],
|
||||
'comment': asset.comment
|
||||
})
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.footable {
|
||||
width: 100%;
|
||||
/** SORTING **/
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue