diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index a89698c66..f8ed14cb9 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -40,8 +40,8 @@ class AssetViewSet(IDInCacheFilterMixin, LabelFilter, ApiMessageMixin, BulkModel """ API endpoint that allows Asset to be viewed or edited. """ - filter_fields = ("hostname", "ip") - search_fields = filter_fields + filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id") + search_fields = ("hostname", "ip") ordering_fields = ("hostname", "ip", "port", "cpu_cores") queryset = Asset.objects.all() serializer_class = serializers.AssetSerializer diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py index 573928a76..2b2eb18a5 100644 --- a/apps/assets/api/asset_user.py +++ b/apps/assets/api/asset_user.py @@ -96,7 +96,7 @@ class AssetUserViewSet(IDInCacheFilterMixin, BulkModelViewSet): assets = [asset] elif node_id: node = get_object_or_404(Node, id=node_id) - assets = node.assets.all() + assets = node.get_all_assets() if username: kwargs['username'] = username diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 4450751dd..4f7509d4f 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -74,7 +74,7 @@ class Protocol(models.Model): validators=PORT_VALIDATORS) def __str__(self): - return "{}:{}".format(self.name, self.port) + return "{}/{}".format(self.name, self.port) class Asset(OrgModelMixin): diff --git a/apps/assets/models/base.py b/apps/assets/models/base.py index 42fef8d04..d58b97a18 100644 --- a/apps/assets/models/base.py +++ b/apps/assets/models/base.py @@ -30,8 +30,8 @@ class AssetUser(OrgModelMixin): _private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ]) _public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key')) comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True) - date_updated = models.DateTimeField(auto_now=True) + date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created")) + date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) UNREACHABLE, REACHABLE, UNKNOWN = range(0, 3) diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index 0298f776c..2ef970b23 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -22,8 +22,25 @@ class ProtocolSerializer(serializers.ModelSerializer): fields = ["name", "port"] +class ProtocolsRelatedField(serializers.RelatedField): + def to_representation(self, value): + return str(value) + + def to_internal_value(self, data): + if '/' not in data: + raise ValidationError("protocol not contain /: {}".format(data)) + v = data.split("/") + if len(v) != 2: + raise ValidationError("protocol format should be name/port: {}".format(data)) + name, port = v + cleaned_data = {"name": name, "port": port} + return cleaned_data + + class AssetSerializer(BulkOrgResourceModelSerializer): - protocols = ProtocolSerializer(many=True) + protocols = ProtocolsRelatedField( + many=True, queryset=Protocol.objects.all(), label=_("Protocols") + ) """ 资产的数据结构 @@ -47,6 +64,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer): 'created_by', 'date_created', ) extra_kwargs = { + 'protocol': {'write_only': True}, + 'port': {'write_only': True}, 'hardware_info': {'label': _('Hardware info')}, 'connectivity': {'label': _('Connectivity')}, 'org_name': {'label': _('Org name')} @@ -61,6 +80,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer): @staticmethod def validate_protocols(attr): + protocols_serializer = ProtocolSerializer(data=attr, many=True) + protocols_serializer.is_valid(raise_exception=True) protocols_name = [i.get("name", "ssh") for i in attr] errors = [{} for i in protocols_name] for i, name in enumerate(protocols_name): @@ -71,7 +92,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer): return attr def create(self, validated_data): - protocols_data = validated_data.pop("protocols") + protocols_data = validated_data.pop("protocols", []) # 兼容老的api protocol = validated_data.get("protocol") @@ -91,7 +112,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer): return instance def update(self, instance, validated_data): - protocols_data = validated_data.pop("protocols", None) + protocols_data = validated_data.pop("protocols", []) # 兼容老的api protocol = validated_data.get("protocol") diff --git a/apps/assets/serializers/asset_user.py b/apps/assets/serializers/asset_user.py index fe04b675a..bb5f83142 100644 --- a/apps/assets/serializers/asset_user.py +++ b/apps/assets/serializers/asset_user.py @@ -7,7 +7,6 @@ from rest_framework import serializers from ..models import AuthBook, Asset from ..backends import AssetUserManager from common.utils import validate_ssh_private_key -from common.mixins import BulkSerializerMixin from common.serializers import AdaptedBulkListSerializer from orgs.mixins import BulkOrgResourceModelSerializer diff --git a/apps/assets/templates/assets/_asset_user_auth_view_modal.html b/apps/assets/templates/assets/_asset_user_auth_view_modal.html index 4164f2a2d..6fbd48fcd 100644 --- a/apps/assets/templates/assets/_asset_user_auth_view_modal.html +++ b/apps/assets/templates/assets/_asset_user_auth_view_modal.html @@ -35,11 +35,10 @@ -{% include 'authentication/_mfa_confirm_modal.html' %} diff --git a/apps/assets/templates/assets/_asset_user_list.html b/apps/assets/templates/assets/_asset_user_list.html index 4f7050504..ccf8c8ef1 100644 --- a/apps/assets/templates/assets/_asset_user_list.html +++ b/apps/assets/templates/assets/_asset_user_list.html @@ -25,12 +25,14 @@ {% include 'assets/_asset_user_auth_update_modal.html' %} {% include 'assets/_asset_user_auth_view_modal.html' %} +{% include 'authentication/_mfa_confirm_modal.html' %} \ No newline at end of file diff --git a/apps/assets/templates/assets/asset_create.html b/apps/assets/templates/assets/asset_create.html index 097cda11e..ffd7516e3 100644 --- a/apps/assets/templates/assets/asset_create.html +++ b/apps/assets/templates/assets/asset_create.html @@ -201,49 +201,47 @@ $(document).ready(function () { } $(this).parent().parent().find(".protocol-port").val(port); }) - -{% block form_submit %} - + }); + + protocols = $.map(protocols, function (v) { + return v.name + '/' + v.port + }); + data["protocols"] = protocols; + if (typeof data.labels === "string") { + data["labels"] = [data["labels"]]; + } + if (typeof data["nodes"] == "string") { + data["nodes"] = [data["nodes"]] + } + var props = { + url: the_url, + data: data, + method: method, + form: form, + redirect_to: redirect_to + }; + formSubmit(props); + }) + {% endblock %} -{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html index e89b56283..2dcb569ac 100644 --- a/apps/assets/templates/assets/asset_detail.html +++ b/apps/assets/templates/assets/asset_detail.html @@ -72,8 +72,7 @@ {% trans 'Protocol' %} {% for protocol in asset.protocols.all %} - {{ protocol.name }}: - {{ protocol.port }} + {{ protocol }} {% endfor %} diff --git a/apps/assets/templates/assets/asset_update.html b/apps/assets/templates/assets/asset_update.html index 98de90ea5..4c23f7095 100644 --- a/apps/assets/templates/assets/asset_update.html +++ b/apps/assets/templates/assets/asset_update.html @@ -8,47 +8,8 @@ {% bootstrap_field form.number layout="horizontal" %} {% endblock %} -{% block form_submit %} - + var method = 'PUT'; {% endblock %} \ No newline at end of file diff --git a/apps/authentication/templates/authentication/_mfa_confirm_modal.html b/apps/authentication/templates/authentication/_mfa_confirm_modal.html index 9e1932911..0d7b794bb 100644 --- a/apps/authentication/templates/authentication/_mfa_confirm_modal.html +++ b/apps/authentication/templates/authentication/_mfa_confirm_modal.html @@ -22,32 +22,6 @@