You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.5 KiB
Python

# Copyright (C) 2022 CVAT.ai Corporation
#
# SPDX-License-Identifier: MIT
from .event_type import EventTypeChoice, ProjectEvents, OrganizationEvents
from .models import (
Webhook,
WebhookContentTypeChoice,
WebhookTypeChoice,
WebhookDelivery,
)
from rest_framework import serializers
from cvat.apps.engine.serializers import BasicUserSerializer, WriteOnceMixin
class EventTypeValidator:
requires_context = True
def get_webhook_type(self, attrs, serializer):
if serializer.instance is not None:
return serializer.instance.type
return attrs.get("type")
def __call__(self, attrs, serializer):
if attrs.get("events") is not None:
webhook_type = self.get_webhook_type(attrs, serializer)
events = set(EventTypesSerializer().to_representation(attrs["events"]))
if (
webhook_type == WebhookTypeChoice.PROJECT
and not events.issubset(set(ProjectEvents.events))
) or (
webhook_type == WebhookTypeChoice.ORGANIZATION
and not events.issubset(set(OrganizationEvents.events))
):
raise serializers.ValidationError(
f"Invalid events list for {webhook_type} webhook"
)
class EventTypesSerializer(serializers.MultipleChoiceField):
def __init__(self, *args, **kwargs):
super().__init__(choices=EventTypeChoice.choices(), *args, **kwargs)
def to_representation(self, value):
if isinstance(value, list):
return sorted(super().to_representation(value))
return sorted(list(super().to_representation(value.split(","))))
def to_internal_value(self, data):
return ",".join(super().to_internal_value(data))
class EventsSerializer(serializers.Serializer):
webhook_type = serializers.ChoiceField(choices=WebhookTypeChoice.choices())
events = EventTypesSerializer()
class WebhookReadSerializer(serializers.ModelSerializer):
owner = BasicUserSerializer(read_only=True, required=False)
events = EventTypesSerializer(read_only=True)
type = serializers.ChoiceField(choices=WebhookTypeChoice.choices())
content_type = serializers.ChoiceField(choices=WebhookContentTypeChoice.choices())
last_status = serializers.IntegerField(
source="deliveries.last.status_code", read_only=True
)
last_delivery_date = serializers.DateTimeField(
source="deliveries.last.updated_date", read_only=True
)
class Meta:
model = Webhook
fields = (
"id",
"url",
"target_url",
"description",
"type",
"content_type",
"is_active",
"enable_ssl",
"created_date",
"updated_date",
"owner",
"project",
"organization",
"events",
"last_status",
"last_delivery_date",
)
read_only_fields = fields
class WebhookWriteSerializer(WriteOnceMixin, serializers.ModelSerializer):
events = EventTypesSerializer(write_only=True)
# Q: should be owner_id required or not?
owner_id = serializers.IntegerField(
write_only=True, allow_null=True, required=False
)
project_id = serializers.IntegerField(
write_only=True, allow_null=True, required=False
)
def to_representation(self, instance):
serializer = WebhookReadSerializer(instance, context=self.context)
return serializer.data
class Meta:
model = Webhook
fields = (
"target_url",
"description",
"type",
"content_type",
"secret",
"is_active",
"enable_ssl",
"owner_id",
"project_id",
"events",
)
write_once_fields = ("type", "owner_id", "project_id")
validators = [EventTypeValidator()]
def create(self, validated_data):
db_webhook = Webhook.objects.create(**validated_data)
return db_webhook
class WebhookDeliveryReadSerializer(serializers.ModelSerializer):
webhook_id = serializers.IntegerField(read_only=True)
class Meta:
model = WebhookDelivery
fields = (
"id",
"webhook_id",
"event",
"status_code",
"redelivery",
"created_date",
"updated_date",
"changed_fields",
"request",
"response",
)
read_only_fields = fields