mirror of https://github.com/jumpserver/jumpserver
feat: 优化工单模块
parent
167734ca5d
commit
5c483084b7
|
@ -1,13 +1,16 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import copy
|
||||||
|
from collections import OrderedDict
|
||||||
|
from rest_framework.serializers import ALL_FIELDS
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'StringIDField', 'StringManyToManyField', 'ChoiceDisplayField',
|
'StringIDField', 'StringManyToManyField', 'ChoiceDisplayField',
|
||||||
'CustomMetaDictField', 'ReadableHiddenField',
|
'CustomMetaDictField', 'ReadableHiddenField', 'JSONFieldModelSerializer'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,3 +133,184 @@ class CustomMetaDictField(serializers.DictField):
|
||||||
value = self.filter_value_key(dictionary, value)
|
value = self.filter_value_key(dictionary, value)
|
||||||
value = self.strip_value(value)
|
value = self.strip_value(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class JSONFieldModelSerializer(serializers.Serializer):
|
||||||
|
""" Model JSONField Serializer"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
mode_field = getattr(self.Meta, 'model_field')
|
||||||
|
if mode_field:
|
||||||
|
kwargs['label'] = mode_field.field.verbose_name
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = None
|
||||||
|
model_field = None
|
||||||
|
fields = None
|
||||||
|
exclude = None
|
||||||
|
|
||||||
|
def get_fields(self):
|
||||||
|
assert hasattr(self, 'Meta'), (
|
||||||
|
'Class {serializer_class} missing "Meta" attribute'.format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert hasattr(self.Meta, 'model'), (
|
||||||
|
'Class {serializer_class} missing "Meta.model" attribute'.format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
model_fields_mapping = {field.name: field for field in self.Meta.model._meta.fields}
|
||||||
|
assert hasattr(self.Meta, 'model_field'), (
|
||||||
|
'Class {serializer_class} missing "Meta.model_field" attribute'.format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert self.Meta.model_field.field.name in model_fields_mapping.keys(), (
|
||||||
|
'Class {serializer_class} "Meta.model_field" attribute not in '
|
||||||
|
'"Meta.model._meta.fields"'.format(
|
||||||
|
serializer_class=self.__class__.__name__,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
declared_fields = copy.deepcopy(self._declared_fields)
|
||||||
|
|
||||||
|
read_only_field_names = self.get_read_only_field_names()
|
||||||
|
|
||||||
|
field_names = self.get_field_names(declared_fields)
|
||||||
|
|
||||||
|
fields = OrderedDict()
|
||||||
|
for field_name in field_names:
|
||||||
|
if field_name not in declared_fields:
|
||||||
|
continue
|
||||||
|
field = declared_fields[field_name]
|
||||||
|
if field_name in read_only_field_names:
|
||||||
|
setattr(field, 'read_only', True)
|
||||||
|
fields[field_name] = field
|
||||||
|
return fields
|
||||||
|
|
||||||
|
def get_field_names(self, declared_fields):
|
||||||
|
"""
|
||||||
|
Returns the list of all field names that should be created when
|
||||||
|
instantiating this serializer class. This is based on the default
|
||||||
|
set of fields, but also takes into account the `Meta.fields` or
|
||||||
|
`Meta.exclude` options if they have been specified.
|
||||||
|
"""
|
||||||
|
|
||||||
|
fields = getattr(self.Meta, 'fields', None)
|
||||||
|
exclude = getattr(self.Meta, 'exclude', None)
|
||||||
|
|
||||||
|
if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
|
||||||
|
raise TypeError(
|
||||||
|
'The `fields` option must be a list or tuple or "__all__". '
|
||||||
|
'Got %s.' % type(fields).__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
if exclude and not isinstance(exclude, (list, tuple)):
|
||||||
|
raise TypeError(
|
||||||
|
'The `exclude` option must be a list or tuple. Got %s.' %
|
||||||
|
type(exclude).__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not (fields and exclude), (
|
||||||
|
"Cannot set both 'fields' and 'exclude' options on "
|
||||||
|
"serializer {serializer_class}.".format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not (fields is None and exclude is None), (
|
||||||
|
"Creating a ModelSerializer without either the 'fields' attribute "
|
||||||
|
"or the 'exclude' attribute has been deprecated since 3.3.0, "
|
||||||
|
"and is now disallowed. Add an explicit fields = '__all__' to the "
|
||||||
|
"{serializer_class} serializer.".format(
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if fields == ALL_FIELDS:
|
||||||
|
fields = None
|
||||||
|
|
||||||
|
if fields is not None:
|
||||||
|
# Ensure that all declared fields have also been included in the
|
||||||
|
# `Meta.fields` option.
|
||||||
|
|
||||||
|
# Do not require any fields that are declared in a parent class,
|
||||||
|
# in order to allow serializer subclasses to only include
|
||||||
|
# a subset of fields.
|
||||||
|
required_field_names = set(declared_fields)
|
||||||
|
for cls in self.__class__.__bases__:
|
||||||
|
required_field_names -= set(getattr(cls, '_declared_fields', []))
|
||||||
|
|
||||||
|
for field_name in required_field_names:
|
||||||
|
assert field_name in fields, (
|
||||||
|
"The field '{field_name}' was declared on serializer "
|
||||||
|
"{serializer_class}, but has not been included in the "
|
||||||
|
"'fields' option.".format(
|
||||||
|
field_name=field_name,
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return fields
|
||||||
|
|
||||||
|
# Use the default set of field names if `Meta.fields` is not specified.
|
||||||
|
fields = self.get_default_field_names(declared_fields)
|
||||||
|
|
||||||
|
if exclude is not None:
|
||||||
|
# If `Meta.exclude` is included, then remove those fields.
|
||||||
|
for field_name in exclude:
|
||||||
|
assert field_name not in self._declared_fields, (
|
||||||
|
"Cannot both declare the field '{field_name}' and include "
|
||||||
|
"it in the {serializer_class} 'exclude' option. Remove the "
|
||||||
|
"field or, if inherited from a parent serializer, disable "
|
||||||
|
"with `{field_name} = None`."
|
||||||
|
.format(
|
||||||
|
field_name=field_name,
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert field_name in fields, (
|
||||||
|
"The field '{field_name}' was included on serializer "
|
||||||
|
"{serializer_class} in the 'exclude' option, but does "
|
||||||
|
"not match any model field.".format(
|
||||||
|
field_name=field_name,
|
||||||
|
serializer_class=self.__class__.__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fields.remove(field_name)
|
||||||
|
return fields
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_default_field_names(declared_fields):
|
||||||
|
return declared_fields
|
||||||
|
|
||||||
|
def get_read_only_field_names(self):
|
||||||
|
read_only_fields = getattr(self.Meta, 'read_only_fields', None)
|
||||||
|
if read_only_fields is not None:
|
||||||
|
if not isinstance(read_only_fields, (list, tuple)):
|
||||||
|
raise TypeError(
|
||||||
|
'The `read_only_fields` option must be a list or tuple. '
|
||||||
|
'Got %s.' % type(read_only_fields).__name__
|
||||||
|
)
|
||||||
|
return read_only_fields
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
return super().to_internal_value(data)
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
if not isinstance(instance, dict):
|
||||||
|
return super().to_representation(instance)
|
||||||
|
for field_name, field in self.fields.items():
|
||||||
|
if field_name in instance:
|
||||||
|
continue
|
||||||
|
if field.allow_null:
|
||||||
|
continue
|
||||||
|
setattr(field, 'allow_null', True)
|
||||||
|
return super().to_representation(instance)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class GenericSerializerMixin:
|
||||||
return serializer_class
|
return serializer_class
|
||||||
|
|
||||||
|
|
||||||
class JSONFieldsSerializerMixin:
|
class JSONFieldsModelSerializerMixin:
|
||||||
"""
|
"""
|
||||||
作用: 获取包含 JSONField 字段的序列类
|
作用: 获取包含 JSONField 字段的序列类
|
||||||
|
|
||||||
|
@ -76,31 +76,20 @@ class JSONFieldsSerializerMixin:
|
||||||
'json_field_1': {
|
'json_field_1': {
|
||||||
'type': {
|
'type': {
|
||||||
'apply_asset': {
|
'apply_asset': {
|
||||||
'get': {
|
'get': TestSerializer,
|
||||||
'class': TestSerializer,
|
'post': TestSerializer,
|
||||||
'attrs': {'required': True},
|
'open':TestSerializer,
|
||||||
},
|
'approve': TestSerializer,
|
||||||
'post': {
|
|
||||||
'class': TestSerializer,
|
|
||||||
'attrs': {'required': True}
|
|
||||||
},
|
|
||||||
'open': {
|
|
||||||
'class': TestSerializer,
|
|
||||||
'attrs': {'required': False}
|
|
||||||
},
|
|
||||||
'approve': {
|
|
||||||
'class': TestSerializer,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'apply_application': {
|
'apply_application': {
|
||||||
'get': {},
|
'get': TestSerializer,
|
||||||
'post': {},
|
'post': TestSerializer,
|
||||||
'put': {},
|
'put': TestSerializer,
|
||||||
},
|
},
|
||||||
'login_confirm': {
|
'login_confirm': {
|
||||||
'get': {},
|
'get': TestSerializer,
|
||||||
'post': {},
|
'post': TestSerializer,
|
||||||
'put': {},
|
'put': TestSerializer,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'category': {}
|
'category': {}
|
||||||
|
@ -113,19 +102,13 @@ class JSONFieldsSerializerMixin:
|
||||||
json_fields_category_mapping = {}
|
json_fields_category_mapping = {}
|
||||||
json_fields_serializer_classes = None
|
json_fields_serializer_classes = None
|
||||||
|
|
||||||
@lazyproperty
|
# 保存当前处理的JSONField名称
|
||||||
def default_json_field_serializer(self):
|
__field = None
|
||||||
class DefaultJSONFieldSerializer(serializers.JSONField):
|
serializer_class = None
|
||||||
pass
|
|
||||||
if self.action in ['get', 'list', 'retrieve']:
|
|
||||||
attrs = {'readonly': False}
|
|
||||||
else:
|
|
||||||
attrs = {'readonly': True}
|
|
||||||
return DefaultJSONFieldSerializer(attrs)
|
|
||||||
|
|
||||||
def get_json_field_query_category(self, field, category):
|
def get_json_field_query_category(self, category):
|
||||||
query_category = self.request.query_params.get(category)
|
query_category = self.request.query_params.get(category)
|
||||||
category_choices = self.json_fields_category_mapping[field][category]
|
category_choices = self.json_fields_category_mapping[self.__field][category]
|
||||||
if query_category and query_category not in category_choices:
|
if query_category and query_category not in category_choices:
|
||||||
error = _(
|
error = _(
|
||||||
'Please bring the query parameter `{}`, '
|
'Please bring the query parameter `{}`, '
|
||||||
|
@ -135,56 +118,57 @@ class JSONFieldsSerializerMixin:
|
||||||
raise JMSException({'query_params_error': error})
|
raise JMSException({'query_params_error': error})
|
||||||
return query_category
|
return query_category
|
||||||
|
|
||||||
def get_json_field_serializer_classes_by_query_category(self, field):
|
def get_json_field_action_serializer_classes_by_query_category(self):
|
||||||
serializer_classes = None
|
action_serializer_classes = None
|
||||||
category_collection = self.json_fields_category_mapping[field]
|
category_collection = self.json_fields_category_mapping[self.__field]
|
||||||
for category in category_collection:
|
for category in category_collection:
|
||||||
query_category = self.get_json_field_query_category(field, category)
|
category_value = self.get_json_field_query_category(category)
|
||||||
if not query_category:
|
if not category_value:
|
||||||
continue
|
continue
|
||||||
category_serializer_classes = self.json_fields_serializer_classes[field][category]
|
category_serializer_classes = self.json_fields_serializer_classes[self.__field][category]
|
||||||
if query_category not in category_serializer_classes.keys():
|
action_serializer_classes = category_serializer_classes.get(category_value)
|
||||||
continue
|
if action_serializer_classes:
|
||||||
serializer_classes = category_serializer_classes[query_category]
|
break
|
||||||
|
return action_serializer_classes
|
||||||
|
|
||||||
|
def get_json_field_action_serializer_classes(self):
|
||||||
|
category_collection = self.json_fields_category_mapping[self.__field]
|
||||||
|
if category_collection:
|
||||||
|
serializer_classes = self.get_json_field_action_serializer_classes_by_query_category()
|
||||||
|
else:
|
||||||
|
serializer_classes = self.json_fields_serializer_classes[self.__field]
|
||||||
return serializer_classes
|
return serializer_classes
|
||||||
|
|
||||||
def get_json_field_serializer_info_by_view_action(self, serializer_classes):
|
def get_json_field_serializer_class_by_action(self, serializer_classes):
|
||||||
|
if serializer_classes is None:
|
||||||
|
return None
|
||||||
if self.action in ['metadata']:
|
if self.action in ['metadata']:
|
||||||
action = self.request.query_params.get('action')
|
action = self.request.query_params.get('action')
|
||||||
if not action:
|
if not action:
|
||||||
raise JMSException('The `metadata` methods must carry query parameter `action`')
|
raise JMSException('The `metadata` methods must carry query parameter `action`')
|
||||||
else:
|
else:
|
||||||
action = self.action
|
action = self.action
|
||||||
serializer_info = serializer_classes.get(action)
|
serializer_class = serializer_classes.get(action)
|
||||||
return serializer_info
|
return serializer_class
|
||||||
|
|
||||||
def get_json_field_serializer_info(self, field):
|
@lazyproperty
|
||||||
category_collection = self.json_fields_category_mapping[field]
|
def default_json_field_serializer_class(self):
|
||||||
if category_collection:
|
readonly_json_field_serializer_class = type(
|
||||||
serializer_classes = self.get_json_field_serializer_classes_by_query_category(field)
|
'DefaultReadonlyJSONFieldSerializer', (serializers.JSONField,),
|
||||||
else:
|
)
|
||||||
serializer_classes = self.json_fields_serializer_classes[field]
|
return readonly_json_field_serializer_class
|
||||||
|
|
||||||
if not serializer_classes:
|
def get_json_field_serializer(self):
|
||||||
return None
|
serializer_classes = self.get_json_field_action_serializer_classes()
|
||||||
|
serializer_class = self.get_json_field_serializer_class_by_action(serializer_classes)
|
||||||
serializer_info = self.get_json_field_serializer_info_by_view_action(serializer_classes)
|
if serializer_class:
|
||||||
return serializer_info
|
serializer = serializer_class()
|
||||||
|
return serializer
|
||||||
@staticmethod
|
serializer_class = serializer_classes.get('default')
|
||||||
def new_json_field_serializer(class_info):
|
if serializer_class:
|
||||||
serializer_class = class_info['class']
|
serializer = serializer_class(**{'read_only': True})
|
||||||
serializer_attrs = class_info.get('attrs', {})
|
return serializer
|
||||||
serializer = serializer_class(serializer_attrs)
|
return self.default_json_field_serializer_class(**{'read_only': True})
|
||||||
return serializer
|
|
||||||
|
|
||||||
def get_json_field_serializer(self, field):
|
|
||||||
serializer_info = self.get_json_field_serializer_info(field)
|
|
||||||
if not serializer_info:
|
|
||||||
return None
|
|
||||||
serializer = self.new_json_field_serializer(serializer_info)
|
|
||||||
return serializer
|
|
||||||
|
|
||||||
def get_json_fields_serializer_mapping(self):
|
def get_json_fields_serializer_mapping(self):
|
||||||
"""
|
"""
|
||||||
|
@ -196,14 +180,12 @@ class JSONFieldsSerializerMixin:
|
||||||
fields_serializer_mapping = {}
|
fields_serializer_mapping = {}
|
||||||
fields = self.json_fields_serializer_classes.keys()
|
fields = self.json_fields_serializer_classes.keys()
|
||||||
for field in fields:
|
for field in fields:
|
||||||
serializer = self.get_json_field_serializer(field)
|
self.__field = field
|
||||||
if serializer is None:
|
serializer = self.get_json_field_serializer()
|
||||||
serializer = self.default_json_field_serializer
|
fields_serializer_mapping[self.__field] = serializer
|
||||||
fields_serializer_mapping[field] = serializer
|
|
||||||
return fields_serializer_mapping
|
return fields_serializer_mapping
|
||||||
|
|
||||||
@staticmethod
|
def build_include_json_fields_serializer_class(self, base, attrs):
|
||||||
def new_include_json_fields_serializer_class(base, attrs):
|
|
||||||
serializer_class_name = ''.join([
|
serializer_class_name = ''.join([
|
||||||
field_serializer.__class__.__name__ for field_serializer in attrs.values()
|
field_serializer.__class__.__name__ for field_serializer in attrs.values()
|
||||||
])
|
])
|
||||||
|
@ -217,13 +199,13 @@ class JSONFieldsSerializerMixin:
|
||||||
fields_serializer_mapping = self.get_json_fields_serializer_mapping()
|
fields_serializer_mapping = self.get_json_fields_serializer_mapping()
|
||||||
if not fields_serializer_mapping:
|
if not fields_serializer_mapping:
|
||||||
return serializer_class
|
return serializer_class
|
||||||
serializer_class = self.new_include_json_fields_serializer_class(
|
serializer_class = self.build_include_json_fields_serializer_class(
|
||||||
base=serializer_class, attrs=fields_serializer_mapping
|
base=serializer_class, attrs=fields_serializer_mapping
|
||||||
)
|
)
|
||||||
return serializer_class
|
return serializer_class
|
||||||
|
|
||||||
|
|
||||||
class SerializerMixin(JSONFieldsSerializerMixin, GenericSerializerMixin):
|
class SerializerMixin(JSONFieldsModelSerializerMixin, GenericSerializerMixin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from common.exceptions import JMSException
|
|
||||||
from tickets import const, serializers
|
from tickets import const, serializers
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['TicketJSONFieldsSerializerViewMixin']
|
__all__ = ['TicketJSONFieldsModelSerializerViewMixin']
|
||||||
|
|
||||||
|
|
||||||
class TicketJSONFieldsSerializerViewMixin:
|
class TicketJSONFieldsModelSerializerViewMixin:
|
||||||
json_fields_category_mapping = {
|
json_fields_category_mapping = {
|
||||||
'meta': {
|
'meta': {
|
||||||
'type': const.TicketTypeChoices.values,
|
'type': const.TicketTypeChoices.values,
|
||||||
|
@ -15,30 +14,18 @@ class TicketJSONFieldsSerializerViewMixin:
|
||||||
'meta': {
|
'meta': {
|
||||||
'type': {
|
'type': {
|
||||||
const.TicketTypeChoices.apply_asset.value: {
|
const.TicketTypeChoices.apply_asset.value: {
|
||||||
'open': {
|
'default': serializers.TicketMetaApplyAssetSerializer,
|
||||||
'class': serializers.TicketMetaApplyAssetApplySerializer,
|
'open': serializers.TicketMetaApplyAssetApplySerializer,
|
||||||
'attrs': {'required': True}
|
'approve': serializers.TicketMetaApplyAssetApproveSerializer
|
||||||
},
|
|
||||||
'approve': {
|
|
||||||
'class': serializers.TicketMetaApplyAssetApproveSerializer,
|
|
||||||
'attrs': {'required': True}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
const.TicketTypeChoices.apply_application.value: {
|
const.TicketTypeChoices.apply_application.value: {
|
||||||
'open': {
|
'default': serializers.TicketMetaApplyApplicationSerializer,
|
||||||
'class': serializers.TicketMetaApplyApplicationApplySerializer,
|
'open': serializers.TicketMetaApplyApplicationApplySerializer,
|
||||||
'attrs': {'required': True}
|
'approve': serializers.TicketMetaApplyApplicationApproveSerializer,
|
||||||
},
|
|
||||||
'approve': {
|
|
||||||
'class': serializers.TicketMetaApplyApplicationApproveSerializer,
|
|
||||||
'attrs': {'required': True}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
const.TicketTypeChoices.login_confirm.value: {
|
const.TicketTypeChoices.login_confirm.value: {
|
||||||
'open': {
|
'default': serializers.TicketMetaLoginConfirmSerializer,
|
||||||
'class': serializers.TicketMetaLoginConfirmApplySerializer,
|
'open': serializers.TicketMetaLoginConfirmApplySerializer
|
||||||
'attrs': {'required': True}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ from common.const.http import POST, PUT
|
||||||
from tickets import serializers
|
from tickets import serializers
|
||||||
from tickets.permissions.ticket import IsAssignee, NotClosed
|
from tickets.permissions.ticket import IsAssignee, NotClosed
|
||||||
from tickets.models import Ticket
|
from tickets.models import Ticket
|
||||||
from tickets.api.ticket.mixin import TicketJSONFieldsSerializerViewMixin
|
from tickets.api.ticket.mixin import TicketJSONFieldsModelSerializerViewMixin
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['TicketViewSet']
|
__all__ = ['TicketViewSet']
|
||||||
|
|
||||||
|
|
||||||
class TicketViewSet(TicketJSONFieldsSerializerViewMixin, CommonApiMixin, viewsets.ModelViewSet):
|
class TicketViewSet(TicketJSONFieldsModelSerializerViewMixin, CommonApiMixin, viewsets.ModelViewSet):
|
||||||
permission_classes = (IsValidUser,)
|
permission_classes = (IsValidUser,)
|
||||||
serializer_class = serializers.TicketSerializer
|
serializer_class = serializers.TicketSerializer
|
||||||
serializer_classes = {
|
serializer_classes = {
|
||||||
|
|
|
@ -3,15 +3,18 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from applications.models import Category, Application
|
from applications.models import Category, Application
|
||||||
from assets.models import SystemUser
|
from assets.models import SystemUser
|
||||||
from .base import BaseTicketMetaSerializer, BaseTicketMetaApproveSerializerMixin
|
from .base import BaseTicketMetaApproveSerializerMixin
|
||||||
|
from common.fields.serializer import JSONFieldModelSerializer
|
||||||
|
from tickets.models import Ticket
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'TicketMetaApplyApplicationSerializer',
|
||||||
'TicketMetaApplyApplicationApplySerializer',
|
'TicketMetaApplyApplicationApplySerializer',
|
||||||
'TicketMetaApplyApplicationApproveSerializer',
|
'TicketMetaApplyApplicationApproveSerializer',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaApplyApplicationSerializer(BaseTicketMetaSerializer):
|
class TicketMetaApplyApplicationSerializer(JSONFieldModelSerializer):
|
||||||
# 申请信息
|
# 申请信息
|
||||||
apply_category = serializers.ChoiceField(
|
apply_category = serializers.ChoiceField(
|
||||||
required=True, choices=Category.choices, label=_('Category')
|
required=True, choices=Category.choices, label=_('Category')
|
||||||
|
@ -63,16 +66,33 @@ class TicketMetaApplyApplicationSerializer(BaseTicketMetaSerializer):
|
||||||
required=True, label=_('Date expired')
|
required=True, label=_('Date expired')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaApplyApplicationApplySerializer(TicketMetaApplyApplicationSerializer):
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
model = Ticket
|
||||||
|
model_field = Ticket.meta
|
||||||
fields = [
|
fields = [
|
||||||
'apply_category', 'apply_category_display',
|
'apply_category', 'apply_category_display',
|
||||||
'apply_type', 'apply_type_display',
|
'apply_type', 'apply_type_display',
|
||||||
'apply_application_group', 'apply_system_user_group',
|
'apply_application_group', 'apply_system_user_group',
|
||||||
'apply_date_start', 'apply_date_expired',
|
'apply_date_start', 'apply_date_expired',
|
||||||
|
|
||||||
|
'approve_applications', 'approve_applications_snapshot',
|
||||||
|
'approve_system_users', 'approve_system_users_snapshot',
|
||||||
|
'approve_date_start', 'approve_date_expired'
|
||||||
]
|
]
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
class TicketMetaApplyApplicationApplySerializer(TicketMetaApplyApplicationSerializer):
|
||||||
|
|
||||||
|
class Meta(TicketMetaApplyApplicationSerializer.Meta):
|
||||||
|
required_fields = [
|
||||||
|
'apply_category', 'apply_type',
|
||||||
|
'apply_application_group', 'apply_system_user_group',
|
||||||
|
'apply_date_start', 'apply_date_expired',
|
||||||
|
]
|
||||||
|
read_only_fields = list(
|
||||||
|
set(TicketMetaApplyApplicationSerializer.Meta.fields) - set(required_fields)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_apply_type(self, tp):
|
def validate_apply_type(self, tp):
|
||||||
category = self.root.initial_data['meta'].get('apply_category')
|
category = self.root.initial_data['meta'].get('apply_category')
|
||||||
|
@ -89,11 +109,13 @@ class TicketMetaApplyApplicationApproveSerializer(BaseTicketMetaApproveSerialize
|
||||||
TicketMetaApplyApplicationSerializer):
|
TicketMetaApplyApplicationSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = {
|
required_fields = {
|
||||||
'approve_applications', 'approve_applications_snapshot',
|
'approve_applications', 'approve_system_users',
|
||||||
'approve_system_users', 'approve_system_users_snapshot',
|
|
||||||
'approve_date_start', 'approve_date_expired'
|
'approve_date_start', 'approve_date_expired'
|
||||||
}
|
}
|
||||||
|
read_only_fields = list(
|
||||||
|
set(TicketMetaApplyApplicationSerializer.Meta.fields) - set(required_fields)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_approve_applications(self, approve_applications):
|
def validate_approve_applications(self, approve_applications):
|
||||||
application_type = self.root.instance.meta['apply_type']
|
application_type = self.root.instance.meta['apply_type']
|
||||||
|
|
|
@ -2,16 +2,20 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from perms.serializers import ActionsField
|
from perms.serializers import ActionsField
|
||||||
from assets.models import Asset, SystemUser
|
from assets.models import Asset, SystemUser
|
||||||
from .base import BaseTicketMetaSerializer, BaseTicketMetaApproveSerializerMixin
|
from .base import BaseTicketMetaApproveSerializerMixin
|
||||||
|
from tickets.models import Ticket
|
||||||
|
|
||||||
|
from common.fields.serializer import JSONFieldModelSerializer
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'TicketMetaApplyAssetSerializer',
|
||||||
'TicketMetaApplyAssetApplySerializer',
|
'TicketMetaApplyAssetApplySerializer',
|
||||||
'TicketMetaApplyAssetApproveSerializer',
|
'TicketMetaApplyAssetApproveSerializer',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaApplyAssetSerializer(BaseTicketMetaSerializer):
|
class TicketMetaApplyAssetSerializer(JSONFieldModelSerializer):
|
||||||
# 申请信息
|
# 申请信息
|
||||||
apply_ip_group = serializers.ListField(
|
apply_ip_group = serializers.ListField(
|
||||||
required=False, child=serializers.IPAddressField(), label=_('IP group'),
|
required=False, child=serializers.IPAddressField(), label=_('IP group'),
|
||||||
|
@ -71,28 +75,46 @@ class TicketMetaApplyAssetSerializer(BaseTicketMetaSerializer):
|
||||||
required=True, label=_('Date expired')
|
required=True, label=_('Date expired')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaApplyAssetApplySerializer(TicketMetaApplyAssetSerializer):
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
model = Ticket
|
||||||
|
model_field = Ticket.meta
|
||||||
fields = [
|
fields = [
|
||||||
'apply_ip_group',
|
'apply_ip_group',
|
||||||
'apply_hostname_group', 'apply_system_user_group',
|
'apply_hostname_group', 'apply_system_user_group',
|
||||||
'apply_actions', 'apply_actions_display',
|
'apply_actions', 'apply_actions_display',
|
||||||
'apply_date_start', 'apply_date_expired',
|
'apply_date_start', 'apply_date_expired',
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaApplyAssetApproveSerializer(BaseTicketMetaApproveSerializerMixin,
|
|
||||||
TicketMetaApplyAssetSerializer):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
fields = [
|
|
||||||
'approve_assets', 'approve_assets_snapshot',
|
'approve_assets', 'approve_assets_snapshot',
|
||||||
'approve_system_users', 'approve_system_users_snapshot',
|
'approve_system_users', 'approve_system_users_snapshot',
|
||||||
'approve_actions', 'approve_actions_display',
|
'approve_actions', 'approve_actions_display',
|
||||||
'approve_date_start', 'approve_date_expired',
|
'approve_date_start', 'approve_date_expired',
|
||||||
]
|
]
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
class TicketMetaApplyAssetApplySerializer(TicketMetaApplyAssetSerializer):
|
||||||
|
|
||||||
|
class Meta(TicketMetaApplyAssetSerializer.Meta):
|
||||||
|
required_fields = [
|
||||||
|
'apply_ip_group', 'apply_hostname_group', 'apply_system_user_group',
|
||||||
|
'apply_actions', 'apply_date_start', 'apply_date_expired',
|
||||||
|
]
|
||||||
|
read_only_fields = list(
|
||||||
|
set(TicketMetaApplyAssetSerializer.Meta.fields) - set(required_fields)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TicketMetaApplyAssetApproveSerializer(BaseTicketMetaApproveSerializerMixin,
|
||||||
|
TicketMetaApplyAssetSerializer):
|
||||||
|
|
||||||
|
class Meta(TicketMetaApplyAssetSerializer.Meta):
|
||||||
|
required_fields = [
|
||||||
|
'approve_assets', 'approve_system_users', 'approve_actions',
|
||||||
|
'approve_date_start', 'approve_date_expired',
|
||||||
|
]
|
||||||
|
read_only_fields = list(
|
||||||
|
set(TicketMetaApplyAssetSerializer.Meta.fields) - set(required_fields)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_approve_assets(self, approve_assets):
|
def validate_approve_assets(self, approve_assets):
|
||||||
assets_id = self.filter_approve_resources(resource_model=Asset, resources_id=approve_assets)
|
assets_id = self.filter_approve_resources(resource_model=Asset, resources_id=approve_assets)
|
||||||
|
|
|
@ -1,29 +1,13 @@
|
||||||
|
import copy
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.serializers import ALL_FIELDS
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orgs.utils import tmp_to_org
|
from orgs.utils import tmp_to_org
|
||||||
from assets.models import SystemUser
|
from assets.models import SystemUser
|
||||||
|
|
||||||
|
|
||||||
class BaseTicketMetaSerializer(serializers.Serializer):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
def get_fields(self):
|
|
||||||
fields = super().get_fields()
|
|
||||||
required_fields = self.Meta.fields
|
|
||||||
if required_fields == '__all__':
|
|
||||||
return fields
|
|
||||||
|
|
||||||
fields = OrderedDict({
|
|
||||||
field_name: fields.pop(field_name) for field_name in set(required_fields)
|
|
||||||
if field_name in fields.keys()
|
|
||||||
})
|
|
||||||
return fields
|
|
||||||
|
|
||||||
|
|
||||||
class BaseTicketMetaApproveSerializerMixin:
|
class BaseTicketMetaApproveSerializerMixin:
|
||||||
|
|
||||||
def _filter_approve_resources_by_org(self, model, resources_id):
|
def _filter_approve_resources_by_org(self, model, resources_id):
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from .base import BaseTicketMetaSerializer
|
from common.fields.serializer import JSONFieldModelSerializer
|
||||||
|
from tickets.models import Ticket
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'TicketMetaLoginConfirmApplySerializer',
|
'TicketMetaLoginConfirmSerializer', 'TicketMetaLoginConfirmApplySerializer',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaLoginConfirmSerializer(BaseTicketMetaSerializer):
|
class TicketMetaLoginConfirmSerializer(JSONFieldModelSerializer):
|
||||||
apply_login_ip = serializers.IPAddressField(
|
apply_login_ip = serializers.IPAddressField(
|
||||||
required=True, label=_('Login ip')
|
required=True, label=_('Login ip')
|
||||||
)
|
)
|
||||||
|
@ -19,6 +20,21 @@ class TicketMetaLoginConfirmSerializer(BaseTicketMetaSerializer):
|
||||||
required=True, label=_('Login datetime')
|
required=True, label=_('Login datetime')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Ticket
|
||||||
|
model_field = Ticket.meta
|
||||||
|
fields = [
|
||||||
|
'apply_login_ip', 'apply_login_city', 'apply_login_datetime'
|
||||||
|
]
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
class TicketMetaLoginConfirmApplySerializer(TicketMetaLoginConfirmSerializer):
|
class TicketMetaLoginConfirmApplySerializer(TicketMetaLoginConfirmSerializer):
|
||||||
pass
|
|
||||||
|
class Meta(TicketMetaLoginConfirmSerializer.Meta):
|
||||||
|
required_fields = [
|
||||||
|
'apply_login_ip', 'apply_login_city', 'apply_login_datetime'
|
||||||
|
]
|
||||||
|
read_only_fields = list(
|
||||||
|
set(TicketMetaLoginConfirmSerializer.Meta.fields) - set(required_fields)
|
||||||
|
)
|
||||||
|
|
|
@ -92,8 +92,7 @@ class TicketApplySerializer(TicketActionSerializer):
|
||||||
raise serializers.ValidationError(error)
|
raise serializers.ValidationError(error)
|
||||||
return valid_assignees
|
return valid_assignees
|
||||||
|
|
||||||
@staticmethod
|
def validate_action(self, action):
|
||||||
def validate_action(action):
|
|
||||||
return const.TicketActionChoices.open.value
|
return const.TicketActionChoices.open.value
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,15 +122,13 @@ class TicketApproveSerializer(TicketProcessSerializer):
|
||||||
|
|
||||||
class TicketRejectSerializer(TicketProcessSerializer):
|
class TicketRejectSerializer(TicketProcessSerializer):
|
||||||
|
|
||||||
@staticmethod
|
def validate_action(self, action):
|
||||||
def validate_action(action):
|
|
||||||
return const.TicketActionChoices.reject.value
|
return const.TicketActionChoices.reject.value
|
||||||
|
|
||||||
|
|
||||||
class TicketCloseSerializer(TicketProcessSerializer):
|
class TicketCloseSerializer(TicketProcessSerializer):
|
||||||
|
|
||||||
@staticmethod
|
def validate_action(self, action):
|
||||||
def validate_action(action):
|
|
||||||
return const.TicketActionChoices.close.value
|
return const.TicketActionChoices.close.value
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue