From c300f0b549300dc53ec3fd0db2b13c80435db8db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Tue, 11 Jun 2019 10:09:08 +0800 Subject: [PATCH 1/6] =?UTF-8?q?[Update]=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E9=A1=B5=E9=9D=A2=E7=9A=84=E8=B5=84=E4=BA=A7=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E8=BF=87=E6=BB=A4=E5=8A=9F=E8=83=BD=20(#2781)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 优化用户页面的资产标签下拉框选项 * [Update]增加用户页面的过滤资产标签功能 * [Update]优化用户页面的资产标签过滤 * [Update]优化用户页面的资产标签过滤代码 * [Update] 优化用户页面的资产标签过滤 --- .../templates/assets/user_asset_list.html | 6 ++++- apps/assets/views/asset.py | 1 + apps/perms/mixins.py | 26 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/assets/templates/assets/user_asset_list.html b/apps/assets/templates/assets/user_asset_list.html index 329f24c72..23d0b34ed 100644 --- a/apps/assets/templates/assets/user_asset_list.html +++ b/apps/assets/templates/assets/user_asset_list.html @@ -153,7 +153,11 @@ function initTree() { $(document).ready(function () { initTree(); initTable(); -}) +}).on('click', '.labels li', function () { + var val = $(this).text(); + $("#user_assets_table_filter input").val(val); + asset_table.search(val).draw(); + }) .on('click', '.asset_detail', function() { var data = asset_table.ajax.json(); var asset_id = this.getAttribute("asset-id"); diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py index 653fa12c3..4a3ce2273 100644 --- a/apps/assets/views/asset.py +++ b/apps/assets/views/asset.py @@ -79,6 +79,7 @@ class UserAssetListView(LoginRequiredMixin, TemplateView): def get_context_data(self, **kwargs): context = { 'action': _('My assets'), + 'labels': Label.objects.all().order_by('name'), 'system_users': SystemUser.objects.all(), } kwargs.update(context) diff --git a/apps/perms/mixins.py b/apps/perms/mixins.py index 3adaa6e5b..f302285a6 100644 --- a/apps/perms/mixins.py +++ b/apps/perms/mixins.py @@ -14,6 +14,7 @@ class AssetsFilterMixin(object): def filter_queryset(self, queryset): queryset = self.search_assets(queryset) + queryset = self.filter_labels(queryset) queryset = self.sort_assets(queryset) return queryset @@ -40,6 +41,31 @@ class AssetsFilterMixin(object): queryset = sort_assets(queryset, order_by=order_by, reverse=reverse) return queryset + def filter_labels(self, queryset): + from assets.models import Label + query_keys = self.request.query_params.keys() + all_label_keys = Label.objects.values_list('name', flat=True) + valid_keys = set(all_label_keys) & set(query_keys) + labels_query = {} + for key in valid_keys: + labels_query[key] = self.request.query_params.get(key) + if not labels_query: + return queryset + + labels = set() + for k, v in labels_query.items(): + label = Label.objects.filter(name=k, value=v).first() + if not label: + continue + labels.add(label) + + _queryset = [] + for asset in queryset: + _labels = set(asset.labels.all()) & set(labels) + if _labels and len(_labels) == len(set(labels)): + _queryset.append(asset) + return _queryset + class RemoteAppFilterMixin(object): """ From 03d9570895433258f9c6cd78f5dda809da131c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Tue, 11 Jun 2019 10:09:40 +0800 Subject: [PATCH 2/6] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7API,=E5=88=9B=E5=BB=BA=E7=94=A8=E6=88=B7=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=BB=84=E7=BB=87=E5=85=B3=E7=B3=BB=20(#2776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/api/user.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/users/api/user.py b/apps/users/api/user.py index c7668cb86..116819770 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -48,6 +48,9 @@ class UserViewSet(IDInCacheFilterMixin, BulkModelViewSet): def perform_create(self, serializer): users = serializer.save() + for user in users: + if current_org and current_org.is_real(): + user.orgs.add(current_org.id) self.send_created_signal(users) def get_queryset(self): From 0574b43971709d4f4b0c756638e6e05da7f2eb18 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Tue, 11 Jun 2019 10:10:04 +0800 Subject: [PATCH 3/6] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E9=AB=98=E5=BA=A6=E6=98=BE=E7=A4=BAcss=20(#2749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/static/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/static/css/style.css b/apps/static/css/style.css index 1bfc8ed34..2457db6a0 100644 --- a/apps/static/css/style.css +++ b/apps/static/css/style.css @@ -8118,7 +8118,7 @@ body.md-skin { #page-wrapper { position: inherit; margin: 0 0 0 220px; - min-height: 1200px; + /*min-height: 1200px;*/ } .navbar-static-side { z-index: 2001; From 44d33f70e45db8431680b7d17400765ba14fac4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=B9=BF?= Date: Tue, 11 Jun 2019 13:30:45 +0800 Subject: [PATCH 4/6] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E6=A0=91=E6=98=BE=E7=A4=BA=E7=AD=96=E7=95=A5=20(#2784?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 修改授权树显示策略 * [Update] 是否允许用户执行批量命令 * [Update] 优化授权节点构建 * [Update] 修改节点大小判断 * [Update] 修改节点大小判断 --- apps/assets/models/node.py | 8 +- apps/jumpserver/context_processor.py | 3 +- apps/jumpserver/settings.py | 1 + apps/locale/zh/LC_MESSAGES/django.mo | Bin 76482 -> 76615 bytes apps/locale/zh/LC_MESSAGES/django.po | 310 ++++++++++++++------------- apps/ops/api/command.py | 6 + apps/perms/utils/asset_permission.py | 24 ++- apps/settings/forms.py | 5 + apps/templates/_nav_user.html | 2 + 9 files changed, 202 insertions(+), 157 deletions(-) diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 170a5135f..ea3fd70f5 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -40,8 +40,10 @@ class Node(OrgModelMixin): return self.key == other.key def __gt__(self, other): - if self.is_root(): + if self.is_root() and not other.is_root(): return True + elif not self.is_root() and other.is_root(): + return False self_key = [int(k) for k in self.key.split(':')] other_key = [int(k) for k in other.key.split(':')] self_parent_key = self_key[:-1] @@ -49,6 +51,10 @@ class Node(OrgModelMixin): if self_parent_key == other_parent_key: return self.name > other.name + if len(self_parent_key) < len(other_parent_key): + return True + elif len(self_parent_key) > len(other_parent_key): + return False return self_key > other_key def __lt__(self, other): diff --git a/apps/jumpserver/context_processor.py b/apps/jumpserver/context_processor.py index c6312aaf0..148611359 100644 --- a/apps/jumpserver/context_processor.py +++ b/apps/jumpserver/context_processor.py @@ -15,7 +15,8 @@ def jumpserver_processor(request): 'FAVICON_URL': static('img/facio.ico'), 'JMS_TITLE': 'Jumpserver', 'VERSION': settings.VERSION, - 'COPYRIGHT': 'FIT2CLOUD 飞致云' + ' © 2014-2019' + 'COPYRIGHT': 'FIT2CLOUD 飞致云' + ' © 2014-2019', + 'SECURITY_COMMAND_EXECUTION': settings.SECURITY_COMMAND_EXECUTION, } return context diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index d9be8c346..d43006c85 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -546,6 +546,7 @@ TERMINAL_REPLAY_STORAGE = { SECURITY_MFA_AUTH = False +SECURITY_COMMAND_EXECUTION = True SECURITY_LOGIN_LIMIT_COUNT = 7 SECURITY_LOGIN_LIMIT_TIME = 30 # Unit: minute SECURITY_MAX_IDLE_TIME = 30 # Unit: minute diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index fb8aab6444d1016140b90b68c22ae5d4fb64a578..d1d1a34cb0fde8ec77331e779f14f972c4d77ed9 100644 GIT binary patch delta 22660 zcmZwP1(X#>*Y5G2VbH;57~BTe;1D!Gkl-E&Zeg$i0)vNe@Zb)?g1ZIRK!8B75FCQL zy9Vd`Kc_a|W!-ywt>RaES9Mi&b@!Pw@aElhGHCCqAm7E%ph+G_;vmmUg}cK&uSayx zi!80I=T)fZd84o*_QuorYoO=V`p)x)6F+X?dHwLmhMspk!1LZ=O4^S!CMJKsspo~_ zj%J=08;@gRynr!0&*wd(5|6|i48~Z^JueA{VLHrVR>ic$oshM9V=ymH#NzlD7QtvO zJTDuTz%FCMSr^{9Z{a7fDn^Eg%rmG9zKjW&-+M?UDSki=kfaq?ff+Cyv!J%F0%{?(P&?EK zwY5Vq7EZ;KI2X0W+ffTUVeOYOJ@Fk(hjAm=e+`(6icYMILD(8~g^`#LyP~dqFh<8| z7zbyY%P@p^117+I$S!;TqOP=9YtPG!6;Ze52keB?TC@LARN}PZs<1EC#-nDYwl3cb zza;-RY5_s*+?K{c?NkV6#l)Beze4qkKwW7hmc`MiXW=+%!GZ1B|5#MQ+B;LDwk$L1 zR^&rHbR|*uvMK6{qEI{4A2rbsRR58vXJRVq7A?kL`~%f~5Ow~)mcQwvl99wyjDtxd z-2mzF3*x*O8=GQWY>VpO9d&D_qi)@D)HAdXb?+}@3VeyWB_SQ0=}-&Ii!snw${N1G zOeE@IF#d#E&@j{%Peh$C1$E`KFfPtVO}N_fdr@2aH)`P*QLo``)Iwr*^t?Qn6lwQ) z6{u+7TBr%@qdI=?I(S`CTih4p;UIH7YKv#1&fjQm$GOCNP~)`eK6Wtx`62z zQ}6$5D%!fmr~!ANR({&w!Sk-5Cb)yzna8Lre22*~{txa}WW{8}MNm6d3pGw%vzgh> z>?-yC_obqTa406kai~wSxu}WHV@$k;3Gg1O|65FmL7m;bPKQ*g5Eo2qywcLq` z@B(VQCzkiRxgAX9qoM(Gp&r6wsC!l$6Jul4dmM$@fzhZPSb!REE$aMTs4F{+dW)`N z7(PJVs=)4U!C{z~INV}iAu1Z^Yt%zi(`=6#a4_mhr&xZzxg9m|zo-H4q9*owxSb3} z?L;Ef&SXSAyg5)8Pzo~997H`6M^IOC7Q^ud>Z3JA zZ_lfQneZ|GfEuUykM8_-s0DOFEx0>s{6XmRubj#^B<5pEypQS_tB?D_kp#ac&Tnyd zEJZv4HPH#w6n^eD^RLdOx{mBs*%{Qm6%0`-%P6z514ft}FsIP-oP@z03ia zm3Rbdi`StZ&fVAwPh(Cj(bs*_wL{&4sh9*8qZalD>Vo&6#y{GZ{nvzNNoYk^Q77K9 z4zExr23WtCsDAq1rYlK;x^)>b9P?US3pGJgRR1=pc{-sM(8KZreN?o<;iwblScj$N z1}s2+7v{nLP!neD=N3>9^{|#f?aa5RiCUrhb-?7<8+FeoqMoV6m
    sAxq8P!HKD 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 delta 22532 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 Nzee8}eC6wE{|7`J=~4gy diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index c1acf7792..86481fbc4 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-27 15:38+0800\n" +"POT-Creation-Date: 2019-06-11 11:39+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -163,7 +163,7 @@ msgstr "系统用户" #: settings/templates/settings/replay_storage_create.html:44 #: settings/templates/settings/terminal_setting.html:83 #: settings/templates/settings/terminal_setting.html:105 terminal/models.py:22 -#: terminal/models.py:241 terminal/templates/terminal/terminal_detail.html:43 +#: terminal/models.py:258 terminal/templates/terminal/terminal_detail.html:43 #: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14 #: users/models/user.py:61 users/templates/users/_select_user_modal.html:13 #: users/templates/users/user_detail.html:63 @@ -302,7 +302,7 @@ msgstr "备注" #: perms/templates/perms/remote_app_permission_list.html:17 #: perms/templates/perms/remote_app_permission_remote_app.html:26 #: perms/templates/perms/remote_app_permission_user.html:26 -#: templates/_nav.html:35 templates/_nav.html:45 templates/_nav_user.html:14 +#: templates/_nav.html:36 templates/_nav.html:48 templates/_nav_user.html:14 msgid "RemoteApp" msgstr "远程应用" @@ -411,7 +411,7 @@ msgstr "详情" #: applications/templates/applications/remote_app_list.html:56 #: assets/templates/assets/admin_user_detail.html:24 #: assets/templates/assets/admin_user_list.html:29 -#: assets/templates/assets/admin_user_list.html:111 +#: assets/templates/assets/admin_user_list.html:112 #: assets/templates/assets/asset_detail.html:27 #: assets/templates/assets/asset_list.html:86 #: assets/templates/assets/asset_list.html:190 @@ -425,7 +425,7 @@ msgstr "详情" #: assets/templates/assets/label_list.html:39 #: assets/templates/assets/system_user_detail.html:26 #: assets/templates/assets/system_user_list.html:33 -#: assets/templates/assets/system_user_list.html:117 audits/models.py:33 +#: assets/templates/assets/system_user_list.html:118 audits/models.py:33 #: perms/templates/perms/asset_permission_detail.html:30 #: perms/templates/perms/asset_permission_list.html:181 #: perms/templates/perms/remote_app_permission_detail.html:30 @@ -435,7 +435,7 @@ msgstr "详情" #: users/templates/users/user_detail.html:25 #: users/templates/users/user_group_detail.html:28 #: users/templates/users/user_group_list.html:20 -#: users/templates/users/user_group_list.html:69 +#: users/templates/users/user_group_list.html:70 #: users/templates/users/user_list.html:20 #: users/templates/users/user_list.html:96 #: users/templates/users/user_list.html:99 @@ -454,7 +454,7 @@ msgstr "更新" #: applications/templates/applications/remote_app_detail.html:25 #: applications/templates/applications/remote_app_list.html:57 #: assets/templates/assets/admin_user_detail.html:28 -#: assets/templates/assets/admin_user_list.html:112 +#: assets/templates/assets/admin_user_list.html:113 #: assets/templates/assets/asset_detail.html:31 #: assets/templates/assets/asset_list.html:191 #: assets/templates/assets/cmd_filter_detail.html:33 @@ -466,7 +466,7 @@ msgstr "更新" #: assets/templates/assets/domain_list.html:55 #: assets/templates/assets/label_list.html:40 #: assets/templates/assets/system_user_detail.html:30 -#: assets/templates/assets/system_user_list.html:118 audits/models.py:34 +#: assets/templates/assets/system_user_list.html:119 audits/models.py:34 #: ops/templates/ops/task_list.html:64 #: perms/templates/perms/asset_permission_detail.html:34 #: perms/templates/perms/asset_permission_list.html:182 @@ -477,7 +477,7 @@ msgstr "更新" #: terminal/templates/terminal/terminal_list.html:74 #: users/templates/users/user_detail.html:30 #: users/templates/users/user_group_detail.html:32 -#: users/templates/users/user_group_list.html:71 +#: users/templates/users/user_group_list.html:72 #: users/templates/users/user_list.html:104 #: users/templates/users/user_list.html:108 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:33 @@ -742,7 +742,7 @@ msgstr "密码或密钥密码" #: authentication/forms.py:13 #: authentication/templates/authentication/login.html:67 #: authentication/templates/authentication/new_login.html:93 -#: settings/forms.py:103 users/forms.py:15 users/forms.py:33 +#: settings/forms.py:103 users/forms.py:15 users/forms.py:27 #: users/templates/users/reset_password.html:53 #: users/templates/users/user_password_authentication.html:18 #: users/templates/users/user_password_update.html:43 @@ -1137,7 +1137,7 @@ msgstr "默认资产组" #: terminal/models.py:154 terminal/templates/terminal/command_list.html:32 #: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/session_list.html:33 -#: terminal/templates/terminal/session_list.html:71 users/forms.py:293 +#: terminal/templates/terminal/session_list.html:71 users/forms.py:300 #: users/models/user.py:36 users/models/user.py:467 users/serializers/v1.py:61 #: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_list.html:36 users/views/user.py:399 @@ -1215,7 +1215,7 @@ msgstr "连接" msgid "Org name" msgstr "组织名" -#: assets/serializers/asset_user.py:23 users/forms.py:240 +#: assets/serializers/asset_user.py:23 users/forms.py:247 #: users/models/user.py:91 users/templates/users/first_login.html:42 #: users/templates/users/user_password_update.html:46 #: users/templates/users/user_profile.html:68 @@ -1370,7 +1370,7 @@ msgstr "资产用户信息" #: assets/templates/assets/_asset_user_view_auth_modal.html:14 #: audits/models.py:99 audits/templates/audits/login_log_list.html:56 -#: users/forms.py:152 users/models/user.py:83 +#: users/forms.py:159 users/models/user.py:83 #: users/templates/users/first_login.html:45 msgid "MFA" msgstr "MFA" @@ -1382,11 +1382,11 @@ msgstr "需要二次认证来查看账号信息" #: assets/templates/assets/_asset_user_view_auth_modal.html:20 #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:211 -#: assets/templates/assets/asset_list.html:700 +#: assets/templates/assets/asset_list.html:682 #: assets/templates/assets/cmd_filter_detail.html:106 #: assets/templates/assets/system_user_asset.html:112 #: assets/templates/assets/system_user_detail.html:182 -#: assets/templates/assets/system_user_list.html:168 +#: assets/templates/assets/system_user_list.html:170 #: settings/templates/settings/terminal_setting.html:168 #: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:108 #: users/templates/users/user_detail.html:388 @@ -1394,8 +1394,8 @@ msgstr "需要二次认证来查看账号信息" #: users/templates/users/user_detail.html:437 #: users/templates/users/user_detail.html:482 #: users/templates/users/user_group_create_update.html:32 -#: users/templates/users/user_group_list.html:114 -#: users/templates/users/user_list.html:269 +#: users/templates/users/user_group_list.html:119 +#: users/templates/users/user_list.html:257 #: users/templates/users/user_profile.html:238 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:34 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36 @@ -1602,16 +1602,16 @@ msgstr "创建管理用户" msgid "Ratio" msgstr "比例" -#: assets/templates/assets/admin_user_list.html:159 -#: assets/templates/assets/admin_user_list.html:197 -#: assets/templates/assets/asset_list.html:499 -#: assets/templates/assets/asset_list.html:543 -#: assets/templates/assets/system_user_list.html:226 -#: assets/templates/assets/system_user_list.html:262 +#: assets/templates/assets/admin_user_list.html:160 +#: assets/templates/assets/admin_user_list.html:191 +#: assets/templates/assets/asset_list.html:492 +#: assets/templates/assets/asset_list.html:529 +#: assets/templates/assets/system_user_list.html:223 +#: assets/templates/assets/system_user_list.html:254 #: users/templates/users/user_group_list.html:163 -#: users/templates/users/user_group_list.html:199 -#: users/templates/users/user_list.html:162 -#: users/templates/users/user_list.html:198 +#: users/templates/users/user_group_list.html:194 +#: users/templates/users/user_list.html:158 +#: users/templates/users/user_list.html:190 msgid "Please select file" msgstr "选择文件" @@ -1787,45 +1787,45 @@ msgstr "重命名成功" msgid "Rename failed, do not change the root node name" msgstr "重命名失败,不能更改root节点的名称" -#: assets/templates/assets/asset_list.html:694 -#: assets/templates/assets/system_user_list.html:162 +#: assets/templates/assets/asset_list.html:676 +#: assets/templates/assets/system_user_list.html:164 #: users/templates/users/user_detail.html:382 #: users/templates/users/user_detail.html:408 #: users/templates/users/user_detail.html:476 -#: users/templates/users/user_group_list.html:108 -#: users/templates/users/user_list.html:263 +#: users/templates/users/user_group_list.html:113 +#: users/templates/users/user_list.html:251 #: xpack/plugins/interface/templates/interface/interface.html:97 msgid "Are you sure?" msgstr "你确认吗?" -#: assets/templates/assets/asset_list.html:695 +#: assets/templates/assets/asset_list.html:677 msgid "This will delete the selected assets !!!" msgstr "删除选择资产" -#: assets/templates/assets/asset_list.html:698 -#: assets/templates/assets/system_user_list.html:166 +#: assets/templates/assets/asset_list.html:680 +#: assets/templates/assets/system_user_list.html:168 #: settings/templates/settings/terminal_setting.html:166 #: users/templates/users/user_detail.html:386 #: users/templates/users/user_detail.html:412 #: users/templates/users/user_detail.html:480 #: users/templates/users/user_group_create_update.html:31 -#: users/templates/users/user_group_list.html:112 -#: users/templates/users/user_list.html:267 +#: users/templates/users/user_group_list.html:117 +#: users/templates/users/user_list.html:255 #: xpack/plugins/interface/templates/interface/interface.html:101 #: xpack/plugins/orgs/templates/orgs/org_create_update.html:32 msgid "Cancel" msgstr "取消" -#: assets/templates/assets/asset_list.html:711 +#: assets/templates/assets/asset_list.html:693 msgid "Asset Deleted." msgstr "已被删除" -#: assets/templates/assets/asset_list.html:712 -#: assets/templates/assets/asset_list.html:716 +#: assets/templates/assets/asset_list.html:694 +#: assets/templates/assets/asset_list.html:698 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:715 +#: assets/templates/assets/asset_list.html:697 msgid "Asset Deleting failed." msgstr "删除失败" @@ -2013,20 +2013,20 @@ msgstr "" msgid "Create system user" msgstr "创建系统用户" -#: assets/templates/assets/system_user_list.html:163 +#: assets/templates/assets/system_user_list.html:165 msgid "This will delete the selected System Users !!!" msgstr "删除选择系统用户" -#: assets/templates/assets/system_user_list.html:172 +#: assets/templates/assets/system_user_list.html:174 msgid "System Users Deleted." msgstr "已被删除" -#: assets/templates/assets/system_user_list.html:173 -#: assets/templates/assets/system_user_list.html:178 +#: assets/templates/assets/system_user_list.html:175 +#: assets/templates/assets/system_user_list.html:180 msgid "System Users Delete" msgstr "删除系统用户" -#: assets/templates/assets/system_user_list.html:177 +#: assets/templates/assets/system_user_list.html:179 msgid "System Users Deleting failed." msgstr "系统用户删除失败" @@ -2308,23 +2308,23 @@ msgid "Datetime" msgstr "日期" #: audits/views.py:85 audits/views.py:129 audits/views.py:165 -#: audits/views.py:209 audits/views.py:241 templates/_nav.html:83 +#: audits/views.py:209 audits/views.py:241 templates/_nav.html:87 msgid "Audits" msgstr "日志审计" -#: audits/views.py:86 templates/_nav.html:87 +#: audits/views.py:86 templates/_nav.html:91 msgid "FTP log" msgstr "FTP日志" -#: audits/views.py:130 templates/_nav.html:88 +#: audits/views.py:130 templates/_nav.html:92 msgid "Operate log" msgstr "操作日志" -#: audits/views.py:166 templates/_nav.html:89 +#: audits/views.py:166 templates/_nav.html:93 msgid "Password change log" msgstr "改密日志" -#: audits/views.py:210 templates/_nav.html:86 +#: audits/views.py:210 templates/_nav.html:90 msgid "Login log" msgstr "登录日志" @@ -2949,7 +2949,7 @@ msgstr "更新任务内容: {}" msgid "Ops" msgstr "作业中心" -#: ops/views/adhoc.py:45 templates/_nav.html:77 +#: ops/views/adhoc.py:45 templates/_nav.html:81 msgid "Task list" msgstr "任务列表" @@ -2987,7 +2987,7 @@ msgstr "下载文件" #: perms/templates/perms/asset_permission_list.html:75 #: perms/templates/perms/asset_permission_list.html:122 #: perms/templates/perms/remote_app_permission_list.html:16 -#: templates/_nav.html:14 users/forms.py:263 users/models/group.py:26 +#: templates/_nav.html:14 users/forms.py:270 users/models/group.py:26 #: users/models/user.py:67 users/templates/users/_select_user_modal.html:16 #: users/templates/users/user_detail.html:213 #: users/templates/users/user_list.html:38 @@ -3010,7 +3010,7 @@ msgid "Asset or group at least one required" msgstr "资产和节点至少选一个" #: perms/models/asset_permission.py:44 perms/models/asset_permission.py:70 -#: templates/_nav.html:42 +#: templates/_nav.html:44 msgid "Asset permission" msgstr "资产授权" @@ -3171,7 +3171,7 @@ msgstr "添加用户组" #: perms/views/remote_app_permission.py:63 #: perms/views/remote_app_permission.py:76 #: perms/views/remote_app_permission.py:102 -#: perms/views/remote_app_permission.py:138 templates/_nav.html:39 +#: perms/views/remote_app_permission.py:138 templates/_nav.html:41 #: xpack/plugins/orgs/templates/orgs/org_list.html:21 msgid "Perms" msgstr "权限管理" @@ -3224,33 +3224,33 @@ msgstr "远程应用授权用户列表" msgid "RemoteApp permission RemoteApp list" msgstr "远程应用授权远程应用列表" -#: settings/api.py:26 +#: settings/api.py:28 msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api.py:50 +#: settings/api.py:52 msgid "Test ldap success" msgstr "连接LDAP成功" -#: settings/api.py:87 +#: settings/api.py:89 msgid "Match {} s users" msgstr "匹配 {} 个用户" -#: settings/api.py:120 +#: settings/api.py:158 msgid "succeed: {} failed: {} total: {}" msgstr "成功:{} 失败:{} 总数:{}" -#: settings/api.py:142 settings/api.py:178 +#: settings/api.py:180 settings/api.py:216 msgid "" "Error: Account invalid (Please make sure the information such as Access key " "or Secret key is correct)" msgstr "错误:账户无效 (请确保 Access key 或 Secret key 等信息正确)" -#: settings/api.py:148 settings/api.py:184 +#: settings/api.py:186 settings/api.py:222 msgid "Create succeed" msgstr "创建成功" -#: settings/api.py:166 settings/api.py:204 +#: settings/api.py:204 settings/api.py:242 #: settings/templates/settings/terminal_setting.html:154 msgid "Delete succeed" msgstr "删除成功" @@ -3295,7 +3295,7 @@ msgstr "SMTP密码" msgid "Some provider use token except password" msgstr "一些邮件提供商需要输入的是Token" -#: settings/forms.py:86 settings/forms.py:125 +#: settings/forms.py:86 msgid "Use SSL" msgstr "使用SSL" @@ -3407,35 +3407,43 @@ msgid "" "for all users, including administrators)" msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)" +#: settings/forms.py:185 +msgid "Batch execute commands" +msgstr "批量命令" + #: settings/forms.py:186 +msgid "Allow user batch execute commands" +msgstr "允许用户批量执行命令" + +#: settings/forms.py:191 msgid "Limit the number of login failures" msgstr "限制登录失败次数" -#: settings/forms.py:190 +#: settings/forms.py:195 msgid "No logon interval" msgstr "禁止登录时间间隔" -#: settings/forms.py:192 +#: settings/forms.py:197 msgid "" "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." msgstr "" "提示:(单位:分)当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录" -#: settings/forms.py:199 +#: settings/forms.py:204 msgid "Connection max idle time" msgstr "SSH最大空闲时间" -#: settings/forms.py:201 +#: settings/forms.py:206 msgid "" "If idle time more than it, disconnect connection(only ssh now) Unit: minute" msgstr "提示:(单位:分)如果超过该配置没有操作,连接会被断开(仅ssh)" -#: settings/forms.py:207 +#: settings/forms.py:212 msgid "Password expiration time" msgstr "密码过期时间" -#: settings/forms.py:209 +#: settings/forms.py:214 msgid "" "Tip: (unit: day) If the user does not update the password during the time, " "the user password will expire failure;The password expiration reminder mail " @@ -3445,81 +3453,81 @@ msgstr "" "提示:(单位:天)如果用户在此期间没有更新密码,用户密码将过期失效; 密码过期" "提醒邮件将在密码过期前5天内由系统(每天)自动发送给用户" -#: settings/forms.py:218 +#: settings/forms.py:223 msgid "Password minimum length" msgstr "密码最小长度 " -#: settings/forms.py:222 +#: settings/forms.py:227 msgid "Must contain capital letters" msgstr "必须包含大写字母" -#: settings/forms.py:224 +#: settings/forms.py:229 msgid "" "After opening, the user password changes and resets must contain uppercase " "letters" msgstr "开启后,用户密码修改、重置必须包含大写字母" -#: settings/forms.py:229 +#: settings/forms.py:234 msgid "Must contain lowercase letters" msgstr "必须包含小写字母" -#: settings/forms.py:230 +#: settings/forms.py:235 msgid "" "After opening, the user password changes and resets must contain lowercase " "letters" msgstr "开启后,用户密码修改、重置必须包含小写字母" -#: settings/forms.py:235 +#: settings/forms.py:240 msgid "Must contain numeric characters" msgstr "必须包含数字字符" -#: settings/forms.py:236 +#: settings/forms.py:241 msgid "" "After opening, the user password changes and resets must contain numeric " "characters" msgstr "开启后,用户密码修改、重置必须包含数字字符" -#: settings/forms.py:241 +#: settings/forms.py:246 msgid "Must contain special characters" msgstr "必须包含特殊字符" -#: settings/forms.py:242 +#: settings/forms.py:247 msgid "" "After opening, the user password changes and resets must contain special " "characters" msgstr "开启后,用户密码修改、重置必须包含特殊字符" -#: settings/forms.py:249 +#: settings/forms.py:254 msgid "Create user email subject" msgstr "创建用户邮件的主题" -#: settings/forms.py:250 +#: settings/forms.py:255 msgid "" "Tips: When creating a user, send the subject of the email (eg:Create account " "successfully)" msgstr "提示: 创建用户时,发送设置密码邮件的主题 (例如: 创建用户成功)" -#: settings/forms.py:254 +#: settings/forms.py:259 msgid "Create user honorific" msgstr "创建用户邮件的敬语" -#: settings/forms.py:255 +#: settings/forms.py:260 msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)" msgstr "提示: 创建用户时,发送设置密码邮件的敬语 (例如: 您好)" -#: settings/forms.py:260 +#: settings/forms.py:265 msgid "Create user email content" msgstr "创建用户邮件的内容" -#: settings/forms.py:261 +#: settings/forms.py:266 msgid "Tips:When creating a user, send the content of the email" msgstr "提示: 创建用户时,发送设置密码邮件的内容" -#: settings/forms.py:264 +#: settings/forms.py:269 msgid "Signature" msgstr "署名" -#: settings/forms.py:265 +#: settings/forms.py:270 msgid "Tips: Email signature (eg:jumpserver)" msgstr "提示: 邮件的署名 (例如: jumpserver)" @@ -3622,7 +3630,7 @@ msgstr "创建用户设置" msgid "Bulk import" msgstr "一键导入" -#: settings/templates/settings/ldap_setting.html:119 +#: settings/templates/settings/ldap_setting.html:116 msgid "" "User is not currently selected, please check the user you want to import" msgstr "当前无勾选用户,请勾选你想要导入的用户" @@ -3731,17 +3739,17 @@ msgstr "删除失败" msgid "Are you sure about deleting it?" msgstr "您确定删除吗?" -#: settings/utils.py:85 +#: settings/utils.py:84 msgid "Search no entry matched in ou {}" msgstr "在ou:{}中没有匹配条目" -#: settings/utils.py:113 +#: settings/utils.py:112 msgid "The user source is not LDAP" msgstr "用户来源不是LDAP" #: settings/views.py:18 settings/views.py:44 settings/views.py:70 #: settings/views.py:99 settings/views.py:126 settings/views.py:138 -#: settings/views.py:151 settings/views.py:177 templates/_nav.html:118 +#: settings/views.py:151 settings/views.py:177 templates/_nav.html:122 msgid "Settings" msgstr "系统设置" @@ -3770,7 +3778,7 @@ msgstr "文档" msgid "Commercial support" msgstr "商业支持" -#: templates/_header_bar.html:89 templates/_nav_user.html:26 users/forms.py:131 +#: templates/_header_bar.html:89 templates/_nav_user.html:26 users/forms.py:138 #: users/templates/users/_user.html:43 #: users/templates/users/first_login.html:39 #: users/templates/users/user_password_update.html:40 @@ -3885,58 +3893,58 @@ msgstr "用户列表" msgid "Command filters" msgstr "命令过滤" -#: templates/_nav.html:32 +#: templates/_nav.html:33 msgid "Applications" msgstr "应用管理" -#: templates/_nav.html:51 +#: templates/_nav.html:55 msgid "Sessions" msgstr "会话管理" -#: templates/_nav.html:54 +#: templates/_nav.html:58 msgid "Session online" msgstr "在线会话" -#: templates/_nav.html:55 +#: templates/_nav.html:59 msgid "Session offline" msgstr "历史会话" -#: templates/_nav.html:56 +#: templates/_nav.html:60 msgid "Commands" msgstr "命令记录" -#: templates/_nav.html:59 templates/_nav_user.html:31 +#: templates/_nav.html:63 templates/_nav_user.html:31 msgid "Web terminal" msgstr "Web终端" -#: templates/_nav.html:64 templates/_nav_user.html:36 +#: templates/_nav.html:68 templates/_nav_user.html:36 msgid "File manager" msgstr "文件管理" -#: templates/_nav.html:68 terminal/views/command.py:50 +#: templates/_nav.html:72 terminal/views/command.py:50 #: terminal/views/session.py:74 terminal/views/session.py:92 #: terminal/views/session.py:115 terminal/views/terminal.py:31 #: terminal/views/terminal.py:46 terminal/views/terminal.py:58 msgid "Terminal" msgstr "终端管理" -#: templates/_nav.html:74 +#: templates/_nav.html:78 msgid "Job Center" msgstr "作业中心" -#: templates/_nav.html:78 templates/_nav.html:90 +#: templates/_nav.html:82 templates/_nav.html:94 msgid "Batch command" msgstr "批量命令" -#: templates/_nav.html:96 +#: templates/_nav.html:100 msgid "XPack" msgstr "" -#: templates/_nav.html:104 xpack/plugins/cloud/views.py:26 +#: templates/_nav.html:108 xpack/plugins/cloud/views.py:26 msgid "Account list" msgstr "账户列表" -#: templates/_nav.html:105 +#: templates/_nav.html:109 msgid "Sync instance" msgstr "同步实例" @@ -4190,7 +4198,7 @@ msgstr "最后活跃日期" msgid "Date end" msgstr "结束日期" -#: terminal/models.py:242 +#: terminal/models.py:259 msgid "Args" msgstr "参数" @@ -4331,15 +4339,7 @@ msgstr "你没有权限" msgid "Could not reset self otp, use profile reset instead" msgstr "不能再该页面重置MFA, 请去个人信息页面重置" -#: users/forms.py:25 -msgid "Reset link will be generated and sent to the user" -msgstr "生成重置密码链接,通过邮件发送给用户" - -#: users/forms.py:26 -msgid "Set password" -msgstr "设置密码" - -#: users/forms.py:38 users/models/user.py:71 +#: users/forms.py:32 users/models/user.py:71 #: users/templates/users/_select_user_modal.html:15 #: users/templates/users/user_detail.html:87 #: users/templates/users/user_list.html:37 @@ -4347,19 +4347,39 @@ msgstr "设置密码" msgid "Role" msgstr "角色" -#: users/forms.py:41 users/forms.py:210 +#: users/forms.py:35 users/forms.py:217 msgid "ssh public key" msgstr "ssh公钥" -#: users/forms.py:42 users/forms.py:211 +#: users/forms.py:36 users/forms.py:218 msgid "ssh-rsa AAAA..." msgstr "" -#: users/forms.py:43 +#: users/forms.py:37 msgid "Paste user id_rsa.pub here." msgstr "复制用户公钥到这里" -#: users/forms.py:47 xpack/plugins/change_auth_plan/models.py:83 +#: users/forms.py:51 users/templates/users/user_detail.html:221 +msgid "Join user groups" +msgstr "添加到用户组" + +#: users/forms.py:85 users/forms.py:232 +msgid "Public key should not be the same as your old one." +msgstr "不能和原来的密钥相同" + +#: users/forms.py:89 users/forms.py:236 users/serializers/v1.py:47 +msgid "Not a valid ssh public key" +msgstr "ssh密钥不合法" + +#: users/forms.py:109 +msgid "Reset link will be generated and sent to the user" +msgstr "生成重置密码链接,通过邮件发送给用户" + +#: users/forms.py:110 +msgid "Set password" +msgstr "设置密码" + +#: users/forms.py:117 xpack/plugins/change_auth_plan/models.py:83 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:51 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:69 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57 @@ -4367,19 +4387,7 @@ msgstr "复制用户公钥到这里" msgid "Password strategy" msgstr "密码策略" -#: users/forms.py:61 users/templates/users/user_detail.html:221 -msgid "Join user groups" -msgstr "添加到用户组" - -#: users/forms.py:95 users/forms.py:225 -msgid "Public key should not be the same as your old one." -msgstr "不能和原来的密钥相同" - -#: users/forms.py:99 users/forms.py:229 users/serializers/v1.py:47 -msgid "Not a valid ssh public key" -msgstr "ssh密钥不合法" - -#: users/forms.py:137 +#: users/forms.py:144 msgid "" "Tip: when enabled, you will enter the MFA binding process the next time you " "log in. you can also directly bind in \"personal information -> quick " @@ -4388,11 +4396,11 @@ msgstr "" "提示:启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修" "改->更改MFA设置)中直接绑定!" -#: users/forms.py:147 +#: users/forms.py:154 msgid "* Enable MFA authentication to make the account more secure." msgstr "* 启用MFA认证,使账号更加安全." -#: users/forms.py:157 +#: users/forms.py:164 msgid "" "In order to protect you and your company, please keep your account, password " "and key sensitive information properly. (for example: setting complex " @@ -4401,41 +4409,41 @@ msgstr "" "为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:" "设置复杂密码,启用MFA认证)" -#: users/forms.py:164 users/templates/users/first_login.html:48 +#: users/forms.py:171 users/templates/users/first_login.html:48 #: users/templates/users/first_login.html:107 #: users/templates/users/first_login.html:130 msgid "Finish" msgstr "完成" -#: users/forms.py:170 +#: users/forms.py:177 msgid "Old password" msgstr "原来密码" -#: users/forms.py:175 +#: users/forms.py:182 msgid "New password" msgstr "新密码" -#: users/forms.py:180 +#: users/forms.py:187 msgid "Confirm password" msgstr "确认密码" -#: users/forms.py:190 +#: users/forms.py:197 msgid "Old password error" msgstr "原来密码错误" -#: users/forms.py:198 +#: users/forms.py:205 msgid "Password does not match" msgstr "密码不一致" -#: users/forms.py:208 +#: users/forms.py:215 msgid "Automatically configure and download the SSH key" msgstr "自动配置并下载SSH密钥" -#: users/forms.py:212 +#: users/forms.py:219 msgid "Paste your id_rsa.pub here." msgstr "复制你的公钥到这里" -#: users/forms.py:246 users/forms.py:251 users/forms.py:297 +#: users/forms.py:253 users/forms.py:258 users/forms.py:304 #: xpack/plugins/orgs/forms.py:30 msgid "Select users" msgstr "选择用户" @@ -4827,45 +4835,45 @@ msgstr "添加用户" msgid "Create user group" msgstr "创建用户组" -#: users/templates/users/user_group_list.html:109 +#: users/templates/users/user_group_list.html:114 msgid "This will delete the selected groups !!!" msgstr "删除选择组" -#: users/templates/users/user_group_list.html:118 +#: users/templates/users/user_group_list.html:123 msgid "UserGroups Deleted." msgstr "用户组删除" -#: users/templates/users/user_group_list.html:119 #: users/templates/users/user_group_list.html:124 +#: users/templates/users/user_group_list.html:129 msgid "UserGroups Delete" msgstr "用户组删除" -#: users/templates/users/user_group_list.html:123 +#: users/templates/users/user_group_list.html:128 msgid "UserGroup Deleting failed." msgstr "用户组删除失败" -#: users/templates/users/user_list.html:264 +#: users/templates/users/user_list.html:252 msgid "This will delete the selected users !!!" msgstr "删除选中用户 !!!" -#: users/templates/users/user_list.html:280 +#: users/templates/users/user_list.html:268 msgid "User Deleted." msgstr "已被删除" -#: users/templates/users/user_list.html:281 -#: users/templates/users/user_list.html:285 +#: users/templates/users/user_list.html:269 +#: users/templates/users/user_list.html:273 msgid "User Delete" msgstr "删除" -#: users/templates/users/user_list.html:284 +#: users/templates/users/user_list.html:272 msgid "User Deleting failed." msgstr "用户删除失败" -#: users/templates/users/user_list.html:337 +#: users/templates/users/user_list.html:325 msgid "User is expired" msgstr "用户已失效" -#: users/templates/users/user_list.html:340 +#: users/templates/users/user_list.html:328 msgid "User is inactive" msgstr "用户已禁用" diff --git a/apps/ops/api/command.py b/apps/ops/api/command.py index 29f1b742c..dbc3aa218 100644 --- a/apps/ops/api/command.py +++ b/apps/ops/api/command.py @@ -2,6 +2,7 @@ # from rest_framework import viewsets from django.db import transaction +from django.conf import settings from common.permissions import IsValidUser from ..models import CommandExecution @@ -18,6 +19,11 @@ class CommandExecutionViewSet(viewsets.ModelViewSet): user_id=str(self.request.user.id) ) + def check_permissions(self, request): + if not settings.SECURITY_COMMAND_EXECUTION: + return self.permission_denied(request, "Command execution disabled") + return super().check_permissions(request) + def perform_create(self, serializer): instance = serializer.save() instance.user = self.request.user diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index fb0676a5e..90fd68569 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -37,9 +37,21 @@ class GenerateTree: def add_asset(self, asset, system_users): nodes = asset.nodes.all() - self.add_nodes(nodes) + in_nodes = False for node in nodes: + if node not in self.nodes: + continue self.nodes[node][asset].update(system_users) + in_nodes = True + if not in_nodes: + all_nodes = self.nodes.keys() + # 如果没有授权节点,就放到默认的根节点下 + if not all_nodes: + root_node = Node.root() + self.add_node(root_node) + else: + root_node = max(all_nodes) + self.nodes[root_node][asset].update(system_users) def get_nodes(self): for node in self.nodes: @@ -50,6 +62,7 @@ class GenerateTree: node.assets_amount = len(assets) return self.nodes + # 添加节点时,追溯到根节点 def add_node(self, node): if node in self.nodes: return @@ -62,9 +75,11 @@ class GenerateTree: self.add_node(n) break + # 添加树节点 def add_nodes(self, nodes): for node in nodes: self.add_node(node) + self.add_nodes(node.get_all_children(with_self=False)) def get_user_permissions(user, include_group=True): @@ -123,6 +138,7 @@ class AssetPermissionUtil: self._assets = None self._filter_id = 'None' # 当通过filter更改 permission是标记 self.cache_policy = cache_policy + self.tree = GenerateTree() @classmethod def is_not_using_cache(cls, cache_policy): @@ -181,6 +197,7 @@ class AssetPermissionUtil: permissions = self.permissions.prefetch_related('nodes', 'system_users') for perm in permissions: actions = perm.actions.all() + self.tree.add_nodes(perm.nodes.all()) for node in perm.nodes.all(): system_users = perm.system_users.all() system_users = self._structured_system_user(system_users, actions) @@ -275,10 +292,9 @@ class AssetPermissionUtil: :return: """ assets = self.get_assets_without_cache() - tree = GenerateTree() for asset, system_users in assets.items(): - tree.add_asset(asset, system_users) - return tree.get_nodes() + self.tree.add_asset(asset, system_users) + return self.tree.get_nodes() def get_nodes_with_assets_from_cache(self): cached = cache.get(self.node_key) diff --git a/apps/settings/forms.py b/apps/settings/forms.py index 3f6a690a8..228abb7ec 100644 --- a/apps/settings/forms.py +++ b/apps/settings/forms.py @@ -180,6 +180,11 @@ class SecuritySettingForm(BaseForm): 'authentication (valid for all users, including administrators)' ) ) + # Execute commands for user + SECURITY_COMMAND_EXECUTION = forms.BooleanField( + required=False, label=_("Batch execute commands"), + help_text=_("Allow user batch execute commands") + ) # limit login count SECURITY_LOGIN_LIMIT_COUNT = forms.IntegerField( min_value=3, max_value=99999, diff --git a/apps/templates/_nav_user.html b/apps/templates/_nav_user.html index 5412dc37d..5f77fb99e 100644 --- a/apps/templates/_nav_user.html +++ b/apps/templates/_nav_user.html @@ -16,11 +16,13 @@ +{% if SECURITY_COMMAND_EXECUTION %}
  1. {% trans 'Command execution' %}
  2. +{% endif %}
  3. {% trans 'Profile' %} From 3e86c07411682a5213242c69f5871ecd8cdc6f5b Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 12 Jun 2019 17:04:49 +0800 Subject: [PATCH 5/6] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E8=8A=82=E7=82=B9=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/node.py | 2 +- apps/locale/zh/LC_MESSAGES/django.mo | Bin 76615 -> 76651 bytes apps/locale/zh/LC_MESSAGES/django.po | 53 ++++++++++++------------ apps/perms/api/user_group_permission.py | 7 +++- apps/perms/api/user_permission.py | 14 +++++-- apps/perms/const.py | 2 + apps/perms/utils/asset_permission.py | 53 +++++++++++++++++------- 7 files changed, 83 insertions(+), 48 deletions(-) diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index ea3fd70f5..7f7487f06 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -37,7 +37,7 @@ class Node(OrgModelMixin): def __eq__(self, other): if not other: return False - return self.key == other.key + return self.id == other.id def __gt__(self, other): if self.is_root() and not other.is_root(): diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index d1d1a34cb0fde8ec77331e779f14f972c4d77ed9..e0ec647a877fcb69f447961fe4ea4a1a83baeb69 100644 GIT binary patch delta 16772 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 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 86481fbc4..9251559a9 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-11 11:39+0800\n" +"POT-Creation-Date: 2019-06-12 16:59+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -110,7 +110,7 @@ msgstr "资产" #: applications/templates/applications/remote_app_detail.html:61 #: applications/templates/applications/remote_app_list.html:23 #: applications/templates/applications/user_remote_app_list.html:19 -#: assets/models/user.py:247 assets/templates/assets/user_asset_list.html:168 +#: assets/models/user.py:247 assets/templates/assets/user_asset_list.html:172 #: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49 #: audits/templates/audits/ftp_log_list.html:72 #: perms/forms/asset_permission.py:52 perms/models/asset_permission.py:39 @@ -271,7 +271,7 @@ msgstr "创建日期" #: assets/templates/assets/domain_list.html:28 #: assets/templates/assets/system_user_detail.html:104 #: assets/templates/assets/system_user_list.html:59 -#: assets/templates/assets/user_asset_list.html:171 ops/models/adhoc.py:43 +#: assets/templates/assets/user_asset_list.html:175 ops/models/adhoc.py:43 #: orgs/models.py:17 perms/models/asset_permission.py:64 #: perms/models/base.py:43 #: perms/templates/perms/asset_permission_detail.html:102 @@ -563,8 +563,8 @@ msgstr "连接" #: assets/views/admin_user.py:29 assets/views/admin_user.py:47 #: assets/views/admin_user.py:63 assets/views/admin_user.py:78 #: assets/views/admin_user.py:102 assets/views/asset.py:53 -#: assets/views/asset.py:69 assets/views/asset.py:106 assets/views/asset.py:147 -#: assets/views/asset.py:164 assets/views/asset.py:188 +#: assets/views/asset.py:69 assets/views/asset.py:107 assets/views/asset.py:148 +#: assets/views/asset.py:165 assets/views/asset.py:189 #: assets/views/cmd_filter.py:30 assets/views/cmd_filter.py:46 #: assets/views/cmd_filter.py:62 assets/views/cmd_filter.py:78 #: assets/views/cmd_filter.py:97 assets/views/cmd_filter.py:130 @@ -643,7 +643,7 @@ msgstr "标签" #: assets/forms/asset.py:37 assets/forms/asset.py:73 assets/models/asset.py:79 #: assets/models/domain.py:26 assets/models/domain.py:52 #: assets/templates/assets/asset_detail.html:84 -#: assets/templates/assets/user_asset_list.html:169 +#: assets/templates/assets/user_asset_list.html:173 #: xpack/plugins/orgs/templates/orgs/org_list.html:17 msgid "Domain" msgstr "网域" @@ -807,7 +807,7 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" #: assets/templates/assets/domain_gateway_list.html:68 #: assets/templates/assets/system_user_asset.html:51 #: assets/templates/assets/user_asset_list.html:45 -#: assets/templates/assets/user_asset_list.html:163 +#: assets/templates/assets/user_asset_list.html:167 #: audits/templates/audits/login_log_list.html:54 #: perms/templates/perms/asset_permission_asset.html:55 settings/forms.py:133 #: users/templates/users/user_granted_asset.html:45 @@ -824,7 +824,7 @@ msgstr "IP" #: assets/templates/assets/asset_list.html:104 #: assets/templates/assets/system_user_asset.html:50 #: assets/templates/assets/user_asset_list.html:44 -#: assets/templates/assets/user_asset_list.html:162 +#: assets/templates/assets/user_asset_list.html:166 #: perms/templates/perms/asset_permission_asset.html:54 #: perms/templates/perms/asset_permission_list.html:77 settings/forms.py:132 #: users/templates/users/user_granted_asset.html:44 @@ -838,7 +838,7 @@ msgstr "主机名" #: assets/templates/assets/domain_gateway_list.html:70 #: assets/templates/assets/system_user_detail.html:70 #: assets/templates/assets/system_user_list.html:53 -#: assets/templates/assets/user_asset_list.html:165 +#: assets/templates/assets/user_asset_list.html:169 #: terminal/templates/terminal/session_list.html:75 msgid "Protocol" msgstr "协议" @@ -848,20 +848,20 @@ msgstr "协议" #: assets/templates/assets/asset_detail.html:72 #: assets/templates/assets/domain_gateway_list.html:69 #: assets/templates/assets/system_user_asset.html:52 -#: assets/templates/assets/user_asset_list.html:164 +#: assets/templates/assets/user_asset_list.html:168 #: settings/templates/settings/replay_storage_create.html:59 msgid "Port" msgstr "端口" #: assets/models/asset.py:78 assets/templates/assets/asset_detail.html:108 -#: assets/templates/assets/user_asset_list.html:166 +#: assets/templates/assets/user_asset_list.html:170 msgid "Platform" msgstr "系统平台" #: assets/models/asset.py:81 assets/models/cmd_filter.py:21 #: assets/models/domain.py:54 assets/models/label.py:22 #: assets/templates/assets/asset_detail.html:116 -#: assets/templates/assets/user_asset_list.html:170 +#: assets/templates/assets/user_asset_list.html:174 msgid "Is active" msgstr "激活" @@ -915,7 +915,7 @@ msgid "Disk info" msgstr "硬盘信息" #: assets/models/asset.py:103 assets/templates/assets/asset_detail.html:112 -#: assets/templates/assets/user_asset_list.html:167 +#: assets/templates/assets/user_asset_list.html:171 msgid "OS" msgstr "操作系统" @@ -1015,6 +1015,7 @@ msgid "Operator" msgstr "运营商" #: assets/models/cluster.py:36 assets/models/group.py:34 +#: perms/utils/asset_permission.py:63 msgid "Default" msgstr "默认" @@ -1160,7 +1161,7 @@ msgstr "分类" msgid "Key" msgstr "键" -#: assets/models/node.py:133 +#: assets/models/node.py:139 msgid "New node" msgstr "新节点" @@ -1475,7 +1476,7 @@ msgstr "更新系统用户" #: assets/templates/assets/_user_asset_detail_modal.html:11 #: assets/templates/assets/asset_asset_user_list.html:13 -#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:189 +#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:190 msgid "Asset detail" msgstr "资产详情" @@ -1695,7 +1696,7 @@ msgstr "" "左侧是资产树,右击可以新建、删除、更改树节点,授权资产也是以节点方式组织的," "右侧是属于该节点下的资产" -#: assets/templates/assets/asset_list.html:69 assets/views/asset.py:107 +#: assets/templates/assets/asset_list.html:69 assets/views/asset.py:108 msgid "Create asset" msgstr "创建资产" @@ -2042,19 +2043,19 @@ msgstr "管理用户详情" msgid "My assets" msgstr "我的资产" -#: assets/views/asset.py:121 +#: assets/views/asset.py:122 msgid "Bulk update asset success" msgstr "批量更新资产成功" -#: assets/views/asset.py:148 +#: assets/views/asset.py:149 msgid "Bulk update asset" msgstr "批量更新资产" -#: assets/views/asset.py:165 +#: assets/views/asset.py:166 msgid "Update asset" msgstr "更新资产" -#: assets/views/asset.py:306 +#: assets/views/asset.py:307 msgid "already exists" msgstr "已经存在" @@ -2961,7 +2962,7 @@ msgstr "执行历史" msgid "Command execution list" msgstr "命令执行列表" -#: ops/views/command.py:69 templates/_nav_user.html:21 +#: ops/views/command.py:69 templates/_nav_user.html:22 msgid "Command execution" msgstr "命令执行" @@ -3778,7 +3779,7 @@ msgstr "文档" msgid "Commercial support" msgstr "商业支持" -#: templates/_header_bar.html:89 templates/_nav_user.html:26 users/forms.py:138 +#: templates/_header_bar.html:89 templates/_nav_user.html:28 users/forms.py:138 #: users/templates/users/_user.html:43 #: users/templates/users/first_login.html:39 #: users/templates/users/user_password_update.html:40 @@ -3913,11 +3914,11 @@ msgstr "历史会话" msgid "Commands" msgstr "命令记录" -#: templates/_nav.html:63 templates/_nav_user.html:31 +#: templates/_nav.html:63 templates/_nav_user.html:33 msgid "Web terminal" msgstr "Web终端" -#: templates/_nav.html:68 templates/_nav_user.html:36 +#: templates/_nav.html:68 templates/_nav_user.html:38 msgid "File manager" msgstr "文件管理" @@ -4331,11 +4332,11 @@ msgid "" "You should use your ssh client tools connect terminal: {}

    {}" msgstr "你可以使用ssh客户端工具连接终端" -#: users/api/user.py:75 users/api/user.py:86 users/api/user.py:112 +#: users/api/user.py:78 users/api/user.py:89 users/api/user.py:115 msgid "You do not have permission." msgstr "你没有权限" -#: users/api/user.py:216 +#: users/api/user.py:219 msgid "Could not reset self otp, use profile reset instead" msgstr "不能再该页面重置MFA, 请去个人信息页面重置" diff --git a/apps/perms/api/user_group_permission.py b/apps/perms/api/user_group_permission.py index 4e5c8acd9..159f76a39 100644 --- a/apps/perms/api/user_group_permission.py +++ b/apps/perms/api/user_group_permission.py @@ -17,7 +17,7 @@ from ..hands import ( AssetGrantedSerializer, UserGroup, Node, NodeSerializer, RemoteAppSerializer, ) -from .. import serializers +from .. import serializers, const __all__ = [ @@ -134,8 +134,11 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView): node_id = self.kwargs.get('node_id') user_group = get_object_or_404(UserGroup, id=user_group_id) - node = get_object_or_404(Node, id=node_id) util = AssetPermissionUtil(user_group) + if str(node_id) == const.UNGROUPED_NODE_ID: + node = util.tree.ungrouped_node + else: + node = get_object_or_404(Node, id=node_id) nodes = util.get_nodes_with_assets() assets = nodes.get(node, []) for asset, system_users in assets.items(): diff --git a/apps/perms/api/user_permission.py b/apps/perms/api/user_permission.py index 377bd735c..b4f8fc07e 100644 --- a/apps/perms/api/user_permission.py +++ b/apps/perms/api/user_permission.py @@ -24,7 +24,7 @@ from ..hands import ( User, Asset, Node, SystemUser, RemoteApp, AssetGrantedSerializer, NodeSerializer, RemoteAppSerializer, ) -from .. import serializers +from .. import serializers, const from ..mixins import AssetsFilterMixin, RemoteAppFilterMixin from ..models import Action @@ -300,9 +300,15 @@ class UserGrantedNodeAssetsApi(UserPermissionCacheMixin, AssetsFilterMixin, List user = self.get_object() node_id = self.kwargs.get('node_id') util = AssetPermissionUtil(user, cache_policy=self.cache_policy) - node = get_object_or_404(Node, id=node_id) - nodes = util.get_nodes_with_assets() - assets = nodes.get(node, []) + if str(node_id) == const.UNGROUPED_NODE_ID: + node = util.tree.ungrouped_node + else: + node = get_object_or_404(Node, id=node_id) + if node == util.tree.root_node: + assets = util.get_assets() + else: + nodes = util.get_nodes_with_assets() + assets = nodes.get(node, []) for asset, system_users in assets.items(): asset.system_users_granted = system_users diff --git a/apps/perms/const.py b/apps/perms/const.py index 4dc315c06..457db580c 100644 --- a/apps/perms/const.py +++ b/apps/perms/const.py @@ -20,3 +20,5 @@ PERMS_ACTION_NAME_CHOICES = ( (PERMS_ACTION_NAME_UPLOAD_FILE, _('Upload file')), (PERMS_ACTION_NAME_DOWNLOAD_FILE, _('Download file')), ) + +UNGROUPED_NODE_ID = "00000000-0000-0000-0000-000000000000" diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index 90fd68569..ed9f8f1a3 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -9,11 +9,13 @@ from django.utils import timezone from django.db.models import Q from django.core.cache import cache from django.conf import settings +from django.utils.translation import ugettext as _ from common.utils import get_logger from common.tree import TreeNode -from perms.models import AssetPermission, Action -from perms.hands import Node +from .. import const +from ..models import AssetPermission, Action +from ..hands import Node logger = get_logger(__file__) @@ -34,24 +36,43 @@ class GenerateTree: """ self.__all_nodes = list(Node.objects.all()) self.nodes = defaultdict(dict) + self.direct_nodes = [] + self._root_node = None + self._ungroup_node = None + + @property + def root_node(self): + if self._root_node: + return self._root_node + all_nodes = self.nodes.keys() + # 如果没有授权节点,就放到默认的根节点下 + if not all_nodes: + root_node = Node.root() + self.add_node(root_node) + else: + root_node = max(all_nodes) + self._root_node = root_node + return root_node + + @property + def ungrouped_node(self): + if self._ungroup_node: + return self._ungroup_node + node_id = const.UNGROUPED_NODE_ID + node_key = self.root_node.get_next_child_key() + node_value = _("Default") + node = Node(id=node_id, key=node_key, value=node_value) + self.add_node(node) + self._ungroup_node = node + return node def add_asset(self, asset, system_users): nodes = asset.nodes.all() - in_nodes = False - for node in nodes: - if node not in self.nodes: - continue + in_nodes = set(self.direct_nodes) & set(nodes) + for node in in_nodes: self.nodes[node][asset].update(system_users) - in_nodes = True if not in_nodes: - all_nodes = self.nodes.keys() - # 如果没有授权节点,就放到默认的根节点下 - if not all_nodes: - root_node = Node.root() - self.add_node(root_node) - else: - root_node = max(all_nodes) - self.nodes[root_node][asset].update(system_users) + self.nodes[self.ungrouped_node][asset].update(system_users) def get_nodes(self): for node in self.nodes: @@ -80,6 +101,8 @@ class GenerateTree: for node in nodes: self.add_node(node) self.add_nodes(node.get_all_children(with_self=False)) + # 如果是直接授权的节点,则放到direct_nodes中 + self.direct_nodes.append(node) def get_user_permissions(user, include_group=True): From 69b91df96b2f45265d16b8fae08a60142ada2e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Wed, 12 Jun 2019 17:49:30 +0800 Subject: [PATCH 6/6] =?UTF-8?q?[Update]=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E8=AE=BE=E7=BD=AE=E8=8A=82=E7=82=B9=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#2786)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update]优化资产设置节点的问题 * [Update]优化资产创建的节点设置 --- apps/assets/api/asset.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index c7bbeb094..39182fbf6 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -51,10 +51,12 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, BulkModelViewSet): def set_assets_node(self, assets): if not isinstance(assets, list): assets = [assets] - node = Node.root() node_id = self.request.query_params.get('node_id') - if node_id: - node = get_object_or_none(Node, pk=node_id) + if not node_id: + return + node = get_object_or_none(Node, pk=node_id) + if not node: + return node.assets.add(*assets) def perform_create(self, serializer):