diff --git a/apps/assets/templates/assets/system_user_list.html b/apps/assets/templates/assets/system_user_list.html index 50d294026..a30d25a51 100644 --- a/apps/assets/templates/assets/system_user_list.html +++ b/apps/assets/templates/assets/system_user_list.html @@ -46,7 +46,7 @@ - + {% trans 'Name' %} {% trans 'Username' %} diff --git a/apps/common/permissions.py b/apps/common/permissions.py index a2f4c9286..3289d0af4 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -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: diff --git a/apps/static/css/jumpserver.css b/apps/static/css/jumpserver.css index b1f2633d8..489279189 100644 --- a/apps/static/css/jumpserver.css +++ b/apps/static/css/jumpserver.css @@ -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 diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 471cb00a4..3880b496e 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -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() { diff --git a/apps/static/js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js b/apps/static/js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js new file mode 100644 index 000000000..8e6920b0c --- /dev/null +++ b/apps/static/js/plugins/datepicker/bootstrap-datepicker.zh-CN.min.js @@ -0,0 +1 @@ +!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 diff --git a/apps/terminal/api/session.py b/apps/terminal/api/session.py index 04f97bfc3..f634f5628 100644 --- a/apps/terminal/api/session.py +++ b/apps/terminal/api/session.py @@ -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,11 +40,15 @@ class SessionViewSet(BulkModelViewSet): terminal = get_object_or_404(Terminal, id=terminal_id) queryset = queryset.filter(terminal=terminal) return queryset - # 解决guacamole更新session时并发导致幽灵会话的问题 - if self.request.method in ('PATCH', ): - queryset = queryset.select_for_update() return queryset + def get_object(self): + # 解决guacamole更新session时并发导致幽灵会话的问题 + obj = super().get_object() + if self.request.method in ('PATCH', ): + obj = obj.select_for_update() + return obj + def perform_create(self, serializer): if hasattr(self.request.user, 'terminal'): serializer.validated_data["terminal"] = 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(): diff --git a/apps/terminal/backends/command/db.py b/apps/terminal/backends/command/db.py index fa457b75d..4b9622191 100644 --- a/apps/terminal/backends/command/db.py +++ b/apps/terminal/backends/command/db.py @@ -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, diff --git a/apps/terminal/templates/terminal/command_list.html b/apps/terminal/templates/terminal/command_list.html index 1ce2d80a5..eba0d6a60 100644 --- a/apps/terminal/templates/terminal/command_list.html +++ b/apps/terminal/templates/terminal/command_list.html @@ -3,10 +3,7 @@ {% load static %} {% load common_tags %} {% block custom_head_css_js %} - - -