From b4498f2267cab94f44739b3b735ac260740c4518 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Tue, 10 Dec 2019 15:16:16 +0800 Subject: [PATCH] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=20RemoteApp=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=20Form=20=E6=B8=B2=E6=9F=93=E9=80=BB?= =?UTF-8?q?=E8=BE=91=20(#3523)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 修改 RemoteApp 前端 Form 渲染逻辑 * [Update] RemoteApp 表单添加默认值 --- apps/applications/const.py | 32 ++--- apps/applications/forms/remote_app.py | 107 +++++++------- apps/applications/models/remote_app.py | 2 +- apps/applications/serializers/remote_app.py | 37 ++++- .../remote_app_create_update.html | 131 +++--------------- .../applications/remote_app_list.html | 12 +- apps/applications/views/remote_app.py | 67 ++++++--- apps/common/fields/serializer.py | 45 +++--- apps/terminal/const.py | 4 +- apps/terminal/serializers/storage.py | 18 +-- 10 files changed, 208 insertions(+), 247 deletions(-) diff --git a/apps/applications/const.py b/apps/applications/const.py index a5b6da895..fe5a26945 100644 --- a/apps/applications/const.py +++ b/apps/applications/const.py @@ -12,29 +12,6 @@ REMOTE_APP_TYPE_MYSQL_WORKBENCH = 'mysql_workbench' REMOTE_APP_TYPE_VMWARE_CLIENT = 'vmware_client' REMOTE_APP_TYPE_CUSTOM = 'custom' -REMOTE_APP_TYPE_CHOICES = ( - ( - _('Browser'), - ( - (REMOTE_APP_TYPE_CHROME, 'Chrome'), - ) - ), - ( - _('Database tools'), - ( - (REMOTE_APP_TYPE_MYSQL_WORKBENCH, 'MySQL Workbench'), - ) - ), - ( - _('Virtualization tools'), - ( - (REMOTE_APP_TYPE_VMWARE_CLIENT, 'vSphere Client'), - ) - ), - (REMOTE_APP_TYPE_CUSTOM, _('Custom')), - -) - # Fields attribute write_only default => False REMOTE_APP_TYPE_CHROME_FIELDS = [ @@ -60,9 +37,16 @@ REMOTE_APP_TYPE_CUSTOM_FIELDS = [ {'name': 'custom_password', 'write_only': True} ] -REMOTE_APP_TYPE_MAP_FIELDS = { +REMOTE_APP_TYPE_FIELDS_MAP = { REMOTE_APP_TYPE_CHROME: REMOTE_APP_TYPE_CHROME_FIELDS, REMOTE_APP_TYPE_MYSQL_WORKBENCH: REMOTE_APP_TYPE_MYSQL_WORKBENCH_FIELDS, REMOTE_APP_TYPE_VMWARE_CLIENT: REMOTE_APP_TYPE_VMWARE_CLIENT_FIELDS, REMOTE_APP_TYPE_CUSTOM: REMOTE_APP_TYPE_CUSTOM_FIELDS } + +REMOTE_APP_TYPE_CHOICES = ( + (REMOTE_APP_TYPE_CHROME, 'Chrome'), + (REMOTE_APP_TYPE_MYSQL_WORKBENCH, 'MySQL Workbench'), + (REMOTE_APP_TYPE_VMWARE_CLIENT, 'vSphere Client'), + (REMOTE_APP_TYPE_CUSTOM, _('Custom')), +) diff --git a/apps/applications/forms/remote_app.py b/apps/applications/forms/remote_app.py index b12759462..7a097fcc8 100644 --- a/apps/applications/forms/remote_app.py +++ b/apps/applications/forms/remote_app.py @@ -5,18 +5,52 @@ from django.utils.translation import ugettext as _ from django import forms from orgs.mixins.forms import OrgModelForm -from assets.models import SystemUser from ..models import RemoteApp -from .. import const __all__ = [ - 'RemoteAppCreateUpdateForm', + 'RemoteAppChromeForm', 'RemoteAppMySQLWorkbenchForm', + 'RemoteAppVMwareForm', 'RemoteAppCustomForm' ] -class RemoteAppTypeChromeForm(forms.ModelForm): +class BaseRemoteAppForm(OrgModelForm): + default_initial_data = {} + + def __init__(self, *args, **kwargs): + # 过滤RDP资产和系统用户 + super().__init__(*args, **kwargs) + field_asset = self.fields['asset'] + field_asset.queryset = field_asset.queryset.has_protocol('rdp') + self.fields['type'].widget.attrs['disabled'] = True + self.fields.move_to_end('comment') + self.initial_default() + + def initial_default(self): + for name, value in self.default_initial_data.items(): + field = self.fields.get(name) + if not field: + continue + field.initial = value + + class Meta: + model = RemoteApp + fields = [ + 'name', 'asset', 'type', 'path', 'comment' + ] + widgets = { + 'asset': forms.Select(attrs={ + 'class': 'select2', 'data-placeholder': _('Asset') + }), + } + + +class RemoteAppChromeForm(BaseRemoteAppForm): + default_initial_data = { + 'path': r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' + } + chrome_target = forms.CharField( max_length=128, label=_('Target URL'), required=False ) @@ -29,7 +63,12 @@ class RemoteAppTypeChromeForm(forms.ModelForm): ) -class RemoteAppTypeMySQLWorkbenchForm(forms.ModelForm): +class RemoteAppMySQLWorkbenchForm(BaseRemoteAppForm): + default_initial_data = { + 'path': r'C:\Program Files\MySQL\MySQL Workbench 8.0 CE' + r'\MySQLWorkbench.exe' + } + mysql_workbench_ip = forms.CharField( max_length=128, label=_('Database IP'), required=False ) @@ -45,7 +84,12 @@ class RemoteAppTypeMySQLWorkbenchForm(forms.ModelForm): ) -class RemoteAppTypeVMwareForm(forms.ModelForm): +class RemoteAppVMwareForm(BaseRemoteAppForm): + default_initial_data = { + 'path': r'C:\Program Files (x86)\VMware\Infrastructure' + r'\Virtual Infrastructure Client\Launcher\VpxClient.exe' + } + vmware_target = forms.CharField( max_length=128, label=_('Target address'), required=False ) @@ -58,7 +102,8 @@ class RemoteAppTypeVMwareForm(forms.ModelForm): ) -class RemoteAppTypeCustomForm(forms.ModelForm): +class RemoteAppCustomForm(BaseRemoteAppForm): + custom_cmdline = forms.CharField( max_length=128, label=_('Operating parameter'), required=False ) @@ -73,51 +118,3 @@ class RemoteAppTypeCustomForm(forms.ModelForm): max_length=128, label=_('Login password'), required=False ) - -class RemoteAppTypeForms( - RemoteAppTypeChromeForm, - RemoteAppTypeMySQLWorkbenchForm, - RemoteAppTypeVMwareForm, - RemoteAppTypeCustomForm -): - pass - - -class RemoteAppCreateUpdateForm(RemoteAppTypeForms, OrgModelForm): - def __init__(self, *args, **kwargs): - # 过滤RDP资产和系统用户 - super().__init__(*args, **kwargs) - field_asset = self.fields['asset'] - field_asset.queryset = field_asset.queryset.has_protocol('rdp') - - class Meta: - model = RemoteApp - fields = [ - 'name', 'asset', 'type', 'path', 'comment' - ] - widgets = { - 'asset': forms.Select(attrs={ - 'class': 'select2', 'data-placeholder': _('Asset') - }), - } - - def _clean_params(self): - app_type = self.data.get('type') - fields = const.REMOTE_APP_TYPE_MAP_FIELDS.get(app_type, []) - params = {} - for field in fields: - name = field['name'] - value = self.cleaned_data[name] - params.update({name: value}) - return params - - def _save_params(self, instance): - params = self._clean_params() - instance.params = params - instance.save() - return instance - - def save(self, commit=True): - instance = super().save(commit=commit) - instance = self._save_params(instance) - return instance diff --git a/apps/applications/models/remote_app.py b/apps/applications/models/remote_app.py index 17746833c..b9aee0ade 100644 --- a/apps/applications/models/remote_app.py +++ b/apps/applications/models/remote_app.py @@ -62,7 +62,7 @@ class RemoteApp(OrgModelMixin): _parameters.append(self.type) path = '\"%s\"' % self.path _parameters.append(path) - for field in const.REMOTE_APP_TYPE_MAP_FIELDS[self.type]: + for field in const.REMOTE_APP_TYPE_FIELDS_MAP[self.type]: value = self.params.get(field['name']) if value is None: continue diff --git a/apps/applications/serializers/remote_app.py b/apps/applications/serializers/remote_app.py index a6c1c557c..fb9a7a270 100644 --- a/apps/applications/serializers/remote_app.py +++ b/apps/applications/serializers/remote_app.py @@ -1,7 +1,7 @@ # coding: utf-8 # - +import copy from rest_framework import serializers from common.serializers import AdaptedBulkListSerializer @@ -18,26 +18,53 @@ __all__ = [ class RemoteAppParamsDictField(CustomMetaDictField): - type_map_fields = const.REMOTE_APP_TYPE_MAP_FIELDS + type_fields_map = const.REMOTE_APP_TYPE_FIELDS_MAP default_type = const.REMOTE_APP_TYPE_CHROME + convert_key_remove_type_prefix = False + convert_key_to_upper = False class RemoteAppSerializer(BulkOrgResourceModelSerializer): params = RemoteAppParamsDictField() + type_fields_map = const.REMOTE_APP_TYPE_FIELDS_MAP class Meta: model = RemoteApp list_serializer_class = AdaptedBulkListSerializer fields = [ - 'id', 'name', 'asset', 'type', 'path', 'params', - 'comment', 'created_by', 'date_created', 'asset_info', - 'get_type_display', + 'id', 'name', 'asset', 'asset_info', 'type', 'get_type_display', + 'path', 'params', 'date_created', 'created_by', 'comment', ] read_only_fields = [ 'created_by', 'date_created', 'asset_info', 'get_type_display' ] + def process_params(self, instance, validated_data): + new_params = copy.deepcopy(validated_data.get('params', {})) + tp = validated_data.get('type', '') + + if tp != instance.type: + return new_params + + old_params = instance.params + fields = self.type_fields_map.get(instance.type, []) + for field in fields: + if not field.get('write_only', False): + continue + field_name = field['name'] + new_value = new_params.get(field_name, '') + old_value = old_params.get(field_name, '') + field_value = new_value if new_value else old_value + new_params[field_name] = field_value + + return new_params + + def update(self, instance, validated_data): + params = self.process_params(instance, validated_data) + validated_data['params'] = params + return super().update(instance, validated_data) + class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer): parameter_remote_app = serializers.SerializerMethodField() diff --git a/apps/applications/templates/applications/remote_app_create_update.html b/apps/applications/templates/applications/remote_app_create_update.html index ad7a65545..440219936 100644 --- a/apps/applications/templates/applications/remote_app_create_update.html +++ b/apps/applications/templates/applications/remote_app_create_update.html @@ -4,51 +4,8 @@ {% load i18n %} {% block form %} -
- {% if form.non_field_errors %} -
- {{ form.non_field_errors }} -
- {% endif %} - {% csrf_token %} - {% bootstrap_field form.name layout="horizontal" %} - {% bootstrap_field form.asset layout="horizontal" %} - {% bootstrap_field form.type layout="horizontal" %} - {% bootstrap_field form.path layout="horizontal" %} - -
- - {# chrome #} - - - {# mysql workbench #} - - - {# vmware #} - - - {# custom #} - - - {% bootstrap_field form.comment layout="horizontal" %} + + {% bootstrap_form form layout="horizontal" %}
@@ -57,93 +14,49 @@
-
{% endblock %} {% block custom_foot_js %}