diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index 50c037df9..b3855eba1 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -43,6 +43,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet): queryset = super().get_queryset() admin_user_id = self.request.query_params.get('admin_user_id') node_id = self.request.query_params.get("node_id") + show_current_asset = self.request.query_params.get("show_current_asset") if admin_user_id: admin_user = get_object_or_404(AdminUser, id=admin_user_id) @@ -51,8 +52,11 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet): node = get_object_or_404(Node, id=node_id) if not node.is_root(): queryset = queryset.filter( - nodes__key__regex='{}(:[0-9]+)*$'.format(node.key), + nodes__key__regex='^{}(:[0-9]+)*$'.format(node.key), ).distinct() + if show_current_asset and node_id: + queryset = queryset.filter(nodes=node_id).distinct() + return queryset diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index cc940757f..b0e974f5c 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -14,6 +14,7 @@ # limitations under the License. from rest_framework import generics, mixins +from rest_framework.serializers import ValidationError from rest_framework.views import APIView from rest_framework.response import Response from rest_framework_bulk import BulkModelViewSet @@ -41,7 +42,14 @@ __all__ = [ class NodeViewSet(BulkModelViewSet): queryset = Node.objects.all() permission_classes = (IsSuperUser,) - serializer_class = serializers.NodeSerializer + # serializer_class = serializers.NodeSerializer + + def get_serializer_class(self): + show_current_asset = self.request.query_params.get('show_current_asset') + if show_current_asset: + return serializers.NodeCurrentSerializer + else: + return serializers.NodeSerializer def perform_create(self, serializer): child_key = Node.root().get_next_child_key() @@ -83,16 +91,29 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView): serializer_class = serializers.NodeSerializer instance = None + def counter(self): + values = [ + child.value[child.value.rfind(' '):] + for child in self.get_object().get_children() + if child.value.startswith("新节点 ") + ] + values = [int(value) for value in values if value.strip().isdigit()] + count = max(values)+1 if values else 1 + return count + def post(self, request, *args, **kwargs): if not request.data.get("value"): - request.data["value"] = _("New node {}").format( - Node.root().get_next_child_key().split(":")[-1] - ) + request.data["value"] = _("New node {}").format(self.counter()) return super().post(request, *args, **kwargs) def create(self, request, *args, **kwargs): instance = self.get_object() value = request.data.get("value") + values = [child.value for child in instance.get_children()] + if value in values: + raise ValidationError( + 'The same level node name cannot be the same' + ) node = instance.create_child(value=value) return Response( {"id": node.id, "key": node.key, "value": node.value}, @@ -163,8 +184,9 @@ class NodeAddChildrenApi(generics.UpdateAPIView): for node in children: if not node: continue - node.parent = instance - node.save() + # node.parent = instance + # node.save() + node.set_parent(instance) return Response("OK") @@ -191,6 +213,9 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView): instance = self.get_object() if instance != Node.root(): instance.assets.remove(*tuple(assets)) + else: + assets = [asset for asset in assets if asset.nodes.count() > 1] + instance.assets.remove(*tuple(assets)) class NodeReplaceAssetsApi(generics.UpdateAPIView): diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py index b4e46cc78..1be316567 100644 --- a/apps/assets/api/system_user.py +++ b/apps/assets/api/system_user.py @@ -58,6 +58,9 @@ class SystemUserPushApi(generics.RetrieveAPIView): def retrieve(self, request, *args, **kwargs): system_user = self.get_object() + nodes = system_user.nodes.all() + for node in nodes: + system_user.assets.add(*tuple(node.get_all_assets())) task = push_system_user_to_assets_manual.delay(system_user) return Response({"task": task.id}) diff --git a/apps/assets/models/base.py b/apps/assets/models/base.py index eda00a79a..11afd92cf 100644 --- a/apps/assets/models/base.py +++ b/apps/assets/models/base.py @@ -104,10 +104,15 @@ class AssetUser(models.Model): if update_fields: self.save(update_fields=update_fields) + def clear_auth(self): + self._password = '' + self._private_key = '' + self.save() + def auto_gen_auth(self): password = str(uuid.uuid4()) private_key, public_key = ssh_key_gen( - username=self.username, password=password + username=self.username ) self.set_auth(password=password, private_key=private_key, diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 7939ad1e9..5ee97af9b 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -2,7 +2,7 @@ # import uuid -from django.db import models +from django.db import models, transaction from django.utils.translation import ugettext_lazy as _ @@ -12,7 +12,10 @@ __all__ = ['Node'] class Node(models.Model): id = models.UUIDField(default=uuid.uuid4, primary_key=True) key = models.CharField(unique=True, max_length=64, verbose_name=_("Key")) # '1:1:1:1' - value = models.CharField(max_length=128, unique=True, verbose_name=_("Value")) + # value = models.CharField( + # max_length=128, unique=True, verbose_name=_("Value") + # ) + value = models.CharField(max_length=128, verbose_name=_("Value")) child_mark = models.IntegerField(default=0) date_create = models.DateTimeField(auto_now_add=True) @@ -36,6 +39,16 @@ class Node(models.Model): def level(self): return len(self.key.split(':')) + def set_parent(self, instance): + children = self.get_all_children() + old_key = self.key + with transaction.atomic(): + self.parent = instance + for child in children: + child.key = child.key.replace(old_key, self.key, 1) + child.save() + self.save() + def get_next_child_key(self): mark = self.child_mark self.child_mark += 1 @@ -48,7 +61,7 @@ class Node(models.Model): return child def get_children(self): - return self.__class__.objects.filter(key__regex=r'{}:[0-9]+$'.format(self.key)) + return self.__class__.objects.filter(key__regex=r'^{}:[0-9]+$'.format(self.key)) def get_all_children(self): return self.__class__.objects.filter(key__startswith='{}:'.format(self.key)) @@ -75,6 +88,11 @@ class Node(models.Model): assets = Asset.objects.filter(nodes__in=nodes).distinct() return assets + def get_current_assets(self): + from .asset import Asset + assets = Asset.objects.filter(nodes=self).distinct() + return assets + def has_assets(self): return self.get_all_assets() diff --git a/apps/assets/serializers/node.py b/apps/assets/serializers/node.py index 5b58ff241..b191b0a4f 100644 --- a/apps/assets/serializers/node.py +++ b/apps/assets/serializers/node.py @@ -9,7 +9,7 @@ from .asset import AssetGrantedSerializer __all__ = [ 'NodeSerializer', "NodeGrantedSerializer", "NodeAddChildrenSerializer", - "NodeAssetsSerializer", + "NodeAssetsSerializer", "NodeCurrentSerializer", ] @@ -51,6 +51,17 @@ class NodeSerializer(serializers.ModelSerializer): fields = ['id', 'key', 'value', 'parent', 'assets_amount', 'is_node'] list_serializer_class = BulkListSerializer + def validate(self, data): + value = data.get('value') + instance = self.instance if self.instance else Node.root() + children = instance.parent.get_children().exclude(key=instance.key) + values = [child.value for child in children] + if value in values: + raise serializers.ValidationError( + 'The same level node name cannot be the same' + ) + return data + @staticmethod def get_parent(obj): return obj.parent.id @@ -66,6 +77,12 @@ class NodeSerializer(serializers.ModelSerializer): return fields +class NodeCurrentSerializer(NodeSerializer): + @staticmethod + def get_assets_amount(obj): + return obj.get_current_assets().count() + + class NodeAssetsSerializer(serializers.ModelSerializer): assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html index c5cd48857..db7d165e0 100644 --- a/apps/assets/templates/assets/_asset_list_modal.html +++ b/apps/assets/templates/assets/_asset_list_modal.html @@ -98,7 +98,10 @@ function initTree2() { $.get("{% url 'api-assets:node-list' %}", function(data, status){ $.each(data, function (index, value) { value["pId"] = value["parent"]; - value["open"] = true; + {#value["open"] = true;#} + if (value["key"] === "0") { + value["open"] = true; + } value["name"] = value["value"] + ' (' + value['assets_amount'] + ')'; value['value'] = value['value']; }); diff --git a/apps/assets/templates/assets/_system_user.html b/apps/assets/templates/assets/_system_user.html index 528e271e6..314967d22 100644 --- a/apps/assets/templates/assets/_system_user.html +++ b/apps/assets/templates/assets/_system_user.html @@ -55,7 +55,7 @@ {% bootstrap_field form.private_key_file layout="horizontal" %}
- +
{{ form.auto_push}}
@@ -79,43 +79,50 @@
{% endblock %} {% block custom_foot_js %} - +$(document).ready(function () { + $('.select2').select2(); + authFieldsDisplay(); + protocolChange(); +}) +.on('change', protocol_id, function(){ + protocolChange(); +}) +.on('change', auto_generate_key, function(){ + authFieldsDisplay(); +}); + + {% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/admin_user_assets.html b/apps/assets/templates/assets/admin_user_assets.html index 80ff0cd5f..31314392f 100644 --- a/apps/assets/templates/assets/admin_user_assets.html +++ b/apps/assets/templates/assets/admin_user_assets.html @@ -124,7 +124,7 @@ $(document).ready(function () { var success = function (data) { var task_id = data.task; var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id); - window.open(url, '', 'width=800,height=600') + window.open(url, '', 'width=800,height=600,left=400,top=400') }; APIUpdateAttr({ url: the_url, diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html index 0b1b2865a..b07a7c348 100644 --- a/apps/assets/templates/assets/asset_detail.html +++ b/apps/assets/templates/assets/asset_detail.html @@ -190,7 +190,7 @@ @@ -204,7 +204,7 @@ {% for node in asset.nodes.all %} - {{ node.name }} + {{ node }} diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index 04ba11e57..0100e1e7f 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -47,7 +47,6 @@
-
@@ -87,7 +86,7 @@ {% trans 'IP' %} {% trans 'Hardware' %} {% trans 'Active' %} - {% trans 'Reachable' %} +{# {% trans 'Reachable' %}#} {% trans 'Action' %} @@ -127,6 +126,9 @@
  • +
  • + + @@ -157,26 +159,35 @@ function initTable() { $(td).html('') } }}, - {targets: 5, createdCell: function (td, cellData) { - if (cellData === 'Unknown'){ - $(td).html('') - } else if (!cellData) { - $(td).html('') - } else { - $(td).html('') - } - }}, - {targets: 6, createdCell: function (td, cellData, rowData) { + + {#{targets: 5, createdCell: function (td, cellData) {#} + {# if (cellData === 'Unknown'){#} + {# $(td).html('')#} + {# } else if (!cellData) {#} + {# $(td).html('')#} + {# } else {#} + {# $(td).html('')#} + {# }#} + {# }},#} + + {targets: 5, createdCell: function (td, cellData, rowData) { var update_btn = '{% trans "Update" %}'.replace("{{ DEFAULT_PK }}", cellData); var del_btn = '{% trans "Delete" %}'.replace('{{ DEFAULT_PK }}', cellData); $(td).html(update_btn + del_btn) }} ], ajax_url: '{% url "api-assets:asset-list" %}', + + {#columns: [#} + {# {data: "id"}, {data: "hostname" }, {data: "ip" },#} + {# {data: "cpu_cores"}, {data: "is_active", orderable: false },#} + {# {data: "is_connective", orderable: false}, {data: "id", orderable: false }#} + {#],#} + columns: [ {data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "cpu_cores"}, {data: "is_active", orderable: false }, - {data: "is_connective", orderable: false}, {data: "id", orderable: false } + {data: "id", orderable: false } ], op_html: $('#actions').html() }; @@ -200,6 +211,8 @@ function addTreeNode() { }; newNode.checked = zTree.getSelectedNodes()[0].checked; zTree.addNodes(parentNode, 0, newNode); + var node = zTree.getNodeByParam('id', newNode.id, parentNode) + zTree.editName(node); } else { alert("{% trans 'Create node failed' %}") } @@ -230,9 +243,9 @@ function removeTreeNode() { function editTreeNode() { hideRMenu(); - var current_node = zTree.getSelectedNodes()[0]; - if (!current_node){ - return + var current_node = zTree.getSelectedNodes()[0]; + if (!current_node){ + return } if (current_node.value) { current_node.name = current_node.value; @@ -290,6 +303,7 @@ function onRename(event, treeId, treeNode, isCancel){ function onSelected(event, treeNode) { var url = asset_table.ajax.url(); url = setUrlParam(url, "node_id", treeNode.id); + url = setUrlParam(url, "show_current_asset", getCookie('show_current_asset')); setCookie('node_selected', treeNode.id); asset_table.ajax.url(url); asset_table.ajax.reload(); @@ -382,12 +396,13 @@ function initTree() { }; var zNodes = []; - $.get("{% url 'api-assets:node-list' %}", function(data, status){ + var query_params = {'show_current_asset': getCookie('show_current_asset')}; + $.get("{% url 'api-assets:node-list' %}", query_params, function(data, status){ $.each(data, function (index, value) { value["pId"] = value["parent"]; - {#if (value["key"] === "0") {#} - value["open"] = true; - {# }#} + if (value["key"] === "0") { + value["open"] = true; + } value["name"] = value["value"] + ' (' + value['assets_amount'] + ')'; value['value'] = value['value']; }); @@ -417,6 +432,13 @@ function toggle() { $(document).ready(function(){ initTable(); initTree(); + + if(getCookie('show_current_asset') === 'yes'){ + $('#show_all_asset').css('display', 'inline-block'); + } + else{ + $('#show_current_asset').css('display', 'inline-block'); + } }) .on('click', '.labels li', function () { var val = $(this).text(); @@ -535,6 +557,20 @@ $(document).ready(function(){ flash_message: false }); }) +.on('click', '.btn-show-current-asset', function(){ + hideRMenu(); + $(this).css('display', 'none'); + $('#show_all_asset').css('display', 'inline-block'); + setCookie('show_current_asset', 'yes'); + location.reload(); +}) +.on('click', '.btn-show-all-asset', function(){ + hideRMenu(); + $(this).css('display', 'none'); + $('#show_current_asset').css('display', 'inline-block'); + setCookie('show_current_asset', ''); + location.reload(); +}) .on('click', '.btn_asset_delete', function () { var $this = $(this); var $data_table = $("#asset_list_table").DataTable(); diff --git a/apps/assets/templates/assets/domain_gateway_list.html b/apps/assets/templates/assets/domain_gateway_list.html index 581f6c08a..c2d5528ee 100644 --- a/apps/assets/templates/assets/domain_gateway_list.html +++ b/apps/assets/templates/assets/domain_gateway_list.html @@ -85,6 +85,9 @@ function initTable() { var update_btn = '{% trans "Update" %}'.replace('{{ DEFAULT_PK }}', cellData); var del_btn = '{% trans "Delete" %}'.replace('{{ DEFAULT_PK }}', cellData); var test_btn = '{% trans "Test connection" %}'.replace('{{ DEFAULT_PK }}', cellData); + if(rowData.protocol === 'rdp'){ + test_btn = '{% trans "Test connection" %}'.replace('{{ DEFAULT_PK }}', cellData); + } $(td).html(update_btn + test_btn + del_btn) }} ], @@ -120,7 +123,6 @@ $(document).ready(function(){ success_message: "可连接", fail_message: "连接失败" }) - -}) +}); {% endblock %} diff --git a/apps/assets/templates/assets/gateway_create_update.html b/apps/assets/templates/assets/gateway_create_update.html index 7d6800c41..e0b10ba73 100644 --- a/apps/assets/templates/assets/gateway_create_update.html +++ b/apps/assets/templates/assets/gateway_create_update.html @@ -66,3 +66,28 @@ {% endblock %} + +{% block custom_foot_js %} + +{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index a02bf1e44..cc686a62b 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -64,14 +64,14 @@ {% trans 'Protocol' %}: - {{ system_user.protocol }} + {{ system_user.protocol }} - + {% trans 'Sudo' %}: {{ system_user.sudo }} {% if system_user.shell %} - + {% trans 'Shell' %}: {{ system_user.shell }} @@ -107,7 +107,7 @@
    -
    +
    {% trans 'Quick update' %}
    @@ -236,6 +236,9 @@ function updateSystemUserNode(nodes) { } jumpserver.nodes_selected = {}; $(document).ready(function () { + if($('#id_protocol_type').text() === 'rdp'){ + $('.only-ssh').addClass('hidden') + } $('.select2').select2() .on('select2:select', function(evt) { var data = evt.params.data; @@ -296,7 +299,7 @@ $(document).ready(function () { var success = function (data) { var task_id = data.task; var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id); - window.open(url, '', 'width=800,height=600') + window.open(url, '', 'width=800,height=600,left=400,top=400') }; APIUpdateAttr({ url: the_url, diff --git a/apps/assets/templates/assets/system_user_update.html b/apps/assets/templates/assets/system_user_update.html index 46ef8d6a3..7e1590db5 100644 --- a/apps/assets/templates/assets/system_user_update.html +++ b/apps/assets/templates/assets/system_user_update.html @@ -15,10 +15,3 @@
    {% endblock %} -{% block custom_foot_js %} - -{% endblock %} \ No newline at end of file diff --git a/apps/common/api.py b/apps/common/api.py index 4b74b6b0d..209d09747 100644 --- a/apps/common/api.py +++ b/apps/common/api.py @@ -96,14 +96,7 @@ class LDAPTestingAPI(APIView): class DjangoSettingsAPI(APIView): def get(self, request): - if not settings.DEBUG: - return Response('Only debug mode support') - - configs = {} - for i in dir(settings): - if i.isupper(): - configs[i] = str(getattr(settings, i)) - return Response(configs) + return Response('Danger, Close now') diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 038e65f43..36220e321 100644 Binary files a/apps/i18n/zh/LC_MESSAGES/django.mo and b/apps/i18n/zh/LC_MESSAGES/django.mo differ diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po index 2dc77a3fd..8f95f9291 100644 --- a/apps/i18n/zh/LC_MESSAGES/django.po +++ b/apps/i18n/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: 2018-04-27 11:39+0800\n" +"POT-Creation-Date: 2018-05-08 17:24+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -17,15 +17,15 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: assets/api/node.py:88 +#: assets/api/node.py:96 msgid "New node {}" msgstr "新节点 {}" -#: assets/api/node.py:217 +#: assets/api/node.py:225 msgid "更新节点资产硬件信息: {}" msgstr "" -#: assets/api/node.py:230 +#: assets/api/node.py:238 msgid "测试节点下资产是否可连接: {}" msgstr "" @@ -46,7 +46,7 @@ msgstr "管理用户" #: assets/forms/asset.py:30 assets/forms/asset.py:69 assets/forms/asset.py:125 #: assets/templates/assets/asset_create.html:35 #: assets/templates/assets/asset_create.html:37 -#: assets/templates/assets/asset_list.html:75 +#: assets/templates/assets/asset_list.html:74 #: assets/templates/assets/asset_update.html:40 #: assets/templates/assets/asset_update.html:42 #: assets/templates/assets/user_asset_list.html:34 @@ -206,7 +206,7 @@ msgstr "高优先级的系统用户将会作为默认登录用户" #: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/admin_user_assets.html:52 #: assets/templates/assets/asset_detail.html:61 -#: assets/templates/assets/asset_list.html:87 +#: assets/templates/assets/asset_list.html:86 #: assets/templates/assets/domain_gateway_list.html:57 #: assets/templates/assets/system_user_asset.html:50 #: assets/templates/assets/user_asset_list.html:46 common/forms.py:144 @@ -220,7 +220,7 @@ msgstr "IP" #: assets/models/asset.py:62 assets/templates/assets/_asset_list_modal.html:45 #: assets/templates/assets/admin_user_assets.html:51 #: assets/templates/assets/asset_detail.html:57 -#: assets/templates/assets/asset_list.html:86 +#: assets/templates/assets/asset_list.html:85 #: assets/templates/assets/system_user_asset.html:49 #: assets/templates/assets/user_asset_list.html:45 common/forms.py:143 #: perms/templates/perms/asset_permission_asset.html:54 @@ -650,7 +650,7 @@ msgstr "重置" #: assets/templates/assets/admin_user_create_update.html:46 #: assets/templates/assets/asset_bulk_update.html:24 #: assets/templates/assets/asset_create.html:67 -#: assets/templates/assets/asset_list.html:108 +#: assets/templates/assets/asset_list.html:107 #: assets/templates/assets/asset_update.html:71 #: assets/templates/assets/domain_create_update.html:17 #: assets/templates/assets/gateway_create_update.html:59 @@ -699,7 +699,6 @@ msgstr "资产列表" #: assets/templates/assets/admin_user_assets.html:54 #: assets/templates/assets/admin_user_list.html:26 -#: assets/templates/assets/asset_list.html:90 #: assets/templates/assets/system_user_asset.html:52 #: assets/templates/assets/system_user_list.html:30 #: users/templates/users/user_group_granted_asset.html:47 @@ -728,7 +727,7 @@ msgstr "测试" #: assets/templates/assets/admin_user_detail.html:24 #: assets/templates/assets/admin_user_list.html:85 #: assets/templates/assets/asset_detail.html:24 -#: assets/templates/assets/asset_list.html:170 +#: assets/templates/assets/asset_list.html:174 #: assets/templates/assets/domain_detail.html:24 #: assets/templates/assets/domain_detail.html:103 #: assets/templates/assets/domain_gateway_list.html:85 @@ -752,7 +751,7 @@ msgstr "更新" #: assets/templates/assets/admin_user_detail.html:28 #: assets/templates/assets/admin_user_list.html:86 #: assets/templates/assets/asset_detail.html:28 -#: assets/templates/assets/asset_list.html:171 +#: assets/templates/assets/asset_list.html:175 #: assets/templates/assets/domain_detail.html:28 #: assets/templates/assets/domain_detail.html:104 #: assets/templates/assets/domain_gateway_list.html:86 @@ -783,7 +782,7 @@ msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:200 -#: assets/templates/assets/asset_list.html:600 +#: assets/templates/assets/asset_list.html:634 #: assets/templates/assets/system_user_detail.html:183 #: assets/templates/assets/system_user_list.html:138 templates/_modal.html:22 #: terminal/templates/terminal/session_detail.html:108 @@ -815,7 +814,7 @@ msgid "Ratio" msgstr "比例" #: assets/templates/assets/admin_user_list.html:30 -#: assets/templates/assets/asset_list.html:91 +#: assets/templates/assets/asset_list.html:90 #: assets/templates/assets/domain_gateway_list.html:62 #: assets/templates/assets/domain_list.html:18 #: assets/templates/assets/label_list.html:17 @@ -856,7 +855,7 @@ msgid "Quick modify" msgstr "快速修改" #: assets/templates/assets/asset_detail.html:143 -#: assets/templates/assets/asset_list.html:89 +#: assets/templates/assets/asset_list.html:88 #: assets/templates/assets/user_asset_list.html:47 perms/models.py:35 #: perms/models.py:79 #: perms/templates/perms/asset_permission_create_update.html:47 @@ -886,89 +885,97 @@ msgstr "刷新" msgid "Update successfully!" msgstr "更新成功" -#: assets/templates/assets/asset_list.html:63 assets/views/asset.py:97 +#: assets/templates/assets/asset_list.html:62 assets/views/asset.py:97 msgid "Create asset" msgstr "创建资产" -#: assets/templates/assets/asset_list.html:67 +#: assets/templates/assets/asset_list.html:66 #: users/templates/users/user_list.html:7 msgid "Import" msgstr "导入" -#: assets/templates/assets/asset_list.html:70 +#: assets/templates/assets/asset_list.html:69 #: users/templates/users/user_list.html:10 msgid "Export" msgstr "导出" -#: assets/templates/assets/asset_list.html:88 +#: assets/templates/assets/asset_list.html:87 msgid "Hardware" msgstr "硬件" -#: assets/templates/assets/asset_list.html:100 +#: assets/templates/assets/asset_list.html:99 #: users/templates/users/user_list.html:37 msgid "Delete selected" msgstr "批量删除" -#: assets/templates/assets/asset_list.html:101 +#: assets/templates/assets/asset_list.html:100 #: users/templates/users/user_list.html:38 msgid "Update selected" msgstr "批量更新" -#: assets/templates/assets/asset_list.html:102 +#: assets/templates/assets/asset_list.html:101 msgid "Remove from this node" msgstr "从节点移除" -#: assets/templates/assets/asset_list.html:103 +#: assets/templates/assets/asset_list.html:102 #: users/templates/users/user_list.html:39 msgid "Deactive selected" msgstr "禁用所选" -#: assets/templates/assets/asset_list.html:104 +#: assets/templates/assets/asset_list.html:103 #: users/templates/users/user_list.html:40 msgid "Active selected" msgstr "激活所选" -#: assets/templates/assets/asset_list.html:121 +#: assets/templates/assets/asset_list.html:120 msgid "Add node" msgstr "新建节点" -#: assets/templates/assets/asset_list.html:122 +#: assets/templates/assets/asset_list.html:121 msgid "Rename node" msgstr "重命名节点" -#: assets/templates/assets/asset_list.html:123 +#: assets/templates/assets/asset_list.html:122 msgid "Delete node" msgstr "删除节点" -#: assets/templates/assets/asset_list.html:125 +#: assets/templates/assets/asset_list.html:124 msgid "Add assets to node" msgstr "添加资产到节点" -#: assets/templates/assets/asset_list.html:126 +#: assets/templates/assets/asset_list.html:125 msgid "Move assets to node" msgstr "移动资产到节点" -#: assets/templates/assets/asset_list.html:128 +#: assets/templates/assets/asset_list.html:127 msgid "Refresh node hardware info" msgstr "更新节点资产硬件信息" -#: assets/templates/assets/asset_list.html:129 +#: assets/templates/assets/asset_list.html:128 msgid "Test node connective" msgstr "测试节点资产可连接性" -#: assets/templates/assets/asset_list.html:204 +#: assets/templates/assets/asset_list.html:130 +msgid "Display only current node assets" +msgstr "仅显示当前节点资产" + +#: assets/templates/assets/asset_list.html:131 +msgid "Displays all child node assets" +msgstr "显示所有子节点资产" + +#: assets/templates/assets/asset_list.html:215 msgid "Create node failed" msgstr "创建节点失败" -#: assets/templates/assets/asset_list.html:216 +#: assets/templates/assets/asset_list.html:227 msgid "Have child node, cancel" msgstr "存在子节点,不能删除" -#: assets/templates/assets/asset_list.html:218 +#: assets/templates/assets/asset_list.html:229 msgid "Have assets, cancel" msgstr "存在资产,不能删除" -#: assets/templates/assets/asset_list.html:595 +#: assets/templates/assets/asset_list.html:629 #: assets/templates/assets/system_user_list.html:133 #: users/templates/users/user_detail.html:357 #: users/templates/users/user_detail.html:382 @@ -977,20 +984,20 @@ msgstr "存在资产,不能删除" msgid "Are you sure?" msgstr "你确认吗?" -#: assets/templates/assets/asset_list.html:596 +#: assets/templates/assets/asset_list.html:630 msgid "This will delete the selected assets !!!" msgstr "删除选择资产" -#: assets/templates/assets/asset_list.html:604 +#: assets/templates/assets/asset_list.html:638 msgid "Asset Deleted." msgstr "已被删除" -#: assets/templates/assets/asset_list.html:605 -#: assets/templates/assets/asset_list.html:610 +#: assets/templates/assets/asset_list.html:639 +#: assets/templates/assets/asset_list.html:644 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:609 +#: assets/templates/assets/asset_list.html:643 msgid "Asset Deleting failed." msgstr "删除失败" diff --git a/apps/ops/api.py b/apps/ops/api.py index 0134fbd4a..35c9b8dc5 100644 --- a/apps/ops/api.py +++ b/apps/ops/api.py @@ -72,7 +72,7 @@ class CeleryTaskLogApi(generics.RetrieveAPIView): def get(self, request, *args, **kwargs): mark = request.query_params.get("mark") or str(uuid.uuid4()) - task = super().get_object() + task = self.get_object() log_path = task.full_log_path if not log_path or not os.path.isfile(log_path): diff --git a/apps/ops/templates/ops/adhoc_history_detail.html b/apps/ops/templates/ops/adhoc_history_detail.html index 16adbc4e3..b8a48d4e5 100644 --- a/apps/ops/templates/ops/adhoc_history_detail.html +++ b/apps/ops/templates/ops/adhoc_history_detail.html @@ -19,7 +19,7 @@ {% trans 'Run history detail' %}
  • - {% trans 'Output' %} + {% trans 'Output' %}
  • diff --git a/apps/ops/templates/ops/celery_task_log.html b/apps/ops/templates/ops/celery_task_log.html index 9b0826949..13885c2cc 100644 --- a/apps/ops/templates/ops/celery_task_log.html +++ b/apps/ops/templates/ops/celery_task_log.html @@ -2,38 +2,25 @@ term.js + + -
    -
    +
    -
    - -