Add is_default fields to templates, remove WritableSerialiserMethodFi… (#1759)
…eld, refactor fields # What this PR does ## Which issue(s) this PR fixes ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [ ] Documentation added (or `pr:no public docs` PR label added if not required) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
This commit is contained in:
parent
5da5b8d430
commit
61dced5bd9
4 changed files with 69 additions and 347 deletions
|
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Helm chart: add the option to use a helm hook for the migration job ([1386](https://github.com/grafana/oncall/pull/1386))
|
||||
- Add endpoints to start and stop maintenance in alert receive channel private api ([1755](https://github.com/grafana/oncall/pull/1755))
|
||||
- Send demo alert with dynamic payload and get demo payload example on private api ([1700](https://github.com/grafana/oncall/pull/1700))
|
||||
- Add is_default fields to templates, remove WritableSerialiserMethodField ([1759](https://github.com/grafana/oncall/pull/1759))
|
||||
- Allow use of dynamic payloads in alert receive channels preview template in private api ([1756](https://github.com/grafana/oncall/pull/1756))
|
||||
|
||||
## v1.2.11 (2023-04-14)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,19 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Mapping
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from jinja2 import TemplateSyntaxError
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import SerializerMethodField, SkipField, get_error_detail, set_value
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.fields import SerializerMethodField, set_value
|
||||
|
||||
from apps.alerts.grafana_alerting_sync_manager.grafana_alerting_sync import GrafanaAlertingSyncManager
|
||||
from apps.alerts.models import AlertReceiveChannel
|
||||
from apps.base.messaging import get_messaging_backends
|
||||
from common.api_helpers.custom_fields import TeamPrimaryKeyRelatedField, WritableSerializerMethodField
|
||||
from common.api_helpers.custom_fields import TeamPrimaryKeyRelatedField
|
||||
from common.api_helpers.exceptions import BadRequest
|
||||
from common.api_helpers.mixins import APPEARANCE_TEMPLATE_NAMES, EagerLoadingMixin
|
||||
from common.api_helpers.utils import CurrentTeamDefault
|
||||
|
|
@ -197,96 +194,23 @@ class FilterAlertReceiveChannelSerializer(serializers.ModelSerializer):
|
|||
|
||||
class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.ModelSerializer):
|
||||
id = serializers.CharField(read_only=True, source="public_primary_key")
|
||||
slack_title_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
slack_message_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
slack_image_url_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
web_title_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
web_message_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
web_image_url_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
sms_title_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
phone_call_title_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
telegram_title_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
telegram_message_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
telegram_image_url_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
source_link_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
grouping_id_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
acknowledge_condition_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
resolve_condition_template = WritableSerializerMethodField(
|
||||
allow_null=True,
|
||||
deserializer_field=serializers.CharField(),
|
||||
validators=[valid_jinja_template_for_serializer_method_field],
|
||||
required=False,
|
||||
)
|
||||
CORE_TEMPLATE_NAMES = [
|
||||
"slack_title_template",
|
||||
"slack_message_template",
|
||||
"slack_image_url_template",
|
||||
"web_title_template",
|
||||
"web_message_template",
|
||||
"web_image_url_template",
|
||||
"telegram_title_template",
|
||||
"telegram_message_template",
|
||||
"telegram_image_url_template",
|
||||
"sms_title_template",
|
||||
"phone_call_title_template",
|
||||
"source_link_template",
|
||||
"grouping_id_template",
|
||||
"resolve_condition_template",
|
||||
"acknowledge_condition_template",
|
||||
]
|
||||
|
||||
payload_example = SerializerMethodField()
|
||||
|
||||
|
|
@ -295,207 +219,10 @@ class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.Mode
|
|||
fields = [
|
||||
"id",
|
||||
"verbal_name",
|
||||
"slack_title_template",
|
||||
"slack_message_template",
|
||||
"slack_image_url_template",
|
||||
"sms_title_template",
|
||||
"phone_call_title_template",
|
||||
"web_title_template",
|
||||
"web_message_template",
|
||||
"web_image_url_template",
|
||||
"telegram_title_template",
|
||||
"telegram_message_template",
|
||||
"telegram_image_url_template",
|
||||
"source_link_template",
|
||||
"grouping_id_template",
|
||||
"resolve_condition_template",
|
||||
"payload_example",
|
||||
"acknowledge_condition_template",
|
||||
]
|
||||
extra_kwargs = {"integration": {"required": True}}
|
||||
|
||||
# MethodFields are used instead of relevant properties because of properties hit db on each instance in queryset
|
||||
|
||||
def get_slack_title_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_TITLE_TEMPLATE[obj.integration]
|
||||
return obj.slack_title_template or default_template
|
||||
|
||||
def set_slack_title_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_TITLE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.slack_title_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.slack_title_template = None
|
||||
|
||||
def get_slack_message_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_MESSAGE_TEMPLATE[obj.integration]
|
||||
return obj.slack_message_template or default_template
|
||||
|
||||
def set_slack_message_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_MESSAGE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.slack_message_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.slack_message_template = None
|
||||
|
||||
def get_slack_image_url_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_IMAGE_URL_TEMPLATE[obj.integration]
|
||||
return obj.slack_image_url_template or default_template
|
||||
|
||||
def set_slack_image_url_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SLACK_IMAGE_URL_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.slack_image_url_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.slack_image_url_template = None
|
||||
|
||||
def get_sms_title_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SMS_TITLE_TEMPLATE[obj.integration]
|
||||
return obj.sms_title_template or default_template
|
||||
|
||||
def set_sms_title_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SMS_TITLE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.sms_title_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.sms_title_template = None
|
||||
|
||||
def get_phone_call_title_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_PHONE_CALL_TITLE_TEMPLATE[obj.integration]
|
||||
return obj.phone_call_title_template or default_template
|
||||
|
||||
def set_phone_call_title_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_PHONE_CALL_TITLE_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.phone_call_title_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.phone_call_title_template = None
|
||||
|
||||
def get_web_title_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_TITLE_TEMPLATE[obj.integration]
|
||||
return obj.web_title_template or default_template
|
||||
|
||||
def set_web_title_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_TITLE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.web_title_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.web_title_template = None
|
||||
self.instance.web_templates_modified_at = timezone.now()
|
||||
|
||||
def get_web_message_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_MESSAGE_TEMPLATE[obj.integration]
|
||||
return obj.web_message_template or default_template
|
||||
|
||||
def set_web_message_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_MESSAGE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.web_message_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.web_message_template = None
|
||||
self.instance.web_templates_modified_at = timezone.now()
|
||||
|
||||
def get_web_image_url_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_IMAGE_URL_TEMPLATE[obj.integration]
|
||||
return obj.web_image_url_template or default_template
|
||||
|
||||
def set_web_image_url_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_WEB_IMAGE_URL_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.web_image_url_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.web_image_url_template = None
|
||||
self.instance.web_templates_modified_at = timezone.now()
|
||||
|
||||
def get_telegram_title_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_TITLE_TEMPLATE[obj.integration]
|
||||
return obj.telegram_title_template or default_template
|
||||
|
||||
def set_telegram_title_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_TITLE_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.telegram_title_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.telegram_title_template = None
|
||||
|
||||
def get_telegram_message_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_MESSAGE_TEMPLATE[obj.integration]
|
||||
return obj.telegram_message_template or default_template
|
||||
|
||||
def set_telegram_message_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_MESSAGE_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.telegram_message_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.telegram_message_template = None
|
||||
|
||||
def get_telegram_image_url_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_IMAGE_URL_TEMPLATE[obj.integration]
|
||||
return obj.telegram_image_url_template or default_template
|
||||
|
||||
def set_telegram_image_url_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_TELEGRAM_IMAGE_URL_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.telegram_image_url_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.telegram_image_url_template = None
|
||||
|
||||
def get_source_link_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SOURCE_LINK_TEMPLATE[obj.integration]
|
||||
return obj.source_link_template or default_template
|
||||
|
||||
def set_source_link_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_SOURCE_LINK_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.source_link_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.source_link_template = None
|
||||
|
||||
def get_grouping_id_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_GROUPING_ID_TEMPLATE[obj.integration]
|
||||
return obj.grouping_id_template or default_template
|
||||
|
||||
def set_grouping_id_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_GROUPING_ID_TEMPLATE[self.instance.integration]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.grouping_id_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.grouping_id_template = None
|
||||
|
||||
def get_acknowledge_condition_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_ACKNOWLEDGE_CONDITION_TEMPLATE[obj.integration]
|
||||
return obj.acknowledge_condition_template or default_template
|
||||
|
||||
def set_acknowledge_condition_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_ACKNOWLEDGE_CONDITION_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.acknowledge_condition_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.acknowledge_condition_template = None
|
||||
|
||||
def get_resolve_condition_template(self, obj):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_RESOLVE_CONDITION_TEMPLATE[obj.integration]
|
||||
return obj.resolve_condition_template or default_template
|
||||
|
||||
def set_resolve_condition_template(self, value):
|
||||
default_template = AlertReceiveChannel.INTEGRATION_TO_DEFAULT_RESOLVE_CONDITION_TEMPLATE[
|
||||
self.instance.integration
|
||||
]
|
||||
if default_template is None or default_template.strip() != value.strip():
|
||||
self.instance.resolve_condition_template = value.strip()
|
||||
elif default_template is not None and default_template.strip() == value.strip():
|
||||
self.instance.resolve_condition_template = None
|
||||
|
||||
def get_payload_example(self, obj):
|
||||
AlertGroup = apps.get_model("alerts", "AlertGroup")
|
||||
if "alert_group_id" in self.context["request"].query_params:
|
||||
|
|
@ -517,33 +244,15 @@ class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.Mode
|
|||
"""
|
||||
Dict of native values <- Dict of primitive datatypes.
|
||||
"""
|
||||
if not isinstance(data, Mapping):
|
||||
message = self.error_messages["invalid"].format(datatype=type(data).__name__)
|
||||
raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code="invalid")
|
||||
# First validate and save data from serializer fields
|
||||
ret = super().to_internal_value(data)
|
||||
|
||||
ret = OrderedDict()
|
||||
# Separately validate and save template fields we generate dynamically
|
||||
errors = OrderedDict()
|
||||
fields = self._writable_fields
|
||||
|
||||
for field in fields:
|
||||
validate_method = getattr(self, "validate_" + field.field_name, None)
|
||||
primitive_value = field.get_value(data)
|
||||
try:
|
||||
validated_value = field.run_validation(primitive_value)
|
||||
if validate_method is not None:
|
||||
validated_value = validate_method(validated_value)
|
||||
except ValidationError as exc:
|
||||
errors[field.field_name] = exc.detail
|
||||
except DjangoValidationError as exc:
|
||||
errors[field.field_name] = get_error_detail(exc)
|
||||
except SkipField:
|
||||
pass
|
||||
else:
|
||||
# Line because of which method is overriden
|
||||
if validated_value is None and isinstance(field, WritableSerializerMethodField):
|
||||
set_value(ret, [field.field_name], validated_value)
|
||||
else:
|
||||
set_value(ret, field.source_attrs, validated_value)
|
||||
# handle updates for core templates
|
||||
core_template_errors = self._handle_core_template_updates(data, ret)
|
||||
errors.update(core_template_errors)
|
||||
|
||||
# handle updates for messaging backend templates
|
||||
messaging_backend_errors = self._handle_messaging_backend_updates(data, ret)
|
||||
|
|
@ -551,7 +260,6 @@ class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.Mode
|
|||
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
return ret
|
||||
|
||||
def _handle_messaging_backend_updates(self, data, ret):
|
||||
|
|
@ -586,10 +294,33 @@ class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.Mode
|
|||
|
||||
return errors
|
||||
|
||||
def _handle_core_template_updates(self, data, ret):
|
||||
"""Update core templates if needed."""
|
||||
errors = {}
|
||||
|
||||
core_template_names = self.CORE_TEMPLATE_NAMES
|
||||
|
||||
for field_name in core_template_names:
|
||||
value = data.get(field_name)
|
||||
validator = jinja_template_env.from_string
|
||||
if value is not None:
|
||||
try:
|
||||
if value:
|
||||
validator(value)
|
||||
except TemplateSyntaxError:
|
||||
errors[field_name] = "invalid template"
|
||||
except DjangoValidationError:
|
||||
errors[field_name] = "invalid URL"
|
||||
set_value(ret, [field_name], value)
|
||||
return errors
|
||||
|
||||
def to_representation(self, obj):
|
||||
ret = super().to_representation(obj)
|
||||
ret = self._get_templates_to_show(ret)
|
||||
|
||||
core_templates = self._get_core_templates(obj)
|
||||
ret.update(core_templates)
|
||||
|
||||
# include messaging backend templates
|
||||
additional_templates = self._get_messaging_backend_templates(obj)
|
||||
ret.update(additional_templates)
|
||||
|
|
@ -627,10 +358,26 @@ class AlertReceiveChannelTemplatesSerializer(EagerLoadingMixin, serializers.Mode
|
|||
continue
|
||||
for field in backend.template_fields:
|
||||
value = None
|
||||
is_default = False
|
||||
if obj.messaging_backends_templates:
|
||||
value = obj.messaging_backends_templates.get(backend_id, {}).get(field)
|
||||
if not value:
|
||||
value = obj.get_default_template_attribute(backend_id, field)
|
||||
is_default = True
|
||||
field_name = f"{backend.slug}_{field}_template"
|
||||
templates[field_name] = value
|
||||
templates[f"{field_name}_is_default"] = is_default
|
||||
return templates
|
||||
|
||||
def _get_core_templates(self, obj):
|
||||
core_templates = {}
|
||||
|
||||
core_template_names = self.CORE_TEMPLATE_NAMES
|
||||
for template_name in core_template_names:
|
||||
template_value = getattr(obj, template_name)
|
||||
defaults = getattr(obj, f"INTEGRATION_TO_DEFAULT_{template_name.upper()}", {})
|
||||
default_template_value = defaults.get(obj.integration)
|
||||
core_templates[template_name] = template_value or default_template_value
|
||||
core_templates[f"{template_name}_is_default"] = not bool(template_value)
|
||||
|
||||
return core_templates
|
||||
|
|
|
|||
|
|
@ -376,4 +376,7 @@ def test_update_alert_receive_channel_templates(
|
|||
# check if updated templates are applied
|
||||
updated_templates_data = response.json()
|
||||
for template_name, prev_template_value in existing_templates_data.items():
|
||||
assert updated_templates_data[template_name] == template_update_func(prev_template_value)
|
||||
if template_name.endswith("_is_default"):
|
||||
assert updated_templates_data[template_name] is False
|
||||
else:
|
||||
assert updated_templates_data[template_name] == template_update_func(prev_template_value)
|
||||
|
|
|
|||
|
|
@ -101,35 +101,6 @@ class UsersFilteredByOrganizationField(serializers.Field):
|
|||
return queryset.filter(organization=request.user.organization, public_primary_key__in=data).distinct()
|
||||
|
||||
|
||||
class WritableSerializerMethodField(serializers.SerializerMethodField):
|
||||
"""
|
||||
Please, NEVER use this field.
|
||||
It was a mistake to create this one due to necessity to dig deep in drf to fix bugs there.
|
||||
This field is a workaround to allow to write into SerializerMethodField.
|
||||
"""
|
||||
|
||||
def __init__(self, method_name=None, **kwargs):
|
||||
self.method_name = method_name
|
||||
self.setter_method_name = kwargs.pop("setter_method_name", None)
|
||||
self.deserializer_field = kwargs.pop("deserializer_field")
|
||||
|
||||
kwargs["source"] = "*"
|
||||
super(serializers.SerializerMethodField, self).__init__(**kwargs)
|
||||
|
||||
def bind(self, field_name, parent):
|
||||
retval = super().bind(field_name, parent)
|
||||
if not self.setter_method_name:
|
||||
self.setter_method_name = f"set_{field_name}"
|
||||
|
||||
return retval
|
||||
|
||||
def to_internal_value(self, data):
|
||||
value = self.deserializer_field.to_internal_value(data)
|
||||
method = getattr(self.parent, self.setter_method_name)
|
||||
method(value)
|
||||
return {self.method_name: value}
|
||||
|
||||
|
||||
class CustomTimeField(fields.TimeField):
|
||||
def to_representation(self, value):
|
||||
result = super().to_representation(value)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue