Back to index

plone3  3.1.7
testPortalFactory.py
Go to the documentation of this file.
00001 #
00002 # Test portal factory
00003 #
00004 
00005 import urlparse
00006 from Products.CMFPlone.tests import PloneTestCase
00007 
00008 from Products.CMFCore.permissions import AddPortalContent
00009 from Products.PluggableAuthService.interfaces.plugins import IChallengePlugin
00010 
00011 from AccessControl import Unauthorized
00012 default_user = PloneTestCase.default_user
00013 default_password = PloneTestCase.default_password
00014 
00015 def sortTuple(t):
00016     l = list(t)
00017     l.sort()
00018     return tuple(l)
00019 
00020 ADD_DOC_PERM = 'ATContentTypes: Add Document'
00021 
00022 
00023 class TestPortalFactory(PloneTestCase.PloneTestCase):
00024 
00025     def afterSetUp(self):
00026         self.membership = self.portal.portal_membership
00027         self.membership.addMember('member', 'secret', ['Member'], [])
00028         self.membership.addMember('manager', 'secret', ['Manager'], [])
00029 
00030     def testTraverse(self):
00031         temp_doc = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00032         self.assertEqual(temp_doc.portal_type, 'Document')
00033         self.assertEqual(temp_doc.getId(), 'tmp_id')
00034 
00035     def testTraverseTwiceByDifferentContentTypes(self):
00036         temp_doc = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00037         self.assertEqual(temp_doc.portal_type, 'Document')
00038         self.assertEqual(temp_doc.getId(), 'tmp_id')
00039         temp_img = self.folder.restrictedTraverse('portal_factory/Image/tmp_id_image')
00040         self.assertEqual(temp_img.portal_type, 'Image')
00041         self.assertEqual(temp_img.getId(), 'tmp_id_image')
00042 
00043     def testTempFolderLocalRoles(self):
00044         # Temporary objects should "inherit" local roles from container
00045         member = self.membership.getMemberById('member')
00046         self.portal.acl_users.addRole('Foo')
00047 
00048         self.folder.manage_addLocalRoles('member', ('Foo',))
00049         self.folder.invokeFactory('Folder', id='folder2')
00050         self.folder.folder2.manage_addLocalRoles('member', ('Reviewer',))
00051 
00052         self.assertEqual(sortTuple(member.getRolesInContext(self.folder)),
00053                          ('Authenticated', 'Foo', 'Member'))
00054 
00055         temp_object = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00056         self.assertEqual(sortTuple(member.getRolesInContext(temp_object)),
00057                          ('Authenticated', 'Foo', 'Member'))
00058 
00059         temp_object2 = self.folder.folder2.restrictedTraverse('portal_factory/Document/tmp_id')
00060         self.assertEqual(sortTuple(member.getRolesInContext(temp_object2)),
00061                          ('Authenticated', 'Foo', 'Member', 'Reviewer'))
00062 
00063     def testTempFolderLocalRolesWithBlocking(self):
00064         # Temporary objects should "inherit" local roles from container,
00065         # but also need to respect PLIP 16 local role blocking
00066         member = self.membership.getMemberById('member')
00067         self.portal.acl_users.addRole('Foo')
00068 
00069         self.folder.manage_addLocalRoles('member', ('Foo',))
00070         self.folder.invokeFactory('Folder', id='folder2')
00071         self.folder.folder2.manage_addLocalRoles('member', ('Reviewer',))
00072         # make folder2 not inherit local roles
00073         self.portal.plone_utils.acquireLocalRoles(self.folder.folder2, status=0)
00074 
00075         self.assertEqual(sortTuple(member.getRolesInContext(self.folder.folder2)),
00076                          ('Authenticated', 'Member', 'Reviewer'))
00077 
00078         temp_object2 = self.folder.folder2.restrictedTraverse('portal_factory/Document/tmp_id')
00079         self.assertEqual(sortTuple(member.getRolesInContext(temp_object2)),
00080                          ('Authenticated', 'Member', 'Reviewer'))
00081 
00082     def testTempFolderPermissionAq(self):
00083         from Products.CMFPlone.FactoryTool import FACTORY_INFO
00084         # Temporary folder should acquire same permissions as the intended parent
00085         self.login('manager')
00086         self.portal.invokeFactory('Folder', id='folder1')
00087         folder1 = self.portal.folder1
00088         folder1.invokeFactory('Folder', id='folder2')
00089         folder2 = folder1.folder2
00090         folder2.invokeFactory('Folder', id='folder3')
00091         folder3 = folder1.folder2.folder3
00092         folder3.restrictedTraverse('portal_factory/Document/tmp_id')
00093         # clear out the cached factory info (this would happen by itself in an actual request)
00094         self.portal.REQUEST.set(FACTORY_INFO, {})
00095 
00096         # make sure no permission is available initially
00097         self.login('member')
00098         pm = self.portal.portal_membership
00099         assert (not pm.checkPermission(ADD_DOC_PERM, folder3))
00100         self.assertRaises(Unauthorized, folder3.restrictedTraverse, 'portal_factory/Document/tmp_id/atct_edit')
00101         # clear out the cached factory info (this would happen by itself in an actual request)
00102         self.portal.REQUEST.set(FACTORY_INFO, {})
00103 
00104         # grant the add permission on the parent
00105         self.login('manager')
00106         folder3.manage_permission(ADD_DOC_PERM, ['Authenticated'], 1)
00107 
00108         # now make sure we can see it
00109         self.login('member')
00110         assert (pm.checkPermission(ADD_DOC_PERM, folder3))
00111         #folder3.setConstrainTypesMode(0)
00112         folder3.restrictedTraverse('portal_factory/Document/tmp_id/atct_edit')
00113         # clear out the cached factory info (this would happen by itself in an actual request)
00114         self.portal.REQUEST.set(FACTORY_INFO, {})
00115 
00116         # blow away folder3 and start again
00117         self.login('manager')
00118         folder2.manage_delObjects(['folder3'])
00119         folder2.invokeFactory('Folder', id='folder3')
00120         folder3 = folder1.folder2.folder3
00121 
00122         # grant the add permission on the grandparent
00123         folder2.manage_permission(ADD_DOC_PERM, ['Authenticated'], 1)
00124 
00125         # now make sure we can see it
00126         self.login('member')
00127         assert (pm.checkPermission(ADD_DOC_PERM, folder3))
00128         folder3.restrictedTraverse('portal_factory/Document/tmp_id')
00129         # clear out the cached factory info (this would happen by itself in an actual request)
00130         self.portal.REQUEST.set(FACTORY_INFO, {})
00131 
00132         # blow away folder2 and start again
00133         self.login('manager')
00134         folder1.manage_delObjects(['folder2'])
00135         folder1.invokeFactory('Folder', id='folder2')
00136         folder2 = folder1.folder2
00137         folder2.invokeFactory('Folder', id='folder3')
00138         folder3 = folder1.folder2.folder3
00139 
00140         # add the permission on the portal root
00141         self.portal.manage_permission(ADD_DOC_PERM, ['Authenticated'], 1)
00142 
00143         # now make sure we can see it
00144         self.login('member')
00145         assert (pm.checkPermission(ADD_DOC_PERM, folder3))
00146         folder3.restrictedTraverse('portal_factory/Document/tmp_id')
00147         # clear out the cached factory info (this would happen by itself in an actual request)
00148         self.portal.REQUEST.set(FACTORY_INFO, {})
00149 
00150 
00151     def testTempObjectLocalRolesBug(self):
00152         # Evil monkey patch should not change all objects of a class
00153         self.createMemberarea('member')
00154         member = self.membership.getMemberById('member')
00155 
00156         # Make an unrelated non-temporary object for comparison
00157         self.login('manager')
00158         self.portal.invokeFactory('Document', id='nontmp_id')
00159         nontemp_object = getattr(self.portal, 'nontmp_id')
00160 
00161         # Assume identify of the ordinary member
00162         self.login('member')
00163         folder = self.membership.getHomeFolder()
00164         temp_object = folder.restrictedTraverse('portal_factory/Document/tmp_id')
00165 
00166         # Make sure member is owner of temporary object
00167         self.assertEqual(sortTuple(member.getRolesInContext(temp_object)),
00168                          ('Authenticated', 'Member', 'Owner'))
00169         self.assertEqual(temp_object.Creator(), 'member')
00170 
00171         # Make sure member is not owner of non-temporary object
00172         # (i.e. make sure our evil monkey patch of the temporary instance has
00173         # not resulted in our patching all instances of the class)
00174         self.assertEqual(sortTuple(member.getRolesInContext(nontemp_object)),
00175                          ('Authenticated', 'Member'))
00176 
00177     def testTempFolderPermissions(self):
00178         # TempFolder should "inherit" permission mappings from container
00179         previous_roles = [r for r in self.folder.rolesOfPermission(AddPortalContent) if r['name'] == 'Anonymous']
00180         self.folder.manage_permission(AddPortalContent, ['Anonymous'], 1)
00181         new_roles = [r for r in self.folder.rolesOfPermission(AddPortalContent) if r['name'] == 'Anonymous']
00182         self.failIfEqual(previous_roles, new_roles)
00183 
00184         temp_folder = self.folder.restrictedTraverse(
00185                                 'portal_factory/Document/tmp_id').aq_parent
00186         temp_roles = [r for r in temp_folder.rolesOfPermission(AddPortalContent) if r['name'] == 'Anonymous']
00187 
00188         self.assertEqual(temp_roles, new_roles)
00189 
00190 
00191 class TestCreateObject(PloneTestCase.PloneTestCase):
00192 
00193     def testCreateObjectByDoCreate(self):
00194         # doCreate should create the real object
00195         temp_object = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00196         foo = temp_object.portal_factory.doCreate(temp_object, 'foo')
00197         self.failUnless('foo' in self.folder.objectIds())
00198         self.assertEqual(foo.get_local_roles_for_userid(default_user), ('Owner',))
00199 
00200     def testUnauthorizedToCreateObjectByDoCreate(self):
00201         # Anonymous should not be able to create the (real) object
00202         # Note that Anonymous used to be able to create the temp object...
00203         temp_object = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00204         self.logout()
00205         self.assertRaises(Unauthorized, temp_object.portal_factory.doCreate,
00206                           temp_object, 'foo')
00207 
00208     def testCreateObjectByDocumentEdit(self):
00209         # document_edit should create the real object
00210         temp_object = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00211         temp_object.document_edit(id='foo', title='Foo', text_format='plain', text='')
00212         self.failUnless('foo' in self.folder.objectIds())
00213         self.assertEqual(self.folder.foo.Title(), 'Foo')
00214         self.assertEqual(self.folder.foo.get_local_roles_for_userid(default_user), ('Owner',))
00215 
00216     def testUnauthorizedToCreateObjectByDocumentEdit(self):
00217         # Anonymous should not be able to create the (real) object
00218         # Note that Anonymous used to be able to create the temp object...
00219         temp_object = self.folder.restrictedTraverse('portal_factory/Document/tmp_id')
00220         self.logout()
00221         self.assertRaises(Unauthorized, temp_object.document_edit,
00222                           id='foo', title='Foo', text_format='plain', text='')
00223 
00224 
00225 class TestCreateObjectByURL(PloneTestCase.FunctionalTestCase):
00226     '''Weeee, functional tests'''
00227 
00228     def afterSetUp(self):
00229         self.folder_url = self.folder.absolute_url()
00230         self.folder_path = '/%s' % self.folder.absolute_url(1)
00231         self.basic_auth = '%s:%s' % (default_user, default_password)
00232         # We want 401 responses, not redirects to a login page
00233         plugins = self.portal.acl_users.plugins
00234         plugins.deactivatePlugin( IChallengePlugin, 'credentials_cookie_auth')
00235 
00236         # Enable portal_factory for Document type
00237         self.factory = self.portal.portal_factory
00238         self.factory.manage_setPortalFactoryTypes(listOfTypeIds=['Document'])
00239 
00240     def testCreateObject(self):
00241         # createObject script should make a temp object
00242         response = self.publish(self.folder_path +
00243                                 '/createObject?type_name=Document',
00244                                 self.basic_auth)
00245 
00246         self.assertEqual(response.getStatus(), 302) # Redirect to document_edit_form
00247 
00248         # The redirect URL should contain the factory parts
00249         location = response.getHeader('Location')
00250         self.failUnless(location.startswith(self.folder_url+'/portal_factory/Document/'))
00251         # CMFFormController redirects should not do alias translation
00252         self.failUnless(location.endswith('/edit'))
00253 
00254         # Perform the redirect
00255         edit_form_path = location[len(self.app.REQUEST.SERVER_URL):]
00256         response = self.publish(edit_form_path, self.basic_auth)
00257         self.assertEqual(response.getStatus(), 200) # OK
00258 
00259     def testCreateNonGloballyAllowedObject(self):
00260         # TempFolder allows to create all portal types
00261         self.portal.portal_types.Document.manage_changeProperties(global_allow=0)
00262         response = self.publish(self.folder_path +
00263                                 '/createObject?type_name=Document',
00264                                 self.basic_auth)
00265 
00266         self.assertEqual(response.getStatus(), 302) # Redirect to document_edit_form
00267 
00268         # The redirect URL should contain the factory parts
00269         location = response.getHeader('Location')
00270         self.failUnless(location.startswith(self.folder_url+'/portal_factory/Document/'))
00271         self.failUnless(location.endswith('/edit'))
00272 
00273         # Perform the redirect
00274         edit_form_path = location[len(self.app.REQUEST.SERVER_URL):]
00275         response = self.publish(edit_form_path, self.basic_auth)
00276         self.assertEqual(response.getStatus(), 200) # OK
00277 
00278     def testUnauthorizedToViewEditForm(self):
00279         # Anonymous should not be able to see document_edit_form
00280         response = self.publish(self.folder_path +
00281                                 '/createObject?type_name=Document',
00282                                 ) # No basic out info
00283         # We got redirected to the factory
00284         self.assertEqual(response.getStatus(), 302)
00285         newpath = response.getHeader('location')
00286         proto, host, path, query, fragment = urlparse.urlsplit(newpath)
00287         # Let's follow it
00288         response = self.publish(path)
00289         # And we are forbidden
00290         self.assertEqual(response.getStatus(), 401) # Unauthorized
00291 
00292     def testUnauthorizedToViewEditFormOfNonFactoryObject(self):
00293         # Anonymous should not be able to see newsitem_edit_form
00294         response = self.publish(self.folder_path +
00295                                 '/createObject?type_name=News%20Item',
00296                                 ) # No basic out info
00297 
00298         self.assertEqual(response.getStatus(), 401) # Unauthorized
00299 
00300     def testCreateObjectByDocumentEdit(self):
00301         # document_edit should create the real object
00302         response = self.publish(self.folder_path +
00303             '/portal_factory/Document/tmp_id/document_edit?id=foo&title=Foo&text_format=plain&text=',
00304             self.basic_auth)
00305 
00306         self.assertEqual(response.getStatus(), 302) # Redirect to document_view
00307         viewAction = self.portal.portal_types['Document'].getActionInfo('object/view', self.folder.foo)['url']
00308         self.failUnless(response.getHeader('Location').startswith(viewAction))
00309 
00310         self.failUnless('foo' in self.folder.objectIds())
00311         self.assertEqual(self.folder.foo.Title(), 'Foo')
00312         self.assertEqual(self.folder.foo.get_local_roles_for_userid(default_user), ('Owner',))
00313 
00314     def testUnauthorizedToCreateObjectByDocumentEdit(self):
00315         # Anonymous should not be able to create the real object
00316         response = self.publish(self.folder_path +
00317             '/portal_factory/Document/tmp_id/document_edit?id=foo&title=Foo&text_format=plain&text=',
00318             ) # No basic auth info
00319 
00320         self.assertEqual(response.getStatus(), 401) # Unauthorized
00321 
00322 
00323 def test_suite():
00324     from unittest import TestSuite, makeSuite
00325     suite = TestSuite()
00326     suite.addTest(makeSuite(TestPortalFactory))
00327     suite.addTest(makeSuite(TestCreateObject))
00328     suite.addTest(makeSuite(TestCreateObjectByURL))
00329     return suite