class SocketSerializer(RevalidateMixin, MetadataMixin, DynamicFieldsMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'socket-detail', ( 'instance.name', 'name', )), ('update', 'socket-update', ( 'instance.name', 'name', )), ('endpoints', 'socket-endpoint-endpoint', ( 'instance.name', 'name', )), ('handlers', 'socket-handler-list', ( 'instance.name', 'name', )), ('zip_file', 'socket-zip-file', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=Socket.objects.all()), DjangoValidator() ]) zip_file = FileField(write_only=True) zip_file_list = JSONField(validators=[FileListValidator()], default=None, write_only=True) config = JSONField(validators=[validate_config], default={}) install_config = JSONField(write_only=True, default={}) status = DisplayedChoiceField(Socket.STATUSES.as_choices(), read_only=True) status_info = JSONField(read_only=True) installed = JSONField(read_only=True) files = serializers.SerializerMethodField() environment = SlugRelatedField(slug_field='name', queryset=SocketEnvironment.objects.all(), default=None, allow_null=True) class Meta: model = Socket fields = ('name', 'description', 'created_at', 'updated_at', 'version', 'status', 'status_info', 'install_url', 'metadata', 'config', 'zip_file', 'zip_file_list', 'installed', 'files', 'environment', 'install_config', ) read_only_fields = ('install_url', 'version') def get_files(self, obj): file_list = copy.deepcopy(obj.file_list) for val in file_list.values(): if not val['file'].startswith('<'): val['file'] = default_storage.url(val['file']) return file_list
class WebhookRunSerializer(serializers.Serializer): payload_validator = PayloadValidator() POST = JSONField(default={}) GET = JSONField(default={}) def validate(self, data): data = super().validate(data) # Call validators manually as we don't want to output validation error specific to a non user field self.payload_validator(data['POST']) return data
class PricingPlanSerializer(DynamicFieldsMixin, HyperlinkedMixin, serializers.ModelSerializer): hyperlinks = ( ('self', 'plan-detail', ('name', )), ('subscribe', 'plan-subscribe', ('name', )), ) pricing = JSONField() options = JSONField() class Meta: model = PricingPlan fields = ('name', 'pricing', 'options')
class ChangeSerializer(DynamicFieldsMixin, HyperlinkedMixin, serializers.Serializer): hyperlinks = (('self', 'change-detail', ( 'instance.name', 'channel.name', 'id', )), ) id = serializers.IntegerField() created_at = serializers.DateTimeField() action = DisplayedChoiceField(choices=Change.ACTIONS.as_choices()) author = JSONField() metadata = JSONField() payload = JSONField()
class CodeBoxSerializer(DynamicFieldsMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'codebox-detail', ( 'instance.name', 'pk', )), ('runtimes', 'runtime-list', ('instance.name', )), ('run', 'codebox-run', ( 'instance.name', 'pk', )), ('traces', 'codebox-trace-list', ( 'instance.name', 'pk', )), ) config = JSONField(validators=[validate_config], default={}) source = TruncatedCharField(cutoff=settings.CODEBOX_SOURCE_CUTOFF, trim_whitespace=False, max_length=settings.CODEBOX_SOURCE_SIZE_LIMIT, default='', allow_blank=True) runtime_name = serializers.ChoiceField(choices=RUNTIME_CHOICES) class Meta: model = CodeBox fields = ('id', 'runtime_name', 'source', 'created_at', 'updated_at', 'config', 'label', 'description')
class SubscriptionSerializer(DynamicFieldsMixin, HyperlinkedMixin, serializers.ModelSerializer): hyperlinks = ( ('self', 'subscription-detail', ('id', )), ('cancel', 'subscription-cancel', ('id', )), ) plan = serializers.CharField(source='plan.name') pricing = serializers.SerializerMethodField() commitment = JSONField(default={}) start = serializers.DateField() end = serializers.DateField() class Meta: model = Subscription fields = ( 'id', 'start', 'end', 'plan', 'commitment', 'pricing', ) def get_pricing(self, obj): pricing = {} commitment = obj.commitment for key, value in commitment.items(): pricing[key] = obj.plan.pricing[key][value] return pricing
class PricingPlanSubscribeSerializer(serializers.Serializer): commitment = JSONField() def validate_commitment(self, value): if not value: return value commitment = value plan = self.context['view'].object options = plan.options if not isinstance(commitment, dict): raise serializers.ValidationError( 'Not a valid value type. Specify it in a form of JSON object, e.g. {"api": 20, "cbx": 5}.' ) if len(commitment) != len(options): raise serializers.ValidationError( 'You need to specify all of plan\'s options. ' 'Expected: {num}, got {keys}.'.format(num=len(options), keys=len(commitment))) for key, val in commitment.items(): if key not in options: raise serializers.ValidationError( 'Invalid key: {key}. ' 'Does not match any key in plan\'s options.'.format( key=key)) if val not in options[key]: raise serializers.ValidationError( 'Invalid value: {value} for key "{key}". ' 'Not a valid option for selected plan.'.format(value=val, key=key)) return value
class ResponseTemplateSerializer(DynamicFieldsMixin, RevalidateMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'response-templates-detail', ( 'instance.name', 'name', )), ('rename', 'response-templates-rename', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=ResponseTemplate.objects.all()), DjangoValidator() ]) context = JSONField(default={}, validators=[validate_template_context]) content = serializers.CharField(validators=[Jinja2TemplateValidator()]) content_type = serializers.CharField(validators=[RegexValidator( regex=re.compile(r'^([a-z]+)\/([a-z0-9+-\.]+)*$', re.IGNORECASE), message='Not a valid content_type.')], ) class Meta: fields = ('name', 'content', 'content_type', 'context', 'description') model = ResponseTemplate
class UserSchemaSerializer(serializers.ModelSerializer): schema = JSONField( validators=[SchemaValidator(ADDITIONAL_RESERVED_FIELD_NAMES)], default=[]) class Meta: model = Klass fields = ('schema', )
class WebhookTraceBaseSerializer(serializers.Serializer): hyperlinks = (('self', 'webhook-trace-detail', ( 'instance.name', 'webhook.name', 'id', )), ) meta = JSONField(default={})
class WebhookTraceBaseSerializer(serializers.Serializer): hyperlinks = (('self', 'webhook-trace-detail', ( 'instance.name', 'webhook.name', 'id', )), ) meta = JSONField(default={}) args = JSONFieldWithCutoff(cutoff=settings.CODEBOX_PAYLOAD_CUTOFF, placeholder=WEBHOOK_PAYLOAD_PLACEHOLDER, default={})
class DataObjectHighLevelApiSerializer(RevalidateMixin, DynamicFieldsMixin, RemapperMixin, HyperlinkedMixin, HStoreSerializer): hyperlinks = ( ('self', 'hla-objects-detail', ( 'instance.name', 'name', )), ('get', 'hla-objects-get', ( 'instance.name', 'name', )), ('post', 'hla-objects-post', ( 'instance.name', 'name', )), ('rename', 'hla-objects-rename', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=DataObjectHighLevelApi.objects.all()), DjangoValidator() ]) query = JSONField(validators=[validate_query], default={}) klass = SlugRelatedField(slug_field='name', label='class', queryset=Klass.objects.all()) field_mappings = {'klass': 'class'} class Meta: model = DataObjectHighLevelApi fields = ('name', 'description', 'klass', 'query', 'excluded_fields', 'order_by', 'page_size', 'expand') extra_kwargs = { 'excluded_fields': {'validators': [data_field_list_validator]}, 'fields': {'validators': [data_field_list_validator]}, 'expand': {'validators': [data_field_list_validator]}, 'page_size': {'min_value': 0, 'max_value': api_settings.PAGE_SIZE}, }
class SocketEnvironmentSerializer(RevalidateMixin, MetadataMixin, DynamicFieldsMixin, HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'socket-environment-detail', ( 'instance.name', 'name', )), ) name = LowercaseCharField(validators=[ UniqueValidator(queryset=SocketEnvironment.objects.all()), DjangoValidator() ]) zip_file = FileField(write_only=True) status = DisplayedChoiceField(SocketEnvironment.STATUSES.as_choices(), read_only=True) status_info = JSONField(read_only=True) checksum = CharField(read_only=True) class Meta: model = SocketEnvironment fields = ('name', 'description', 'created_at', 'updated_at', 'status', 'status_info', 'metadata', 'zip_file', 'checksum')
class BackupSerializer(MetadataMixin, ModelSerializer): instance = SlugRelatedField(slug_field='name', required=False, read_only=True, allow_null=False) status = DisplayedChoiceField(Backup.STATUSES.as_choices(), read_only=True) author = AdminFullSerializer(read_only=True, source="owner") details = JSONField(read_only=True) class Meta: model = Backup read_only_fields = ('id', 'instance', 'created_at', 'updated_at', 'archive', 'size', 'status', 'status_info', 'author', 'details') fields = read_only_fields + ('description', 'label', 'query_args', 'metadata') extra_kwargs = { 'description': { 'required': False }, 'label': { 'required': False } }
class HostingSerializer(v1_1_serializers.HostingSerializer): hyperlinks = ( ('self', 'hosting-detail', ( 'instance.name', 'name', )), ('files', 'hosting-file-list', ( 'instance.name', 'name', )), ('set_default', 'hosting-set-default', ( 'instance.name', 'name', )), ('enable_ssl', 'hosting-enable-ssl', ( 'instance.name', 'name', )), ('socket', 'socket-detail', ( 'instance.name', 'socket.name', )), ) config = JSONField(validators=[HostingConfigValidator()], default={}) class Meta(v1_1_serializers.HostingSerializer.Meta): fields = ('name', 'is_default', 'description', 'created_at', 'updated_at', 'domains', 'is_active', 'ssl_status', 'auth', 'config') def validate_auth(self, value): for uname, passwd in value.items(): if not passwd.startswith('crypt:'): value[uname] = Hosting.encrypt_passwd(passwd) return value
class RenderSerializer(serializers.Serializer): # on render endpoint allow to override restricted keys; context = JSONField(default={}, validators=[validate_render_template_context])
class BatchRequestSerializer(serializers.Serializer): method = serializers.ChoiceField(choices=('GET', 'POST', 'PUT', 'PATCH', 'DELETE')) path = LowercaseCharField(max_length=8192, validators=[PathValidator()]) body = JSONField(default={}, validators=[validate_batch_body])
class GCMMessageSerializer(HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'gcm-messages-detail', ('instance.name', 'pk')), ) # More info: https://developers.google.com/cloud-messaging/http-server-ref SCHEMA = { 'type': 'object', 'additionalProperties': False, 'required': [ 'registration_ids', 'environment', ], 'properties': { # Targets 'registration_ids': { 'type': 'array', 'uniqueItems': True, 'maxItems': 1000, 'items': { 'type': 'string' } }, 'environment': { 'type': 'string', 'enum': [ 'development', 'production', ] }, # Payload 'data': { 'type': 'object', 'maxProperties': 256 }, 'notification': { 'type': 'object', 'maxProperties': 256 }, # Options 'collapse_key': { 'type': 'string' }, 'priority': { 'type': 'string', 'enum': ['normal', 'high'] }, 'content_available': { 'type': 'boolean' }, 'delay_while_idle': { 'type': 'boolean' }, 'time_to_live': { 'type': 'integer', 'maximum': 3600 * 24 * 28, # 4 weeks 'minimum': 1 }, 'restricted_package_name': { 'type': 'string' }, 'dry_run': { 'type': 'boolean' } } } status = DisplayedChoiceField(choices=GCMMessage.STATUSES.as_choices(), read_only=True) content = JSONField(required=True, schema=SCHEMA) result = JSONField(default={}, read_only=True) class Meta: model = GCMMessage read_only_fields = ( 'created_at', 'updated_at', 'status', 'result', ) fields = '__all__' def validate(self, data): config = Cached(GCMConfig, kwargs={'id': 1}).get() if 'content' in data: environment = data['content']['environment'] else: environment = self.instance.content['environment'] api_key = getattr(config, '{}_api_key'.format(environment)) if not api_key: raise ValidationError('GCM api key for "{}" environment is required.'.format(environment)) return data
class APNSMessageSerializer(HyperlinkedMixin, ModelSerializer): hyperlinks = ( ('self', 'apns-messages-detail', ('instance.name', 'pk')), ) SCHEMA = { 'type': 'object', 'maxItems': 128, 'required': [ 'registration_ids', 'environment', 'aps' ], 'properties': { # Targets 'registration_ids': { 'type': 'array', 'uniqueItems': True, 'maxItems': 1000, 'items': { 'type': 'string' } }, 'environment': { 'type': 'string', 'enum': [ 'development', 'production', ] }, 'aps': { 'type': 'object', 'required': ['alert'], 'properties': { 'alert': { 'oneOf': [ {'type': 'string'}, { 'type': 'object', 'required': ['title', 'body'], 'properties': { 'title': { 'type': 'string' }, 'body': { 'type': 'string' }, 'title-loc-key': { 'type': 'string' }, 'title-loc-args': { 'type': 'array', 'items': { 'type': 'string' } }, 'action-loc-key': { 'type': 'string' }, 'loc-key': { 'type': 'string' }, 'loc-args': { 'type': 'array', 'items': { 'type': 'string' } }, 'launch-image': { 'type': 'string' } } }, ] }, 'badge': { 'type': 'integer' }, 'sound': { 'type': 'string' }, 'content-available': { 'type': 'integer' }, 'category': { 'type': 'string' } } }, } } status = DisplayedChoiceField(choices=APNSMessage.STATUSES.as_choices(), read_only=True) content = JSONField(required=True, schema=SCHEMA) result = JSONField(default={}, read_only=True) class Meta: model = APNSMessage read_only_fields = ( 'created_at', 'updated_at', 'status', 'result', ) fields = '__all__' def validate(self, data): config = Cached(APNSConfig, kwargs={'id': 1}).get() if 'content' in data: environment = data['content']['environment'] else: environment = self.instance.content['environment'] certificate = getattr(config, '{}_certificate'.format(environment)) bundle_identifier = getattr(config, '{}_bundle_identifier'.format(environment)) if not certificate: raise ValidationError('APNS certificate for "{}" environment is required.'.format(environment)) if not bundle_identifier: raise ValidationError('APNS bundle identifier for "{}" environment is required.'.format(environment)) return data
class TriggerEmitSerializer(serializers.Serializer): signal = serializers.CharField(max_length=128, validators=[SignalValidator()]) payload = JSONField(validators=[PayloadValidator()], default={})
def __init__(self, *args, **kwargs): if self.metadata_field not in self._declared_fields: metadata_field = JSONField(validators=[validate_metadata], default={}) self._declared_fields[self.metadata_field] = metadata_field super(MetadataMixin, self).__init__(*args, **kwargs)
class CodeBoxRunSerializer(serializers.Serializer): payload = JSONField(validators=[PayloadValidator()], default={})
class TraceDetailSerializer(TraceSerializer): result = JSONField(default={})
class WebhookTraceDetailSerializer(WebhookTraceBaseSerializer, TraceDetailSerializer): args = JSONField(default={})
class PartialBackupSerializer(HyperlinkedMixin, BackupSerializer): hyperlinks = (('self', 'partial_backups-toplevel-detail', ('id', )), ) query_args = JSONField(required=True, validators=[default_site.validate_query_args], write_only=True, schema=lambda: default_site.jsonschema)
class InstanceConfigSerializer(ModelSerializer): config = JSONField(validators=[validate_config], default={}) class Meta: model = Instance fields = ('config', )
class ChannelPublishSerializer(serializers.Serializer): payload = JSONField(validators=[validate_payload], default={}) room = serializers.CharField(max_length=128, required=False)