diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py index 3500862e5..69e64ceaf 100644 --- a/apps/assets/forms/asset.py +++ b/apps/assets/forms/asset.py @@ -33,11 +33,16 @@ class AssetCreateForm(OrgModelForm): return nodes_field = self.fields['nodes'] if self.instance: - nodes_field.choices = ((n.id, n.full_value) for n in - self.instance.nodes.all()) + nodes_field.choices = [(n.id, n.full_value) for n in + self.instance.nodes.all()] else: nodes_field.choices = [] + def add_nodes_initial(self, node): + nodes_field = self.fields['nodes'] + nodes_field.choices.append((node.id, node.full_value)) + nodes_field.initial = [node] + class Meta: model = Asset fields = [ diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 37ebbd6d3..243c352a7 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -37,19 +37,22 @@ class TreeMixin: def tree(cls): from ..utils import TreeService tree_updated_time = cache.get(cls.tree_updated_time_cache_key, 0) + now = time.time() + # 什么时候重新初始化 _tree_service if not cls.tree_created_time or \ tree_updated_time > cls.tree_created_time: logger.debug("Create node tree") tree = TreeService.new() - cls.tree_created_time = time.time() - cls.tree_assets_created_time = time.time() + cls.tree_created_time = now + cls.tree_assets_created_time = now cls._tree_service = tree return tree + # 是否要重新初始化节点资产 node_assets_updated_time = cache.get(cls.tree_assets_cache_key, 0) if not cls.tree_assets_created_time or \ node_assets_updated_time > cls.tree_assets_created_time: - cls._tree_service.init_assets_async() - cls.tree_assets_created_time = time.time() + cls._tree_service.init_assets() + cls.tree_assets_created_time = now logger.debug("Refresh node tree assets") return cls._tree_service diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html index beafa9ae1..06aa4a707 100644 --- a/apps/assets/templates/assets/_asset_list_modal.html +++ b/apps/assets/templates/assets/_asset_list_modal.html @@ -15,11 +15,11 @@ text-align: center; } -#assetTree2.ztree * { - background-color: #f8fafb; +#asset_modal_tree.ztree * { + background-color: white; } -#assetTree2.ztree { - background-color: #f8fafb; +#asset_modal_tree.ztree { + background-color: white; } </style> @@ -29,7 +29,8 @@ <div class="ibox float-e-margins"> <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px"> <div class="file-manager "> - <div id="assetTree2" class="ztree"> + <div id="asset_modal_tree" class="ztree"> + {% trans 'Loading' %} ... </div> <div class="clearfix"></div> </div> @@ -55,12 +56,77 @@ </div> <script> -var zTree2, asset_table2 = 0; -function initTable2() { - if(asset_table2){ - return +function syncTableSelectedAssetToSelect2(table) { + var assets = table.selected; + var options = []; + var select2Id = assetModalOption.select2Id; + $(select2Id + ' option').each(function (i, v) { + options.push(v.value) + }); + table.selected_rows.forEach(function (i) { + var name = i.hostname + '(' + i.ip + ')'; + var option = new Option(name, i.id, false, true); + + if (options.indexOf(i.id) === -1) { + $(select2Id).append(option).trigger('change'); + } + }); + $(select2Id).val(assets).trigger('change'); +} + + + +// 解决input框中的资产和弹出表格中资产的显示不一致 +function syncSelectedAssetsToModalTable(assetModalTable) { + var select2Id = assetModalOption.select2Id; + var inputAssets = $(select2Id).val(); + var selectedAssets = assetModalTable.selected.concat(); + + // input assets无,table assets选中,则取消勾选(再次click) + if (selectedAssets.length !== 0) { + $.each(selectedAssets, function (index, assetId) { + if ($.inArray(assetId, inputAssets) === -1) { + $('#' + assetId).trigger('click'); // 取消勾选 + } + }); } + // input assets有,table assets没选,则选中(click) + if (inputAssets !== null) { + assetModalTable.selected = inputAssets; + $.each(inputAssets, function (index, assetId) { + var dom = document.getElementById(assetId); + if (dom !== null) { + var selected = dom.parentElement.parentElement.className.indexOf('selected') + } + if (selected === -1) { + $('#' + assetId).trigger('click'); + } + }); + } +} + +defaultOnAssetModalConfirm = syncTableSelectedAssetToSelect2; +defaultOnModalTableDone = syncSelectedAssetsToModalTable; + + +var assetModalOption = { + selectStyle: 'multi', + select2Id: '#id_assets', + onModalTableDone: defaultOnModalTableDone, + onModalTreeDone: null, + onModalConfirm: defaultOnAssetModalConfirm, +}; + +var assetModalTable, assetModalTree = null; + +function initAssetModalTable() { + if(assetModalTable){ + return + } + if (assetModalOption.selectStyle === 'single') { + $('.ipt_check_all').addClass('hidden') + } var options = { ele: $('#asset_list_modal_table'), ajax_url: '{% url "api-assets:asset-list" %}?show_current_asset=1', @@ -68,22 +134,26 @@ function initTable2() { {data: "id"}, {data: "hostname" }, {data: "ip" } ], lengthMenu: [[10, 25, 50], [10, 25, 50]], - pageLength: 10 + pageLength: 10, + select_style: assetModalOption.selectStyle }; - asset_table2 = jumpserver.initServerSideDataTable(options); - return asset_table2 + assetModalTable = jumpserver.initServerSideDataTable(options); + if (assetModalOption.onModalTableDone) { + assetModalOption.onModalTableDone(assetModalTable); + } + return assetModalTable } -function onNodeSelected2(event, treeNode) { - var url = asset_table2.ajax.url(); +function onModalTreeNodeSelected(event, treeNode) { + var url = assetModalTable.ajax.url(); url = setUrlParam(url, "node_id", treeNode.meta.node.id); url = setUrlParam(url, "show_current_asset", ""); - asset_table2.ajax.url(url); - asset_table2.ajax.reload(); + assetModalTable.ajax.url(url); + assetModalTable.ajax.reload(); } -function initTree2() { +function initModalTree() { var url = '{% url 'api-assets:node-children-tree' %}?assets=0'; var setting = { view: { @@ -102,17 +172,34 @@ function initTree2() { type: 'get' }, callback: { - onSelected: onNodeSelected2 + onSelected: onModalTreeNodeSelected } }; - zTree2 = $.fn.zTree.init($("#assetTree2"), setting); + $.get(url, function(data, status){ + $.fn.zTree.init($("#asset_modal_tree"), setting); + assetModalTree = $.fn.zTree.getZTreeObj("assetTree2"); + if (assetModalOption.onModalTreeDone) { + assetModalOption.onModalTreeDone(assetModalTree); + } + return assetModalTree; + }); +} + +function setAssetModalOptions(options) { + assetModalOption = options; } $(document).ready(function(){ + }).on('show.bs.modal', function () { - initTable2(); - initTree2(); + initAssetModalTable(); + initModalTree(); +}).on('click', '#btn_asset_modal_confirm', function () { + if (assetModalOption.onModalConfirm) { + assetModalOption.onModalConfirm(assetModalTable, assetModalTree); + } + $("#asset_list_modal").modal('hide'); }) </script> {% endblock %} diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index 58e0d86e5..fcd0f79ff 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -226,6 +226,33 @@ function onNodeSelected(event, treeNode) { asset_table.ajax.reload(); } +function onAssetModalConfirmAddAssetToNode(table) { + var assets_selected = table.selected; + if (!current_node_id) { + return + } + + var data = {'assets': assets_selected}; + var success = function () { + table.selected = []; + table.ajax.reload() + }; + + var url = ''; + if (update_node_action === "move") { + url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); + } else { + url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); + } + + requestApi({ + 'url': url, + 'method': 'PUT', + 'body': JSON.stringify(data), + 'success': success + }) +} + $(document).ready(function(){ initTable(); initTree(); @@ -236,6 +263,12 @@ $(document).ready(function(){ else{ $('#show_current_asset').css('display', 'inline-block'); } + + var modalOption = { + onModalConfirm: onAssetModalConfirmAddAssetToNode, + onModalTableDone: null + }; + setAssetModalOptions(modalOption); }) .on('click', '.labels li', function () { var val = $(this).text(); @@ -429,7 +462,6 @@ $(document).ready(function(){ } function doRemove() { - var nodes = zTree.getSelectedNodes(); if (!current_node_id) { return } @@ -472,32 +504,7 @@ $(document).ready(function(){ } $(".ipt_check_all").prop("checked", false) }) -.on('click', '#btn_asset_modal_confirm', function () { - var assets_selected = asset_table2.selected; - if (!current_node_id) { - return - } - - var data = {'assets': assets_selected}; - var success = function () { - asset_table2.selected = []; - asset_table2.ajax.reload() - }; - - var url = ''; - if (update_node_action === "move") { - url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); - } else { - url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); - } - - requestApi({ - 'url': url, - 'method': 'PUT', - 'body': JSON.stringify(data), - 'success': success - }) -}).on('hidden.bs.modal', '#asset_list_modal', function () { +.on('hidden.bs.modal', '#asset_list_modal', function () { window.location.reload(); }).on('click', '#menu_asset_add', function () { update_node_action = "add" diff --git a/apps/assets/templates/assets/domain_create_update.html b/apps/assets/templates/assets/domain_create_update.html index 399b38011..96bfd02aa 100644 --- a/apps/assets/templates/assets/domain_create_update.html +++ b/apps/assets/templates/assets/domain_create_update.html @@ -28,25 +28,6 @@ $(document).ready(function () { }).on('click', '.select2-selection__rendered', function (e) { e.preventDefault(); $("#asset_list_modal").modal(); - initSelectedAssets2Table(); -}) -.on('click', '#btn_asset_modal_confirm', function () { - var assets = asset_table2.selected; - var options = []; - $('#id_assets option').each(function (i, v) { - options.push(v.value) - }); - asset_table2.selected_rows.forEach(function (i) { - var name = i.hostname + '(' + i.ip + ')'; - var option = new Option(name, i.id, false, true); - - if (options.indexOf(i.id) === -1) { - $('#id_assets').append(option).trigger('change'); - } - }); - $('.select2').val(assets).trigger('change'); - $("#asset_list_modal").modal('hide'); - }) .on("submit", "form", function (evt) { evt.preventDefault(); diff --git a/apps/assets/templates/assets/label_create_update.html b/apps/assets/templates/assets/label_create_update.html index a6b9582a5..41646003c 100644 --- a/apps/assets/templates/assets/label_create_update.html +++ b/apps/assets/templates/assets/label_create_update.html @@ -32,24 +32,6 @@ $(document).ready(function () { }).on('click', '.select2-selection__rendered', function (e) { e.preventDefault(); $("#asset_list_modal").modal(); - initSelectedAssets2Table(); -}) -.on('click', '#btn_asset_modal_confirm', function () { - var assets = asset_table2.selected; - var options = []; - $('#id_assets option').each(function (i, v) { - options.push(v.value) - }); - asset_table2.selected_rows.forEach(function (i) { - var name = i.hostname + '(' + i.ip + ')'; - var option = new Option(name, i.id, false, true); - - if (options.indexOf(i.id) === -1) { - $('#id_assets').append(option).trigger('change'); - } - }); - $('#id_assets').val(assets).trigger('change'); - $("#asset_list_modal").modal('hide'); }) .on("submit", "form", function (evt) { evt.preventDefault(); diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py index 257691fa4..f08c08db8 100644 --- a/apps/assets/views/asset.py +++ b/apps/assets/views/asset.py @@ -86,7 +86,7 @@ class AssetCreateView(PermissionsMixin, FormMixin, TemplateView): node = get_object_or_none(Node, id=node_id) else: node = Node.org_root() - form["nodes"].initial = node + form.add_nodes_initial(node) return form def get_protocol_formset(self): diff --git a/apps/audits/templates/audits/ftp_log_list.html b/apps/audits/templates/audits/ftp_log_list.html index 91ea6c49d..a5e3fceec 100644 --- a/apps/audits/templates/audits/ftp_log_list.html +++ b/apps/audits/templates/audits/ftp_log_list.html @@ -11,6 +11,9 @@ #search_btn { margin-bottom: 0; } + .form-control { + height: 30px; + } </style> {% endblock %} diff --git a/apps/audits/templates/audits/login_log_list.html b/apps/audits/templates/audits/login_log_list.html index c855db1c1..6a3bae989 100644 --- a/apps/audits/templates/audits/login_log_list.html +++ b/apps/audits/templates/audits/login_log_list.html @@ -8,6 +8,12 @@ #search_btn { margin-bottom: 0; } + .form-control { + height: 30px; + } + .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single { + height: 30px !important; + } </style> {% endblock %} diff --git a/apps/audits/templates/audits/operate_log_list.html b/apps/audits/templates/audits/operate_log_list.html index 736c4f7ac..ae072187d 100644 --- a/apps/audits/templates/audits/operate_log_list.html +++ b/apps/audits/templates/audits/operate_log_list.html @@ -11,6 +11,12 @@ #search_btn { margin-bottom: 0; } + .form-control { + height: 30px; + } + .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single { + height: 30px !important; + } </style> {% endblock %} diff --git a/apps/audits/templates/audits/password_change_log_list.html b/apps/audits/templates/audits/password_change_log_list.html index a8a2f818d..1440dca2d 100644 --- a/apps/audits/templates/audits/password_change_log_list.html +++ b/apps/audits/templates/audits/password_change_log_list.html @@ -11,6 +11,12 @@ #search_btn { margin-bottom: 0; } + .form-control { + height: 30px; + } + .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single { + height: 30px !important; + } </style> {% endblock %} diff --git a/apps/common/mixins/api.py b/apps/common/mixins/api.py index ae92e3e97..21f0394ce 100644 --- a/apps/common/mixins/api.py +++ b/apps/common/mixins/api.py @@ -44,8 +44,10 @@ class IDInCacheFilterMixin(object): return queryset cache_key = KEY_CACHE_RESOURCES_ID.format(spm) resources_id = cache.get(cache_key) - if resources_id and isinstance(resources_id, list): - queryset = queryset.filter(id__in=resources_id) + if not resources_id or not isinstance(resources_id, list): + queryset = queryset.none() + return queryset + queryset = queryset.filter(id__in=resources_id) return queryset diff --git a/apps/common/signals_handlers.py b/apps/common/signals_handlers.py index 91901676d..e7dd728c3 100644 --- a/apps/common/signals_handlers.py +++ b/apps/common/signals_handlers.py @@ -14,7 +14,7 @@ from .local import thread_local pattern = re.compile(r'FROM `(\w+)`') logger = get_logger(__name__) -DEBUG_DB_QUERY = os.environ.get('DEBUG_DB_QUERY', '0') == '1' +DEBUG_DB = os.environ.get('DEBUG_DB', '0') == '1' class Counter: @@ -58,7 +58,7 @@ def on_request_finished_release_local(sender, **kwargs): thread_local.__release_local__() -if settings.DEBUG and DEBUG_DB_QUERY: +if settings.DEBUG and DEBUG_DB: request_finished.connect(on_request_finished_logging_db_query) diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 27df6314f..f211eef82 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -609,6 +609,7 @@ SWAGGER_SETTINGS = { }, } + # Default email suffix EMAIL_SUFFIX = CONFIG.EMAIL_SUFFIX LOGIN_LOG_KEEP_DAYS = CONFIG.LOGIN_LOG_KEEP_DAYS diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 3ec0085d8..7e3bfc87f 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 8a804450c..7962b471b 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-08-28 18:19+0800\n" +"POT-Creation-Date: 2019-09-12 18:01+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler <ibuler@qq.com>\n" "Language-Team: Jumpserver team<ibuler@qq.com>\n" @@ -84,9 +84,9 @@ msgstr "运行参数" #: assets/templates/assets/domain_list.html:26 #: assets/templates/assets/label_list.html:16 #: assets/templates/assets/system_user_list.html:55 audits/models.py:19 -#: audits/templates/audits/ftp_log_list.html:41 -#: audits/templates/audits/ftp_log_list.html:71 -#: perms/forms/asset_permission.py:69 perms/models/asset_permission.py:78 +#: audits/templates/audits/ftp_log_list.html:44 +#: audits/templates/audits/ftp_log_list.html:74 +#: perms/forms/asset_permission.py:79 perms/models/asset_permission.py:78 #: perms/templates/perms/asset_permission_create_update.html:45 #: perms/templates/perms/asset_permission_list.html:52 #: perms/templates/perms/asset_permission_list.html:121 @@ -95,8 +95,8 @@ msgstr "运行参数" #: terminal/templates/terminal/command_list.html:66 #: terminal/templates/terminal/session_list.html:28 #: terminal/templates/terminal/session_list.html:72 -#: xpack/plugins/change_auth_plan/forms.py:64 -#: xpack/plugins/change_auth_plan/models.py:416 +#: xpack/plugins/change_auth_plan/forms.py:121 +#: xpack/plugins/change_auth_plan/models.py:413 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13 @@ -112,11 +112,10 @@ 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:168 assets/templates/assets/user_asset_list.html:53 -#: 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:75 perms/models/asset_permission.py:80 -#: perms/models/asset_permission.py:115 +#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:52 +#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52 +#: audits/templates/audits/ftp_log_list.html:75 +#: perms/forms/asset_permission.py:85 perms/models/asset_permission.py:80 #: perms/templates/perms/asset_permission_detail.html:140 #: perms/templates/perms/asset_permission_list.html:54 #: perms/templates/perms/asset_permission_list.html:75 @@ -160,7 +159,7 @@ msgstr "系统用户" #: perms/templates/perms/remote_app_permission_remote_app.html:53 #: perms/templates/perms/remote_app_permission_user.html:53 #: settings/models.py:29 -#: settings/templates/settings/_ldap_list_users_modal.html:38 +#: settings/templates/settings/_ldap_list_users_modal.html:31 #: settings/templates/settings/command_storage_create.html:41 #: settings/templates/settings/replay_storage_create.html:44 #: settings/templates/settings/terminal_setting.html:83 @@ -174,8 +173,8 @@ msgstr "系统用户" #: users/templates/users/user_list.html:35 #: users/templates/users/user_profile.html:51 #: users/templates/users/user_pubkey_update.html:57 -#: xpack/plugins/change_auth_plan/forms.py:47 -#: xpack/plugins/change_auth_plan/models.py:64 +#: xpack/plugins/change_auth_plan/forms.py:104 +#: xpack/plugins/change_auth_plan/models.py:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12 #: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:144 @@ -215,12 +214,12 @@ msgstr "参数" #: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/system_user_detail.html:100 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:14 -#: perms/models/asset_permission.py:118 perms/models/base.py:54 +#: perms/models/base.py:54 #: perms/templates/perms/asset_permission_detail.html:98 #: perms/templates/perms/remote_app_permission_detail.html:90 #: users/models/user.py:371 users/serializers/v1.py:119 #: users/templates/users/user_detail.html:111 -#: xpack/plugins/change_auth_plan/models.py:109 +#: xpack/plugins/change_auth_plan/models.py:106 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113 #: xpack/plugins/cloud/models.py:80 xpack/plugins/cloud/models.py:179 msgid "Created by" @@ -238,8 +237,7 @@ msgstr "创建者" #: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/system_user_detail.html:96 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64 -#: orgs/models.py:15 perms/models/asset_permission.py:119 -#: perms/models/base.py:55 +#: orgs/models.py:15 perms/models/base.py:55 #: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/remote_app_permission_detail.html:86 #: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17 @@ -273,8 +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 ops/models/adhoc.py:43 -#: orgs/models.py:16 perms/models/asset_permission.py:120 -#: perms/models/base.py:56 +#: orgs/models.py:16 perms/models/base.py:56 #: perms/templates/perms/asset_permission_detail.html:102 #: perms/templates/perms/remote_app_permission_detail.html:94 #: settings/models.py:34 terminal/models.py:32 @@ -283,7 +280,7 @@ msgstr "创建日期" #: users/templates/users/user_group_detail.html:67 #: users/templates/users/user_group_list.html:37 #: users/templates/users/user_profile.html:138 -#: xpack/plugins/change_auth_plan/models.py:105 +#: xpack/plugins/change_auth_plan/models.py:102 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 #: xpack/plugins/cloud/models.py:77 xpack/plugins/cloud/models.py:173 @@ -355,7 +352,7 @@ msgstr "重置" #: assets/templates/assets/domain_create_update.html:17 #: assets/templates/assets/gateway_create_update.html:59 #: assets/templates/assets/label_create_update.html:19 -#: audits/templates/audits/login_log_list.html:89 +#: audits/templates/audits/login_log_list.html:95 #: perms/templates/perms/asset_permission_create_update.html:84 #: perms/templates/perms/remote_app_permission_create_update.html:84 #: settings/templates/settings/basic_setting.html:65 @@ -404,7 +401,7 @@ msgstr "提交" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:20 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:17 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:106 -#: xpack/plugins/change_auth_plan/views.py:91 +#: xpack/plugins/change_auth_plan/views.py:88 msgid "Detail" msgstr "详情" @@ -526,8 +523,8 @@ msgstr "创建远程应用" #: assets/templates/assets/domain_list.html:29 #: assets/templates/assets/label_list.html:17 #: assets/templates/assets/system_user_list.html:60 audits/models.py:38 -#: audits/templates/audits/operate_log_list.html:41 -#: audits/templates/audits/operate_log_list.html:67 +#: audits/templates/audits/operate_log_list.html:47 +#: audits/templates/audits/operate_log_list.html:73 #: authentication/templates/authentication/_access_key_modal.html:30 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64 #: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34 @@ -619,25 +616,25 @@ msgstr "未知" msgid "Port" msgstr "端口" -#: assets/forms/asset.py:50 assets/models/asset.py:145 +#: assets/forms/asset.py:55 assets/models/asset.py:145 #: assets/models/user.py:110 assets/templates/assets/asset_detail.html:190 #: assets/templates/assets/asset_detail.html:198 #: assets/templates/assets/system_user_assets.html:83 #: perms/models/asset_permission.py:79 -#: xpack/plugins/change_auth_plan/models.py:75 +#: xpack/plugins/change_auth_plan/models.py:72 msgid "Nodes" msgstr "节点" -#: assets/forms/asset.py:53 assets/forms/asset.py:99 assets/models/asset.py:149 -#: assets/models/cluster.py:19 assets/models/user.py:68 -#: assets/templates/assets/asset_detail.html:76 templates/_nav.html:24 -#: xpack/plugins/cloud/models.py:161 +#: assets/forms/asset.py:58 assets/forms/asset.py:104 +#: assets/models/asset.py:149 assets/models/cluster.py:19 +#: assets/models/user.py:68 assets/templates/assets/asset_detail.html:76 +#: templates/_nav.html:24 xpack/plugins/cloud/models.py:161 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:68 #: xpack/plugins/orgs/templates/orgs/org_list.html:18 msgid "Admin user" msgstr "管理用户" -#: assets/forms/asset.py:56 assets/forms/asset.py:102 assets/forms/asset.py:141 +#: assets/forms/asset.py:61 assets/forms/asset.py:107 assets/forms/asset.py:146 #: assets/templates/assets/asset_create.html:48 #: assets/templates/assets/asset_create.html:50 #: assets/templates/assets/asset_list.html:85 @@ -645,23 +642,22 @@ msgstr "管理用户" msgid "Label" msgstr "标签" -#: assets/forms/asset.py:59 assets/forms/asset.py:105 +#: assets/forms/asset.py:64 assets/forms/asset.py:110 #: assets/models/asset.py:144 assets/models/domain.py:26 #: assets/models/domain.py:52 assets/templates/assets/asset_detail.html:80 -#: assets/templates/assets/user_asset_list.html:54 +#: assets/templates/assets/user_asset_list.html:53 #: xpack/plugins/orgs/templates/orgs/org_list.html:17 msgid "Domain" msgstr "网域" -#: assets/forms/asset.py:63 assets/forms/asset.py:96 assets/forms/asset.py:109 -#: assets/forms/asset.py:144 assets/models/node.py:369 +#: assets/forms/asset.py:68 assets/forms/asset.py:101 assets/forms/asset.py:114 +#: assets/forms/asset.py:149 assets/models/node.py:393 #: assets/templates/assets/asset_create.html:42 -#: perms/forms/asset_permission.py:72 perms/forms/asset_permission.py:79 -#: perms/models/asset_permission.py:113 +#: perms/forms/asset_permission.py:82 perms/forms/asset_permission.py:89 #: perms/templates/perms/asset_permission_list.html:53 #: perms/templates/perms/asset_permission_list.html:74 #: perms/templates/perms/asset_permission_list.html:124 -#: xpack/plugins/change_auth_plan/forms.py:65 +#: xpack/plugins/change_auth_plan/forms.py:122 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15 #: xpack/plugins/cloud/models.py:157 @@ -670,7 +666,7 @@ msgstr "网域" msgid "Node" msgstr "节点" -#: assets/forms/asset.py:67 assets/forms/asset.py:113 +#: assets/forms/asset.py:72 assets/forms/asset.py:118 msgid "" "root or other NOPASSWD sudo privilege user existed in asset,If asset is " "windows or other set any one, more see admin user left menu" @@ -678,20 +674,20 @@ msgstr "" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "个, 更多信息查看左侧 `管理用户` 菜单" -#: assets/forms/asset.py:70 assets/forms/asset.py:116 +#: assets/forms/asset.py:75 assets/forms/asset.py:121 msgid "Windows 2016 RDP protocol is different, If is window 2016, set it" msgstr "Windows 2016的RDP协议与之前不同,如果是请设置" -#: assets/forms/asset.py:71 assets/forms/asset.py:117 +#: assets/forms/asset.py:76 assets/forms/asset.py:122 msgid "" "If your have some network not connect with each other, you can set domain" msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录" -#: assets/forms/asset.py:124 assets/forms/asset.py:128 +#: assets/forms/asset.py:129 assets/forms/asset.py:133 #: assets/forms/domain.py:17 assets/forms/label.py:15 #: perms/templates/perms/asset_permission_asset.html:78 -#: xpack/plugins/change_auth_plan/forms.py:55 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:74 +#: xpack/plugins/change_auth_plan/forms.py:112 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:84 msgid "Select assets" msgstr "选择资产" @@ -717,20 +713,20 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: assets/templates/assets/domain_gateway_list.html:71 #: assets/templates/assets/system_user_detail.html:62 #: assets/templates/assets/system_user_list.html:52 audits/models.py:80 -#: audits/templates/audits/login_log_list.html:51 authentication/forms.py:13 +#: audits/templates/audits/login_log_list.html:57 authentication/forms.py:13 #: authentication/templates/authentication/login.html:65 #: authentication/templates/authentication/new_login.html:92 #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:70 #: perms/templates/perms/asset_permission_user.html:55 #: perms/templates/perms/remote_app_permission_user.html:54 -#: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:14 +#: settings/templates/settings/_ldap_list_users_modal.html:30 users/forms.py:14 #: users/models/user.py:328 users/templates/users/_select_user_modal.html:14 #: users/templates/users/user_detail.html:67 #: users/templates/users/user_list.html:36 #: users/templates/users/user_profile.html:47 -#: xpack/plugins/change_auth_plan/forms.py:49 -#: xpack/plugins/change_auth_plan/models.py:66 -#: xpack/plugins/change_auth_plan/models.py:412 +#: xpack/plugins/change_auth_plan/forms.py:106 +#: xpack/plugins/change_auth_plan/models.py:63 +#: xpack/plugins/change_auth_plan/models.py:409 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:65 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12 @@ -756,8 +752,8 @@ msgstr "密码或密钥密码" #: users/templates/users/user_profile_update.html:41 #: users/templates/users/user_pubkey_update.html:41 #: users/templates/users/user_update.html:20 -#: xpack/plugins/change_auth_plan/models.py:96 -#: xpack/plugins/change_auth_plan/models.py:267 +#: xpack/plugins/change_auth_plan/models.py:93 +#: xpack/plugins/change_auth_plan/models.py:264 msgid "Password" msgstr "密码" @@ -805,31 +801,31 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" #: assets/models/asset.py:135 assets/models/domain.py:49 #: assets/serializers/asset_user.py:28 -#: assets/templates/assets/_asset_list_modal.html:46 +#: assets/templates/assets/_asset_list_modal.html:47 #: assets/templates/assets/_asset_user_list.html:15 #: assets/templates/assets/asset_detail.html:64 #: assets/templates/assets/asset_list.html:97 #: assets/templates/assets/domain_gateway_list.html:68 -#: assets/templates/assets/user_asset_list.html:50 -#: audits/templates/audits/login_log_list.html:54 +#: assets/templates/assets/user_asset_list.html:49 +#: audits/templates/audits/login_log_list.html:60 #: perms/templates/perms/asset_permission_asset.html:58 settings/forms.py:140 #: users/templates/users/_granted_assets.html:26 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:54 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:51 msgid "IP" msgstr "IP" #: assets/models/asset.py:136 assets/serializers/asset_user.py:27 -#: assets/templates/assets/_asset_list_modal.html:45 +#: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_user_auth_update_modal.html:9 #: assets/templates/assets/_asset_user_auth_view_modal.html:15 #: assets/templates/assets/_asset_user_list.html:14 #: assets/templates/assets/asset_detail.html:60 #: assets/templates/assets/asset_list.html:96 -#: assets/templates/assets/user_asset_list.html:49 +#: assets/templates/assets/user_asset_list.html:48 #: perms/templates/perms/asset_permission_asset.html:57 #: perms/templates/perms/asset_permission_list.html:73 settings/forms.py:139 #: users/templates/users/_granted_assets.html:25 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:53 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50 msgid "Hostname" msgstr "主机名" @@ -844,13 +840,13 @@ msgstr "协议" #: assets/models/asset.py:142 assets/serializers/asset.py:63 #: assets/templates/assets/asset_create.html:24 -#: assets/templates/assets/user_asset_list.html:51 +#: assets/templates/assets/user_asset_list.html:50 #: perms/serializers/user_permission.py:38 msgid "Protocols" msgstr "协议组" #: assets/models/asset.py:143 assets/templates/assets/asset_detail.html:104 -#: assets/templates/assets/user_asset_list.html:52 +#: assets/templates/assets/user_asset_list.html:51 msgid "Platform" msgstr "系统平台" @@ -946,13 +942,13 @@ msgstr "版本" msgid "AuthBook" msgstr "" -#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:100 -#: xpack/plugins/change_auth_plan/models.py:274 +#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:97 +#: xpack/plugins/change_auth_plan/models.py:271 msgid "SSH private key" msgstr "ssh密钥" -#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:103 -#: xpack/plugins/change_auth_plan/models.py:270 +#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:100 +#: xpack/plugins/change_auth_plan/models.py:267 msgid "SSH public key" msgstr "ssh公钥" @@ -1024,7 +1020,7 @@ msgid "Regex" msgstr "正则表达式" #: assets/models/cmd_filter.py:39 ops/models/command.py:21 -#: ops/templates/ops/command_execution_list.html:61 terminal/models.py:161 +#: ops/templates/ops/command_execution_list.html:64 terminal/models.py:161 #: terminal/templates/terminal/command_list.html:28 #: terminal/templates/terminal/command_list.html:68 #: terminal/templates/terminal/session_detail.html:48 @@ -1046,7 +1042,7 @@ msgstr "过滤器" #: assets/models/cmd_filter.py:50 #: assets/templates/assets/cmd_filter_rule_list.html:58 -#: audits/templates/audits/login_log_list.html:52 +#: audits/templates/audits/login_log_list.html:58 #: perms/templates/perms/remote_app_permission_remote_app.html:54 #: settings/templates/settings/command_storage_create.html:31 #: settings/templates/settings/replay_storage_create.html:31 @@ -1094,15 +1090,15 @@ msgid "Default asset group" msgstr "默认资产组" #: assets/models/label.py:15 audits/models.py:17 audits/models.py:37 -#: audits/models.py:50 audits/templates/audits/ftp_log_list.html:33 -#: audits/templates/audits/ftp_log_list.html:70 -#: audits/templates/audits/operate_log_list.html:33 -#: audits/templates/audits/operate_log_list.html:66 -#: audits/templates/audits/password_change_log_list.html:33 -#: audits/templates/audits/password_change_log_list.html:50 -#: ops/templates/ops/command_execution_list.html:35 -#: ops/templates/ops/command_execution_list.html:60 -#: perms/forms/asset_permission.py:63 perms/forms/remote_app_permission.py:31 +#: audits/models.py:50 audits/templates/audits/ftp_log_list.html:36 +#: audits/templates/audits/ftp_log_list.html:73 +#: audits/templates/audits/operate_log_list.html:39 +#: audits/templates/audits/operate_log_list.html:72 +#: audits/templates/audits/password_change_log_list.html:39 +#: audits/templates/audits/password_change_log_list.html:56 +#: ops/templates/ops/command_execution_list.html:38 +#: ops/templates/ops/command_execution_list.html:63 +#: perms/forms/asset_permission.py:73 perms/forms/remote_app_permission.py:31 #: perms/models/base.py:49 #: perms/templates/perms/asset_permission_create_update.html:41 #: perms/templates/perms/asset_permission_list.html:50 @@ -1123,7 +1119,7 @@ msgstr "默认资产组" msgid "User" msgstr "用户" -#: assets/models/label.py:19 assets/models/node.py:360 +#: assets/models/label.py:19 assets/models/node.py:384 #: assets/templates/assets/label_list.html:15 settings/models.py:30 msgid "Value" msgstr "值" @@ -1132,19 +1128,19 @@ msgstr "值" msgid "Category" msgstr "分类" -#: assets/models/node.py:198 +#: assets/models/node.py:222 msgid "New node" msgstr "新节点" -#: assets/models/node.py:284 perms/api/mixin.py:146 +#: assets/models/node.py:308 perms/api/mixin.py:146 msgid "ungrouped" msgstr "未分组" -#: assets/models/node.py:286 perms/api/mixin.py:151 +#: assets/models/node.py:310 perms/api/mixin.py:151 msgid "empty" msgstr "空" -#: assets/models/node.py:359 +#: assets/models/node.py:383 msgid "Key" msgstr "键" @@ -1175,7 +1171,7 @@ msgstr "手动登录" #: assets/views/label.py:27 assets/views/label.py:45 assets/views/label.py:73 #: assets/views/system_user.py:29 assets/views/system_user.py:46 #: assets/views/system_user.py:63 assets/views/system_user.py:79 -#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:71 +#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:68 msgid "Assets" msgstr "资产管理" @@ -1322,30 +1318,30 @@ msgstr "测试系统用户可连接性: {} => {}" msgid "Test system user connectivity period: {}" msgstr "定期测试系统用户可连接性: {}" -#: assets/tasks.py:478 assets/tasks.py:564 -#: xpack/plugins/change_auth_plan/models.py:525 +#: assets/tasks.py:487 assets/tasks.py:573 +#: xpack/plugins/change_auth_plan/models.py:522 msgid "The asset {} system platform {} does not support run Ansible tasks" msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务" -#: assets/tasks.py:490 +#: assets/tasks.py:499 msgid "" "Push system user task skip, auto push not enable or protocol is not ssh or " "rdp: {}" msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh或rdp: {}" -#: assets/tasks.py:497 +#: assets/tasks.py:506 msgid "For security, do not push user {}" msgstr "为了安全,禁止推送用户 {}" -#: assets/tasks.py:525 assets/tasks.py:539 +#: assets/tasks.py:534 assets/tasks.py:548 msgid "Push system users to assets: {}" msgstr "推送系统用户到入资产: {}" -#: assets/tasks.py:531 +#: assets/tasks.py:540 msgid "Push system users to asset: {} => {}" msgstr "推送系统用户到入资产: {} => {}" -#: assets/tasks.py:611 +#: assets/tasks.py:620 msgid "Test asset user connectivity: {}" msgstr "测试资产用户可连接性: {}" @@ -1389,10 +1385,18 @@ msgid "Import assets" msgstr "导入资产" #: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:38 -#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:118 +#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:115 msgid "Asset list" msgstr "资产列表" +#: assets/templates/assets/_asset_list_modal.html:33 +#: assets/templates/assets/_node_tree.html:40 +#: users/templates/users/_granted_assets.html:7 +#: users/templates/users/_granted_assets.html:83 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66 +msgid "Loading" +msgstr "加载中" + #: assets/templates/assets/_asset_update_modal.html:4 msgid "Update assets" msgstr "更新资产" @@ -1402,7 +1406,7 @@ msgid "Update asset user auth" msgstr "更新资产用户认证信息" #: assets/templates/assets/_asset_user_auth_update_modal.html:23 -#: xpack/plugins/change_auth_plan/forms.py:51 +#: xpack/plugins/change_auth_plan/forms.py:108 msgid "Please input password" msgstr "请输入密码" @@ -1430,14 +1434,14 @@ msgstr "获取认证信息错误" #: assets/templates/assets/_user_asset_detail_modal.html:23 #: authentication/templates/authentication/_access_key_modal.html:143 #: authentication/templates/authentication/_mfa_confirm_modal.html:53 -#: settings/templates/settings/_ldap_list_users_modal.html:99 +#: settings/templates/settings/_ldap_list_users_modal.html:92 #: templates/_modal.html:22 msgid "Close" msgstr "关闭" #: assets/templates/assets/_asset_user_list.html:19 -#: audits/templates/audits/operate_log_list.html:71 -#: audits/templates/audits/password_change_log_list.html:53 +#: audits/templates/audits/operate_log_list.html:77 +#: audits/templates/audits/password_change_log_list.html:59 #: ops/templates/ops/task_adhoc.html:63 #: terminal/templates/terminal/command_list.html:33 #: terminal/templates/terminal/session_detail.html:50 @@ -1480,12 +1484,6 @@ msgstr "SSH端口" msgid "If use nat, set the ssh real port" msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口" -#: assets/templates/assets/_node_tree.html:40 -#: users/templates/users/_granted_assets.html:7 -#: users/templates/users/_granted_assets.html:83 -msgid "Loading" -msgstr "加载中..." - #: assets/templates/assets/_node_tree.html:50 msgid "Add node" msgstr "新建节点" @@ -1498,19 +1496,19 @@ msgstr "重命名节点" msgid "Delete node" msgstr "删除节点" -#: assets/templates/assets/_node_tree.html:161 +#: assets/templates/assets/_node_tree.html:166 msgid "Create node failed" msgstr "创建节点失败" -#: assets/templates/assets/_node_tree.html:173 +#: assets/templates/assets/_node_tree.html:178 msgid "Have child node, cancel" msgstr "存在子节点,不能删除" -#: assets/templates/assets/_node_tree.html:175 +#: assets/templates/assets/_node_tree.html:180 msgid "Have assets, cancel" msgstr "存在资产,不能删除" -#: assets/templates/assets/_node_tree.html:250 +#: assets/templates/assets/_node_tree.html:255 msgid "Rename success" msgstr "重命名成功" @@ -1592,14 +1590,14 @@ msgstr "替换资产的管理员" #: assets/templates/assets/admin_user_detail.html:91 #: perms/templates/perms/asset_permission_asset.html:103 -#: xpack/plugins/change_auth_plan/forms.py:59 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:99 +#: xpack/plugins/change_auth_plan/forms.py:116 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:109 msgid "Select nodes" msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:204 -#: assets/templates/assets/asset_list.html:385 +#: assets/templates/assets/asset_list.html:418 #: assets/templates/assets/cmd_filter_detail.html:106 #: assets/templates/assets/system_user_assets.html:97 #: assets/templates/assets/system_user_detail.html:182 @@ -1637,7 +1635,7 @@ msgstr "Jumpserver 使用该用户来 `推送系统用户`、`获取资产硬件 #: assets/templates/assets/admin_user_list.html:16 #: assets/templates/assets/asset_list.html:68 #: assets/templates/assets/system_user_list.html:23 -#: audits/templates/audits/login_log_list.html:85 +#: audits/templates/audits/login_log_list.html:91 #: users/templates/users/user_group_list.html:10 #: users/templates/users/user_list.html:10 #: xpack/plugins/vault/templates/vault/vault.html:55 @@ -1647,7 +1645,7 @@ msgstr "导出" #: assets/templates/assets/admin_user_list.html:21 #: assets/templates/assets/asset_list.html:73 #: assets/templates/assets/system_user_list.html:28 -#: settings/templates/settings/_ldap_list_users_modal.html:100 +#: settings/templates/settings/_ldap_list_users_modal.html:93 #: users/templates/users/user_group_list.html:15 #: users/templates/users/user_list.html:15 #: xpack/plugins/license/templates/license/license_detail.html:110 @@ -1662,8 +1660,8 @@ msgstr "创建管理用户" #: assets/templates/assets/admin_user_list.html:162 #: assets/templates/assets/admin_user_list.html:193 -#: assets/templates/assets/asset_list.html:266 -#: assets/templates/assets/asset_list.html:303 +#: assets/templates/assets/asset_list.html:299 +#: assets/templates/assets/asset_list.html:336 #: assets/templates/assets/system_user_list.html:192 #: assets/templates/assets/system_user_list.html:223 #: users/templates/users/user_group_list.html:164 @@ -1720,7 +1718,7 @@ msgstr "创建日期" #: assets/templates/assets/asset_detail.html:150 authentication/models.py:15 #: authentication/templates/authentication/_access_key_modal.html:28 -#: perms/models/asset_permission.py:116 perms/models/base.py:51 +#: perms/models/base.py:51 #: perms/templates/perms/asset_permission_create_update.html:55 #: perms/templates/perms/asset_permission_detail.html:120 #: perms/templates/perms/remote_app_permission_create_update.html:54 @@ -1805,7 +1803,7 @@ msgstr "仅显示当前节点资产" msgid "Displays all child node assets" msgstr "显示所有子节点资产" -#: assets/templates/assets/asset_list.html:379 +#: assets/templates/assets/asset_list.html:412 #: assets/templates/assets/system_user_list.html:133 #: users/templates/users/user_detail.html:386 #: users/templates/users/user_detail.html:412 @@ -1816,11 +1814,11 @@ msgstr "显示所有子节点资产" msgid "Are you sure?" msgstr "你确认吗?" -#: assets/templates/assets/asset_list.html:380 +#: assets/templates/assets/asset_list.html:413 msgid "This will delete the selected assets !!!" msgstr "删除选择资产" -#: assets/templates/assets/asset_list.html:383 +#: assets/templates/assets/asset_list.html:416 #: assets/templates/assets/system_user_list.html:137 #: settings/templates/settings/terminal_setting.html:166 #: users/templates/users/user_detail.html:390 @@ -1834,16 +1832,16 @@ msgstr "删除选择资产" msgid "Cancel" msgstr "取消" -#: assets/templates/assets/asset_list.html:396 +#: assets/templates/assets/asset_list.html:429 msgid "Asset Deleted." msgstr "已被删除" -#: assets/templates/assets/asset_list.html:397 -#: assets/templates/assets/asset_list.html:401 +#: assets/templates/assets/asset_list.html:430 +#: assets/templates/assets/asset_list.html:434 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:400 +#: assets/templates/assets/asset_list.html:433 msgid "Asset Deleting failed." msgstr "删除失败" @@ -2133,27 +2131,27 @@ msgid "System user asset" msgstr "系统用户资产" #: audits/models.py:18 audits/models.py:41 audits/models.py:52 -#: audits/templates/audits/ftp_log_list.html:73 -#: audits/templates/audits/operate_log_list.html:70 -#: audits/templates/audits/password_change_log_list.html:52 +#: audits/templates/audits/ftp_log_list.html:76 +#: audits/templates/audits/operate_log_list.html:76 +#: audits/templates/audits/password_change_log_list.html:58 #: terminal/models.py:158 terminal/templates/terminal/session_list.html:30 #: terminal/templates/terminal/session_list.html:74 #: terminal/templates/terminal/terminal_detail.html:47 msgid "Remote addr" msgstr "远端地址" -#: audits/models.py:21 audits/templates/audits/ftp_log_list.html:74 +#: audits/models.py:21 audits/templates/audits/ftp_log_list.html:77 msgid "Operate" msgstr "操作" -#: audits/models.py:22 audits/templates/audits/ftp_log_list.html:56 -#: audits/templates/audits/ftp_log_list.html:75 +#: audits/models.py:22 audits/templates/audits/ftp_log_list.html:59 +#: audits/templates/audits/ftp_log_list.html:78 msgid "Filename" msgstr "文件名" #: audits/models.py:23 audits/models.py:76 -#: audits/templates/audits/ftp_log_list.html:76 -#: ops/templates/ops/command_execution_list.html:65 +#: audits/templates/audits/ftp_log_list.html:79 +#: ops/templates/ops/command_execution_list.html:68 #: ops/templates/ops/task_list.html:31 #: users/templates/users/user_detail.html:462 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:14 @@ -2167,16 +2165,16 @@ msgstr "成功" msgid "Create" msgstr "创建" -#: audits/models.py:39 audits/templates/audits/operate_log_list.html:49 -#: audits/templates/audits/operate_log_list.html:68 +#: audits/models.py:39 audits/templates/audits/operate_log_list.html:55 +#: audits/templates/audits/operate_log_list.html:74 msgid "Resource Type" msgstr "资源类型" -#: audits/models.py:40 audits/templates/audits/operate_log_list.html:69 +#: audits/models.py:40 audits/templates/audits/operate_log_list.html:75 msgid "Resource" msgstr "资源" -#: audits/models.py:51 audits/templates/audits/password_change_log_list.html:51 +#: audits/models.py:51 audits/templates/audits/password_change_log_list.html:57 msgid "Change by" msgstr "修改者" @@ -2214,22 +2212,22 @@ msgstr "登录城市" msgid "User agent" msgstr "Agent" -#: audits/models.py:85 audits/templates/audits/login_log_list.html:56 +#: audits/models.py:85 audits/templates/audits/login_log_list.html:62 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: users/forms.py:175 users/models/user.py:352 #: users/templates/users/first_login.html:45 msgid "MFA" msgstr "MFA" -#: audits/models.py:86 audits/templates/audits/login_log_list.html:57 -#: xpack/plugins/change_auth_plan/models.py:420 +#: audits/models.py:86 audits/templates/audits/login_log_list.html:63 +#: xpack/plugins/change_auth_plan/models.py:417 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 #: xpack/plugins/cloud/models.py:281 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:69 msgid "Reason" msgstr "原因" -#: audits/models.py:87 audits/templates/audits/login_log_list.html:58 +#: audits/models.py:87 audits/templates/audits/login_log_list.html:64 #: xpack/plugins/cloud/models.py:278 xpack/plugins/cloud/models.py:313 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:70 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:65 @@ -2240,33 +2238,33 @@ msgstr "状态" msgid "Date login" msgstr "登录日期" -#: audits/templates/audits/ftp_log_list.html:77 +#: audits/templates/audits/ftp_log_list.html:80 #: ops/templates/ops/adhoc_history.html:52 #: ops/templates/ops/adhoc_history_detail.html:61 -#: ops/templates/ops/command_execution_list.html:66 +#: ops/templates/ops/command_execution_list.html:69 #: ops/templates/ops/task_history.html:58 perms/models/base.py:52 #: perms/templates/perms/asset_permission_detail.html:86 #: perms/templates/perms/remote_app_permission_detail.html:78 #: terminal/models.py:165 terminal/templates/terminal/session_list.html:34 -#: xpack/plugins/change_auth_plan/models.py:253 -#: xpack/plugins/change_auth_plan/models.py:423 +#: xpack/plugins/change_auth_plan/models.py:250 +#: xpack/plugins/change_auth_plan/models.py:420 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17 msgid "Date start" msgstr "开始日期" -#: audits/templates/audits/login_log_list.html:28 +#: audits/templates/audits/login_log_list.html:34 #: perms/templates/perms/asset_permission_user.html:88 #: perms/templates/perms/remote_app_permission_user.html:87 msgid "Select user" msgstr "选择用户" -#: audits/templates/audits/login_log_list.html:35 -#: audits/templates/audits/login_log_list.html:40 -#: audits/templates/audits/operate_log_list.html:58 -#: audits/templates/audits/password_change_log_list.html:42 -#: ops/templates/ops/command_execution_list.html:43 -#: ops/templates/ops/command_execution_list.html:48 +#: audits/templates/audits/login_log_list.html:41 +#: audits/templates/audits/login_log_list.html:46 +#: audits/templates/audits/operate_log_list.html:64 +#: audits/templates/audits/password_change_log_list.html:48 +#: ops/templates/ops/command_execution_list.html:46 +#: ops/templates/ops/command_execution_list.html:51 #: ops/templates/ops/task_list.html:13 ops/templates/ops/task_list.html:18 #: templates/_base_list.html:41 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:52 @@ -2274,7 +2272,7 @@ msgstr "选择用户" msgid "Search" msgstr "搜索" -#: audits/templates/audits/login_log_list.html:50 +#: audits/templates/audits/login_log_list.html:56 #: authentication/templates/authentication/_access_key_modal.html:26 #: ops/templates/ops/adhoc_detail.html:49 #: ops/templates/ops/adhoc_history_detail.html:49 @@ -2285,15 +2283,15 @@ msgstr "搜索" msgid "ID" msgstr "ID" -#: audits/templates/audits/login_log_list.html:53 +#: audits/templates/audits/login_log_list.html:59 msgid "UA" msgstr "Agent" -#: audits/templates/audits/login_log_list.html:55 +#: audits/templates/audits/login_log_list.html:61 msgid "City" msgstr "城市" -#: audits/templates/audits/login_log_list.html:59 +#: audits/templates/audits/login_log_list.html:65 #: authentication/templates/authentication/_access_key_modal.html:29 #: ops/templates/ops/task_list.html:32 msgid "Date" @@ -2672,16 +2670,16 @@ msgstr "" msgid "Encrypt field using Secret Key" msgstr "" -#: common/mixins/api.py:62 +#: common/mixins/api.py:63 #, python-format msgid "%(name)s was %(action)s successfully" msgstr "%(name)s %(action)s成功" -#: common/mixins/api.py:63 +#: common/mixins/api.py:64 msgid "create" msgstr "创建" -#: common/mixins/api.py:63 +#: common/mixins/api.py:64 msgid "update" msgstr "更新" @@ -2757,7 +2755,7 @@ msgid "Options" msgstr "选项" #: ops/models/adhoc.py:161 ops/templates/ops/adhoc_detail.html:53 -#: ops/templates/ops/command_execution_list.html:59 +#: ops/templates/ops/command_execution_list.html:62 #: ops/templates/ops/task_adhoc.html:59 ops/templates/ops/task_list.html:30 #: settings/templates/settings/command_storage_create.html:49 msgid "Hosts" @@ -2802,8 +2800,8 @@ msgstr "完成时间" #: ops/models/adhoc.py:327 ops/templates/ops/adhoc_history.html:57 #: ops/templates/ops/task_history.html:63 ops/templates/ops/task_list.html:33 -#: xpack/plugins/change_auth_plan/models.py:256 -#: xpack/plugins/change_auth_plan/models.py:426 +#: xpack/plugins/change_auth_plan/models.py:253 +#: xpack/plugins/change_auth_plan/models.py:423 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16 msgid "Time" @@ -2859,7 +2857,7 @@ msgstr "执行历史" #: ops/templates/ops/adhoc_detail.html:72 #: ops/templates/ops/adhoc_detail.html:77 -#: ops/templates/ops/command_execution_list.html:62 +#: ops/templates/ops/command_execution_list.html:65 #: ops/templates/ops/task_adhoc.html:61 msgid "Run as" msgstr "运行用户" @@ -2922,7 +2920,7 @@ msgid "Run history detail" msgstr "执行历史详情" #: ops/templates/ops/adhoc_history_detail.html:22 -#: ops/templates/ops/command_execution_list.html:63 +#: ops/templates/ops/command_execution_list.html:66 #: terminal/backends/command/models.py:16 msgid "Output" msgstr "输出" @@ -2988,7 +2986,7 @@ msgstr "没有选择系统用户" msgid "Pending" msgstr "等待" -#: ops/templates/ops/command_execution_list.html:64 +#: ops/templates/ops/command_execution_list.html:67 msgid "Finished" msgstr "结束" @@ -3078,9 +3076,8 @@ msgstr "未分组" msgid "Empty" msgstr "空" -#: perms/forms/asset_permission.py:66 perms/forms/remote_app_permission.py:34 -#: perms/models/asset_permission.py:114 perms/models/base.py:50 -#: perms/templates/perms/asset_permission_list.html:51 +#: perms/forms/asset_permission.py:76 perms/forms/remote_app_permission.py:34 +#: perms/models/base.py:50 perms/templates/perms/asset_permission_list.html:51 #: perms/templates/perms/asset_permission_list.html:71 #: perms/templates/perms/asset_permission_list.html:118 #: perms/templates/perms/remote_app_permission_list.html:16 @@ -3092,17 +3089,17 @@ msgstr "空" msgid "User group" msgstr "用户组" -#: perms/forms/asset_permission.py:82 +#: perms/forms/asset_permission.py:92 msgid "" "Tips: The RDP protocol does not support separate controls for uploading or " "downloading files" msgstr "提示:RDP 协议不支持单独控制上传或下载文件" -#: perms/forms/asset_permission.py:92 perms/forms/remote_app_permission.py:47 +#: perms/forms/asset_permission.py:102 perms/forms/remote_app_permission.py:47 msgid "User or group at least one required" msgstr "用户和用户组至少选一个" -#: perms/forms/asset_permission.py:101 +#: perms/forms/asset_permission.py:111 msgid "Asset or group at least one required" msgstr "资产和节点至少选一个" @@ -3122,16 +3119,15 @@ msgstr "下载文件" msgid "Upload download" msgstr "上传下载" -#: perms/models/asset_permission.py:82 +#: perms/models/asset_permission.py:81 msgid "Actions" msgstr "动作" -#: perms/models/asset_permission.py:86 perms/models/asset_permission.py:126 -#: templates/_nav.html:44 +#: perms/models/asset_permission.py:85 templates/_nav.html:44 msgid "Asset permission" msgstr "资产授权" -#: perms/models/asset_permission.py:117 perms/models/base.py:53 +#: perms/models/base.py:53 #: perms/templates/perms/asset_permission_detail.html:90 #: perms/templates/perms/remote_app_permission_detail.html:82 #: users/models/user.py:368 users/templates/users/user_detail.html:107 @@ -3175,7 +3171,7 @@ msgstr "添加资产" #: settings/templates/settings/terminal_setting.html:98 #: settings/templates/settings/terminal_setting.html:120 #: users/templates/users/user_group_detail.html:95 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:80 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:90 #: xpack/plugins/orgs/templates/orgs/org_detail.html:93 #: xpack/plugins/orgs/templates/orgs/org_detail.html:130 msgid "Add" @@ -3185,9 +3181,9 @@ msgstr "添加" msgid "Add node to this permission" msgstr "添加节点" -#: perms/templates/perms/asset_permission_asset.html:112 +#: perms/templates/perms/asset_permission_asset.html:109 #: users/templates/users/user_detail.html:234 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:105 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:115 msgid "Join" msgstr "加入" @@ -3242,7 +3238,7 @@ msgstr "刷新授权缓存" msgid "Validity" msgstr "有效" -#: perms/templates/perms/asset_permission_list.html:245 +#: perms/templates/perms/asset_permission_list.html:244 msgid "Refresh success" msgstr "刷新成功" @@ -3687,13 +3683,13 @@ msgstr "LDAP 用户列表" msgid "Please submit the LDAP configuration before import" msgstr "请先提交LDAP配置再进行导入" -#: settings/templates/settings/_ldap_list_users_modal.html:39 +#: settings/templates/settings/_ldap_list_users_modal.html:32 #: users/models/user.py:332 users/templates/users/user_detail.html:71 #: users/templates/users/user_profile.html:59 msgid "Email" msgstr "邮件" -#: settings/templates/settings/_ldap_list_users_modal.html:40 +#: settings/templates/settings/_ldap_list_users_modal.html:33 msgid "Existing" msgstr "已存在" @@ -4529,7 +4525,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户" msgid "Set password" msgstr "设置密码" -#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:89 +#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:86 #: 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 @@ -5416,7 +5412,21 @@ msgstr "MFA 解绑成功,返回登录页面" msgid "Password length" msgstr "密码长度" -#: xpack/plugins/change_auth_plan/forms.py:66 +#: xpack/plugins/change_auth_plan/forms.py:51 +#: xpack/plugins/change_auth_plan/models.py:213 +msgid "* For security, do not change {} user's password" +msgstr "* 为了安全,禁止更改 {} 用户的密码" + +#: xpack/plugins/change_auth_plan/forms.py:61 +msgid "* Please enter custom password" +msgstr "* 请输入自定义密码" + +#: xpack/plugins/change_auth_plan/forms.py:70 +#: xpack/plugins/cloud/serializers.py:73 +msgid "* Please enter a valid crontab expression" +msgstr "* 请输入有效的 crontab 表达式" + +#: xpack/plugins/change_auth_plan/forms.py:123 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:60 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:81 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 @@ -5427,7 +5437,7 @@ msgstr "密码长度" msgid "Periodic perform" msgstr "定时执行" -#: xpack/plugins/change_auth_plan/forms.py:70 +#: xpack/plugins/change_auth_plan/forms.py:127 msgid "" "Tips: The username of the user on the asset to be modified. if the user " "exists, change the password; If the user does not exist, create the user." @@ -5435,11 +5445,11 @@ msgstr "" "提示:用户名为将要修改的资产上的用户的用户名。如果用户存在,则修改密码;如果" "用户不存在,则创建用户。" -#: xpack/plugins/change_auth_plan/forms.py:74 xpack/plugins/cloud/forms.py:90 +#: xpack/plugins/change_auth_plan/forms.py:131 xpack/plugins/cloud/forms.py:90 msgid "Tips: (Units: hour)" msgstr "提示:(单位: 时)" -#: xpack/plugins/change_auth_plan/forms.py:75 xpack/plugins/cloud/forms.py:91 +#: xpack/plugins/change_auth_plan/forms.py:132 xpack/plugins/cloud/forms.py:91 msgid "" "eg: Every Sunday 03:05 run <5 3 * * 0> <br> Tips: Using 5 digits linux " "crontab expressions <min hour day month week> (<a href='https://tool.lu/" @@ -5451,113 +5461,88 @@ msgstr "" "具</a>) <br>注意: 如果同时设置了定期执行和周期执行,优先使用定期执行" #: xpack/plugins/change_auth_plan/meta.py:9 -#: xpack/plugins/change_auth_plan/models.py:117 -#: xpack/plugins/change_auth_plan/models.py:260 +#: xpack/plugins/change_auth_plan/models.py:114 +#: xpack/plugins/change_auth_plan/models.py:257 #: xpack/plugins/change_auth_plan/views.py:33 #: xpack/plugins/change_auth_plan/views.py:50 -#: xpack/plugins/change_auth_plan/views.py:74 -#: xpack/plugins/change_auth_plan/views.py:90 -#: xpack/plugins/change_auth_plan/views.py:117 -#: xpack/plugins/change_auth_plan/views.py:132 -#: xpack/plugins/change_auth_plan/views.py:147 +#: xpack/plugins/change_auth_plan/views.py:72 +#: xpack/plugins/change_auth_plan/views.py:87 +#: xpack/plugins/change_auth_plan/views.py:114 +#: xpack/plugins/change_auth_plan/views.py:129 +#: xpack/plugins/change_auth_plan/views.py:144 msgid "Change auth plan" msgstr "改密计划" -#: xpack/plugins/change_auth_plan/models.py:58 +#: xpack/plugins/change_auth_plan/models.py:55 msgid "Custom password" msgstr "自定义密码" -#: xpack/plugins/change_auth_plan/models.py:59 +#: xpack/plugins/change_auth_plan/models.py:56 msgid "All assets use the same random password" msgstr "所有资产使用相同的随机密码" -#: xpack/plugins/change_auth_plan/models.py:60 +#: xpack/plugins/change_auth_plan/models.py:57 msgid "All assets use different random password" msgstr "所有资产使用不同的随机密码" -#: xpack/plugins/change_auth_plan/models.py:79 -#: xpack/plugins/change_auth_plan/models.py:148 +#: xpack/plugins/change_auth_plan/models.py:76 +#: xpack/plugins/change_auth_plan/models.py:145 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:100 #: xpack/plugins/cloud/models.py:165 xpack/plugins/cloud/models.py:219 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:91 msgid "Cycle perform" msgstr "周期执行" -#: xpack/plugins/change_auth_plan/models.py:84 -#: xpack/plugins/change_auth_plan/models.py:146 +#: xpack/plugins/change_auth_plan/models.py:81 +#: xpack/plugins/change_auth_plan/models.py:143 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:92 #: xpack/plugins/cloud/models.py:170 xpack/plugins/cloud/models.py:217 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83 msgid "Regularly perform" msgstr "定期执行" -#: xpack/plugins/change_auth_plan/models.py:93 +#: xpack/plugins/change_auth_plan/models.py:90 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:74 msgid "Password rules" msgstr "密码规则" -#: xpack/plugins/change_auth_plan/models.py:216 -msgid "* For security, do not change {} user's password" -msgstr "* 为了安全,禁止更改 {} 用户的密码" - -#: xpack/plugins/change_auth_plan/models.py:220 +#: xpack/plugins/change_auth_plan/models.py:217 msgid "Assets is empty, please add the asset" msgstr "资产为空,请添加资产" -#: xpack/plugins/change_auth_plan/models.py:264 +#: xpack/plugins/change_auth_plan/models.py:261 msgid "Change auth plan snapshot" msgstr "改密计划快照" -#: xpack/plugins/change_auth_plan/models.py:279 -#: xpack/plugins/change_auth_plan/models.py:430 +#: xpack/plugins/change_auth_plan/models.py:276 +#: xpack/plugins/change_auth_plan/models.py:427 msgid "Change auth plan execution" msgstr "改密计划执行" -#: xpack/plugins/change_auth_plan/models.py:439 +#: xpack/plugins/change_auth_plan/models.py:436 msgid "Change auth plan execution subtask" msgstr "改密计划执行子任务" -#: xpack/plugins/change_auth_plan/models.py:457 +#: xpack/plugins/change_auth_plan/models.py:454 msgid "Authentication failed" msgstr "认证失败" -#: xpack/plugins/change_auth_plan/models.py:459 +#: xpack/plugins/change_auth_plan/models.py:456 msgid "Connection timeout" msgstr "连接超时" -#: xpack/plugins/change_auth_plan/serializers.py:58 -msgid "* For security, do not change {}'s password" -msgstr "* 为了安全,禁止更改 {} 的密码" - -#: xpack/plugins/change_auth_plan/serializers.py:65 -msgid "* Please enter custom password" -msgstr "* 请输入自定义密码" - -#: xpack/plugins/change_auth_plan/serializers.py:75 -msgid "* Please enter the correct password length" -msgstr "* 请输入正确的密码长度" - -#: xpack/plugins/change_auth_plan/serializers.py:78 -msgid "* Password length range 6-30 bits" -msgstr "* 密码长度范围 6-30 位" - -#: xpack/plugins/change_auth_plan/serializers.py:94 -#: xpack/plugins/cloud/serializers.py:73 -msgid "* Please enter a valid crontab expression" -msgstr "* 请输入有效的 crontab 表达式" - #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:23 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:26 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:23 -#: xpack/plugins/change_auth_plan/views.py:133 +#: xpack/plugins/change_auth_plan/views.py:130 msgid "Plan execution list" msgstr "执行列表" -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:66 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:76 msgid "Add asset to this plan" msgstr "添加资产" -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:91 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:101 msgid "Add node to this plan" msgstr "添加节点" @@ -5616,11 +5601,11 @@ msgstr "创建计划" msgid "Plan list" msgstr "计划列表" -#: xpack/plugins/change_auth_plan/views.py:75 +#: xpack/plugins/change_auth_plan/views.py:73 msgid "Update plan" msgstr "更新计划" -#: xpack/plugins/change_auth_plan/views.py:148 +#: xpack/plugins/change_auth_plan/views.py:145 msgid "Plan execution task list" msgstr "执行任务列表" @@ -5776,10 +5761,6 @@ msgstr "地域 & 实例" msgid "Node & AdminUser" msgstr "节点 & 管理用户" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66 -msgid "Loading..." -msgstr "加载中..." - #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:67 msgid "Load failed" msgstr "加载失败" @@ -6087,6 +6068,18 @@ msgstr "密码匣子" msgid "vault create" msgstr "创建" +#~ msgid "* For security, do not change {}'s password" +#~ msgstr "* 为了安全,禁止更改 {} 的密码" + +#~ msgid "* Please enter the correct password length" +#~ msgstr "* 请输入正确的密码长度" + +#~ msgid "* Password length range 6-30 bits" +#~ msgstr "* 密码长度范围 6-30 位" + +#~ msgid "Loading..." +#~ msgstr "加载中..." + #~ msgid "You do not have permission." #~ msgstr "你没有权限" diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 64d979c25..d2f55f623 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -40,7 +40,7 @@ def run_ansible_task(tid, callback=None, **kwargs): logger.error("No task found") -@shared_task(soft_time_limit=60) +@shared_task(soft_time_limit=60, queue="ansible") def run_command_execution(cid, **kwargs): execution = get_object_or_none(CommandExecution, id=cid) if execution: diff --git a/apps/ops/templates/ops/command_execution_list.html b/apps/ops/templates/ops/command_execution_list.html index fe8b7122c..81e9635c6 100644 --- a/apps/ops/templates/ops/command_execution_list.html +++ b/apps/ops/templates/ops/command_execution_list.html @@ -9,6 +9,9 @@ <link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet"> <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script> <style> + .form-control { + height: 30px; + } #search_btn { margin-bottom: 0; @@ -88,13 +91,6 @@ <script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script> <script> $(document).ready(function() { - {#$('table').DataTable({#} - {# "searching": false,#} - {# "paging": false,#} - {# "bInfo" : false,#} - {# "order": []#} - {# });#} - {#$('.footable').footable();#} $('.select2').select2({ dropdownAutoWidth : true, width: 'auto' @@ -116,7 +112,14 @@ $(document).ready(function() { var html = createPopover(data_list); $(this).html(html); }); - $('[data-toggle="popover"]').popover(); + $('[data-toggle="popover"]').popover({ + html: true, + placement: 'bottom', + trigger: 'click', + container: 'body' + }).on('click', function (e) { + $('[data-toggle="popover"]').not(this).popover('hide'); + }); }) </script> {% endblock %} diff --git a/apps/orgs/mixins/api.py b/apps/orgs/mixins/api.py index 1537982a0..d36360f51 100644 --- a/apps/orgs/mixins/api.py +++ b/apps/orgs/mixins/api.py @@ -35,6 +35,10 @@ class OrgBulkModelViewSet(IDInCacheFilterMixin, BulkModelViewSet): return queryset def allow_bulk_destroy(self, qs, filtered): + if qs.count() <= filtered.count(): + return False + if self.request.query_params.get('spm', ''): + return True return False diff --git a/apps/perms/api/asset_permission.py b/apps/perms/api/asset_permission.py index 810ae5ac9..3e7f4a078 100644 --- a/apps/perms/api/asset_permission.py +++ b/apps/perms/api/asset_permission.py @@ -97,6 +97,8 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): inherit_nodes_keys = assets.all().values_list('nodes__key', flat=True) for key in inherit_nodes_keys: + if key is None: + continue ancestor_keys = Node.get_nodes_ancestor_keys_by_key(key, with_self=True) inherit_all_nodes.update(ancestor_keys) queryset = queryset.filter( diff --git a/apps/perms/forms/asset_permission.py b/apps/perms/forms/asset_permission.py index 1d80258d4..6fdaee30b 100644 --- a/apps/perms/forms/asset_permission.py +++ b/apps/perms/forms/asset_permission.py @@ -53,6 +53,16 @@ class AssetPermissionForm(OrgModelForm): assets_field.queryset = Asset.objects.none() nodes_field.queryset = Node.objects.none() + def set_nodes_initial(self, nodes): + field = self.fields['nodes'] + field.choices = [(n.id, n.full_value) for n in nodes] + field.initial = nodes + + def set_assets_initial(self, assets): + field = self.fields['assets'] + field.choices = [(a.id, a.hostname) for a in assets] + field.initial = assets + class Meta: model = AssetPermission exclude = ( diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py index e23bc1f8c..8066ce5ca 100644 --- a/apps/perms/signals_handler.py +++ b/apps/perms/signals_handler.py @@ -47,7 +47,7 @@ def on_permission_nodes_changed(sender, instance=None, action='', **kwargs): if isinstance(instance, AssetPermission): logger.debug("Asset permission nodes change signal received") nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - system_users = instance.system_users.all().values_list('id', flat=True) + system_users = instance.system_users.all() for system_user in system_users: system_user.nodes.add(*tuple(nodes)) @@ -59,7 +59,7 @@ def on_permission_assets_changed(sender, instance=None, action='', **kwargs): if isinstance(instance, AssetPermission): logger.debug("Asset permission assets change signal received") assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - system_users = instance.system_users.all().values_list('id', flat=True) + system_users = instance.system_users.all() for system_user in system_users: system_user.assets.add(*tuple(assets)) diff --git a/apps/perms/templates/perms/asset_permission_asset.html b/apps/perms/templates/perms/asset_permission_asset.html index ccb1b7f90..093ab39a8 100644 --- a/apps/perms/templates/perms/asset_permission_asset.html +++ b/apps/perms/templates/perms/asset_permission_asset.html @@ -100,10 +100,7 @@ <form> <tr> <td colspan="2" class="no-borders"> - <select data-placeholder="{% trans 'Select nodes' %}" class="select2" id="node_select2" style="width: 100%" multiple="" tabindex="4"> - {% for node in nodes_remain %} - <option value="{{ node.id }}" id="opt_{{ node.id }}">{{ node.full_value }}</option> - {% endfor %} + <select data-placeholder="{% trans 'Select nodes' %}" class="nodes-select2" id="nodes_select2" style="width: 100%" multiple="" tabindex="4"> </select> </td> </tr> @@ -202,35 +199,22 @@ function initAssetTable() { return table } + $(document).ready(function () { $('.select2').select2(); table = initAssetTable(); + + var nodeListUrl = "{% url 'api-assets:node-list' %}"; + nodesSelect2Init(".nodes-select2", nodeListUrl); + $("#asset_select2").parent().find(".select2-selection").on('click', function (e) { if ($(e.target).attr('class') !== 'select2-selection__choice__remove'){ e.preventDefault(); e.stopPropagation(); $("#asset_list_modal").modal(); - initSelectedAssets2Table('#asset_select2'); } }) }) -.on('click', '#btn_asset_modal_confirm', function () { - var assets = asset_table2.selected; - var options = []; - $('#asset_select2 option').each(function (i, v) { - options.push(v.value) - }); - asset_table2.selected_rows.forEach(function (i) { - var name = i.hostname + '(' + i.ip + ')'; - var option = new Option(name, i.id, false, true); - - if (options.indexOf(i.id) === -1) { - $('#asset_select2').append(option).trigger('change'); - } - }); - $('#asset_select2').val(assets).trigger('change'); - $("#asset_list_modal").modal('hide'); -}) .on('click', '.btn-add-assets', function () { var assets_selected = $("#asset_select2 option:selected").map(function () { return $(this).attr('value'); @@ -250,7 +234,7 @@ $(document).ready(function () { }) .on('click', '#btn-add-node', function () { var nodes_selected = {}; - $("#node_select2 option:selected").each(function (i, data) { + $("#nodes_select2 option:selected").each(function (i, data) { nodes_selected[$(data).attr('value')] = $(data).text(); }); if (Object.keys(nodes_selected).length === 0) { diff --git a/apps/perms/templates/perms/asset_permission_create_update.html b/apps/perms/templates/perms/asset_permission_create_update.html index 5b69f7b4c..02d51e220 100644 --- a/apps/perms/templates/perms/asset_permission_create_update.html +++ b/apps/perms/templates/perms/asset_permission_create_update.html @@ -111,42 +111,25 @@ var dateOptions = { } }; var api_action = "{{ api_action }}"; + $(document).ready(function () { $('.select2').select2({ closeOnSelect: false }); var url = "{% url 'api-assets:node-list' %}"; nodesSelect2Init(".nodes-select2", url); + $('#date_start').daterangepicker(dateOptions); $('#date_expired').daterangepicker(dateOptions); + $("#id_assets").parent().find(".select2-selection").on('click', function (e) { if ($(e.target).attr('class') !== 'select2-selection__choice__remove'){ e.preventDefault(); e.stopPropagation(); $("#asset_list_modal").modal(); - initSelectedAssets2Table(); } }) }) -.on('click', '#btn_asset_modal_confirm', function () { - var assets = asset_table2.selected; - - var options = []; - $('#id_assets option').each(function (i, v) { - options.push(v.value) - }); - asset_table2.selected_rows.forEach(function (i) { - var name = i.hostname + '(' + i.ip + ')'; - var option = new Option(name, i.id, false, true); - - if (options.indexOf(i.id) === -1) { - $('#id_assets').append(option).trigger('change'); - } - }); - - $('#id_assets').val(assets).trigger('change'); - $("#asset_list_modal").modal('hide'); -}) .on("submit", "form", function (evt) { evt.preventDefault(); var the_url = '{% url 'api-perms:asset-permission-list' %}'; diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 95a92f16b..2a493e16b 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -227,7 +227,6 @@ function toggle() { $(document).ready(function(){ initTable(); initTree(); - }) .on('click', '.btn-del', function () { var $this = $(this); @@ -247,17 +246,19 @@ $(document).ready(function(){ }) .on('click', '.btn-create-permission', function () { var url = "{% url 'perms:asset-permission-create' %}"; - var nodes = zTree.getSelectedNodes(); - var _nodes = []; - var _assets = []; - $.each(nodes, function (id, node) { - if (node.meta.type === 'node') { - _nodes.push(node.meta.node.id) - } else { - _assets.push(node.meta.asset.id) - } - }); - url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(","); + if (zTree) { + var nodes = zTree.getSelectedNodes(); + var _nodes = []; + var _assets = []; + $.each(nodes, function (id, node) { + if (node.meta.type === 'node') { + _nodes.push(node.meta.node.id) + } else { + _assets.push(node.meta.asset.id) + } + }); + url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(","); + } window.open(url, '_self'); }).on('click', '.toggle', function (e) { e.preventDefault(); @@ -283,7 +284,6 @@ $(document).ready(function(){ detailRows.push(tr.attr('id')); } } - }).on('click', '#permission_list_table_filter input', function (e) { e.preventDefault(); e.stopPropagation(); diff --git a/apps/perms/views/asset_permission.py b/apps/perms/views/asset_permission.py index e7d2f155b..94c7c8c62 100644 --- a/apps/perms/views/asset_permission.py +++ b/apps/perms/views/asset_permission.py @@ -53,11 +53,11 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView): nodes_id = nodes_id.split(",") nodes = Node.objects.filter(id__in=nodes_id)\ .exclude(id=Node.org_root().id) - form['nodes'].initial = nodes + form.set_nodes_initial(nodes) if assets_id: assets_id = assets_id.split(",") assets = Asset.objects.filter(id__in=assets_id) - form['assets'].initial = assets + form.set_assets_initial(assets) return form def get_context_data(self, **kwargs): diff --git a/apps/settings/templates/settings/_ldap_list_users_modal.html b/apps/settings/templates/settings/_ldap_list_users_modal.html index c0d062714..dd839eb5b 100644 --- a/apps/settings/templates/settings/_ldap_list_users_modal.html +++ b/apps/settings/templates/settings/_ldap_list_users_modal.html @@ -17,13 +17,6 @@ padding: 10px 10px; text-align: center; } - -#assetTree2.ztree * { - background-color: #f8fafb; -} -#assetTree2.ztree { - background-color: #f8fafb; -} </style> <div class="wrapper wrapper-content"> diff --git a/apps/static/js/inspinia.js b/apps/static/js/inspinia.js index ed8c1c6ba..979f41005 100644 --- a/apps/static/js/inspinia.js +++ b/apps/static/js/inspinia.js @@ -76,10 +76,9 @@ $(document).ready(function () { if(!$("body").hasClass('body-small')) { fix_height(); } - }) + }); - $("[data-toggle=popover]") - .popover(); + $("[data-toggle=popover]").popover(); }); diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 400fd637e..127529a73 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -1,7 +1,8 @@ //jumpserver 自定义js 2015-01-29 //此函数用于checkbox的全选和反选 -var checked=false; +var checked = false; + function check_all(form) { var checkboxes = document.getElementById(form); if (checked === false) { @@ -16,26 +17,23 @@ function check_all(form) { } } -function checkAll(id, name){ +function checkAll(id, name) { var checklist = document.getElementsByName(name); - if(document.getElementById(id).checked) - { - for(var i=0;i<checklist.length;i++) - { - checklist[i].checked = 1; + if (document.getElementById(id).checked) { + for (var i = 0; i < checklist.length; i++) { + checklist[i].checked = 1; } - }else{ - for(var j=0;j<checklist.length;j++) - { - checklist[j].checked = 0; + } else { + for (var j = 0; j < checklist.length; j++) { + checklist[j].checked = 0; } } } //提取指定行的数据,JSON格式 -function GetRowData(row){ +function GetRowData(row) { var rowData = {}; - for(var j=0;j<row.cells.length; j++) { + for (var j = 0; j < row.cells.length; j++) { name = row.parentNode.rows[0].cells[j].getAttribute("Name"); if (name) { var value = row.cells[j].getAttribute("Value"); @@ -56,16 +54,16 @@ function GetTableDataBox() { var checkboxes = document.getElementById("contents_form"); var id_list = []; len = checkboxes.elements.length; - for (var i=0; i < len; i++) { + for (var i = 0; i < len; i++) { if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked === true && checkboxes.elements[i].value != "checkall") { id_list.push(i); - } } + } for (i in id_list) { tableData.push(GetRowData(tabProduct.rows[id_list[i]])); } - if (id_list.length === 0){ + if (id_list.length === 0) { alert('请至少选择一行!'); } returnData.push(tableData); @@ -77,8 +75,8 @@ function move(from, to, from_o, to_o) { $("#" + from + " option").each(function () { if ($(this).prop("selected") === true) { $("#" + to).append(this); - if( typeof from_o !== 'undefined'){ - $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']")); + if (typeof from_o !== 'undefined') { + $("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']")); } } }); @@ -88,18 +86,18 @@ function move_left(from, to, from_o, to_o) { $("#" + from + " option").each(function () { if ($(this).prop("selected") === true) { $("#" + to).append(this); - if( typeof from_o !== 'undefined'){ - $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']")); + if (typeof from_o !== 'undefined') { + $("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']")); } } - $(this).attr("selected",'true'); + $(this).attr("selected", 'true'); }); } -function selectAll(){ +function selectAll() { // Select all check box - $('option').each(function(){ + $('option').each(function () { $(this).attr('selected', true); }); } @@ -131,7 +129,7 @@ function setAjaxCSRFToken() { var sessionid = getCookie('sessionid'); $.ajaxSetup({ - beforeSend: function(xhr, settings) { + beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } @@ -143,19 +141,16 @@ function activeNav() { var url_array = document.location.pathname.split("/"); var app = url_array[1]; var resource = url_array[2]; - if (app === ''){ + if (app === '') { $('#index').addClass('active'); - } - else if (app === 'xpack' && resource === 'cloud') { + } else if (app === 'xpack' && resource === 'cloud') { var item = url_array[3]; $("#" + app).addClass('active'); $('#' + app + ' #' + resource).addClass('active'); $('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff'); - } - else if (app === 'settings'){ + } else if (app === 'settings') { $("#" + app).addClass('active'); - } - else { + } else { $("#" + app).addClass('active'); $('#' + app + ' #' + resource).addClass('active'); } @@ -186,14 +181,14 @@ function formSubmit(props) { }).done(function (data, textState, jqXHR) { if (redirect_to) { if (props.message) { - var messages="ed65330a45559c87345a0eb6ac7812d18d0d8976$[[\"__json_message\"\0540\05425\054\"asdfasdf \\u521b\\u5efa\\u6210\\u529f\"]]" + var messages = "ed65330a45559c87345a0eb6ac7812d18d0d8976$[[\"__json_message\"\0540\05425\054\"asdfasdf \\u521b\\u5efa\\u6210\\u529f\"]]" setCookie("messages", messages) } location.href = redirect_to; } else if (typeof props.success === 'function') { return props.success(data, textState, jqXHR); } - }).fail(function(jqXHR, textStatus, errorThrown) { + }).fail(function (jqXHR, textStatus, errorThrown) { if (typeof props.error === 'function') { return props.error(jqXHR, textStatus, errorThrown) } @@ -233,7 +228,7 @@ function formSubmit(props) { } if (fieldRef.length === 1 && formGroupRef.length === 1) { formGroupRef.addClass('has-error'); - var help_msg = v.join("<br/>") ; + var help_msg = v.join("<br/>"); helpBlockRef.html(help_msg); } else { $.each(v, function (kk, vv) { @@ -241,7 +236,7 @@ function formSubmit(props) { $.each(vv, function (kkk, vvv) { noneFieldErrorMsg += " " + vvv + '<br/>'; }) - } else{ + } else { noneFieldErrorMsg += vv + '<br/>'; } }) @@ -264,7 +259,7 @@ function requestApi(props) { var user_fail_message = props.fail_message; var default_failed_message = gettext('An unknown error occurred while updating..'); var flash_message = props.flash_message || true; - if (props.flash_message === false){ + if (props.flash_message === false) { flash_message = false; } @@ -274,7 +269,7 @@ function requestApi(props) { data: props.body, contentType: props.content_type || "application/json; charset=utf-8", dataType: props.data_type || "json" - }).done(function(data, textStatue, jqXHR) { + }).done(function (data, textStatue, jqXHR) { if (flash_message) { var msg = ""; if (user_success_message) { @@ -287,7 +282,7 @@ function requestApi(props) { if (typeof props.success === 'function') { return props.success(data); } - }).fail(function(jqXHR, textStatus, errorThrown) { + }).fail(function (jqXHR, textStatus, errorThrown) { if (flash_message) { var msg = ""; if (user_fail_message) { @@ -308,24 +303,24 @@ function requestApi(props) { return props.error(jqXHR.responseText, jqXHR.status); } }); - // return true; + // return true; } // Sweet Alert for Delete function objectDelete(obj, name, url, redirectTo) { function doDelete() { var body = {}; - var success = function() { + var success = function () { // swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); if (!redirectTo) { $(obj).parent().parent().remove(); } else { - window.location.href=redirectTo; + window.location.href = redirectTo; } }; - var fail = function() { + var fail = function () { // swal("错误", "删除"+"[ "+name+" ]"+"遇到错误", "error"); - swal(gettext('Error'), "[ "+name+" ]" + gettext("Being used by the asset, please unbind the asset first."), "error"); + swal(gettext('Error'), "[ " + name + " ]" + gettext("Being used by the asset, please unbind the asset first."), "error"); }; requestApi({ url: url, @@ -336,6 +331,7 @@ function objectDelete(obj, name, url, redirectTo) { error: fail }); } + swal({ title: gettext('Are you sure about deleting it?'), text: " [" + name + "] ", @@ -350,22 +346,21 @@ function objectDelete(obj, name, url, redirectTo) { }); } -function orgDelete(obj, name, url, redirectTo){ +function orgDelete(obj, name, url, redirectTo) { function doDelete() { var body = {}; - var success = function() { + var success = function () { if (!redirectTo) { $(obj).parent().parent().remove(); } else { - window.location.href=redirectTo; + window.location.href = redirectTo; } }; - var fail = function(responseText, status) { - if (status === 400){ - swal(gettext("Error"), "[ " + name + " ] " + gettext("The organization contains undeleted information. Please try again after deleting"), "error"); - } - else if (status === 405){ - swal(gettext("Error"), " [ "+ name + " ] " + gettext("Do not perform this operation under this organization. Try again after switching to another organization"), "error"); + var fail = function (responseText, status) { + if (status === 400) { + swal(gettext("Error"), "[ " + name + " ] " + gettext("The organization contains undeleted information. Please try again after deleting"), "error"); + } else if (status === 405) { + swal(gettext("Error"), " [ " + name + " ] " + gettext("Do not perform this operation under this organization. Try again after switching to another organization"), "error"); } }; requestApi({ @@ -377,6 +372,7 @@ function orgDelete(obj, name, url, redirectTo){ error: fail }); } + swal({ title: gettext("Please ensure that the following information in the organization has been deleted"), text: gettext("User list、User group、Asset list、Domain list、Admin user、System user、Labels、Asset permission"), @@ -391,11 +387,10 @@ function orgDelete(obj, name, url, redirectTo){ }); } -$.fn.serializeObject = function() -{ +$.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); - $.each(a, function() { + $.each(a, function () { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; @@ -413,16 +408,15 @@ function makeLabel(data) { } - var jumpserver = {}; jumpserver.checked = false; jumpserver.selected = {}; jumpserver.language = { - processing: gettext('Loading ...'), + processing: gettext('Loading') + '...', search: gettext('Search'), select: { rows: { - _: gettext("Selected item %d"), + _: gettext("Selected item %d"), 0: "" } }, @@ -440,36 +434,40 @@ jumpserver.language = { } }; jumpserver.initDataTable = function (options) { - // options = { - // ele *: $('#dataTable_id'), - // ajax_url *: '{% url 'users:user-list-api' %}', - // columns *: [{data: ''}, ....], - // dom: 'fltip', - // i18n_url: '{% static "js/...../en-us.json" %}', - // order: [[1, 'asc'], [2, 'asc'], ...], - // buttons: ['excel', 'pdf', 'print'], - // columnDefs: [{target: 0, createdCell: ()=>{}}, ...], - // uc_html: '<a>header button</a>', - // op_html: 'div.btn-group?', - // paging: true - // } - var ele = options.ele || $('.dataTable'); - var columnDefs = [ - { - targets: 0, - orderable: false, - createdCell: function (td, cellData) { - $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData)); - } - }, - {className: 'text-center', render: $.fn.dataTable.render.text(), targets: '_all'} - ]; - columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs; - var select = { - style: 'multi', - selector: 'td:first-child' - }; - var table = ele.DataTable({ + // options = { + // ele *: $('#dataTable_id'), + // ajax_url *: '{% url 'users:user-list-api' %}', + // columns *: [{data: ''}, ....], + // dom: 'fltip', + // i18n_url: '{% static "js/...../en-us.json" %}', + // order: [[1, 'asc'], [2, 'asc'], ...], + // buttons: ['excel', 'pdf', 'print'], + // columnDefs: [{target: 0, createdCell: ()=>{}}, ...], + // uc_html: '<a>header button</a>', + // op_html: 'div.btn-group?', + // paging: true + // } + var ele = options.ele || $('.dataTable'); + var columnDefs = [ + { + targets: 0, + orderable: false, + createdCell: function (td, cellData) { + $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData)); + } + }, + { + className: 'text-center', + render: $.fn.dataTable.render.text(), + targets: '_all' + } + ]; + columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs; + var select = { + style: 'multi', + selector: 'td:first-child' + }; + var table = ele.DataTable({ pageLength: options.pageLength || 15, 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 || [], @@ -486,15 +484,15 @@ jumpserver.initDataTable = function (options) { language: jumpserver.language, lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]] }); - table.on('select', function(e, dt, type, indexes) { - var $node = table[ type ]( indexes ).nodes().to$(); + table.on('select', function (e, dt, type, indexes) { + var $node = table[type](indexes).nodes().to$(); $node.find('input.ipt_check').prop('checked', true); jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true - }).on('deselect', function(e, dt, type, indexes) { - var $node = table[ type ]( indexes ).nodes().to$(); + }).on('deselect', function (e, dt, type, indexes) { + var $node = table[type](indexes).nodes().to$(); $node.find('input.ipt_check').prop('checked', false); jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false - }).on('draw', function(){ + }).on('draw', function () { $('#op').html(options.op_html || ''); $('#uc').html(options.uc_html || ''); $('[data-toggle="popover"]').popover({ @@ -506,16 +504,16 @@ jumpserver.initDataTable = function (options) { $('[data-toggle="popover"]').not(this).popover('hide'); }); }); - $('.ipt_check_all').on('click', function() { - if ($(this).prop("checked")) { - $(this).closest('table').find('.ipt_check').prop('checked', true); - jumpserver.checked = true; - table.rows({search:'applied', page:'current'}).select(); - } else { - $(this).closest('table').find('.ipt_check').prop('checked', false); - jumpserver.checked = false; - table.rows({search:'applied', page:'current'}).deselect(); - } + $('.ipt_check_all').on('click', function () { + if ($(this).prop("checked")) { + $(this).closest('table').find('.ipt_check').prop('checked', true); + jumpserver.checked = true; + table.rows({search: 'applied', page: 'current'}).select(); + } else { + $(this).closest('table').find('.ipt_check').prop('checked', false); + jumpserver.checked = false; + table.rows({search: 'applied', page: 'current'}).deselect(); + } }); return table; @@ -532,40 +530,42 @@ jumpserver.initStaticTable = function (selector) { }; jumpserver.initServerSideDataTable = function (options) { - // options = { - // ele *: $('#dataTable_id'), - // ajax_url *: '{% url 'users:user-list-api' %}', - // columns *: [{data: ''}, ....], - // dom: 'fltip', - // i18n_url: '{% static "js/...../en-us.json" %}', - // order: [[1, 'asc'], [2, 'asc'], ...], - // buttons: ['excel', 'pdf', 'print'], - // columnDefs: [{target: 0, createdCell: ()=>{}}, ...], - // uc_html: '<a>header button</a>', - // op_html: 'div.btn-group?', - // paging: true - // } - var ele = options.ele || $('.dataTable'); - var columnDefs = [ - { - targets: 0, - orderable: false, - createdCell: function (td, cellData) { - $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData)); - } - }, - { - targets: '_all', - className: 'text-center', - render: $.fn.dataTable.render.text() - } - ]; - columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs; - var select = { - style: 'multi', - selector: 'td:first-child' - }; - var table = ele.DataTable({ + // options = { + // ele *: $('#dataTable_id'), + // ajax_url *: '{% url 'users:user-list-api' %}', + // select_style: 'multi', + // columns *: [{data: ''}, ....], + // dom: 'fltip', + // i18n_url: '{% static "js/...../en-us.json" %}', + // order: [[1, 'asc'], [2, 'asc'], ...], + // buttons: ['excel', 'pdf', 'print'], + // columnDefs: [{target: 0, createdCell: ()=>{}}, ...], + // uc_html: '<a>header button</a>', + // op_html: 'div.btn-group?', + // paging: true + // } + var ele = options.ele || $('.dataTable'); + var columnDefs = [ + { + targets: 0, + orderable: false, + createdCell: function (td, cellData) { + $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData)); + } + }, + { + targets: '_all', + className: 'text-center', + render: $.fn.dataTable.render.text() + } + ]; + var select_style = options.select_style || 'multi'; + columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs; + var select = { + style: select_style, + selector: 'td:first-child' + }; + 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"><"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>>', @@ -576,8 +576,8 @@ jumpserver.initServerSideDataTable = function (options) { processing: true, searchDelay: 800, ajax: { - url: options.ajax_url , - error: function(jqXHR, textStatus, errorThrown) { + url: options.ajax_url, + error: function (jqXHR, textStatus, errorThrown) { var msg = gettext("Unknown error occur"); if (jqXHR.responseJSON) { if (jqXHR.responseJSON.error) { @@ -590,7 +590,7 @@ jumpserver.initServerSideDataTable = function (options) { }, data: function (data) { delete data.columns; - if (data.length !== null){ + if (data.length !== null) { data.limit = data.length; delete data.length; } @@ -605,15 +605,15 @@ jumpserver.initServerSideDataTable = function (options) { var search_raw = []; search_list.map(function (val, index) { - var kv = val.split(":"); - if (kv.length === 2) { - var value = kv[1]; - var key = kv[0].trim(); - value = value.replace("+", " ").trim(); - search_attr[key] = value - } else { - search_raw.push(kv) - } + var kv = val.split(":"); + if (kv.length === 2) { + var value = kv[1]; + var key = kv[0].trim(); + value = value.replace("+", " ").trim(); + search_attr[key] = value + } else { + search_raw.push(kv) + } }); data.search = search_raw.join(""); $.each(search_attr, function (k, v) { @@ -629,8 +629,8 @@ jumpserver.initServerSideDataTable = function (options) { data.order = order; } }, - dataFilter: function(data){ - var json = jQuery.parseJSON( data ); + dataFilter: function (data) { + var json = jQuery.parseJSON(data); json.recordsTotal = json.count; json.recordsFiltered = json.count; return JSON.stringify(json); // return JSON string @@ -644,35 +644,36 @@ jumpserver.initServerSideDataTable = function (options) { }); table.selected = []; table.selected_rows = []; - table.on('select', function(e, dt, type, indexes) { - var $node = table[ type ]( indexes ).nodes().to$(); + table.on('select', function (e, dt, type, indexes) { + var $node = table[type](indexes).nodes().to$(); $node.find('input.ipt_check').prop('checked', true); jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true; 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) + if (row.id && $.inArray(row.id, table.selected) === -1) { + table.selected.push(row.id); + table.selected_rows.push(row); } }) } - }).on('deselect', function(e, dt, type, indexes) { - var $node = table[ type ]( indexes ).nodes().to$(); + }).on('deselect', function (e, dt, type, indexes) { + var $node = table[type](indexes).nodes().to$(); $node.find('input.ipt_check').prop('checked', false); jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false; if (type === 'row') { var rows = table.rows(indexes).data(); $.each(rows, function (id, row) { - if (row.id){ + if (row.id) { var index = table.selected.indexOf(row.id); - if (index > -1){ - table.selected.splice(index, 1) + if (index > -1) { + table.selected.splice(index, 1); + table.selected_rows.splice(index, 1); } } }) } - }).on('draw', function(){ + }).on('draw', function () { $('[data-toggle="popover"]').popover({ html: true, placement: 'bottom', @@ -690,7 +691,7 @@ jumpserver.initServerSideDataTable = function (options) { $.each(table.selected, function (id, data) { var index = table_data.indexOf(data); - if (index > -1){ + if (index > -1) { table.rows(index).select() } }); @@ -701,13 +702,16 @@ jumpserver.initServerSideDataTable = function (options) { $('#fa').html(options.fa_html || ''); }); var table_id = table.settings()[0].sTableId; - $('#' + table_id + ' .ipt_check_all').on('click', function() { + $('#' + table_id + ' .ipt_check_all').on('click', function () { + if (select_style !== 'multi') { + return + } if ($(this).prop("checked")) { $(this).closest('table').find('.ipt_check').prop('checked', true); - table.rows({search:'applied', page:'current'}).select(); + table.rows({search: 'applied', page: 'current'}).select(); } else { $(this).closest('table').find('.ipt_check').prop('checked', false); - table.rows({search:'applied', page:'current'}).deselect(); + table.rows({search: 'applied', page: 'current'}).deselect(); } }); @@ -728,7 +732,7 @@ String.prototype.replaceAll = function (exp, newStr) { * 原型:字符串格式化 * @param args 格式化参数值 */ -String.prototype.format = function(args) { +String.prototype.format = function (args) { var result = this; if (arguments.length < 1) { return result; @@ -738,7 +742,7 @@ String.prototype.format = function(args) { if (arguments.length == 1 && typeof (args) == "object") { data = args; } - for ( var key in data) { + for (var key in data) { var value = data[key]; if (undefined != value) { result = result.replaceAll("\\{" + key + "\\}", value); @@ -750,7 +754,7 @@ String.prototype.format = function(args) { function setCookie(key, value, time) { var expires = new Date(); if (!time) { - time = expires.getTime() + (24 * 60 * 60 * 1000); + time = expires.getTime() + (24 * 60 * 60 * 1000); } expires.setTime(time); document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/'; @@ -767,26 +771,26 @@ function delCookie(key) { } function createPopover(dataset, title, callback) { - if (callback !== undefined){ + if (callback !== undefined) { var new_dataset = []; $.each(dataset, function (index, value) { new_dataset.push(callback(value)) }); dataset = new_dataset; } - var data_content = dataset.join("</br>"); - + var data_content = dataset.join("<br>"); var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>"; return html; } - $(function () { +$(function () { (function ($) { $.getUrlParam = function (name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); - if (r != null) return unescape(r[2]); return null; + if (r != null) return unescape(r[2]); + return null; } })(jQuery); }); @@ -794,12 +798,13 @@ function createPopover(dataset, title, callback) { function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); - if (r != null) return unescape(r[2]); return null; + if (r != null) return unescape(r[2]); + return null; } function setUrlParam(url, name, value) { var urlArray = url.split("?"); - if (urlArray.length===1){ + if (urlArray.length === 1) { url += "?" + name + "=" + value; } else { var oriParam = urlArray[1].split("&"); @@ -836,12 +841,11 @@ var rules_id_map_label = { 'id_security_password_special_char': gettext('Must contain special characters') }; -function getRuleLabel(rule){ +function getRuleLabel(rule) { var label = ''; - if (rule.key === rules_short_map_id['min']){ + if (rule.key === rules_short_map_id['min']) { label = rules_id_map_label[rule.key].replace('{N}', rule.value) - } - else{ + } else { label = rules_id_map_label[rule.key] } return label @@ -850,38 +854,33 @@ function getRuleLabel(rule){ // 校验密码-改变规则颜色 function checkPasswordRules(password, minLength) { if (wordMinLength(password, minLength)) { - $('#'+rules_short_map_id['min']).css('color', 'green') - } - else { - $('#'+rules_short_map_id['min']).css('color', '#908a8a') + $('#' + rules_short_map_id['min']).css('color', 'green') + } else { + $('#' + rules_short_map_id['min']).css('color', '#908a8a') } if (wordUpperCase(password)) { - $('#'+rules_short_map_id['upper']).css('color', 'green') - } - else { - $('#'+rules_short_map_id['upper']).css('color', '#908a8a') + $('#' + rules_short_map_id['upper']).css('color', 'green') + } else { + $('#' + rules_short_map_id['upper']).css('color', '#908a8a') } if (wordLowerCase(password)) { - $('#'+rules_short_map_id['lower']).css('color', 'green') - } - else { - $('#'+rules_short_map_id['lower']).css('color', '#908a8a') + $('#' + rules_short_map_id['lower']).css('color', 'green') + } else { + $('#' + rules_short_map_id['lower']).css('color', '#908a8a') } if (wordNumber(password)) { - $('#'+rules_short_map_id['number']).css('color', 'green') - } - else { - $('#'+rules_short_map_id['number']).css('color', '#908a8a') + $('#' + rules_short_map_id['number']).css('color', 'green') + } else { + $('#' + rules_short_map_id['number']).css('color', '#908a8a') } if (wordSpecialChar(password)) { - $('#'+rules_short_map_id['special']).css('color', 'green') - } - else { - $('#'+rules_short_map_id['special']).css('color', '#908a8a') + $('#' + rules_short_map_id['special']).css('color', 'green') + } else { + $('#' + rules_short_map_id['special']).css('color', '#908a8a') } } @@ -891,18 +890,22 @@ function wordMinLength(word, minLength) { var re = new RegExp("^(.{" + minLength + ",})$"); return word.match(re) } + // 大写字母 function wordUpperCase(word) { return word.match(/([A-Z]+)/) } + // 小写字母 function wordLowerCase(word) { return word.match(/([a-z]+)/) } + // 数字字符 function wordNumber(word) { return word.match(/([\d]+)/) } + // 特殊字符 function wordSpecialChar(word) { return word.match(/[`,~,!,@,#,\$,%,\^,&,\*,\(,\),\-,_,=,\+,\{,\},\[,\],\|,\\,;,',:,",\,,\.,<,>,\/,\?]+/) @@ -920,7 +923,7 @@ function popoverPasswordRules(password_check_rules, $el) { } // 初始化弹窗popover -function initPopover($container, $progress, $idPassword, $el, password_check_rules, i18n_fallback){ +function initPopover($container, $progress, $idPassword, $el, password_check_rules, i18n_fallback) { options = {}; // User Interface options.ui = { @@ -944,37 +947,6 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul popoverPasswordRules(password_check_rules, $el); } -// 解决input框中的资产和弹出表格中资产的显示不一致 -function initSelectedAssets2Table(id){ - if (!id) { - id = "#id_assets" - } - var inputAssets = $(id).val(); - var selectedAssets = asset_table2.selected.concat(); - - // input assets无,table assets选中,则取消勾选(再次click) - if (selectedAssets.length !== 0){ - $.each(selectedAssets, function (index, assetId){ - if ($.inArray(assetId, inputAssets) === -1){ - $('#'+assetId).trigger('click'); // 取消勾选 - } - }); - } - - // input assets有,table assets没选,则选中(click) - if (inputAssets !== null){ - asset_table2.selected = inputAssets; - $.each(inputAssets, function(index, assetId){ - var dom = document.getElementById(assetId); - if (dom !== null){ - var selected = dom.parentElement.parentElement.className.indexOf('selected') - } - if (selected === -1){ - $('#'+assetId).trigger('click'); - } - }); - } -} function rootNodeAddDom(ztree, callback) { @@ -1002,7 +974,7 @@ function APIExportData(props) { var params = props.params || {}; params['format'] = props.format; params['spm'] = data.spm; - for (var k in params){ + for (var k in params) { export_url = setUrlParam(export_url, k, params[k]) } window.open(export_url); @@ -1013,7 +985,7 @@ function APIExportData(props) { }) } -function APIImportData(props){ +function APIImportData(props) { props = props || {}; $.ajax({ url: props.url, @@ -1022,12 +994,12 @@ function APIImportData(props){ data: props.body, contentType: props.content_type || 'text/csv', success: function (data) { - if(props.method === 'POST'){ + if (props.method === 'POST') { $('#created_failed').html(''); $('#created_failed_detail').html(''); $('#success_created').html(gettext("Import Success")); $('#success_created_detail').html("Count" + ": " + data.length); - }else{ + } else { $('#updated_failed').html(''); $('#updated_failed_detail').html(''); $('#success_updated').html(gettext("Update Success")); @@ -1038,11 +1010,11 @@ function APIImportData(props){ }, error: function (error) { var data = error.responseJSON; - if (data instanceof Array){ + if (data instanceof Array) { var html = ''; var li = ''; var err = ''; - $.each(data, function (index, item){ + $.each(data, function (index, item) { err = ''; for (var prop in item) { err += prop + ": " + item[prop][0] + " " @@ -1053,16 +1025,15 @@ function APIImportData(props){ } }); html = "<ul>" + html + "</ul>" - } - else { + } else { html = error.responseText } - if(props.method === 'POST'){ + if (props.method === 'POST') { $('#success_created').html(''); $('#success_created_detail').html(''); $('#created_failed').html(gettext("Import failed")); $('#created_failed_detail').html(html); - }else{ + } else { $('#success_updated').html(''); $('#success_updated_detail').html(''); $('#updated_failed').html(gettext("Update failed")); @@ -1073,7 +1044,7 @@ function APIImportData(props){ } -function htmlEscape ( d ) { +function htmlEscape(d) { return typeof d === 'string' ? d.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : d; @@ -1081,10 +1052,9 @@ function htmlEscape ( d ) { function objectAttrsIsList(obj, attrs) { attrs.forEach(function (attr) { - if (!obj[attr]){ + if (!obj[attr]) { obj[attr] = [] - } - else if (obj[attr] && !(obj[attr] instanceof Array)){ + } else if (obj[attr] && !(obj[attr] instanceof Array)) { obj[attr] = [obj[attr]] } }) @@ -1107,8 +1077,8 @@ function objectAttrsIsBool(obj, attrs) { } function cleanDateStr(d) { - for (var i=0;i<3;i++) { - if (!isNaN(Date.parse(d))){ + for (var i = 0; i < 3; i++) { + if (!isNaN(Date.parse(d))) { return d; } if (!isNaN(Number(d))) { @@ -1145,7 +1115,7 @@ function toSafeLocalDateStr(d) { function getUrlParams(url) { url = url.split("?"); var params = ""; - if (url.length === 2){ + if (url.length === 2) { params = url[1]; } return params @@ -1167,7 +1137,7 @@ function getTimeUnits(u) { function timeOffset(a, b) { var start = safeDate(a); var end = safeDate(b); - var offset = (end - start)/1000; + var offset = (end - start) / 1000; var days = offset / 3600 / 24; var hours = offset / 3600; @@ -1192,7 +1162,7 @@ function readFile(ref) { if (hasFile) { var reader = new FileReader();//新建一个FileReader reader.readAsText(files[0], "UTF-8");//读取文件 - reader.onload = function(evt){ //读取完文件之后会回来这里 + reader.onload = function (evt) { //读取完文件之后会回来这里 ref.trigger("onload", evt.target.result); }; } else { @@ -1210,9 +1180,9 @@ function nodesSelect2Init(selector, url) { data: function (params) { var page = params.page || 1; var query = { - search: params.term, - offset: (page -1) * 10, - limit: 10 + search: params.term, + offset: (page - 1) * 10, + limit: 10 }; return query }, @@ -1221,7 +1191,7 @@ function nodesSelect2Init(selector, url) { return {id: v.id, text: v.full_value} }); var more = !!data.next; - return {results: results, pagination: {"more": more }} + return {results: results, pagination: {"more": more}} } }, })