mirror of https://github.com/jumpserver/jumpserver
perf: 优化 asset info
parent
229e89af03
commit
9ec7a8ac61
|
@ -2,7 +2,6 @@
|
|||
#
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
@ -72,11 +71,13 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
|||
("platform", serializers.PlatformSerializer),
|
||||
("suggestion", serializers.MiniAssetSerializer),
|
||||
("gateways", serializers.GatewaySerializer),
|
||||
("spec_info", serializers.SpecSerializer),
|
||||
)
|
||||
rbac_perms = (
|
||||
("match", "assets.match_asset"),
|
||||
("platform", "assets.view_platform"),
|
||||
("gateways", "assets.view_gateway"),
|
||||
("spec_info", "assets.view_asset"),
|
||||
)
|
||||
extra_filter_backends = [LabelFilterBackend, IpInFilterBackend, NodeFilterBackend]
|
||||
|
||||
|
@ -94,6 +95,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
|||
serializer = super().get_serializer(instance=asset.platform)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(methods=["GET"], detail=True, url_path="spec-info")
|
||||
def spec_info(self, *args, **kwargs):
|
||||
asset = super().get_object()
|
||||
return Response(asset.spec_info)
|
||||
|
||||
@action(methods=["GET"], detail=True, url_path="gateways")
|
||||
def gateways(self, *args, **kwargs):
|
||||
asset = self.get_object()
|
||||
|
|
|
@ -10,8 +10,8 @@ from django.db import models
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from assets import const
|
||||
from common.utils import lazyproperty
|
||||
from common.db.fields import EncryptMixin
|
||||
from common.utils import lazyproperty
|
||||
from orgs.mixins.models import OrgManager, JMSOrgBaseModel
|
||||
from ..base import AbsConnectivity
|
||||
from ..platform import Platform
|
||||
|
@ -113,45 +113,47 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
|
|||
verbose_name=_("Nodes"))
|
||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
|
||||
info = models.JSONField(verbose_name='Info', default=dict, blank=True)
|
||||
info = models.JSONField(verbose_name='Info', default=dict, blank=True) # 资产的一些信息,如 硬件信息
|
||||
|
||||
objects = AssetManager.from_queryset(AssetQuerySet)()
|
||||
|
||||
def __str__(self):
|
||||
return '{0.name}({0.address})'.format(self)
|
||||
|
||||
@property
|
||||
def specific(self):
|
||||
instance = getattr(self, self.category, None)
|
||||
if not instance:
|
||||
return {}
|
||||
specific_fields = self.get_specific_fields(instance)
|
||||
@staticmethod
|
||||
def get_spec_values(instance, fields):
|
||||
info = {}
|
||||
for i in specific_fields:
|
||||
for i in fields:
|
||||
v = getattr(instance, i.name)
|
||||
if isinstance(i, models.JSONField) and not isinstance(v, (list, dict)):
|
||||
v = json.loads(v)
|
||||
info[i.name] = v
|
||||
return info
|
||||
|
||||
@property
|
||||
@lazyproperty
|
||||
def spec_info(self):
|
||||
instance = getattr(self, self.category, None)
|
||||
if not instance:
|
||||
return []
|
||||
specific_fields = self.get_specific_fields(instance)
|
||||
info = [
|
||||
{
|
||||
'label': i.verbose_name,
|
||||
'name': i.name,
|
||||
'value': getattr(instance, i.name)
|
||||
}
|
||||
for i in specific_fields
|
||||
]
|
||||
return info
|
||||
return {}
|
||||
spec_fields = self.get_spec_fields(instance)
|
||||
return self.get_spec_values(instance, spec_fields)
|
||||
|
||||
@staticmethod
|
||||
def get_spec_fields(instance, secret=False):
|
||||
spec_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr']
|
||||
spec_fields = [i for i in spec_fields if isinstance(i, EncryptMixin) == secret]
|
||||
return spec_fields
|
||||
|
||||
@lazyproperty
|
||||
def enabled_info(self):
|
||||
def secret_info(self):
|
||||
instance = getattr(self, self.category, None)
|
||||
if not instance:
|
||||
return {}
|
||||
spec_fields = self.get_spec_fields(instance, secret=True)
|
||||
return self.get_spec_values(instance, spec_fields)
|
||||
|
||||
@lazyproperty
|
||||
def auto_info(self):
|
||||
platform = self.platform
|
||||
automation = self.platform.automation
|
||||
return {
|
||||
|
@ -165,12 +167,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
|
|||
'gather_accounts_enabled': automation.gather_accounts_enabled,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_specific_fields(instance):
|
||||
specific_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr']
|
||||
specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)]
|
||||
return specific_fields
|
||||
|
||||
def get_target_ip(self):
|
||||
return self.address
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ __all__ = [
|
|||
'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer',
|
||||
'AssetTaskSerializer', 'AssetsTaskSerializer', 'AssetProtocolsSerializer',
|
||||
'AssetDetailSerializer', 'DetailMixin', 'AssetAccountSerializer',
|
||||
'AccountSecretSerializer'
|
||||
'AccountSecretSerializer', 'SpecSerializer'
|
||||
]
|
||||
|
||||
|
||||
|
@ -113,13 +113,25 @@ class AccountSecretSerializer(SecretReadableMixin, CommonModelSerializer):
|
|||
}
|
||||
|
||||
|
||||
class SpecSerializer(serializers.Serializer):
|
||||
# 数据库
|
||||
db_name = serializers.CharField(label=_("Database"), max_length=128, required=False)
|
||||
use_ssl = serializers.BooleanField(label=_("Use SSL"), required=False)
|
||||
allow_invalid_cert = serializers.BooleanField(label=_("Allow invalid cert"), required=False)
|
||||
# Web
|
||||
autofill = serializers.CharField(label=_("Auto fill"), required=False)
|
||||
username_selector = serializers.CharField(label=_("Username selector"), required=False)
|
||||
password_selector = serializers.CharField(label=_("Password selector"), required=False)
|
||||
submit_selector = serializers.CharField(label=_("Submit selector"), required=False)
|
||||
script = serializers.JSONField(label=_("Script"), required=False)
|
||||
|
||||
|
||||
class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSerializer):
|
||||
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
|
||||
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
|
||||
labels = AssetLabelSerializer(many=True, required=False, label=_('Label'))
|
||||
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
||||
accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account'))
|
||||
enabled_info = serializers.DictField(read_only=True, label=_('Enabled info'))
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
|
@ -127,11 +139,11 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
|
|||
fields_small = fields_mini + ['is_active', 'comment']
|
||||
fields_fk = ['domain', 'platform']
|
||||
fields_m2m = [
|
||||
'nodes', 'labels', 'protocols', 'nodes_display', 'accounts'
|
||||
'nodes', 'labels', 'protocols',
|
||||
'nodes_display', 'accounts'
|
||||
]
|
||||
read_only_fields = [
|
||||
'category', 'type', 'info', 'enabled_info',
|
||||
'connectivity', 'date_verified',
|
||||
'category', 'type', 'connectivity', 'date_verified',
|
||||
'created_by', 'date_created'
|
||||
]
|
||||
fields = fields_small + fields_fk + fields_m2m + read_only_fields
|
||||
|
@ -235,11 +247,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
|
|||
|
||||
class DetailMixin(serializers.Serializer):
|
||||
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
|
||||
spec_info = serializers.DictField(label=_('Spec info'), read_only=True)
|
||||
auto_info = serializers.DictField(read_only=True, label=_('Auto info'))
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
names = super().get_field_names(declared_fields, info)
|
||||
names.extend([
|
||||
'accounts', 'info', 'specific', 'spec_info'
|
||||
'accounts', 'info', 'spec_info', 'auto_info'
|
||||
])
|
||||
return names
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer):
|
|||
model = Asset
|
||||
fields = [
|
||||
'id', 'name', 'address', 'protocols',
|
||||
'category', 'type', 'org_id', 'specific'
|
||||
'category', 'type', 'org_id', 'spec_info',
|
||||
'secret_info',
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ class JMSInventory:
|
|||
'id': str(asset.id), 'name': asset.name, 'address': asset.address,
|
||||
'type': asset.type, 'category': asset.category,
|
||||
'protocol': asset.protocol, 'port': asset.port,
|
||||
'specific': asset.specific,
|
||||
'specific': asset.spec,
|
||||
'protocols': [{'name': p.name, 'port': p.port} for p in protocols],
|
||||
},
|
||||
'jms_account': {
|
||||
|
|
|
@ -11,7 +11,6 @@ if sys.platform == 'win32':
|
|||
)
|
||||
from common import wait_pid, BaseApplication
|
||||
|
||||
|
||||
_default_path = r'C:\Program Files\PremiumSoft\Navicat Premium 16\navicat.exe'
|
||||
|
||||
|
||||
|
@ -24,7 +23,7 @@ class AppletApplication(BaseApplication):
|
|||
self.privileged = self.account.privileged
|
||||
self.host = self.asset.address
|
||||
self.port = self.asset.get_protocol_port(self.protocol)
|
||||
self.db = self.asset.specific.db_name
|
||||
self.db = self.asset.spec.db_name
|
||||
self.name = '%s-%s' % (self.host, self.db)
|
||||
self.pid = None
|
||||
self.app = None
|
||||
|
|
Loading…
Reference in New Issue