diff --git a/posthog/api/hog_function.py b/posthog/api/hog_function.py index 1381d5b351cde..339400a45aa78 100644 --- a/posthog/api/hog_function.py +++ b/posthog/api/hog_function.py @@ -146,7 +146,7 @@ def validate(self, attrs): {"template_id": "The Data Pipelines addon is required to create custom functions."} ) - if template.status != "free": + if template.status != "free" and not instance: raise serializers.ValidationError( {"template_id": "The Data Pipelines addon is required for this template."} ) diff --git a/posthog/api/test/__snapshots__/test_insight.ambr b/posthog/api/test/__snapshots__/test_insight.ambr index d0cb1a5dc625c..cea3c1e49dcab 100644 --- a/posthog/api/test/__snapshots__/test_insight.ambr +++ b/posthog/api/test/__snapshots__/test_insight.ambr @@ -1380,12 +1380,12 @@ LEFT OUTER JOIN "posthog_organizationmembership" ON ("ee_accesscontrol"."organization_member_id" = "posthog_organizationmembership"."id") WHERE (("ee_accesscontrol"."organization_member_id" IS NULL AND "ee_accesscontrol"."resource" = 'project' - AND "ee_accesscontrol"."resource_id" = '446' + AND "ee_accesscontrol"."resource_id" = '447' AND "ee_accesscontrol"."role_id" IS NULL AND "ee_accesscontrol"."team_id" = 99999) OR ("posthog_organizationmembership"."user_id" = 99999 AND "ee_accesscontrol"."resource" = 'project' - AND "ee_accesscontrol"."resource_id" = '446' + AND "ee_accesscontrol"."resource_id" = '447' AND "ee_accesscontrol"."role_id" IS NULL AND "ee_accesscontrol"."team_id" = 99999) OR ("ee_accesscontrol"."organization_member_id" IS NULL @@ -1493,12 +1493,12 @@ LEFT OUTER JOIN "posthog_organizationmembership" ON ("ee_accesscontrol"."organization_member_id" = "posthog_organizationmembership"."id") WHERE (("ee_accesscontrol"."organization_member_id" IS NULL AND "ee_accesscontrol"."resource" = 'project' - AND "ee_accesscontrol"."resource_id" = '446' + AND "ee_accesscontrol"."resource_id" = '447' AND "ee_accesscontrol"."role_id" IS NULL AND "ee_accesscontrol"."team_id" = 99999) OR ("posthog_organizationmembership"."user_id" = 99999 AND "ee_accesscontrol"."resource" = 'project' - AND "ee_accesscontrol"."resource_id" = '446' + AND "ee_accesscontrol"."resource_id" = '447' AND "ee_accesscontrol"."role_id" IS NULL AND "ee_accesscontrol"."team_id" = 99999) OR ("ee_accesscontrol"."organization_member_id" IS NULL diff --git a/posthog/api/test/test_hog_function.py b/posthog/api/test/test_hog_function.py index 18ef5e9cab2a4..55788bb058191 100644 --- a/posthog/api/test/test_hog_function.py +++ b/posthog/api/test/test_hog_function.py @@ -114,7 +114,7 @@ def test_free_users_cannot_use_without_template(self): assert response.status_code == status.HTTP_400_BAD_REQUEST, response.json() assert response.json()["detail"] == "The Data Pipelines addon is required to create custom functions." - def test_free_users_cannot_use_non_free_templates(self): + def test_free_users_cannot_create_non_free_templates(self): response = self._create_slack_function( { "template_id": template_webhook.id, @@ -124,6 +124,43 @@ def test_free_users_cannot_use_non_free_templates(self): assert response.status_code == status.HTTP_400_BAD_REQUEST, response.json() assert response.json()["detail"] == "The Data Pipelines addon is required for this template." + def test_free_users_can_update_non_free_templates(self): + self.organization.available_product_features = [ + {"key": AvailableFeature.DATA_PIPELINES, "name": AvailableFeature.DATA_PIPELINES} + ] + self.organization.save() + + response = self._create_slack_function( + { + "name": template_webhook.name, + "template_id": template_webhook.id, + "inputs": { + "url": {"value": "https://example.com"}, + }, + } + ) + + assert response.json()["template"]["status"] == template_webhook.status + + self.organization.available_product_features = [] + self.organization.save() + + payload = { + "name": template_webhook.name, + "template_id": template_webhook.id, + "inputs": { + "url": {"value": "https://example.com/posthog-webhook-updated"}, + }, + } + + update_response = self.client.patch( + f"/api/projects/{self.team.id}/hog_functions/{response.json()['id']}/", + data=payload, + ) + + assert update_response.status_code == status.HTTP_200_OK, update_response.json() + assert update_response.json()["inputs"]["url"]["value"] == "https://example.com/posthog-webhook-updated" + class TestHogFunctionAPI(ClickhouseTestMixin, APIBaseTest, QueryMatchingTest): def setUp(self):