mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
f633a50f8e
|
@ -1,5 +1,6 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from common.db.models import IncludesTextChoicesMeta, ChoicesMixin
|
from common.db.models import IncludesTextChoicesMeta, ChoicesMixin
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
|
|
||||||
|
@ -44,21 +45,35 @@ class Category(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
'change_password_enabled': True,
|
'change_password_enabled': True,
|
||||||
'create_account_enabled': True,
|
'create_account_enabled': True,
|
||||||
'gather_accounts_enabled': True,
|
'gather_accounts_enabled': True,
|
||||||
'_protocols': ['ssh', 'telnet']
|
'_protocols': ['ssh', 'sftp']
|
||||||
},
|
},
|
||||||
cls.NETWORKING: {
|
cls.NETWORKING: {
|
||||||
'domain_enabled': True,
|
'domain_enabled': True,
|
||||||
|
'su_enabled': False,
|
||||||
|
'gather_facts_enabled': False,
|
||||||
|
'verify_account_enabled': False,
|
||||||
|
'change_password_enabled': False,
|
||||||
|
'create_account_enabled': False,
|
||||||
|
'gather_accounts_enabled': False,
|
||||||
'_protocols': ['ssh', 'telnet']
|
'_protocols': ['ssh', 'telnet']
|
||||||
},
|
},
|
||||||
cls.DATABASE: {
|
cls.DATABASE: {
|
||||||
'domain_enabled': True,
|
'domain_enabled': True,
|
||||||
|
'su_enabled': False,
|
||||||
|
'gather_facts_enabled': True,
|
||||||
|
'verify_account_enabled': True,
|
||||||
|
'change_password_enabled': True,
|
||||||
|
'create_account_enabled': True,
|
||||||
|
'gather_accounts_enabled': True,
|
||||||
},
|
},
|
||||||
cls.WEB: {
|
cls.WEB: {
|
||||||
'domain_enabled': False,
|
'domain_enabled': False,
|
||||||
'_protocols': []
|
'su_enabled': False,
|
||||||
|
'_protocols': ['http', 'https']
|
||||||
},
|
},
|
||||||
cls.CLOUD: {
|
cls.CLOUD: {
|
||||||
'domain_enabled': False,
|
'domain_enabled': False,
|
||||||
|
'su_enabled': False,
|
||||||
'_protocols': []
|
'_protocols': []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +92,7 @@ class HostTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
def platform_constraints(cls):
|
def platform_constraints(cls):
|
||||||
return {
|
return {
|
||||||
cls.LINUX: {
|
cls.LINUX: {
|
||||||
'_protocols': ['ssh', 'rdp', 'vnc', 'telnet']
|
'_protocols': ['ssh', 'sftp', 'rdp', 'vnc', 'telnet']
|
||||||
},
|
},
|
||||||
cls.WINDOWS: {
|
cls.WINDOWS: {
|
||||||
'_protocols': ['ssh', 'rdp', 'vnc'],
|
'_protocols': ['ssh', 'rdp', 'vnc'],
|
||||||
|
@ -110,7 +125,7 @@ class DatabaseTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
meta = {}
|
meta = {}
|
||||||
for name, label in cls.choices:
|
for name, label in cls.choices:
|
||||||
meta[name] = {
|
meta[name] = {
|
||||||
'protocols': [name]
|
'_protocols': [name]
|
||||||
}
|
}
|
||||||
return meta
|
return meta
|
||||||
|
|
||||||
|
@ -122,6 +137,14 @@ class WebTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
class CloudTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
class CloudTypes(PlatformMixin, ChoicesMixin, models.TextChoices):
|
||||||
K8S = 'k8s', 'Kubernetes'
|
K8S = 'k8s', 'Kubernetes'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def platform_constraints(cls):
|
||||||
|
return {
|
||||||
|
cls.K8S: {
|
||||||
|
'_protocols': ['k8s']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta):
|
class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta):
|
||||||
choices: list
|
choices: list
|
||||||
|
@ -209,6 +232,7 @@ class AllTypes(ChoicesMixin, metaclass=IncludesTextChoicesMeta):
|
||||||
|
|
||||||
class Protocol(ChoicesMixin, models.TextChoices):
|
class Protocol(ChoicesMixin, models.TextChoices):
|
||||||
ssh = 'ssh', 'SSH'
|
ssh = 'ssh', 'SSH'
|
||||||
|
sftp = 'sftp', 'SFTP'
|
||||||
rdp = 'rdp', 'RDP'
|
rdp = 'rdp', 'RDP'
|
||||||
telnet = 'telnet', 'Telnet'
|
telnet = 'telnet', 'Telnet'
|
||||||
vnc = 'vnc', 'VNC'
|
vnc = 'vnc', 'VNC'
|
||||||
|
@ -240,6 +264,7 @@ class Protocol(ChoicesMixin, models.TextChoices):
|
||||||
def default_ports(cls):
|
def default_ports(cls):
|
||||||
return {
|
return {
|
||||||
cls.ssh: 22,
|
cls.ssh: 22,
|
||||||
|
cls.sftp: 22,
|
||||||
cls.rdp: 3389,
|
cls.rdp: 3389,
|
||||||
cls.vnc: 5900,
|
cls.vnc: 5900,
|
||||||
cls.telnet: 21,
|
cls.telnet: 21,
|
||||||
|
|
|
@ -68,7 +68,7 @@ class NodesRelationMixin:
|
||||||
|
|
||||||
class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
name = models.CharField(max_length=128, verbose_name=_('Hostname'))
|
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||||
ip = models.CharField(max_length=128, verbose_name=_('IP'), db_index=True)
|
ip = models.CharField(max_length=128, verbose_name=_('IP'), db_index=True)
|
||||||
protocols = models.ManyToManyField('Protocol', verbose_name=_("Protocols"), blank=True)
|
protocols = models.ManyToManyField('Protocol', verbose_name=_("Protocols"), blank=True)
|
||||||
platform = models.ForeignKey(Platform, default=Platform.default, on_delete=models.PROTECT,
|
platform = models.ForeignKey(Platform, default=Platform.default, on_delete=models.PROTECT,
|
||||||
|
|
|
@ -5,3 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
class Protocol(models.Model):
|
class Protocol(models.Model):
|
||||||
name = models.CharField(max_length=32, verbose_name=_("Name"))
|
name = models.CharField(max_length=32, verbose_name=_("Name"))
|
||||||
port = models.IntegerField(verbose_name=_("Port"))
|
port = models.IntegerField(verbose_name=_("Port"))
|
||||||
|
|
||||||
|
def save(self, force_insert=False, force_update=False, using=None,
|
||||||
|
update_fields=None):
|
||||||
|
pass
|
||||||
|
|
|
@ -22,11 +22,18 @@ class AssetProtocolsSerializer(serializers.ModelSerializer):
|
||||||
model = Protocol
|
model = Protocol
|
||||||
fields = ['id', 'name', 'port']
|
fields = ['id', 'name', 'port']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
instance = Protocol.objects.filter(**validated_data).first()
|
||||||
|
if instance:
|
||||||
|
return instance
|
||||||
|
instance = Protocol.objects.create(**validated_data)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class AssetLabelSerializer(serializers.ModelSerializer):
|
class AssetLabelSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Label
|
model = Label
|
||||||
fields = ['id', 'name', 'value']
|
fields = ['name', 'value']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'name': {'required': False},
|
'name': {'required': False},
|
||||||
'value': {'required': False}
|
'value': {'required': False}
|
||||||
|
@ -51,7 +58,6 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
labels = AssetLabelSerializer(many=True, required=False, label=_('Labels'))
|
labels = AssetLabelSerializer(many=True, required=False, label=_('Labels'))
|
||||||
accounts = AccountSerializer(many=True, required=False, label=_('Accounts'))
|
accounts = AccountSerializer(many=True, required=False, label=_('Accounts'))
|
||||||
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'))
|
||||||
|
|
||||||
"""
|
"""
|
||||||
资产的数据结构
|
资产的数据结构
|
||||||
"""
|
"""
|
||||||
|
@ -109,23 +115,10 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
nodes_to_set.append(node)
|
nodes_to_set.append(node)
|
||||||
instance.nodes.set(nodes_to_set)
|
instance.nodes.set(nodes_to_set)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def add_accounts(instance, accounts_data):
|
|
||||||
for data in accounts_data:
|
|
||||||
data['asset'] = instance.id
|
|
||||||
serializer = AccountSerializer(data=accounts_data, many=True)
|
|
||||||
try:
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
except Exception as e:
|
|
||||||
raise serializers.ValidationError({'accounts': e})
|
|
||||||
serializer.save()
|
|
||||||
|
|
||||||
@atomic
|
@atomic
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
nodes_display = validated_data.pop('nodes_display', '')
|
nodes_display = validated_data.pop('nodes_display', '')
|
||||||
instance = super().create(validated_data)
|
instance = super().create(validated_data)
|
||||||
if self.accounts_data:
|
|
||||||
self.add_accounts(instance, self.accounts_data)
|
|
||||||
self.perform_nodes_display_create(instance, nodes_display)
|
self.perform_nodes_display_create(instance, nodes_display)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,17 @@ class ProtocolSettingSerializer(serializers.Serializer):
|
||||||
('tls', 'TLS'),
|
('tls', 'TLS'),
|
||||||
('nla', 'NLA'),
|
('nla', 'NLA'),
|
||||||
]
|
]
|
||||||
|
# Common
|
||||||
|
required = serializers.BooleanField(required=True, initial=False, label=_("Required"))
|
||||||
|
# RDP
|
||||||
console = serializers.BooleanField(required=False)
|
console = serializers.BooleanField(required=False)
|
||||||
security = serializers.ChoiceField(choices=SECURITY_CHOICES, default='any', required=False)
|
security = serializers.ChoiceField(choices=SECURITY_CHOICES, default='any', required=False)
|
||||||
|
# SFTP
|
||||||
|
sftp_home = serializers.CharField(default='/tmp', required=False)
|
||||||
|
|
||||||
|
|
||||||
class PlatformProtocolsSerializer(serializers.ModelSerializer):
|
class PlatformProtocolsSerializer(serializers.ModelSerializer):
|
||||||
setting = ProtocolSettingSerializer(required=False)
|
setting = ProtocolSettingSerializer(required=False, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PlatformProtocol
|
model = PlatformProtocol
|
||||||
|
|
Loading…
Reference in New Issue