mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-06-28 15:57:23 +00:00
perf: 优化 asset info
This commit is contained in:
parent
229e89af03
commit
9ec7a8ac61
@ -2,7 +2,6 @@
|
|||||||
#
|
#
|
||||||
import django_filters
|
import django_filters
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
@ -72,11 +71,13 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
|||||||
("platform", serializers.PlatformSerializer),
|
("platform", serializers.PlatformSerializer),
|
||||||
("suggestion", serializers.MiniAssetSerializer),
|
("suggestion", serializers.MiniAssetSerializer),
|
||||||
("gateways", serializers.GatewaySerializer),
|
("gateways", serializers.GatewaySerializer),
|
||||||
|
("spec_info", serializers.SpecSerializer),
|
||||||
)
|
)
|
||||||
rbac_perms = (
|
rbac_perms = (
|
||||||
("match", "assets.match_asset"),
|
("match", "assets.match_asset"),
|
||||||
("platform", "assets.view_platform"),
|
("platform", "assets.view_platform"),
|
||||||
("gateways", "assets.view_gateway"),
|
("gateways", "assets.view_gateway"),
|
||||||
|
("spec_info", "assets.view_asset"),
|
||||||
)
|
)
|
||||||
extra_filter_backends = [LabelFilterBackend, IpInFilterBackend, NodeFilterBackend]
|
extra_filter_backends = [LabelFilterBackend, IpInFilterBackend, NodeFilterBackend]
|
||||||
|
|
||||||
@ -94,6 +95,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
|||||||
serializer = super().get_serializer(instance=asset.platform)
|
serializer = super().get_serializer(instance=asset.platform)
|
||||||
return Response(serializer.data)
|
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")
|
@action(methods=["GET"], detail=True, url_path="gateways")
|
||||||
def gateways(self, *args, **kwargs):
|
def gateways(self, *args, **kwargs):
|
||||||
asset = self.get_object()
|
asset = self.get_object()
|
||||||
|
@ -10,8 +10,8 @@ from django.db import models
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from assets import const
|
from assets import const
|
||||||
from common.utils import lazyproperty
|
|
||||||
from common.db.fields import EncryptMixin
|
from common.db.fields import EncryptMixin
|
||||||
|
from common.utils import lazyproperty
|
||||||
from orgs.mixins.models import OrgManager, JMSOrgBaseModel
|
from orgs.mixins.models import OrgManager, JMSOrgBaseModel
|
||||||
from ..base import AbsConnectivity
|
from ..base import AbsConnectivity
|
||||||
from ..platform import Platform
|
from ..platform import Platform
|
||||||
@ -113,45 +113,47 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
|
|||||||
verbose_name=_("Nodes"))
|
verbose_name=_("Nodes"))
|
||||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||||
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
|
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)()
|
objects = AssetManager.from_queryset(AssetQuerySet)()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{0.name}({0.address})'.format(self)
|
return '{0.name}({0.address})'.format(self)
|
||||||
|
|
||||||
@property
|
@staticmethod
|
||||||
def specific(self):
|
def get_spec_values(instance, fields):
|
||||||
instance = getattr(self, self.category, None)
|
|
||||||
if not instance:
|
|
||||||
return {}
|
|
||||||
specific_fields = self.get_specific_fields(instance)
|
|
||||||
info = {}
|
info = {}
|
||||||
for i in specific_fields:
|
for i in fields:
|
||||||
v = getattr(instance, i.name)
|
v = getattr(instance, i.name)
|
||||||
if isinstance(i, models.JSONField) and not isinstance(v, (list, dict)):
|
if isinstance(i, models.JSONField) and not isinstance(v, (list, dict)):
|
||||||
v = json.loads(v)
|
v = json.loads(v)
|
||||||
info[i.name] = v
|
info[i.name] = v
|
||||||
return info
|
return info
|
||||||
|
|
||||||
@property
|
@lazyproperty
|
||||||
def spec_info(self):
|
def spec_info(self):
|
||||||
instance = getattr(self, self.category, None)
|
instance = getattr(self, self.category, None)
|
||||||
if not instance:
|
if not instance:
|
||||||
return []
|
return {}
|
||||||
specific_fields = self.get_specific_fields(instance)
|
spec_fields = self.get_spec_fields(instance)
|
||||||
info = [
|
return self.get_spec_values(instance, spec_fields)
|
||||||
{
|
|
||||||
'label': i.verbose_name,
|
@staticmethod
|
||||||
'name': i.name,
|
def get_spec_fields(instance, secret=False):
|
||||||
'value': getattr(instance, i.name)
|
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]
|
||||||
for i in specific_fields
|
return spec_fields
|
||||||
]
|
|
||||||
return info
|
|
||||||
|
|
||||||
@lazyproperty
|
@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
|
platform = self.platform
|
||||||
automation = self.platform.automation
|
automation = self.platform.automation
|
||||||
return {
|
return {
|
||||||
@ -165,12 +167,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel):
|
|||||||
'gather_accounts_enabled': automation.gather_accounts_enabled,
|
'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):
|
def get_target_ip(self):
|
||||||
return self.address
|
return self.address
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ __all__ = [
|
|||||||
'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer',
|
'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer',
|
||||||
'AssetTaskSerializer', 'AssetsTaskSerializer', 'AssetProtocolsSerializer',
|
'AssetTaskSerializer', 'AssetsTaskSerializer', 'AssetProtocolsSerializer',
|
||||||
'AssetDetailSerializer', 'DetailMixin', 'AssetAccountSerializer',
|
'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):
|
class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSerializer):
|
||||||
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
|
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
|
||||||
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
|
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
|
||||||
labels = AssetLabelSerializer(many=True, required=False, label=_('Label'))
|
labels = AssetLabelSerializer(many=True, required=False, label=_('Label'))
|
||||||
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
||||||
accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account'))
|
accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account'))
|
||||||
enabled_info = serializers.DictField(read_only=True, label=_('Enabled info'))
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
@ -127,11 +139,11 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
|
|||||||
fields_small = fields_mini + ['is_active', 'comment']
|
fields_small = fields_mini + ['is_active', 'comment']
|
||||||
fields_fk = ['domain', 'platform']
|
fields_fk = ['domain', 'platform']
|
||||||
fields_m2m = [
|
fields_m2m = [
|
||||||
'nodes', 'labels', 'protocols', 'nodes_display', 'accounts'
|
'nodes', 'labels', 'protocols',
|
||||||
|
'nodes_display', 'accounts'
|
||||||
]
|
]
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
'category', 'type', 'info', 'enabled_info',
|
'category', 'type', 'connectivity', 'date_verified',
|
||||||
'connectivity', 'date_verified',
|
|
||||||
'created_by', 'date_created'
|
'created_by', 'date_created'
|
||||||
]
|
]
|
||||||
fields = fields_small + fields_fk + fields_m2m + read_only_fields
|
fields = fields_small + fields_fk + fields_m2m + read_only_fields
|
||||||
@ -235,11 +247,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
|
|||||||
|
|
||||||
class DetailMixin(serializers.Serializer):
|
class DetailMixin(serializers.Serializer):
|
||||||
accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts'))
|
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):
|
def get_field_names(self, declared_fields, info):
|
||||||
names = super().get_field_names(declared_fields, info)
|
names = super().get_field_names(declared_fields, info)
|
||||||
names.extend([
|
names.extend([
|
||||||
'accounts', 'info', 'specific', 'spec_info'
|
'accounts', 'info', 'spec_info', 'auto_info'
|
||||||
])
|
])
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer):
|
|||||||
model = Asset
|
model = Asset
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'address', 'protocols',
|
'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,
|
'id': str(asset.id), 'name': asset.name, 'address': asset.address,
|
||||||
'type': asset.type, 'category': asset.category,
|
'type': asset.type, 'category': asset.category,
|
||||||
'protocol': asset.protocol, 'port': asset.port,
|
'protocol': asset.protocol, 'port': asset.port,
|
||||||
'specific': asset.specific,
|
'specific': asset.spec,
|
||||||
'protocols': [{'name': p.name, 'port': p.port} for p in protocols],
|
'protocols': [{'name': p.name, 'port': p.port} for p in protocols],
|
||||||
},
|
},
|
||||||
'jms_account': {
|
'jms_account': {
|
||||||
|
@ -11,7 +11,6 @@ if sys.platform == 'win32':
|
|||||||
)
|
)
|
||||||
from common import wait_pid, BaseApplication
|
from common import wait_pid, BaseApplication
|
||||||
|
|
||||||
|
|
||||||
_default_path = r'C:\Program Files\PremiumSoft\Navicat Premium 16\navicat.exe'
|
_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.privileged = self.account.privileged
|
||||||
self.host = self.asset.address
|
self.host = self.asset.address
|
||||||
self.port = self.asset.get_protocol_port(self.protocol)
|
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.name = '%s-%s' % (self.host, self.db)
|
||||||
self.pid = None
|
self.pid = None
|
||||||
self.app = None
|
self.app = None
|
||||||
|
Loading…
Reference in New Issue
Block a user