Skip to content

Commit

Permalink
Backport CSRF fix from @vangheem
Browse files Browse the repository at this point in the history
Original commit: 2958b34
  • Loading branch information
gforcada committed Jan 4, 2016
1 parent 4ba1afe commit e7d9ee4
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 23 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changelog
2.1.18 (unreleased)
-------------------

- Nothing changed yet.
- Backport CSRF fixes.
[vangheem] [gforcada]


2.1.17 (2015-09-28)
Expand Down
34 changes: 29 additions & 5 deletions Products/ATContentTypes/tests/atctftestcase.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from zope.component import getUtility
from plone.keyring.interfaces import IKeyManager

from Products.ATContentTypes.tests import atcttestcase

from Products.CMFCore.utils import getToolByName
Expand All @@ -7,6 +10,12 @@

from Products.ATContentTypes.config import HAS_LINGUA_PLONE

import hmac
try:
from hashlib import sha1 as sha
except ImportError:
import sha


class IntegrationTestCase(atcttestcase.ATCTFunctionalSiteTestCase):

Expand All @@ -33,6 +42,16 @@ def setupTestObject(self):
self.obj_url = self.obj.absolute_url()
self.obj_path = '/%s' % self.obj.absolute_url(1)

def getAuthToken(self, user=default_user):
manager = getUtility(IKeyManager)
try:
ring = manager[u"_forms"]
except KeyError:
ring = manager[u'_system']

secret = ring.random()
return hmac.new(secret, user, sha).hexdigest()


