perf: 修改 publications

pull/9008/head
ibuler 2022-11-01 20:37:04 +08:00
parent b159f16513
commit 6ba4b750f2
7 changed files with 154 additions and 109 deletions

View File

@ -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

View File

@ -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

View File

@ -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'))

View File

@ -6,3 +6,4 @@ from .storage import *
from .sharing import *
from .endpoint import *
from .applet import *
from .applet_host import *

View File

@ -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

View File

@ -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

View File

@ -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)