mirror of https://github.com/jumpserver/jumpserver
perf: 修改 publications
parent
b159f16513
commit
6ba4b750f2
|
@ -1,5 +1,7 @@
|
|||
import shutil
|
||||
import zipfile
|
||||
from typing import Callable
|
||||
|
||||
import yaml
|
||||
import os.path
|
||||
|
||||
|
@ -7,6 +9,7 @@ from django.core.files.storage import default_storage
|
|||
from rest_framework import viewsets
|
||||
from django.http import HttpResponse
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
|
||||
|
@ -18,21 +21,10 @@ from terminal.serializers import AppletUploadSerializer
|
|||
__all__ = ['AppletViewSet', 'AppletPublicationViewSet']
|
||||
|
||||
|
||||
class AppletViewSet(viewsets.ModelViewSet):
|
||||
queryset = Applet.objects.all()
|
||||
serializer_class = serializers.AppletSerializer
|
||||
rbac_perms = {
|
||||
'upload': 'terminal.add_applet',
|
||||
'download': 'terminal.view_applet',
|
||||
}
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
if not instance.name:
|
||||
raise ValidationError('Applet is not null')
|
||||
path = default_storage.path('applets/{}'.format(instance.name))
|
||||
if os.path.exists(path):
|
||||
shutil.rmtree(path)
|
||||
instance.delete()
|
||||
class DownloadUploadMixin:
|
||||
get_serializer: Callable
|
||||
request: Request
|
||||
get_object: Callable
|
||||
|
||||
def extract_and_check_file(self, request):
|
||||
serializer = self.get_serializer(data=self.request.data)
|
||||
|
@ -88,7 +80,7 @@ class AppletViewSet(viewsets.ModelViewSet):
|
|||
|
||||
@action(detail=True, methods=['get'])
|
||||
def download(self, request, *args, **kwargs):
|
||||
instance = super().get_object()
|
||||
instance = self.get_object()
|
||||
path = default_storage.path('applets/{}'.format(instance.name))
|
||||
zip_path = shutil.make_archive(path, 'zip', path)
|
||||
with open(zip_path, 'rb') as f:
|
||||
|
@ -97,6 +89,34 @@ class AppletViewSet(viewsets.ModelViewSet):
|
|||
return response
|
||||
|
||||
|
||||
class AppletViewSet(DownloadUploadMixin, viewsets.ModelViewSet):
|
||||
queryset = Applet.objects.all()
|
||||
serializer_class = serializers.AppletSerializer
|
||||
rbac_perms = {
|
||||
'upload': 'terminal.add_applet',
|
||||
'download': 'terminal.view_applet',
|
||||
}
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = list(super().filter_queryset(queryset))
|
||||
host = self.request.query_params.get('host')
|
||||
if not host:
|
||||
return queryset
|
||||
|
||||
publication_mapper = {p.applet: p for p in AppletPublication.objects.filter(host_id=host)}
|
||||
for applet in queryset:
|
||||
applet.publication = publication_mapper.get(applet)
|
||||
return queryset
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
if not instance.name:
|
||||
raise ValidationError('Applet is not null')
|
||||
path = default_storage.path('applets/{}'.format(instance.name))
|
||||
if os.path.exists(path):
|
||||
shutil.rmtree(path)
|
||||
instance.delete()
|
||||
|
||||
|
||||
class AppletPublicationViewSet(viewsets.ModelViewSet):
|
||||
queryset = AppletPublication.objects.all()
|
||||
serializer_class = serializers.AppletPublicationSerializer
|
||||
|
|
|
@ -14,13 +14,6 @@ class AppletHostViewSet(viewsets.ModelViewSet):
|
|||
serializer_class = serializers.AppletHostSerializer
|
||||
queryset = AppletHost.objects.all()
|
||||
|
||||
@action(methods=['get'], detail=True, url_path='')
|
||||
def not_published_applets(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
applets = Applet.objects.exclude(id__in=instance.applets.all())
|
||||
serializer = serializers.AppletSerializer(applets, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class AppletHostDeploymentViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = serializers.AppletHostDeploymentSerializer
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.core.files.storage import default_storage
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
from common.db.models import JMSBaseModel
|
||||
|
||||
|
||||
|
@ -26,7 +27,10 @@ class Applet(JMSBaseModel):
|
|||
protocols = models.JSONField(default=list, verbose_name=_('Protocol'))
|
||||
tags = models.JSONField(default=list, verbose_name=_('Tags'))
|
||||
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
|
||||
hosts = models.ManyToManyField(through_fields=('applet', 'host'), through='AppletPublication', to='AppletHost', verbose_name=_('Hosts'))
|
||||
hosts = models.ManyToManyField(
|
||||
through_fields=('applet', 'host'), through='AppletPublication',
|
||||
to='AppletHost', verbose_name=_('Hosts')
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -50,6 +54,10 @@ class Applet(JMSBaseModel):
|
|||
return None
|
||||
return os.path.join(settings.MEDIA_URL, 'applets', self.name, 'icon.png')
|
||||
|
||||
@lazyproperty
|
||||
def publication(self):
|
||||
return None
|
||||
|
||||
|
||||
class AppletPublication(JMSBaseModel):
|
||||
applet = models.ForeignKey('Applet', on_delete=models.PROTECT, related_name='publications', verbose_name=_('Applet'))
|
||||
|
|
|
@ -6,3 +6,4 @@ from .storage import *
|
|||
from .sharing import *
|
||||
from .endpoint import *
|
||||
from .applet import *
|
||||
from .applet_host import *
|
||||
|
|
|
@ -2,35 +2,15 @@ from rest_framework import serializers
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.drf.fields import ObjectRelatedField, LabeledChoiceField
|
||||
from common.validators import ProjectUniqueValidator
|
||||
from assets.models import Platform
|
||||
from assets.serializers import HostSerializer
|
||||
from ..models import Applet, AppletPublication, AppletHost, AppletHostDeployment
|
||||
from ..models import Applet, AppletPublication, AppletHost
|
||||
|
||||
|
||||
__all__ = [
|
||||
'AppletSerializer', 'AppletPublicationSerializer',
|
||||
'AppletHostSerializer', 'AppletHostDeploymentSerializer',
|
||||
'AppletUploadSerializer',
|
||||
]
|
||||
|
||||
|
||||
class AppletSerializer(serializers.ModelSerializer):
|
||||
icon = serializers.ReadOnlyField(label=_("Icon"))
|
||||
type = LabeledChoiceField(choices=Applet.Type.choices, label=_("Type"))
|
||||
|
||||
class Meta:
|
||||
model = Applet
|
||||
fields_mini = ['id', 'name', 'display_name']
|
||||
read_only_fields = [
|
||||
'icon', 'date_created', 'date_updated'
|
||||
]
|
||||
fields = fields_mini + [
|
||||
'version', 'author', 'type', 'protocols',
|
||||
'tags', 'comment'
|
||||
] + read_only_fields
|
||||
|
||||
|
||||
class AppletUploadSerializer(serializers.Serializer):
|
||||
file = serializers.FileField()
|
||||
|
||||
|
@ -48,69 +28,18 @@ class AppletPublicationSerializer(serializers.ModelSerializer):
|
|||
] + read_only_fields
|
||||
|
||||
|
||||
class DeployOptionsSerializer(serializers.Serializer):
|
||||
LICENSE_MODE_CHOICES = (
|
||||
(4, _('Per Session')),
|
||||
(2, _('Per Device')),
|
||||
)
|
||||
SESSION_PER_USER = (
|
||||
(1, _("Disabled")),
|
||||
(0, _("Enabled")),
|
||||
)
|
||||
RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing"))
|
||||
RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024)
|
||||
RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode'))
|
||||
RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, label=_("RDS fSingleSessionPerUser"))
|
||||
RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time"))
|
||||
RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit"))
|
||||
class AppletSerializer(serializers.ModelSerializer):
|
||||
icon = serializers.ReadOnlyField(label=_("Icon"))
|
||||
type = LabeledChoiceField(choices=Applet.Type.choices, label=_("Type"))
|
||||
publication = AppletPublicationSerializer(allow_null=True, label=_("Publication"))
|
||||
|
||||
|
||||
class AppletHostSerializer(HostSerializer):
|
||||
deploy_options = DeployOptionsSerializer(required=False, label=_("Deploy options"))
|
||||
|
||||
class Meta(HostSerializer.Meta):
|
||||
model = AppletHost
|
||||
fields = HostSerializer.Meta.fields + [
|
||||
'account_automation', 'status', 'date_synced', 'deploy_options'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'status': {'read_only': True},
|
||||
'date_synced': {'read_only': True}
|
||||
}
|
||||
|
||||
def __init__(self, *args, data=None, **kwargs):
|
||||
if data:
|
||||
self.set_initial_data(data)
|
||||
kwargs['data'] = data
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def set_initial_data(data):
|
||||
platform = Platform.objects.get(name='RemoteAppHost')
|
||||
data.update({
|
||||
'platform': platform.id,
|
||||
'nodes_display': [
|
||||
'RemoteAppHosts'
|
||||
]
|
||||
})
|
||||
|
||||
def get_validators(self):
|
||||
validators = super().get_validators()
|
||||
# 不知道为啥没有继承过来
|
||||
uniq_validator = ProjectUniqueValidator(
|
||||
queryset=AppletHost.objects.all(),
|
||||
fields=('org_id', 'name')
|
||||
)
|
||||
validators.append(uniq_validator)
|
||||
return validators
|
||||
|
||||
|
||||
class AppletHostDeploymentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = AppletHostDeployment
|
||||
fields_mini = ['id', 'host', 'status']
|
||||
model = Applet
|
||||
fields_mini = ['id', 'name', 'display_name']
|
||||
read_only_fields = [
|
||||
'status', 'date_created', 'date_updated',
|
||||
'date_start', 'date_finished'
|
||||
'publication', 'icon', 'date_created', 'date_updated',
|
||||
]
|
||||
fields = fields_mini + ['comment'] + read_only_fields
|
||||
fields = fields_mini + [
|
||||
'version', 'author', 'type', 'protocols',
|
||||
'tags', 'comment'
|
||||
] + read_only_fields
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.validators import ProjectUniqueValidator
|
||||
from assets.models import Platform
|
||||
from assets.serializers import HostSerializer
|
||||
from ..models import AppletHost, AppletHostDeployment, Applet
|
||||
from .applet import AppletSerializer
|
||||
|
||||
|
||||
__all__ = [
|
||||
'AppletHostSerializer', 'AppletHostDeploymentSerializer',
|
||||
]
|
||||
|
||||
|
||||
class DeployOptionsSerializer(serializers.Serializer):
|
||||
LICENSE_MODE_CHOICES = (
|
||||
(4, _('Per Session')),
|
||||
(2, _('Per Device')),
|
||||
)
|
||||
SESSION_PER_USER = (
|
||||
(1, _("Disabled")),
|
||||
(0, _("Enabled")),
|
||||
)
|
||||
RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing"))
|
||||
RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024)
|
||||
RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode'))
|
||||
RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, label=_("RDS fSingleSessionPerUser"))
|
||||
RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time"))
|
||||
RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit"))
|
||||
|
||||
|
||||
class AppletHostSerializer(HostSerializer):
|
||||
deploy_options = DeployOptionsSerializer(required=False, label=_("Deploy options"))
|
||||
|
||||
class Meta(HostSerializer.Meta):
|
||||
model = AppletHost
|
||||
fields = HostSerializer.Meta.fields + [
|
||||
'account_automation', 'status', 'date_synced', 'deploy_options'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'status': {'read_only': True},
|
||||
'date_synced': {'read_only': True}
|
||||
}
|
||||
|
||||
def __init__(self, *args, data=None, **kwargs):
|
||||
if data:
|
||||
self.set_initial_data(data)
|
||||
kwargs['data'] = data
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def set_initial_data(data):
|
||||
platform = Platform.objects.get(name='RemoteAppHost')
|
||||
data.update({
|
||||
'platform': platform.id,
|
||||
'nodes_display': [
|
||||
'RemoteAppHosts'
|
||||
]
|
||||
})
|
||||
|
||||
def get_validators(self):
|
||||
validators = super().get_validators()
|
||||
# 不知道为啥没有继承过来
|
||||
uniq_validator = ProjectUniqueValidator(
|
||||
queryset=AppletHost.objects.all(),
|
||||
fields=('org_id', 'name')
|
||||
)
|
||||
validators.append(uniq_validator)
|
||||
return validators
|
||||
|
||||
|
||||
class HostAppletSerializer(AppletSerializer):
|
||||
publication = serializers.SerializerMethodField()
|
||||
|
||||
class Meta(AppletSerializer.Meta):
|
||||
fields = AppletSerializer.Meta.fields + ['publication']
|
||||
|
||||
|
||||
class AppletHostDeploymentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = AppletHostDeployment
|
||||
fields_mini = ['id', 'host', 'status']
|
||||
read_only_fields = [
|
||||
'status', 'date_created', 'date_updated',
|
||||
'date_start', 'date_finished'
|
||||
]
|
||||
fields = fields_mini + ['comment'] + read_only_fields
|
|
@ -10,9 +10,15 @@ from .models import Applet, AppletHost
|
|||
|
||||
@receiver(post_save, sender=AppletHost)
|
||||
def on_applet_host_create(sender, instance, created=False, **kwargs):
|
||||
pass
|
||||
if not created:
|
||||
return
|
||||
applets = Applet.objects.all()
|
||||
instance.applets.set(applets)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Applet)
|
||||
def on_applet_create(sender, instance, created=False, **kwargs):
|
||||
pass
|
||||
if not created:
|
||||
return
|
||||
hosts = AppletHost.objects.all()
|
||||
instance.hosts.set(hosts)
|
||||
|
|
Loading…
Reference in New Issue