class ATCTIntegrationTestCase(IntegrationTestCase):
"""Integration tests for view and edit templates
Expand All @@ -51,17 +70,19 @@ def setupTestObject(self):

def test_createObject(self):
# create an object using the createObject script
response = self.publish(self.folder_path +
'/createObject?type_name=%s' % self.portal_type,
self.basic_auth)
auth = self.getAuthToken()
response = self.publish(
'%s/createObject?type_name=%s&_authenticator=%s' % (
self.folder_path, self.portal_type, auth),
self.basic_auth)

self.assertEqual(response.getStatus(), 302) # Redirect to edit

body = response.getBody()

self.assertTrue(body.startswith(self.folder_url), body)
# The url may end with /edit or /atct_edit depending on method aliases
self.assertTrue(body.endswith('edit'), body)
self.assertTrue('edit' in body, body)

# Perform the redirect
edit_form_path = body[len(self.app.REQUEST.SERVER_URL):]
Expand All @@ -78,7 +99,10 @@ def check_newly_created(self):

def test_edit_view(self):
# edit should work
response = self.publish('%s/atct_edit' % self.obj_path, self.basic_auth)
response = self.publish(
'%s/atct_edit?_authenticator=%s' % (
self.obj_path, self.getAuthToken()),
self.basic_auth)
self.assertEqual(response.getStatus(), 200) # OK

def test_base_view(self):
Expand Down
12 changes: 8 additions & 4 deletions Products/ATContentTypes/tests/editing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ We'll try and set the title (a required field) to the empty string:

>>> document.Schema().getField('title').required
1
>>> browser.open(url+'/edit')
>>> browser.open(url)
>>> browser.getLink('Edit').click()
>>> browser.getControl('Title').value = ''
>>> browser.getControl('Save').click()

Expand All @@ -56,7 +57,8 @@ we want to make sure all of them are validated.

>>> document.Schema().getField('title').schemata
'categorization'
>>> browser.open(url+'/edit')
>>> browser.open(url)
>>> browser.getLink('Edit').click()
>>> browser.getControl('Title').value = ''
>>> browser.getControl('Save').click()
>>> document.title_or_id()
Expand All @@ -70,7 +72,8 @@ Buttons name verification

Let's verify that the buttons have the correct name:

>>> browser.open(url+'/edit')
>>> browser.open(url)
>>> browser.getLink('Edit').click()
>>> browser.getControl('Save').name
'form.button.save'

Expand All @@ -95,7 +98,8 @@ and change the schemata of one of its fields
>>> document.Schema().getField('text').schemata
'someschemata'

>>> browser.open(url+'/edit')
>>> browser.open(url)
>>> browser.getLink('Edit').click()
>>> browser.getControl('Next').name
'form.button.next'

Expand Down
4 changes: 2 additions & 2 deletions Products/ATContentTypes/tests/portaltype_criterion.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ We edit the criteria:

>>> browser.getLink('Criteria').click()
>>> browser.url
'http://nohost/plone/my-collection/criterion_edit_form'
'http://nohost/plone/my-collection/criterion_edit_form?_auth...'
>>> 'Add New Search Criteria' in browser.contents
True

Expand Down Expand Up @@ -103,7 +103,7 @@ We now view the collection.

>>> browser.getLink('View').click()
>>> browser.url
'http://nohost/plone/my-collection/'
'http://nohost/plone/my-collection/?_auth...'

The test document should be in the collection.

Expand Down
15 changes: 8 additions & 7 deletions Products/ATContentTypes/tests/test_atdocument.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,17 @@ class TestATDocumentFunctional(atctftestcase.ATCTIntegrationTestCase):
def test_id_change_on_initial_edit(self):
"""Make sure Id is taken from title on initial edit and not otherwise"""
# first create an object using the createObject script

response = self.publish(self.folder_path +
'/createObject?type_name=%s' % self.portal_type,
self.basic_auth)
auth = self.getAuthToken()
response = self.publish(
'%s/createObject?type_name=%s&_authenticator=%s' % (
self.folder_path, self.portal_type, auth),
self.basic_auth)

self.assertEqual(response.getStatus(), 302) # Redirect to edit

location = response.getHeader('Location')
self.assertTrue(location.startswith(self.folder_url), location)
self.assertTrue(location.endswith('edit'), location)
self.assertTrue('edit' in location, location)

# Perform the redirect
edit_form_path = location[len(self.app.REQUEST.SERVER_URL):]
Expand All @@ -299,12 +300,12 @@ def test_id_change_on_initial_edit(self):
new_obj_path = '/%s' % new_obj.absolute_url(1)
self.assertEqual(new_obj.checkCreationFlag(), True) # object is not yet edited

response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank' % (new_obj_path, obj_title,), self.basic_auth) # Edit object
response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank&_authenticator=%s' % (new_obj_path, obj_title, auth), self.basic_auth) # Edit object
self.assertEqual(response.getStatus(), 302) # OK
self.assertEqual(new_obj.getId(), new_id) # does id match
self.assertEqual(new_obj.checkCreationFlag(), False) # object is fully created
new_title = "Second Title"
response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank' % ('/%s' % new_obj.absolute_url(1), new_title,), self.basic_auth) # Edit object
response = self.publish('%s/atct_edit?form.submitted=1&title=%s&text=Blank&_authenticator=%s' % ('/%s' % new_obj.absolute_url(1), new_title, auth), self.basic_auth) # Edit object
self.assertEqual(response.getStatus(), 302) # OK
self.assertEqual(new_obj.getId(), new_id) # id shouldn't have changed

Expand Down
8 changes: 5 additions & 3 deletions Products/ATContentTypes/tests/test_atfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from OFS.interfaces import IOrderedContainer as IOrderedContainer
from Products.ATContentTypes.interfaces import IATFolder
from Products.ATContentTypes.interfaces import IATBTreeFolder
from Products.PloneTestCase.setup import portal_owner

from zope.interface.verify import verifyObject
from Products.ATContentTypes.interfaces import ISelectableConstrainTypes
Expand Down Expand Up @@ -175,9 +176,10 @@ def test_dynamic_view_without_view(self):

def test_selectViewTemplate(self):
# create an object using the createObject script
self.publish(self.obj_path +
'/selectViewTemplate?templateId=atct_album_view',
self.owner_auth)
self.publish(
'%s/selectViewTemplate?templateId=atct_album_view&_authenticator=%s' % (
self.obj_path, self.getAuthToken(portal_owner)),
self.owner_auth)
self.assertEqual(self.obj.getLayout(), 'atct_album_view')

tests.append(TestATFolderFunctional)
Expand Down
2 changes: 1 addition & 1 deletion Products/ATContentTypes/tests/uploading.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Now try to empty value of the text field (#7324)

>>> browser.getLink('Edit').click()
>>> browser.url
'http://nohost/plone/test-collection/edit'
'http://nohost/plone/test-collection/edit?_auth...'
>>> browser.getControl(name='text').value = ''
>>> browser.getControl('Save').click()
>>> 'file contents' in browser.contents
Expand Down

0 comments on commit e7d9ee4

Please sign in to comment.