mirror of https://github.com/jumpserver/jumpserver
perf: 修改平台
parent
1ca0bdf843
commit
9d4a828c53
|
@ -21,7 +21,7 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
|||
search_fields = ['name']
|
||||
rbac_perms = {
|
||||
'categories': 'assets.view_platform',
|
||||
'type_limits': 'assets-view_platform'
|
||||
'type_constraints': 'assets-view_platform'
|
||||
}
|
||||
|
||||
@action(methods=['GET'], detail=False)
|
||||
|
@ -30,14 +30,13 @@ class AssetPlatformViewSet(JMSModelViewSet):
|
|||
serializer = self.get_serializer(data, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(methods=['GET'], detail=False, url_path='type-limits')
|
||||
def type_limits(self, request, *args, **kwargs):
|
||||
@action(methods=['GET'], detail=False, url_path='type-constraints')
|
||||
def type_constraints(self, request, *args, **kwargs):
|
||||
category = request.query_params.get('category')
|
||||
tp = request.query_params.get('type')
|
||||
limits = AllTypes.get_type_limits(category, tp)
|
||||
limits = AllTypes.get_constraints(category, tp)
|
||||
return Response(limits)
|
||||
|
||||
|
||||
def check_object_permissions(self, request, obj):
|
||||
if request.method.lower() in ['delete', 'put', 'patch'] and obj.internal:
|
||||
self.permission_denied(
|
||||
|
|
|
@ -12,8 +12,16 @@ __all__ = [
|
|||
|
||||
class PlatformMixin:
|
||||
@classmethod
|
||||
def platform_limits(cls):
|
||||
return {}
|
||||
def platform_constraints(cls):
|
||||
return {
|
||||
'has_domain': False,
|
||||
'has_su': False,
|
||||
'has_ping': False,
|
||||
'has_change_password': False,
|
||||
'has_verify_account': False,
|
||||
'has_create_account': False,
|
||||
'_protocols': []
|
||||
}
|
||||
|
||||
|
||||
class Category(PlatformMixin, models.TextChoices):
|
||||
|
@ -24,25 +32,30 @@ class Category(PlatformMixin, models.TextChoices):
|
|||
WEB = 'web', _("Web")
|
||||
|
||||
@classmethod
|
||||
def platform_limits(cls):
|
||||
def platform_constraints(cls) -> dict:
|
||||
return {
|
||||
cls.HOST: {
|
||||
'has_domain': True,
|
||||
'protocols_limit': ['ssh', 'rdp', 'vnc', 'telnet']
|
||||
'has_ping': True,
|
||||
'has_verify_account': True,
|
||||
'has_change_password': True,
|
||||
'has_create_account': True,
|
||||
'_protocols': ['ssh', 'telnet']
|
||||
},
|
||||
cls.NETWORK: {
|
||||
'has_domain': True,
|
||||
'protocols_limit': ['ssh', 'telnet']
|
||||
'_protocols': ['ssh', 'telnet']
|
||||
},
|
||||
cls.DATABASE: {
|
||||
'has_domain': True
|
||||
'has_domain': True,
|
||||
},
|
||||
cls.WEB: {
|
||||
'has_domain': False,
|
||||
'_protocols': []
|
||||
},
|
||||
cls.CLOUD: {
|
||||
'has_domain': False,
|
||||
'protocol_limit': []
|
||||
'_protocols': []
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,18 +70,17 @@ class HostTypes(PlatformMixin, models.TextChoices):
|
|||
OTHER_HOST = 'other_host', _("Other host")
|
||||
|
||||
@classmethod
|
||||
def platform_limits(cls):
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def get_default_port(cls):
|
||||
defaults = {
|
||||
cls.LINUX: 22,
|
||||
cls.WINDOWS: 3389,
|
||||
cls.UNIX: 22,
|
||||
cls.BSD: 22,
|
||||
cls.MACOS: 22,
|
||||
cls.MAINFRAME: 22,
|
||||
def platform_constraints(cls):
|
||||
return {
|
||||
cls.LINUX: {
|
||||
'_protocols': ['ssh', 'rdp', 'vnc', 'telnet']
|
||||
},
|
||||
cls.WINDOWS: {
|
||||
'_protocols': ['ssh', 'rdp', 'vnc']
|
||||
},
|
||||
cls.MACOS: {
|
||||
'_protocols': ['ssh', 'vnc']
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,11 +101,11 @@ class DatabaseTypes(PlatformMixin, models.TextChoices):
|
|||
REDIS = 'redis', 'Redis'
|
||||
|
||||
@classmethod
|
||||
def platform_limits(cls):
|
||||
def platform_constraints(cls):
|
||||
meta = {}
|
||||
for name, label in cls.choices:
|
||||
meta[name] = {
|
||||
'protocols_limit': [name]
|
||||
'protocols': [name]
|
||||
}
|
||||
return meta
|
||||
|
||||
|
@ -114,23 +126,25 @@ class AllTypes(metaclass=IncludesTextChoicesMeta):
|
|||
]
|
||||
|
||||
@classmethod
|
||||
def get_type_limits(cls, category, tp):
|
||||
limits = Category.platform_limits().get(category, {})
|
||||
def get_constraints(cls, category, tp):
|
||||
constraints = PlatformMixin.platform_constraints()
|
||||
category_constraints = Category.platform_constraints().get(category) or {}
|
||||
constraints.update(category_constraints)
|
||||
|
||||
types_cls = dict(cls.category_types()).get(category)
|
||||
if not types_cls:
|
||||
return {}
|
||||
types_limits = types_cls.platform_limits() or {}
|
||||
type_limits = types_limits.get(tp, {})
|
||||
limits.update(type_limits)
|
||||
return constraints
|
||||
type_constraints = types_cls.platform_constraints().get(tp) or {}
|
||||
constraints.update(type_constraints)
|
||||
|
||||
_protocols_limit = limits.get('protocols_limit', [])
|
||||
_protocols = constraints.pop('_protocols', [])
|
||||
default_ports = Protocol.default_ports()
|
||||
protocols_limit = []
|
||||
for p in _protocols_limit:
|
||||
protocols = []
|
||||
for p in _protocols:
|
||||
port = default_ports.get(p, 0)
|
||||
protocols_limit.append(f'{p}/{port}')
|
||||
limits['protocols_limit'] = protocols_limit
|
||||
return limits
|
||||
protocols.append({'name': p, 'port': port})
|
||||
constraints['protocols'] = protocols
|
||||
return constraints
|
||||
|
||||
@classmethod
|
||||
def category_types(cls):
|
||||
|
|
|
@ -11,16 +11,6 @@ class Migration(migrations.Migration):
|
|||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='admin_user_default',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.systemuser', verbose_name='Admin user default'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='admin_user_enabled',
|
||||
field=models.BooleanField(default=True, verbose_name='Admin user enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='domain_default',
|
||||
|
@ -34,13 +24,63 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='protocols_default',
|
||||
field=models.CharField(blank=True, default='', max_length=128, verbose_name='Protocols default'),
|
||||
field=models.JSONField(blank=True, default=list, max_length=128, verbose_name='Protocols default'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='protocols_enabled',
|
||||
field=models.BooleanField(default=True, verbose_name='Protocols enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='change_password_enabled',
|
||||
field=models.BooleanField(default=False, verbose_name='Change password enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='change_password_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Change password method'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='create_account_enabled',
|
||||
field=models.BooleanField(default=False, verbose_name='Create account enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='create_account_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Create account method'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='ping_enabled',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='ping_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Ping method'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='su_enabled',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='su_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='SU method'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='verify_account_enabled',
|
||||
field=models.BooleanField(default=False, verbose_name='Verify account enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='verify_account_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='category',
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 3.2.14 on 2022-08-10 06:49
|
||||
|
||||
import assets.models.platform
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0104_auto_20220803_1859'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='category',
|
||||
field=models.CharField(choices=[('host', 'Host'), ('network', 'NetworkDevice'), ('database', 'Database'), ('cloud', 'Clouding'), ('web', 'Web')], max_length=16, verbose_name='Category'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='platform',
|
||||
field=models.ForeignKey(default=assets.models.platform.Platform.default, on_delete=django.db.models.deletion.PROTECT, related_name='assets', to='assets.platform', verbose_name='Platform'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('linux', 'Linux'), ('windows', 'Windows'), ('unix', 'Unix'), ('bsd', 'BSD'), ('macos', 'MacOS'), ('mainframe', 'Mainframe'), ('other_host', 'Other host'), ('switch', 'Switch'), ('router', 'Router'), ('firewall', 'Firewall'), ('other_network', 'Other device'), ('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('oracle', 'Oracle'), ('sqlserver', 'SQLServer'), ('mongodb', 'MongoDB'), ('redis', 'Redis'), ('general', 'General'), ('k8s', 'Kubernetes')], max_length=128, verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='platform',
|
||||
name='category',
|
||||
field=models.CharField(choices=[('host', 'Host'), ('network', 'NetworkDevice'), ('database', 'Database'), ('cloud', 'Clouding'), ('web', 'Web')], default='host', max_length=16, verbose_name='Category'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='platform',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('linux', 'Linux'), ('windows', 'Windows'), ('unix', 'Unix'), ('bsd', 'BSD'), ('macos', 'MacOS'), ('mainframe', 'Mainframe'), ('other_host', 'Other host'), ('switch', 'Switch'), ('router', 'Router'), ('firewall', 'Firewall'), ('other_network', 'Other device'), ('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('oracle', 'Oracle'), ('sqlserver', 'SQLServer'), ('mongodb', 'MongoDB'), ('redis', 'Redis'), ('general', 'General'), ('k8s', 'Kubernetes')], default='Linux', max_length=32, verbose_name='Type'),
|
||||
),
|
||||
]
|
|
@ -9,6 +9,10 @@ __all__ = ['Platform']
|
|||
|
||||
|
||||
class Platform(models.Model):
|
||||
"""
|
||||
对资产提供 约束和默认值
|
||||
对资产进行抽象
|
||||
"""
|
||||
CHARSET_CHOICES = (
|
||||
('utf8', 'UTF-8'),
|
||||
('gbk', 'GBK'),
|
||||
|
@ -26,27 +30,25 @@ class Platform(models.Model):
|
|||
verbose_name=_("Domain default")
|
||||
)
|
||||
protocols_enabled = models.BooleanField(default=True, verbose_name=_("Protocols enabled"))
|
||||
protocols_default = models.CharField(
|
||||
max_length=128, default='', blank=True, verbose_name=_("Protocols default")
|
||||
protocols_default = models.JSONField(
|
||||
max_length=128, default=list, blank=True, verbose_name=_("Protocols default")
|
||||
)
|
||||
admin_user_enabled = models.BooleanField(default=True, verbose_name=_("Admin user enabled"))
|
||||
admin_user_default = models.ForeignKey(
|
||||
'assets.SystemUser', null=True, on_delete=models.SET_NULL,
|
||||
verbose_name=_("Admin user default")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_type_meta(cls, category, tp):
|
||||
meta = Category.platform_meta().get(category, {})
|
||||
types = dict(AllTypes.category_types()).get(category)
|
||||
types_meta = types.platform_meta() or {}
|
||||
type_meta = types_meta.get(tp, {})
|
||||
meta.update(type_meta)
|
||||
return meta
|
||||
# Accounts
|
||||
# 这应该和账号有关
|
||||
su_enabled = models.BooleanField(default=False)
|
||||
su_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("SU method"))
|
||||
ping_enabled = models.BooleanField(default=False)
|
||||
ping_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Ping method"))
|
||||
verify_account_enabled = models.BooleanField(default=False, verbose_name=_("Verify account enabled"))
|
||||
verify_account_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Verify account method"))
|
||||
create_account_enabled = models.BooleanField(default=False, verbose_name=_("Create account enabled"))
|
||||
create_account_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Create account method"))
|
||||
change_password_enabled = models.BooleanField(default=False, verbose_name=_("Change password enabled"))
|
||||
change_password_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Change password method"))
|
||||
|
||||
@property
|
||||
def type_limits(self):
|
||||
return AllTypes.get_type_limits(self.category, self.type)
|
||||
def type_constraints(self):
|
||||
return AllTypes.get_constraints(self.category, self.type)
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
|
@ -55,12 +57,6 @@ class Platform(models.Model):
|
|||
)
|
||||
return linux.id
|
||||
|
||||
def is_windows(self):
|
||||
return self.type.lower() in ('windows',)
|
||||
|
||||
def is_unixlike(self):
|
||||
return self.type.lower() in ("linux", "unix", "macos", "bsd")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
|
|
@ -8,19 +8,15 @@ from .mixin import CategoryDisplayMixin
|
|||
__all__ = ['PlatformSerializer']
|
||||
|
||||
|
||||
class PlatformProtocolsSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=255, required=True)
|
||||
port = serializers.IntegerField(max_value=65535, min_value=1, required=True)
|
||||
|
||||
|
||||
class PlatformSerializer(CategoryDisplayMixin, serializers.ModelSerializer):
|
||||
meta = serializers.DictField(required=False, allow_null=True, label=_('Meta'))
|
||||
protocols_default = serializers.ListField(label=_('Protocols'), required=False)
|
||||
type_limits = serializers.ReadOnlyField(required=False, read_only=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# TODO 修复 drf SlugField RegexValidator bug,之后记得删除
|
||||
validators = self.fields['name'].validators
|
||||
if isinstance(validators[-1], RegexValidator):
|
||||
validators.pop()
|
||||
# self.set_platform_meta()
|
||||
protocols_default = PlatformProtocolsSerializer(label=_('Protocols'), many=True, required=False)
|
||||
type_constraints = serializers.ReadOnlyField(required=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Platform
|
||||
|
@ -29,12 +25,16 @@ class PlatformSerializer(CategoryDisplayMixin, serializers.ModelSerializer):
|
|||
'meta', 'comment', 'charset',
|
||||
'category', 'category_display',
|
||||
'type', 'type_display',
|
||||
'type_limits',
|
||||
'su_enabled', 'su_method',
|
||||
'ping_enabled', 'ping_method',
|
||||
'verify_account_enabled', 'verify_account_method',
|
||||
'create_account_enabled', 'create_account_method',
|
||||
'change_password_enabled', 'change_password_method',
|
||||
'type_constraints',
|
||||
]
|
||||
fields_fk = [
|
||||
'domain_enabled', 'domain_default',
|
||||
'protocols_enabled', 'protocols_default',
|
||||
'admin_user_enabled', 'admin_user_default',
|
||||
]
|
||||
fields = fields_small + fields_fk
|
||||
read_only_fields = [
|
||||
|
|
Loading…
Reference in New Issue