Allow webhook modification by API for advanced webhook (#4175)

# What this PR does

Enables the API to perform updates on the advanced webhooks created via
the UI

## Which issue(s) this PR closes

Closes #3958 

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
This commit is contained in:
Ravishankar 2024-04-24 00:48:12 +05:30 committed by GitHub
parent cb613deedb
commit 6f3f4e3f14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 5 deletions

View file

@ -5,6 +5,7 @@ from rest_framework.validators import UniqueTogetherValidator
from apps.webhooks.models import Webhook, WebhookResponse
from apps.webhooks.models.webhook import PUBLIC_WEBHOOK_HTTP_METHODS, WEBHOOK_FIELD_PLACEHOLDER
from apps.webhooks.presets.preset_options import WebhookPresetOptions
from common.api_helpers.custom_fields import IntegrationFilteredByOrganizationField, TeamPrimaryKeyRelatedField
from common.api_helpers.exceptions import BadRequest
from common.api_helpers.utils import CurrentOrganizationDefault, CurrentTeamDefault, CurrentUserDefault
@ -158,7 +159,13 @@ class WebhookCreateSerializer(serializers.ModelSerializer):
raise serializers.ValidationError(PRESET_VALIDATION_MESSAGE)
def validate(self, data):
if self.instance and self.instance.preset:
if (
self.instance
and self.instance.preset
and WebhookPresetOptions.ADVANCED_PRESET_META_DATA
and WebhookPresetOptions.ADVANCED_PRESET_META_DATA.id
and self.instance.preset != WebhookPresetOptions.ADVANCED_PRESET_META_DATA.id
):
raise serializers.ValidationError(PRESET_VALIDATION_MESSAGE)
return data

View file

@ -7,7 +7,7 @@ from rest_framework.test import APIClient
from apps.public_api.serializers.webhooks import PRESET_VALIDATION_MESSAGE
from apps.webhooks.models import Webhook
from apps.webhooks.tests.test_webhook_presets import TEST_WEBHOOK_PRESET_ID
from apps.webhooks.tests.test_webhook_presets import ADVANCED_WEBHOOK_PRESET_ID, TEST_WEBHOOK_PRESET_ID
def _get_expected_result(webhook):
@ -437,3 +437,23 @@ def test_webhook_block_preset_update(
response = client.put(url, data=data, format="json", HTTP_AUTHORIZATION=f"{token}")
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.json()["non_field_errors"][0] == PRESET_VALIDATION_MESSAGE
@pytest.mark.django_db
def test_webhook_advanced_preset_update(
make_organization_and_user_with_token,
make_custom_webhook,
webhook_preset_api_setup,
):
organization, user, token = make_organization_and_user_with_token()
client = APIClient()
webhook = make_custom_webhook(organization=organization, preset=ADVANCED_WEBHOOK_PRESET_ID)
webhook.refresh_from_db()
url = reverse("api-public:webhooks-detail", kwargs={"pk": webhook.public_primary_key})
data = {
"name": "Test rename preset webhook",
}
response = client.put(url, data=data, format="json", HTTP_AUTHORIZATION=f"{token}")
assert response.status_code == status.HTTP_200_OK
assert response.data["name"] == data["name"]

View file

@ -9,11 +9,14 @@ from apps.webhooks.models import Webhook
class WebhookPresetOptions:
WEBHOOK_PRESETS = {}
ADVANCED_PRESET_META_DATA = {}
for webhook_preset_config in settings.INSTALLED_WEBHOOK_PRESETS:
module_path, class_name = webhook_preset_config.rsplit(".", 1)
module = import_module(module_path)
preset = getattr(module, class_name)()
WEBHOOK_PRESETS[preset.metadata.id] = preset
if webhook_preset_config == settings.ADVANCED_WEBHOOK_PRESET:
ADVANCED_PRESET_META_DATA = preset.metadata
WEBHOOK_PRESET_CHOICES = [webhook_preset.metadata for webhook_preset in WEBHOOK_PRESETS.values()]

View file

@ -6,6 +6,7 @@ import pytest
from apps.webhooks.models import Webhook
from apps.webhooks.models.webhook import WEBHOOK_FIELD_PLACEHOLDER
from apps.webhooks.presets.advanced import AdvancedWebhookPreset
from apps.webhooks.presets.preset import WebhookPreset, WebhookPresetMetadata
from apps.webhooks.tasks.trigger_webhook import make_request
from apps.webhooks.tests.test_trigger_webhook import MockResponse
@ -20,6 +21,7 @@ TEST_WEBHOOK_AUTHORIZATION_HEADER = "Test Auth header 12345"
TEST_WEBHOOK_MASK_HEADER = "X-Secret-Header"
TEST_WEBHOOK_MASK_HEADER_VALUE = "abc123"
INVALID_PRESET_ID = "invalid_preset_id"
ADVANCED_WEBHOOK_PRESET_ID = "advanced_webhook"
class TestWebhookPreset(WebhookPreset):
@ -47,6 +49,10 @@ class TestWebhookPreset(WebhookPreset):
return [TEST_WEBHOOK_MASK_HEADER]
class TestAdvancedWebhookPreset(AdvancedWebhookPreset):
pass
@pytest.mark.django_db
def test_create_webhook_from_preset(make_organization, webhook_preset_api_setup, make_custom_webhook):
organization = make_organization()

View file

@ -103,7 +103,12 @@ from apps.user_management.models.user import User, listen_for_user_model_save
from apps.user_management.tests.factories import OrganizationFactory, RegionFactory, TeamFactory, UserFactory
from apps.webhooks.presets.preset_options import WebhookPresetOptions
from apps.webhooks.tests.factories import CustomWebhookFactory, WebhookResponseFactory
from apps.webhooks.tests.test_webhook_presets import TEST_WEBHOOK_PRESET_ID, TestWebhookPreset
from apps.webhooks.tests.test_webhook_presets import (
ADVANCED_WEBHOOK_PRESET_ID,
TEST_WEBHOOK_PRESET_ID,
TestAdvancedWebhookPreset,
TestWebhookPreset,
)
register(OrganizationFactory)
register(UserFactory)
@ -987,7 +992,10 @@ def shift_swap_request_setup(
@pytest.fixture()
def webhook_preset_api_setup():
WebhookPresetOptions.WEBHOOK_PRESETS = {TEST_WEBHOOK_PRESET_ID: TestWebhookPreset()}
WebhookPresetOptions.WEBHOOK_PRESETS = {
TEST_WEBHOOK_PRESET_ID: TestWebhookPreset(),
ADVANCED_WEBHOOK_PRESET_ID: TestAdvancedWebhookPreset(),
}
WebhookPresetOptions.WEBHOOK_PRESET_CHOICES = [
preset.metadata for preset in WebhookPresetOptions.WEBHOOK_PRESETS.values()
]

View file

@ -837,9 +837,10 @@ INSTALLED_ONCALL_INTEGRATIONS = [
"config_integrations.direct_paging",
]
ADVANCED_WEBHOOK_PRESET = "apps.webhooks.presets.advanced.AdvancedWebhookPreset"
INSTALLED_WEBHOOK_PRESETS = [
"apps.webhooks.presets.simple.SimpleWebhookPreset",
"apps.webhooks.presets.advanced.AdvancedWebhookPreset",
ADVANCED_WEBHOOK_PRESET,
]
if IS_OPEN_SOURCE: