Functional tests stop working after CSRF patch

Hi, I've developed an add-on for a non-csrf patched Plone 4.3 instance and I'm updating it so it can work with it. A couple of functional tests stop to work when the csrf patch is applied. But, curiously, it isn't due to csrf page interception.

This is the idea:

  def test_blah(self):
        self.login('someuser', 'somepwd')

        # STEP 1: we visit a page to alter ZODB content
        browser.open('someurl', 'somedata')
        # it works. browser.contents shows a positive json response
        # indicating that changes were made in ZODB

        # STEP 2:  visit another page to test for changes in ZODB
        browser.open('anotherurl')
        self.assertIn('blah', browser.contents)
        # whith no csrf, test pass. With csrf, it doesn't.

This is a functional test (a method inside a FunctionalTestCase instance) and all steps have been made using browser.open(). Browser.open() always returned a valid page (never "Careful... executing an exploit...").

It is as if the changes in ZODB made in STEP 1 weren't preserved when the test runs with csrf patch. The page returned in STEP 2 shows valid content, but not the chages made in STEP 1.

Any idea why changes aren't preserved between step 1 and step 2?

1 Like

Hi José,

I had the same issue, also using JSON.
The redirection to the "Careful... executing an exploit..." page works when you display HTML, but not with JSON (I guess there is a client side processing involved in plone.protect, but I haven't checked).

So your client does receive the expected JSON, but if you look in the server console, you will see a message saying the transaction will be rolled back because the Form authenticator is missing.

My solution was to change my code, so I check the request before processing it:

from plone.protect import CheckAuthenticator
class MyJSONView:
    def __call__:
         try:
             CheckAuthenticator(self.request)
             do_the_regular_thing()
         except Exception, e:
            self.request.response.setStatus(500)
            return {'error': str(e)}

(the try .. except thing is not mandatory but I prefer my json view to returns an 500 code + a json message rather than the default Plone HTML error message)

1 Like

Thank you very much! I was confused with the apparent positive response, since it was returning a JSON object. After that, I could solve it by disabling csfr for these views (they can't be exploited maliciously):

from zope.interface import alsoProvides
from plone.protect.interfaces import IDisableCSRFProtection

class MyView:
    def __init__(self, context, request):
        ...
        alsoProvides(self.request, IDisableCSRFProtection)