# -*- coding: utf-8 -*- from AccessControl.User import User # before SpecialUsers from AccessControl.SpecialUsers import nobody as user_nobody from AccessControl.PermissionRole import rolesForPermissionOn from Acquisition import aq_chain from plone.app.discussion.testing import \ PLONE_APP_DISCUSSION_INTEGRATION_TESTING from plone.app.discussion.interfaces import IConversation from plone.app.testing import TEST_USER_ID, setRoles from Products.CMFCore.utils import getToolByName from zope.component import createObject import unittest2 as unittest dexterity_type_name = 'sample_content_type' dexterity_object_id = 'instance-of-dexterity-type' archetypes_object_id = 'instance-of-archetypes-type' one_state_workflow = 'one_state_workflow' comment_workflow_acquired_view = 'comment_workflow_acquired_view' class AcquisitionTest(unittest.TestCase): """ Define the expected behaviour of wrapped and unwrapped comments. """ layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING def setUp(self): self.portal = self.layer['portal'] self.request = self.layer['request'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.wftool = getToolByName(self.portal, 'portal_workflow') # Use customized workflow for comments. self.wftool.setChainForPortalTypes( ['Discussion Item'], (comment_workflow_acquired_view,), ) # Use one_state_workflow for Document and sample_content_type, # so they're always published. self.wftool.setChainForPortalTypes( ['Document', dexterity_type_name], (one_state_workflow,), ) # Create a dexterity item and add a comment. self.portal.invokeFactory( id=dexterity_object_id, title='Instance Of Dexterity Type', type_name=dexterity_type_name, ) self.dexterity_object = self.portal.get(dexterity_object_id) dx_conversation = IConversation(self.dexterity_object) self.dexterity_conversation = dx_conversation dx_comment = createObject('plone.Comment') dx_conversation.addComment(dx_comment) self.unwrapped_dexterity_comment = dx_comment self.wrapped_dexterity_comment = dx_conversation[dx_comment.id] # Create an Archetypes item and add a comment. self.portal.invokeFactory( id=archetypes_object_id, title='Instance Of Archetypes Type', type_name='Document', ) self.archetypes_object = self.portal.get(archetypes_object_id) at_conversation = IConversation(self.archetypes_object) self.archetypes_conversation = at_conversation at_comment = createObject('plone.Comment') at_conversation.addComment(at_comment) self.unwrapped_archetypes_comment = at_comment self.wrapped_archetypes_comment = at_conversation[at_comment.id] def test_workflows_installed(self): """Check that the new comment workflow has been installed properly. (Just a test to check our test setup.) """ workflows = self.wftool.objectIds() self.assertTrue('comment_workflow_acquired_view' in workflows) def test_workflows_applied(self): """Check that all objects have the workflow that we expect. (Just a test to check our test setup.)""" self.assertEqual( self.wftool.getChainFor(self.archetypes_object), (one_state_workflow,) ) self.assertEqual( self.wftool.getChainFor(self.dexterity_object), (one_state_workflow,) ) self.assertEqual( self.wftool.getChainFor(self.unwrapped_archetypes_comment), (comment_workflow_acquired_view,) ) self.assertEqual( self.wftool.getChainFor(self.unwrapped_dexterity_comment), (comment_workflow_acquired_view,) ) def test_comment_acquisition_chain(self): """ Test that the acquisition chains for wrapped and unwrapped comments are as expected. """ # Unwrapped comments rely on __parent__ attributes to determine # parentage. Frustratingly there is no guarantee that __parent__ # is always set, so the computed acquisition chain may be short. # In this case the unwrapped AT and DX objects stored as the # conversation parents don't have a __parent__, preventing the portal # from being included in the chain. self.assertNotIn(self.portal, aq_chain(self.unwrapped_archetypes_comment)) self.assertNotIn(self.portal, aq_chain(self.unwrapped_dexterity_comment)) # Wrapped comments however have a complete chain and thus can find the # portal object reliably. self.assertIn(self.portal,aq_chain(self.wrapped_archetypes_comment)) self.assertIn(self.portal,aq_chain(self.wrapped_dexterity_comment)) def test_acquiring_comment_permissions(self): """ Unwrapped comments should not be able to acquire permissions controlled by unreachable objects """ # We use the "Allow sendto" permission as by default it is # controlled by the portal, which is unreachable via __parent__ # attributes on the comments. permission = "Allow sendto" # Unwrapped comments can't find the portal so just return manager self.assertNotIn("Anonymous", rolesForPermissionOn(permission, self.unwrapped_archetypes_comment)) self.assertNotIn("Anonymous", rolesForPermissionOn(permission, self.unwrapped_dexterity_comment)) # Wrapped objects can find the portal and correctly return the # anonymous role. self.assertIn("Anonymous", rolesForPermissionOn(permission, self.wrapped_archetypes_comment)) self.assertIn("Anonymous", rolesForPermissionOn(permission, self.wrapped_dexterity_comment)) def test_acquiring_comment_permissions_via_user_nobody(self): """ The current implementation uses user_nobody.has_permission to check whether anonymous can view comments. This confirms it also works. """ # Again we want to use a permission that's not managed by any of our # content objects so it must be acquired from the portal. permission = "Allow sendto" self.assertFalse( user_nobody.has_permission(permission, self.unwrapped_archetypes_comment)) self.assertFalse( user_nobody.has_permission(permission, self.unwrapped_dexterity_comment)) self.assertTrue( user_nobody.has_permission(permission, self.wrapped_archetypes_comment)) self.assertTrue( user_nobody.has_permission(permission, self.wrapped_dexterity_comment)) def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__)