Commit 5f6af8c0 authored by ibuler's avatar ibuler

[Update] 修改command列表

parent e7d600ee
......@@ -46,7 +46,7 @@
<thead>
<tr>
<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 class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Username' %}</th>
......
......@@ -146,6 +146,8 @@ class CanUpdateSuperUser(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in ['GET', 'OPTIONS']:
return True
if str(request.user.id) == str(obj.id):
return False
if request.user.is_superuser:
return True
if hasattr(obj, 'is_superuser') and obj.is_superuser:
......
......@@ -304,7 +304,7 @@ table.dataTable tbody td.selected td i.text-navy {
div.dataTables_wrapper div.dataTables_filter,
.dataTables_length {
float: right !important;
// float: right !important;
}
div.dataTables_wrapper div.dataTables_filter {
......@@ -466,3 +466,11 @@ div.dataTables_wrapper div.dataTables_filter {
span.select2-selection__placeholder {
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) {
};
var table = ele.DataTable({
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 || [],
buttons: [],
columnDefs: columnDefs,
......@@ -668,8 +669,6 @@ jumpserver.initServerSideDataTable = function (options) {
})
}
}).on('draw', function(){
$('#op').html(options.op_html || '');
$('#uc').html(options.uc_html || '');
$('[data-toggle="popover"]').popover({
html: true,
placement: 'bottom',
......@@ -691,6 +690,11 @@ jumpserver.initServerSideDataTable = function (options) {
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;
$('#' + 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
from django.core.files.storage import default_storage
from django.http import HttpResponseNotFound
from django.conf import settings
from django.utils import timezone
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import viewsets
from rest_framework.response import Response
......@@ -39,10 +40,14 @@ class SessionViewSet(BulkModelViewSet):
terminal = get_object_or_404(Terminal, id=terminal_id)
queryset = queryset.filter(terminal=terminal)
return queryset
return queryset
def get_object(self):
# 解决guacamole更新session时并发导致幽灵会话的问题
obj = super().get_object()
if self.request.method in ('PATCH', ):
queryset = queryset.select_for_update()
return queryset
obj = obj.select_for_update()
return obj
def perform_create(self, serializer):
if hasattr(self.request.user, 'terminal'):
......@@ -71,14 +76,33 @@ class CommandViewSet(viewsets.ModelViewSet):
command_store = get_command_storage()
serializer_class = SessionCommandSerializer
pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdminOrAppUser | IsAuditor,)
filter_fields = ("asset", "system_user", "user", "input")
permission_classes = [IsOrgAdminOrAppUser | IsAuditor]
filter_fields = [
"asset", "system_user", "user", "input", "session",
]
default_days_ago = 5
def get_queryset(self):
date_from, date_to = self.get_date_range()
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
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):
serializer = self.serializer_class(data=request.data, many=True)
if serializer.is_valid():
......
......@@ -71,9 +71,13 @@ class CommandStore(CommandBase):
if not date_to and not session:
date_to = date_to_default
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:
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:
filter_kwargs["user"] = user
......@@ -85,7 +89,6 @@ class CommandStore(CommandBase):
filter_kwargs['input__icontains'] = input
if session:
filter_kwargs['session'] = session
return filter_kwargs
def filter(self, date_from=None, date_to=None,
......
......@@ -3,10 +3,7 @@
{% load static %}
{% load common_tags %}
{% 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/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<style>
.toggle {
cursor: pointer;
......@@ -23,6 +20,7 @@
{% block table_search %}
{% endblock %}
{% block table_container %}
<table class="table table-striped table-bordered table-hover" id="command_table" data-page="false" >
<thead>
......@@ -53,35 +51,60 @@
</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">
<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="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>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}" charset="UTF-8"></script>
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js' %}" charset="UTF-8"></script>
<script>
var table;
$(document).ready(function () {
$('.footable').footable();
$('.select2').select2({
dropdownAutoWidth : true,
width: 'auto'
});
$('#date .input-daterange').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
table = initTable().on("init", function () {
var dateFromRef = $("#date_from");
var dateToRef = $("#date_to");
let options = {
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true,
language: navigator.language || "en",
};
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(){
var action = $('#slct_bulk_update').val();
......@@ -100,13 +123,11 @@ $(document).ready(function () {
var offset1 = $('#command_table_filter input').offset();
var x = offset1.left;
var y = offset1.top;
console.log(x, y)
var offset = $(".search-help").parent().offset();
x -= offset.left;
y -= offset.top;
x += 18;
y += 80;
console.log(x, y)
$('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"});
$('.dropdown-menu.search-help').show();
})
......@@ -149,7 +170,9 @@ $(document).ready(function () {
}
}).on('click', 'body', function (e) {
$('.dropdown-menu.search-help').hide()
})
}).on('change', '#date_start', function () {
console.log("date change")
});
......@@ -186,7 +209,8 @@ function initTable() {
{data: "session"}, {data: "timestamp", width: "160px"},
],
select: {},
op_html: $('#actions').html()
op_html: $('#actions').html(),
fb_html: $("#daterange").html(),
};
table = jumpserver.initServerSideDataTable(options);
return table
......
# -*- coding: utf-8 -*-
#
from django.views.generic import ListView, View
from django.conf import settings
from django.views.generic import View, TemplateView
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.template import loader
from django.utils import timezone
import time
from common.mixins import DatetimeSearchMixin
from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor
from ..models import Command
from .. import utils
from ..backends import get_multi_command_storage
__all__ = ['CommandListView', 'CommandExportView']
common_storage = get_multi_command_storage()
class CommandListView(DatetimeSearchMixin, PermissionsMixin, ListView):
model = Command
class CommandListView(DatetimeSearchMixin, PermissionsMixin, TemplateView):
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]
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
default_days_ago = 5
def get_context_data(self, **kwargs):
now = timezone.now()
context = {
'app': _('Sessions'),
'action': _('Command list'),
'date_from': self.date_from,
'date_to': self.date_to,
'date_from': now - timezone.timedelta(days=self.default_days_ago),
'date_to': now,
}
kwargs.update(context)
return super().get_context_data(**kwargs)
......
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}
<div class="" style="float: right">
<div class="pull-right" >
<div class=" btn-group">
<button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">CSV <span class="caret"></span></button>
<ul class="dropdown-menu">
......@@ -92,23 +92,23 @@ function initTable() {
}},
{targets: 7, createdCell: function (td, cellData, rowData) {
var update_btn = "";
{#if (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin')) {#}
{# update_btn = '<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>';#}
{#}#}
{#else{#}
if (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin')) {
update_btn = '<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>';
}
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);
{#}#}
}
var del_btn = "";
{#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>'#}
{# .replace('{{ DEFAULT_PK }}', cellData)#}
{# .replace('99991938', rowData.name);#}
{#} else {#}
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>'
.replace('{{ DEFAULT_PK }}', cellData)
.replace('99991938', rowData.name);
} 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>'
.replace('{{ DEFAULT_PK }}', cellData)
.replace('99991938', rowData.name);
{#}#}
}
$(td).html(update_btn + del_btn)
}}],
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