Commit 5f6af8c0 authored by ibuler's avatar ibuler

[Update] 修改command列表

parent e7d600ee
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
<thead> <thead>
<tr> <tr>
<th class="text-center"> <th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" > <input type="checkbox" id="check_all" class="ipt_check_all">
</th> </th>
<th class="text-center">{% trans 'Name' %}</th> <th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Username' %}</th> <th class="text-center">{% trans 'Username' %}</th>
......
...@@ -146,6 +146,8 @@ class CanUpdateSuperUser(permissions.BasePermission): ...@@ -146,6 +146,8 @@ class CanUpdateSuperUser(permissions.BasePermission):
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
if request.method in ['GET', 'OPTIONS']: if request.method in ['GET', 'OPTIONS']:
return True return True
if str(request.user.id) == str(obj.id):
return False
if request.user.is_superuser: if request.user.is_superuser:
return True return True
if hasattr(obj, 'is_superuser') and obj.is_superuser: if hasattr(obj, 'is_superuser') and obj.is_superuser:
......
...@@ -304,7 +304,7 @@ table.dataTable tbody td.selected td i.text-navy { ...@@ -304,7 +304,7 @@ table.dataTable tbody td.selected td i.text-navy {
div.dataTables_wrapper div.dataTables_filter, div.dataTables_wrapper div.dataTables_filter,
.dataTables_length { .dataTables_length {
float: right !important; // float: right !important;
} }
div.dataTables_wrapper div.dataTables_filter { div.dataTables_wrapper div.dataTables_filter {
...@@ -466,3 +466,11 @@ div.dataTables_wrapper div.dataTables_filter { ...@@ -466,3 +466,11 @@ div.dataTables_wrapper div.dataTables_filter {
span.select2-selection__placeholder { span.select2-selection__placeholder {
line-height: 34px !important; line-height: 34px !important;
} }
.p-l-5 {
padding-left: 5px;
}
.p-r-5 {
padding-right: 5px;
}
\ No newline at end of file
...@@ -567,7 +567,8 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -567,7 +567,8 @@ jumpserver.initServerSideDataTable = function (options) {
}; };
var table = ele.DataTable({ var table = ele.DataTable({
pageLength: options.pageLength || 15, pageLength: options.pageLength || 15,
dom: options.dom || '<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>', // dom: options.dom || '<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
dom: options.dom || '<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"f><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
order: options.order || [], order: options.order || [],
buttons: [], buttons: [],
columnDefs: columnDefs, columnDefs: columnDefs,
...@@ -668,8 +669,6 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -668,8 +669,6 @@ jumpserver.initServerSideDataTable = function (options) {
}) })
} }
}).on('draw', function(){ }).on('draw', function(){
$('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || '');
$('[data-toggle="popover"]').popover({ $('[data-toggle="popover"]').popover({
html: true, html: true,
placement: 'bottom', placement: 'bottom',
...@@ -691,6 +690,11 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -691,6 +690,11 @@ jumpserver.initServerSideDataTable = function (options) {
table.rows(index).select() table.rows(index).select()
} }
}); });
}).on("init", function () {
$('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || '');
$('#fb').html(options.fb_html || '');
$('#fa').html(options.fa_html || '');
}); });
var table_id = table.settings()[0].sTableId; var table_id = table.settings()[0].sTableId;
$('#' + table_id + ' .ipt_check_all').on('click', function() { $('#' + table_id + ' .ipt_check_all').on('click', function() {
......
!function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",monthsTitle:"选择月份",clear:"清除",format:"yyyy-mm-dd",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery);
\ No newline at end of file
...@@ -7,6 +7,7 @@ from django.shortcuts import get_object_or_404 ...@@ -7,6 +7,7 @@ from django.shortcuts import get_object_or_404
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from django.conf import settings from django.conf import settings
from django.utils import timezone
from rest_framework.pagination import LimitOffsetPagination from rest_framework.pagination import LimitOffsetPagination
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.response import Response from rest_framework.response import Response
...@@ -39,10 +40,14 @@ class SessionViewSet(BulkModelViewSet): ...@@ -39,10 +40,14 @@ class SessionViewSet(BulkModelViewSet):
terminal = get_object_or_404(Terminal, id=terminal_id) terminal = get_object_or_404(Terminal, id=terminal_id)
queryset = queryset.filter(terminal=terminal) queryset = queryset.filter(terminal=terminal)
return queryset return queryset
return queryset
def get_object(self):
# 解决guacamole更新session时并发导致幽灵会话的问题 # 解决guacamole更新session时并发导致幽灵会话的问题
obj = super().get_object()
if self.request.method in ('PATCH', ): if self.request.method in ('PATCH', ):
queryset = queryset.select_for_update() obj = obj.select_for_update()
return queryset return obj
def perform_create(self, serializer): def perform_create(self, serializer):
if hasattr(self.request.user, 'terminal'): if hasattr(self.request.user, 'terminal'):
...@@ -71,14 +76,33 @@ class CommandViewSet(viewsets.ModelViewSet): ...@@ -71,14 +76,33 @@ class CommandViewSet(viewsets.ModelViewSet):
command_store = get_command_storage() command_store = get_command_storage()
serializer_class = SessionCommandSerializer serializer_class = SessionCommandSerializer
pagination_class = LimitOffsetPagination pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdminOrAppUser | IsAuditor,) permission_classes = [IsOrgAdminOrAppUser | IsAuditor]
filter_fields = ("asset", "system_user", "user", "input") filter_fields = [
"asset", "system_user", "user", "input", "session",
]
default_days_ago = 5
def get_queryset(self): def get_queryset(self):
date_from, date_to = self.get_date_range()
multi_command_storage = get_multi_command_storage() multi_command_storage = get_multi_command_storage()
queryset = multi_command_storage.filter() queryset = multi_command_storage.filter(date_from=date_from, date_to=date_to)
return queryset return queryset
def get_filter_fields(self):
fields = self.filter_fields
fields.extend(["date_from", "date_to"])
return fields
def get_date_range(self):
now = timezone.now()
days_ago = now - timezone.timedelta(days=self.default_days_ago)
default_start_st = days_ago.timestamp()
default_end_st = now.timestamp()
query_params = self.request.query_params
date_from_st = query_params.get("date_from") or default_start_st
date_to_st = query_params.get("date_to") or default_end_st
return int(date_from_st), int(date_to_st)
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)
if serializer.is_valid(): if serializer.is_valid():
......
...@@ -71,9 +71,13 @@ class CommandStore(CommandBase): ...@@ -71,9 +71,13 @@ class CommandStore(CommandBase):
if not date_to and not session: if not date_to and not session:
date_to = date_to_default date_to = date_to_default
if date_from is not None: if date_from is not None:
filter_kwargs['timestamp__gte'] = int(date_from.timestamp()) if isinstance(date_from, datetime.datetime):
date_from = date_from.timestamp()
filter_kwargs['timestamp__gte'] = int(date_from)
if date_to is not None: if date_to is not None:
filter_kwargs['timestamp__lte'] = int(date_to.timestamp()) if isinstance(date_to, datetime.datetime):
date_to = date_to.timestamp()
filter_kwargs['timestamp__lte'] = int(date_to)
if user: if user:
filter_kwargs["user"] = user filter_kwargs["user"] = user
...@@ -85,7 +89,6 @@ class CommandStore(CommandBase): ...@@ -85,7 +89,6 @@ class CommandStore(CommandBase):
filter_kwargs['input__icontains'] = input filter_kwargs['input__icontains'] = input
if session: if session:
filter_kwargs['session'] = session filter_kwargs['session'] = session
return filter_kwargs return filter_kwargs
def filter(self, date_from=None, date_to=None, def filter(self, date_from=None, date_to=None,
......
...@@ -3,10 +3,7 @@ ...@@ -3,10 +3,7 @@
{% load static %} {% load static %}
{% load common_tags %} {% load common_tags %}
{% block custom_head_css_js %} {% block custom_head_css_js %}
<link href="{% static "css/plugins/footable/footable.core.css" %}" rel="stylesheet">
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet"> <link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<style> <style>
.toggle { .toggle {
cursor: pointer; cursor: pointer;
...@@ -23,6 +20,7 @@ ...@@ -23,6 +20,7 @@
{% block table_search %} {% block table_search %}
{% endblock %} {% endblock %}
{% block table_container %} {% block table_container %}
<table class="table table-striped table-bordered table-hover" id="command_table" data-page="false" > <table class="table table-striped table-bordered table-hover" id="command_table" data-page="false" >
<thead> <thead>
...@@ -53,35 +51,60 @@ ...@@ -53,35 +51,60 @@
</div> </div>
</div> </div>
<div class="hide" id="daterange">
<div class="form-group p-l-5" id="date" style="padding-left: 5px">
<div class="input-daterange input-group p-l-5" 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;" id="date_from" name="date_from" value="{{ date_from|date:'Y-m-d' }}">
<span class="input-group-addon">to</span>
<input type="text" class="input-sm form-control" style="width: 100px;" id="date_to" name="date_to" value="{{ date_to|date:'Y-m-d' }}">
</div>
</div>
</div>
<ul class="dropdown-menu search-help"> <ul class="dropdown-menu search-help">
<li><a class="search-item" data-value="user">{% trans 'User' %}</a></li> <li><a class="search-item" data-value="user">{% trans 'User' %}</a></li>
<li><a class="search-item" data-value="asset">{% trans 'Asset' %}</a></li> <li><a class="search-item" data-value="asset">{% trans 'Asset' %}</a></li>
<li><a class="search-item" data-value="system_user">{% trans 'System user' %}</a></li> <li><a class="search-item" data-value="system_user">{% trans 'System user' %}</a></li>
<li><a class="search-item" data-value="command">{% trans 'Command' %}</a></li> <li><a class="search-item" data-value="input">{% trans 'Command' %}</a></li>
</ul> </ul>
{% endblock %} {% endblock %}
{% block content_bottom_left %}{% endblock %} {% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script> <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}" charset="UTF-8"></script>
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script> <script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js' %}" charset="UTF-8"></script>
<script> <script>
var table;
$(document).ready(function () { $(document).ready(function () {
$('.footable').footable(); table = initTable().on("init", function () {
$('.select2').select2({ var dateFromRef = $("#date_from");
dropdownAutoWidth : true, var dateToRef = $("#date_to");
width: 'auto' let options = {
}); format: "yyyy-mm-dd",
$('#date .input-daterange').datepicker({ todayBtn: "linked",
format: "yyyy-mm-dd", keyboardNavigation: false,
todayBtn: "linked", forceParse: false,
keyboardNavigation: false, calendarWeeks: true,
forceParse: false, autoclose: true,
calendarWeeks: true, language: navigator.language || "en",
autoclose: true };
dateFromRef.datepicker(options).on("changeDate", function () {
let date = new Date($(this).val() + ' 0:0:0');
let url = table.ajax.url();
url = setUrlParam(url, "date_from", date.getTime()/1000);
table.ajax.url(url);
table.ajax.reload();
console.log("On change")
});
dateToRef.datepicker(options).on("changeDate", function () {
let date = new Date($(this).val() + ' 23:59:59');
let url = table.ajax.url();
url = setUrlParam(url, "date_to", date.getTime()/1000);
table.ajax.url(url);
table.ajax.reload();
});
}); });
initTable();
}) })
.on('click', '#btn_bulk_update', function(){ .on('click', '#btn_bulk_update', function(){
var action = $('#slct_bulk_update').val(); var action = $('#slct_bulk_update').val();
...@@ -100,13 +123,11 @@ $(document).ready(function () { ...@@ -100,13 +123,11 @@ $(document).ready(function () {
var offset1 = $('#command_table_filter input').offset(); var offset1 = $('#command_table_filter input').offset();
var x = offset1.left; var x = offset1.left;
var y = offset1.top; var y = offset1.top;
console.log(x, y)
var offset = $(".search-help").parent().offset(); var offset = $(".search-help").parent().offset();
x -= offset.left; x -= offset.left;
y -= offset.top; y -= offset.top;
x += 18; x += 18;
y += 80; y += 80;
console.log(x, y)
$('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"}); $('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"});
$('.dropdown-menu.search-help').show(); $('.dropdown-menu.search-help').show();
}) })
...@@ -149,7 +170,9 @@ $(document).ready(function () { ...@@ -149,7 +170,9 @@ $(document).ready(function () {
} }
}).on('click', 'body', function (e) { }).on('click', 'body', function (e) {
$('.dropdown-menu.search-help').hide() $('.dropdown-menu.search-help').hide()
}) }).on('change', '#date_start', function () {
console.log("date change")
});
...@@ -186,7 +209,8 @@ function initTable() { ...@@ -186,7 +209,8 @@ function initTable() {
{data: "session"}, {data: "timestamp", width: "160px"}, {data: "session"}, {data: "timestamp", width: "160px"},
], ],
select: {}, select: {},
op_html: $('#actions').html() op_html: $('#actions').html(),
fb_html: $("#daterange").html(),
}; };
table = jumpserver.initServerSideDataTable(options); table = jumpserver.initServerSideDataTable(options);
return table return table
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.views.generic import ListView, View from django.views.generic import View, TemplateView
from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.http import HttpResponse from django.http import HttpResponse
from django.template import loader from django.template import loader
from django.utils import timezone
import time import time
from common.mixins import DatetimeSearchMixin from common.mixins import DatetimeSearchMixin
from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor
from ..models import Command from ..models import Command
from .. import utils
from ..backends import get_multi_command_storage from ..backends import get_multi_command_storage
__all__ = ['CommandListView', 'CommandExportView'] __all__ = ['CommandListView', 'CommandExportView']
common_storage = get_multi_command_storage() common_storage = get_multi_command_storage()
class CommandListView(DatetimeSearchMixin, PermissionsMixin, ListView): class CommandListView(DatetimeSearchMixin, PermissionsMixin, TemplateView):
model = Command
template_name = "terminal/command_list.html" template_name = "terminal/command_list.html"
context_object_name = 'command_list'
paginate_by = settings.DISPLAY_PER_PAGE
date_from = date_to = None
permission_classes = [IsOrgAdmin | IsAuditor] permission_classes = [IsOrgAdmin | IsAuditor]
default_days_ago = 5
def get_queryset(self):
filter_kwargs = dict()
filter_kwargs['date_from'] = self.date_from
filter_kwargs['date_to'] = self.date_to
queryset = common_storage.filter(**filter_kwargs)
return queryset
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
now = timezone.now()
context = { context = {
'app': _('Sessions'), 'app': _('Sessions'),
'action': _('Command list'), 'action': _('Command list'),
'date_from': self.date_from, 'date_from': now - timezone.timedelta(days=self.default_days_ago),
'date_to': self.date_to, 'date_to': now,
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
......
{% extends '_base_list.html' %} {% extends '_base_list.html' %}
{% load i18n static %} {% load i18n static %}
{% block table_search %} {% block table_search %}
<div class="" style="float: right"> <div class="pull-right" >
<div class=" btn-group"> <div class=" btn-group">
<button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">CSV <span class="caret"></span></button> <button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">CSV <span class="caret"></span></button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
...@@ -92,23 +92,23 @@ function initTable() { ...@@ -92,23 +92,23 @@ function initTable() {
}}, }},
{targets: 7, createdCell: function (td, cellData, rowData) { {targets: 7, createdCell: function (td, cellData, rowData) {
var update_btn = ""; var update_btn = "";
{#if (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin')) {#} if (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin')) {
{# update_btn = '<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>';#} update_btn = '<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>';
{#}#} }
{#else{#} else{
update_btn = '<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData); update_btn = '<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData);
{#}#} }
var del_btn = ""; var del_btn = "";
{#if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ request.user.username }}" || (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin'))) {#} if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ request.user.username }}" || (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin'))) {
{# del_btn = '<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'#} del_btn = '<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
{# .replace('{{ DEFAULT_PK }}', cellData)#} .replace('{{ DEFAULT_PK }}', cellData)
{# .replace('99991938', rowData.name);#} .replace('99991938', rowData.name);
{#} else {#} } else {
del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>' del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.replace('{{ DEFAULT_PK }}', cellData) .replace('{{ DEFAULT_PK }}', cellData)
.replace('99991938', rowData.name); .replace('99991938', rowData.name);
{#}#} }
$(td).html(update_btn + del_btn) $(td).html(update_btn + del_btn)
}}], }}],
ajax_url: '{% url "api-users:user-list" %}', ajax_url: '{% url "api-users:user-list" %}',
......
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