Add command list

pull/530/head
ibuler 2016-10-26 19:10:14 +08:00
parent c2aab50c7b
commit 5d3f9b4a03
15 changed files with 149 additions and 56 deletions

View File

@ -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')

View File

@ -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',

View File

@ -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},
# ]
#

View File

@ -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']

View File

@ -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):

View File

@ -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 %}

View File

@ -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);

View File

@ -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'),
]

View File

@ -1,2 +1,5 @@
# ~*~ coding: utf-8 ~*~
#
from users.utils import AdminUserRequiredMixin

View File

@ -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)

View File

@ -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

View File

@ -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
})

View File

@ -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