3

I'm trying to do a curl POST request on a wagtail page. Unfortunately I hit the CSRF protection.

I tried to disabled CSRF on this specific type of page using the @csrf_exempt decorator, without success.

Here is my pseudo code (one of many attemps):

@method_decorator(csrf_exempt, name='serve')
class NewsletterPage(MedorPage):

    class Meta:
        verbose_name = _("newsletter page")

Seems like the csrf verifition is done even before the serve method is called.

Any idea?

thanks

user1415785
  • 342
  • 4
  • 13

2 Answers2

1

You would have to decorate the wagtail.core.views.serve view itself. Since that is patchy as you want to keep its url in your wagtail_urls, you could do the following wherever you include the wagtail urls:

# urls.py

# ...
from wagtail.core import urls as wagtail_urls
# ...


### these two lines can really go anywhere ...
from wagtail.core import views
views.serve.csrf_exempt = True
### ... where they are executed at loading time

urlpatterns = [
    # ...
    re_path(r'^pages/', include(wagtail_urls)),
    # ...
]

This will apply to all wagtail pages then, not just one specific type however.

user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Thank you. It gave me a better understanding on the mecanism of wagtail and the csfr middleware. Unfortunatly this applies to all wagtail pages as you said. Looking for a conditional approach, maybe by subclassing the csfr middleware itself if I can't find something less intrusive. – user1415785 Mar 18 '20 at 12:54
  • That sounds about right. https://stackoverflow.com/questions/29454296/django-check-csrf-token-manually#answer-29455010 looks promising for your purpose. – user2390182 Mar 18 '20 at 13:10
  • Thank you for the link. It helped solving my issue! – user1415785 Mar 18 '20 at 17:10
0

I ended up subclassing the CSRF middleware like so:

from django.middleware.csrf import CsrfViewMiddleware

from wagtail.core.views import serve

from myproject_newsletter.models import NewsletterIndexPage


class CustomCsrfViewMiddleware(CsrfViewMiddleware):

    def process_view(self, request, callback, callback_args, callback_kwargs):

        if callback == serve:
            # We are visiting a wagtail page. Check if this is a NewsletterPage
            # and if so, do not perfom any CSRF validation
            page = NewsletterIndexPage.objects.first()
            path = callback_args[0]

            if page and path.startswith(page.get_url_parts()[-1][1:])
                return None

        return super().process_view(request, callback, callback_args, callback_kwargs)

user1415785
  • 342
  • 4
  • 13