mirror of https://github.com/jumpserver/jumpserver
add proxy log search
parent
1d29c52a43
commit
41337d28c3
|
@ -1,5 +1,7 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
|
||||
from users.models import User
|
||||
from assets.models import Asset, SystemUser
|
||||
from users.backends import IsSuperUserOrTerminalUser
|
||||
from terminal.models import Terminal
|
||||
|
|
|
@ -71,7 +71,7 @@ class ProxyLog(models.Model):
|
|||
|
||||
|
||||
class CommandLog(models.Model):
|
||||
proxy_log = models.ForeignKey(ProxyLog, on_delete=models.CASCADE, related_name='command_log')
|
||||
proxy_log = models.ForeignKey(ProxyLog, on_delete=models.CASCADE, related_name='commands')
|
||||
command_no = models.IntegerField()
|
||||
command = models.CharField(max_length=1000, blank=True)
|
||||
output = models.TextField(blank=True)
|
||||
|
|
|
@ -14,7 +14,8 @@ class ProxyLogSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = models.ProxyLog
|
||||
fields = ['id', 'name', 'username', 'hostname', 'ip', 'system_user', 'login_type', 'terminal',
|
||||
'log_file', 'was_failed', 'is_finished', 'date_start', 'time', 'command_length', "commands_dict"]
|
||||
'log_file', 'was_failed', 'is_finished', 'date_start', 'date_finished', 'time',
|
||||
'command_length', "commands_dict"]
|
||||
|
||||
@staticmethod
|
||||
def get_time(obj):
|
||||
|
@ -25,7 +26,7 @@ class ProxyLogSerializer(serializers.ModelSerializer):
|
|||
|
||||
@staticmethod
|
||||
def get_command_length(obj):
|
||||
return len(obj.command_log.all())
|
||||
return len(obj.commands.all())
|
||||
|
||||
|
||||
class CommandLogSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -3,10 +3,44 @@
|
|||
{% load static %}
|
||||
{% load common_tags %}
|
||||
{% block content_left_head %}
|
||||
{# <a href="{% url 'perms:asset-permission-create' %}" class="btn btn-sm btn-primary "> {% trans "Create permission" %} </a>#}
|
||||
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
|
||||
<style>
|
||||
#search_btn {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_search %}
|
||||
<form id="search_form" method="get" action="" class="pull-right form-inline">
|
||||
<div class="input-group">
|
||||
<select class="select2 form-control" name="user">
|
||||
<option>{% trans 'Select user' %}</option>
|
||||
{% for user in user_list %}
|
||||
<option value="{{ user.username }}">{{ user.username }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="select2 form-control" name="asset">
|
||||
<option>{% trans 'Select asset' %}</option>
|
||||
{% for asset in asset_list %}
|
||||
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" name="keyword" placeholder="Search" value="{{ keyword }}">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
搜索
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block table_container %}
|
||||
<table class="footable table table-stripped toggle-arrow-tiny" data-page="false">
|
||||
<thead>
|
||||
|
@ -16,6 +50,7 @@
|
|||
<th>Username</th>
|
||||
<th>IP</th>
|
||||
<th>System user</th>
|
||||
<th>Proxy log</th>
|
||||
<th>Datetime</th>
|
||||
<th data-hide="all">Output</th>
|
||||
</tr>
|
||||
|
@ -23,11 +58,12 @@
|
|||
<tbody>
|
||||
{% for command in command_list %}
|
||||
<tr>
|
||||
<td>{{ command.command_no }}</td>
|
||||
<td>{{ command.id }}</td>
|
||||
<td>{{ command.command }}</td>
|
||||
<td>{{ command.proxy_log.username }}</td>
|
||||
<td>{{ command.proxy_log.ip }}</td>
|
||||
<td>{{ command.proxy_log.system_user }}</td>
|
||||
<td><a href="{% url 'audits:proxy-log-detail' pk=command.proxy_log.id %}">{{ command.proxy_log.id}}</a></td>
|
||||
<td>{{ command.datetime }}</td>
|
||||
<td>{{ command.output_decode |safe }}</td>
|
||||
</tr>
|
||||
|
@ -41,6 +77,7 @@
|
|||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.footable').footable();
|
||||
$('.select2').select2();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,55 @@
|
|||
{% extends '_base_list.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load common_tags %}
|
||||
{% block content_left_head %}
|
||||
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
|
||||
<style>
|
||||
#search_btn {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block table_search %}
|
||||
<form id="search_form" method="get" action="" class="pull-right form-inline">
|
||||
<div class="form-group" id="date">
|
||||
<div class="input-daterange input-group" id="datepicker">
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_from" value="{{ date_from }}">
|
||||
<span class="input-group-addon">to</span>
|
||||
<input type="text" class="input-sm form-control" style="width: 100px;" name="date_to" value="{{ date_to }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="select2 form-control" name="username">
|
||||
<option value="">{% trans 'Select user' %}</option>
|
||||
{% for user in user_list %}
|
||||
<option value="{{ user.username }}">{{ user.username }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="select2 form-control" name="ip">
|
||||
<option value="">{% trans 'Select asset' %}</option>
|
||||
{% for asset in asset_list %}
|
||||
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" name="keyword" placeholder="Search" value="{{ keyword }}">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
搜索
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_head %}
|
||||
<th class="text-center">{% trans 'ID' %}</th>
|
||||
|
@ -22,8 +71,8 @@
|
|||
</td>
|
||||
<td class="text-center">{{ proxy_log.username }}</td>
|
||||
<td class="text-center">{{ proxy_log.ip }}</td>
|
||||
<td class="text-center">{{ proxy_log.system_user.name }}</td>
|
||||
<td class="text-center">{{ proxy_log.command.count }}</td>
|
||||
<td class="text-center">{{ proxy_log.system_user }}</td>
|
||||
<td class="text-center">{{ proxy_log.commands.all|length}}</td>
|
||||
<td class="text-center">
|
||||
{% if proxy_log.was_failed %}
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
|
@ -33,25 +82,33 @@
|
|||
</td>
|
||||
<td class="text-center">
|
||||
{% if proxy_log.is_finished %}
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-check text-navy"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">{{ proxy_log.date_start }}</td>
|
||||
<td class="text-center">{{ proxy_log.date_finished }}</td>
|
||||
<td class="text-center">{{ proxy_log.date_finished|timeuntil:proxy_log.date_start }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('table').DataTable({
|
||||
"searching": false,
|
||||
"paging": false,
|
||||
"order": []
|
||||
})
|
||||
});
|
||||
$('.select2').select2();
|
||||
$('#date .input-daterange').datepicker({
|
||||
dateFormat: 'mm/dd/yy',
|
||||
keyboardNavigation: false,
|
||||
forceParse: false,
|
||||
autoclose: true
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,25 +1,66 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
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.urls import reverse_lazy
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
|
||||
from .models import ProxyLog, CommandLog
|
||||
from .utils import AdminUserRequiredMixin
|
||||
from .hands import User, Asset, SystemUser
|
||||
|
||||
|
||||
class ProxyLogListView(ListView):
|
||||
class ProxyLogListView(AdminUserRequiredMixin, ListView):
|
||||
model = ProxyLog
|
||||
template_name = 'audits/proxy_log_list.html'
|
||||
context_object_name = 'proxy_log_list'
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = super(ProxyLogListView, self).get_queryset()
|
||||
self.keyword = keyword = self.request.GET.get('keyword', '')
|
||||
self.username = username = self.request.GET.get('username', '')
|
||||
self.ip = ip = self.request.GET.get('ip', '')
|
||||
self.date_from_s = date_from_s = \
|
||||
self.request.GET.get('date_from', '%s' % (datetime.datetime.now()-datetime.timedelta(7)).strftime('%m/%d/%Y'))
|
||||
self.date_to_s = date_to_s = self.request.GET.get('date_to', '%s' % datetime.datetime.now().strftime('%m/%d/%Y'))
|
||||
|
||||
if date_from_s:
|
||||
date_from = timezone.datetime.strptime(date_from_s, '%m/%d/%Y')
|
||||
self.queryset = self.queryset.filter(date_start__gt=date_from)
|
||||
|
||||
if date_to_s:
|
||||
date_to = timezone.datetime.strptime(date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
|
||||
self.queryset = self.queryset.filter(date_start__lt=date_to)
|
||||
if username:
|
||||
self.queryset = self.queryset.filter(username=username)
|
||||
if ip:
|
||||
self.queryset = self.queryset.filter(ip=ip)
|
||||
if keyword:
|
||||
self.queryset = self.queryset.filter(Q(username__contains=keyword) |
|
||||
Q(name__icontains=keyword) |
|
||||
Q(hostname__icontains=keyword) |
|
||||
Q(ip__icontains=keyword) |
|
||||
Q(system_user__icontains=keyword)).distinct()
|
||||
return self.queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ProxyLogListView, self).get_context_data(**kwargs)
|
||||
context.update({'app': _('Audits'), 'action': _('Proxy log list')})
|
||||
return context
|
||||
context = {
|
||||
'app': _('Audits'),
|
||||
'action': _('Proxy log list'),
|
||||
'user_list': User.objects.all(),
|
||||
'asset_list': Asset.objects.all(),
|
||||
'system_user_list': SystemUser.objects.all(),
|
||||
'keyword': self.keyword,
|
||||
'date_from': self.date_from_s,
|
||||
'date_to': self.date_to_s,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ProxyLogListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ProxyLogDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
|
||||
|
@ -31,7 +72,7 @@ class ProxyLogDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
|
|||
return super(ProxyLogDetailView, self).get(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return list(self.object.command_log.all())
|
||||
return list(self.object.commands.all())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
|
@ -74,8 +115,11 @@ class CommandLogListView(AdminUserRequiredMixin, ListView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': 'Audits',
|
||||
'action': 'Command log list'
|
||||
'app': _('Audits'),
|
||||
'action': _('Command log list'),
|
||||
'user_list': User.objects.all(),
|
||||
'asset_list': Asset.objects.all(),
|
||||
'system_user_list': SystemUser.objects.all(),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(CommandLogListView, self).get_context_data(**kwargs)
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
|
|
|
@ -33,15 +33,19 @@
|
|||
<div class="" id="content_start">
|
||||
{% block content_left_head %} {% endblock %}
|
||||
{% block table_search %}
|
||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||
<form id="search_form" method="get" action="" class="pull-right mail-search form-inline">
|
||||
{% block search_form %}
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" name="keyword" placeholder="Search" value="{{ keyword }}">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
搜索
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block tags_list %}{% endblock %}
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
|
|
Loading…
Reference in New Issue