diff --git a/aldryn_forms/action_backends.py b/aldryn_forms/action_backends.py index af0759f2..ce430250 100644 --- a/aldryn_forms/action_backends.py +++ b/aldryn_forms/action_backends.py @@ -27,6 +27,15 @@ def form_valid(self, cmsplugin, instance, request, form): logger.info('Sent email notifications to {} recipients.'.format(len(recipients))) +class WebhookAction(BaseAction): + verbose_name = _('Webhook') + + def form_valid(self, cmsplugin, instance, request, form): + super().form_valid(self, instance, request, form) + status = cmsplugin.send_webhook_data(instance, form) + logger.info('Sent webhook and received {} response-code'.format(status)) + + class NoAction(BaseAction): verbose_name = _('None') diff --git a/aldryn_forms/cms_plugins.py b/aldryn_forms/cms_plugins.py index 01813da6..a4bb2bff 100644 --- a/aldryn_forms/cms_plugins.py +++ b/aldryn_forms/cms_plugins.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from urllib import error, parse, request + from django import forms from django.contrib import messages from django.contrib.admin import TabularInline @@ -67,6 +69,7 @@ class FormPlugin(FieldContainer): 'form_template', 'error_message', 'success_message', + 'webhook_url', 'recipients', 'action_backend', 'custom_classes', @@ -211,6 +214,23 @@ def send_notifications(self, instance, form): (get_user_name(user), user.email) for user in recipients] return users_notified + def send_webhook_data(self, instance, form): + url = instance.webhook_url + if not url: + return + context = { + 'form_name': instance.name, + 'form_data': form.get_serialized_field_choices(), + 'form_plugin': instance, + } + data = parse.urlencode(context).encode() + req = request.Request(url, data=data) + + try: + return request.urlopen(req).code + except error.HTTPError as e: + return e.code + class Fieldset(FieldContainer): render_template = True diff --git a/aldryn_forms/migrations/0013_auto_20190922_1021.py b/aldryn_forms/migrations/0013_auto_20190922_1021.py new file mode 100644 index 00000000..b871a467 --- /dev/null +++ b/aldryn_forms/migrations/0013_auto_20190922_1021.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.23 on 2019-09-22 10:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('aldryn_forms', '0012_auto_20190104_1242'), + ] + + operations = [ + migrations.AddField( + model_name='formplugin', + name='webhook_url', + field=models.URLField(blank=True, help_text='URL that will receive the submitted form data.', verbose_name='Webhook url'), + ), + migrations.AlterField( + model_name='formplugin', + name='action_backend', + field=models.CharField(choices=[('none', 'None'), ('email_only', 'Email only'), ('default', 'Default'), ('webhook_only', 'Webhook')], default='default', max_length=15, verbose_name='Action backend'), + ), + ] diff --git a/aldryn_forms/models.py b/aldryn_forms/models.py index 96dd1faf..9e780fe9 100644 --- a/aldryn_forms/models.py +++ b/aldryn_forms/models.py @@ -158,6 +158,13 @@ class BaseFormPlugin(CMSPlugin): help_text=_('People who will get the form content via e-mail.') ) + # Webhook settings + webhook_url = models.URLField( + verbose_name=_("Webhook url"), + blank=True, + help_text=_('URL that will receive the submitted form data.') + ) + action_backend = models.CharField( verbose_name=_('Action backend'), max_length=ALDRYN_FORMS_ACTION_BACKEND_KEY_MAX_SIZE, diff --git a/aldryn_forms/utils.py b/aldryn_forms/utils.py index d4ff0eab..6247a8c9 100644 --- a/aldryn_forms/utils.py +++ b/aldryn_forms/utils.py @@ -16,6 +16,7 @@ DEFAULT_ALDRYN_FORMS_ACTION_BACKENDS = { 'default': 'aldryn_forms.action_backends.DefaultAction', 'email_only': 'aldryn_forms.action_backends.EmailAction', + 'webhook_only': 'aldryn_forms.action_backends.WebhookAction', 'none': 'aldryn_forms.action_backends.NoAction', } ALDRYN_FORMS_ACTION_BACKEND_KEY_MAX_SIZE = 15 diff --git a/tests/test_cms_plugins.py b/tests/test_cms_plugins.py index 59c1c232..3b86b40c 100644 --- a/tests/test_cms_plugins.py +++ b/tests/test_cms_plugins.py @@ -53,6 +53,18 @@ def test_form_submission_email_action(self): self.assertEquals(FormSubmission.objects.count(), 0) self.assertEquals(len(mail.outbox), 0) + def test_form_submission_webhook_action(self): + self.form_plugin.action_backend = 'webhook_only' + self.form_plugin.save() + if CMS_3_6: + self.page.publish('en') + + response = self.client.post(self.page.get_absolute_url('en'), {}) + + self.assertEquals(response.status_code, 200) + self.assertEquals(FormSubmission.objects.count(), 0) + self.assertEquals(len(mail.outbox), 0) + def test_form_submission_no_action(self): self.form_plugin.action_backend = 'none' self.form_plugin.save() diff --git a/tests/test_utils.py b/tests/test_utils.py index 54036972..d0dafe0f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -4,7 +4,7 @@ from cms.test_utils.testcases import CMSTestCase -from aldryn_forms.action_backends import DefaultAction, EmailAction, NoAction +from aldryn_forms.action_backends import DefaultAction, EmailAction, NoAction, WebhookAction from aldryn_forms.action_backends_base import BaseAction from aldryn_forms.utils import action_backend_choices, get_action_backends @@ -44,6 +44,7 @@ def test_default_backends(self): expected = { 'default': DefaultAction, 'email_only': EmailAction, + 'webhook_only': WebhookAction, 'none': NoAction, } @@ -108,6 +109,7 @@ def test_default_backends(self): expected = [ ('default', _('Default')), ('email_only', _('Email only')), + ('webhook_only', _('Webhook')), ('none', _('None')), ]