From 8e93bfecb07e66a2c1129815e15ef251fd0e328f Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Mon, 24 Dec 2018 15:50:59 +0800 Subject: [PATCH 1/3] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8DDEFAULT?= =?UTF-8?q?=E7=BB=84=E7=BB=87=E4=B8=8B=EF=BC=8C=E6=89=B9=E9=87=8F=E5=88=A0?= =?UTF-8?q?=E9=99=A4(=E6=9F=90=E7=BB=84=E7=BB=87=E4=B8=8B)=E4=B8=80?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=94=A8=E6=88=B7=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?bug=20(#2261)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/api/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/users/api/user.py b/apps/users/api/user.py index f838554e1..a1119e3a7 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -47,7 +47,7 @@ class UserViewSet(IDInFilterMixin, BulkModelViewSet): return super().get_permissions() def allow_bulk_destroy(self, qs, filtered): - return qs.count() == filtered.count() + return qs.count() != filtered.count() class UserChangePasswordApi(generics.RetrieveUpdateAPIView): From dab692c0eb61a41ce79cb0364ebb711e03380911 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Tue, 25 Dec 2018 09:58:01 +0800 Subject: [PATCH 2/3] =?UTF-8?q?[Update]=20=E9=99=90=E5=88=B6=E7=BB=88?= =?UTF-8?q?=E7=AB=AF=E8=AE=BE=E7=BD=AE=E4=B8=AD=E5=BF=83=E8=B7=B3=E9=97=B4?= =?UTF-8?q?=E9=9A=94=E5=92=8C=E4=BC=9A=E8=AF=9D=E4=BF=9D=E7=95=99=E6=97=B6?= =?UTF-8?q?=E9=95=BF=E7=9A=84form=E6=9C=80=E5=B0=8F=E5=80=BC=20(#2262)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 限制终端设置中心跳间隔和会话保留时长的form最小值 * [Update] 删除terminal forms表单的初始化值 * [Update] 取消安全设置中forms的初始化值,并采用默认值;添加密码过期时间的最大值限制 --- apps/common/forms.py | 44 +++++++++++++++++------------------------ apps/jumpserver/conf.py | 10 ++++++++++ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/apps/common/forms.py b/apps/common/forms.py index f29d19ec3..33ee48f03 100644 --- a/apps/common/forms.py +++ b/apps/common/forms.py @@ -139,22 +139,23 @@ class TerminalSettingForm(BaseForm): (50, 50), ) TERMINAL_PASSWORD_AUTH = forms.BooleanField( - initial=True, required=False, label=_("Password auth") + required=False, label=_("Password auth") ) TERMINAL_PUBLIC_KEY_AUTH = forms.BooleanField( - initial=True, required=False, label=_("Public key auth") + required=False, label=_("Public key auth") ) TERMINAL_HEARTBEAT_INTERVAL = forms.IntegerField( - initial=5, label=_("Heartbeat interval"), help_text=_("Units: seconds") + min_value=5, label=_("Heartbeat interval"), + help_text=_("Units: seconds") ) TERMINAL_ASSET_LIST_SORT_BY = forms.ChoiceField( - choices=SORT_BY_CHOICES, initial='hostname', label=_("List sort by") + choices=SORT_BY_CHOICES, label=_("List sort by") ) TERMINAL_ASSET_LIST_PAGE_SIZE = forms.ChoiceField( - choices=PAGE_SIZE_CHOICES, initial='auto', label=_("List page size"), + choices=PAGE_SIZE_CHOICES, label=_("List page size"), ) TERMINAL_SESSION_KEEP_DURATION = forms.IntegerField( - label=_("Session keep duration"), + min_value=1, label=_("Session keep duration"), help_text=_("Units: days, Session, record, command will be delete " "if more than duration, only in database") ) @@ -167,8 +168,7 @@ class TerminalCommandStorage(BaseForm): class SecuritySettingForm(BaseForm): # MFA global setting SECURITY_MFA_AUTH = forms.BooleanField( - initial=False, required=False, - label=_("MFA Secondary certification"), + required=False, label=_("MFA Secondary certification"), help_text=_( 'After opening, the user login must use MFA secondary ' 'authentication (valid for all users, including administrators)' @@ -176,13 +176,11 @@ class SecuritySettingForm(BaseForm): ) # limit login count SECURITY_LOGIN_LIMIT_COUNT = forms.IntegerField( - initial=7, min_value=3, - label=_("Limit the number of login failures") + min_value=3, label=_("Limit the number of login failures") ) # limit login time SECURITY_LOGIN_LIMIT_TIME = forms.IntegerField( - initial=30, min_value=5, - label=_("No logon interval"), + min_value=5, label=_("No logon interval"), help_text=_( "Tip: (unit/minute) if the user has failed to log in for a limited " "number of times, no login is allowed during this time interval." @@ -190,8 +188,7 @@ class SecuritySettingForm(BaseForm): ) # ssh max idle time SECURITY_MAX_IDLE_TIME = forms.IntegerField( - initial=30, required=False, - label=_("Connection max idle time"), + required=False, label=_("Connection max idle time"), help_text=_( 'If idle time more than it, disconnect connection(only ssh now) ' 'Unit: minute' @@ -199,8 +196,8 @@ class SecuritySettingForm(BaseForm): ) # password expiration time SECURITY_PASSWORD_EXPIRATION_TIME = forms.IntegerField( - initial=9999, label=_("Password expiration time"), - min_value=1, + label=_("Password expiration time"), + min_value=1, max_value=99999, help_text=_( "Tip: (unit: day) " "If the user does not update the password during the time, " @@ -211,35 +208,30 @@ class SecuritySettingForm(BaseForm): ) # min length SECURITY_PASSWORD_MIN_LENGTH = forms.IntegerField( - initial=6, label=_("Password minimum length"), - min_value=6 + min_value=6, label=_("Password minimum length"), ) # upper case SECURITY_PASSWORD_UPPER_CASE = forms.BooleanField( - initial=False, required=False, - label=_("Must contain capital letters"), + required=False, label=_("Must contain capital letters"), help_text=_( 'After opening, the user password changes ' 'and resets must contain uppercase letters') ) # lower case SECURITY_PASSWORD_LOWER_CASE = forms.BooleanField( - initial=False, required=False, - label=_("Must contain lowercase letters"), + required=False, label=_("Must contain lowercase letters"), help_text=_('After opening, the user password changes ' 'and resets must contain lowercase letters') ) # number SECURITY_PASSWORD_NUMBER = forms.BooleanField( - initial=False, required=False, - label=_("Must contain numeric characters"), + required=False, label=_("Must contain numeric characters"), help_text=_('After opening, the user password changes ' 'and resets must contain numeric characters') ) # special char SECURITY_PASSWORD_SPECIAL_CHAR = forms.BooleanField( - initial=False, required=False, - label=_("Must contain special characters"), + required=False, label=_("Must contain special characters"), help_text=_('After opening, the user password changes ' 'and resets must contain special characters') ) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 61fd84249..ed19f3567 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -320,6 +320,16 @@ defaults = { 'TERMINAL_ASSET_LIST_SORT_BY': 'hostname', 'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto', 'TERMINAL_SESSION_KEEP_DURATION': 9999, + 'SECURITY_MFA_AUTH': False, + 'SECURITY_LOGIN_LIMIT_COUNT': 7, + 'SECURITY_LOGIN_LIMIT_TIME': 30, + 'SECURITY_MAX_IDLE_TIME': 30, + 'SECURITY_PASSWORD_EXPIRATION_TIME': 9999, + 'SECURITY_PASSWORD_MIN_LENGTH': 6, + 'SECURITY_PASSWORD_UPPER_CASE': False, + 'SECURITY_PASSWORD_LOWER_CASE': False, + 'SECURITY_PASSWORD_NUMBER': False, + 'SECURITY_PASSWORD_SPECIAL_CHAR': False, } From a990098744144c6db1f1d0b387959ea8ba55b62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=B9=BF?= Date: Tue, 25 Dec 2018 13:33:37 +0800 Subject: [PATCH 3/3] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E9=80=89=E6=8B=A9=20(#2267)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 优化资产选择 * [Update] 优化资产任务 --- apps/assets/forms/domain.py | 9 +++++++++ apps/assets/forms/label.py | 9 +++++++++ apps/assets/tasks.py | 12 +++++++++--- .../templates/assets/domain_create_update.html | 13 ++++++++++++- .../templates/assets/label_create_update.html | 12 ++++++++++++ apps/perms/forms.py | 10 ++++++++++ .../perms/asset_permission_create_update.html | 14 +++++++++++++- apps/static/js/jumpserver.js | 2 ++ apps/terminal/api/v1/terminal.py | 2 +- 9 files changed, 77 insertions(+), 6 deletions(-) diff --git a/apps/assets/forms/domain.py b/apps/assets/forms/domain.py index 635796c97..25295782a 100644 --- a/apps/assets/forms/domain.py +++ b/apps/assets/forms/domain.py @@ -28,6 +28,15 @@ class DomainForm(forms.ModelForm): initial['assets'] = kwargs['instance'].assets.all() super().__init__(*args, **kwargs) + # 前端渲染优化, 防止过多资产 + assets_field = self.fields.get('assets') + if not self.data: + instance = kwargs.get('instance') + if instance: + assets_field.queryset = instance.assets.all() + else: + assets_field.queryset = Asset.objects.none() + def save(self, commit=True): instance = super().save(commit=commit) assets = self.cleaned_data['assets'] diff --git a/apps/assets/forms/label.py b/apps/assets/forms/label.py index ebdc9384e..8a5a54e4a 100644 --- a/apps/assets/forms/label.py +++ b/apps/assets/forms/label.py @@ -26,6 +26,15 @@ class LabelForm(forms.ModelForm): initial['assets'] = kwargs['instance'].assets.all() super().__init__(*args, **kwargs) + # 前端渲染优化, 防止过多资产 + assets_field = self.fields.get('assets') + if not self.data: + instance = kwargs.get('instance') + if instance: + assets_field.queryset = instance.assets.all() + else: + assets_field.queryset = Asset.objects.none() + def save(self, commit=True): label = super().save(commit=commit) assets = self.cleaned_data['assets'] diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 9dd58b78e..ce5be0b6f 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -1,16 +1,16 @@ # ~*~ coding: utf-8 ~*~ import json import re +import time import os from celery import shared_task from django.utils.translation import ugettext as _ +from django.core.cache import cache from common.utils import capacity_convert, \ sum_capacity, encrypt_password, get_logger -from ops.celery.utils import register_as_period_task, after_app_shutdown_clean, \ - after_app_ready_start -from orgs.utils import set_to_root_org +from ops.celery.utils import register_as_period_task, after_app_shutdown_clean from .models import SystemUser, AdminUser, Asset from . import const @@ -211,6 +211,12 @@ def test_admin_user_connectivity_period(): """ A period task that update the ansible task period """ + key = '_JMS_TEST_ADMIN_USER_CONNECTIVITY_PERIOD' + prev_execute_time = cache.get(key) + if prev_execute_time: + logger.debug("Test admin user connectivity, less than 40 minutes, skip") + return + cache.set(key, 1, 60*40) admin_users = AdminUser.objects.all() for admin_user in admin_users: task_name = _("Test admin user connectivity period: {}").format(admin_user.name) diff --git a/apps/assets/templates/assets/domain_create_update.html b/apps/assets/templates/assets/domain_create_update.html index 0d6935226..7a31e3e88 100644 --- a/apps/assets/templates/assets/domain_create_update.html +++ b/apps/assets/templates/assets/domain_create_update.html @@ -24,7 +24,6 @@ {% block custom_foot_js %} diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 82990ac5b..e46b32d13 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -528,6 +528,7 @@ jumpserver.initServerSideDataTable = function (options) { lengthMenu: [[10, 15, 25, 50], [10, 15, 25, 50]] }); table.selected = []; + table.selected_rows = []; table.on('select', function(e, dt, type, indexes) { var $node = table[ type ]( indexes ).nodes().to$(); $node.find('input.ipt_check').prop('checked', true); @@ -535,6 +536,7 @@ jumpserver.initServerSideDataTable = function (options) { if (type === 'row') { var rows = table.rows(indexes).data(); $.each(rows, function (id, row) { + table.selected_rows.push(row); if (row.id && $.inArray(row.id, table.selected) === -1){ table.selected.push(row.id) } diff --git a/apps/terminal/api/v1/terminal.py b/apps/terminal/api/v1/terminal.py index 7ab15d381..ac56b3ea9 100644 --- a/apps/terminal/api/v1/terminal.py +++ b/apps/terminal/api/v1/terminal.py @@ -86,7 +86,7 @@ class TerminalTokenApi(APIView): if not terminal.user or not terminal.user.access_key: return Response("No access key generate", status=401) - access_key = terminal.user.access_key.first() + access_key = terminal.user.access_key() data = OrderedDict() data['access_key'] = {'id': access_key.id, 'secret': access_key.secret} return Response(data, status=200)