Back to index

plone3  3.1.7
test_PortalFolder.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Unit tests for PortalFolder module.
00014 
00015 $Id: test_PortalFolder.py 77004 2007-06-24 08:57:54Z yuppie $
00016 """
00017 
00018 import unittest
00019 import Testing
00020 
00021 import transaction
00022 from AccessControl import SecurityManager
00023 from AccessControl import Unauthorized
00024 from AccessControl.SecurityManagement import newSecurityManager
00025 from Acquisition import aq_base
00026 from Acquisition import Implicit
00027 from DateTime import DateTime
00028 from OFS.Image import manage_addFile
00029 from zope.component import getSiteManager
00030 from zope.component.interfaces import IFactory
00031 from zope.interface import implements
00032 
00033 from Products.CMFCore.CatalogTool import CatalogTool
00034 from Products.CMFCore.exceptions import BadRequest
00035 from Products.CMFCore.interfaces import ITypesTool
00036 from Products.CMFCore.testing import ConformsToFolder
00037 from Products.CMFCore.testing import FunctionalZCMLLayer
00038 from Products.CMFCore.testing import TraversingEventZCMLLayer
00039 from Products.CMFCore.tests.base.dummy import DummyContent
00040 from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher
00041 from Products.CMFCore.tests.base.dummy import DummySite
00042 from Products.CMFCore.tests.base.dummy import DummyUserFolder
00043 from Products.CMFCore.tests.base.testcase import SecurityRequestTest
00044 from Products.CMFCore.tests.base.testcase import SecurityTest
00045 from Products.CMFCore.tests.base.tidata import FTIDATA_CMF15
00046 from Products.CMFCore.tests.base.tidata import FTIDATA_DUMMY
00047 from Products.CMFCore.tests.base.utils import has_path
00048 from Products.CMFCore.TypesTool import FactoryTypeInformation as FTI
00049 from Products.CMFCore.TypesTool import TypesTool
00050 from Products.CMFCore.WorkflowTool import WorkflowTool
00051 
00052 
00053 def extra_meta_types():
00054     return [{'name': 'Dummy', 'action': 'manage_addFolder',
00055              'permission': 'View'}]
00056 
00057 
00058 class PortalFolderFactoryTests(SecurityTest):
00059 
00060     layer = TraversingEventZCMLLayer
00061     _PORTAL_TYPE = 'Test Folder'
00062 
00063     def _getTargetObject(self):
00064         from Products.CMFCore.PortalFolder import PortalFolderFactory
00065 
00066         return PortalFolderFactory
00067 
00068     def setUp(self):
00069         from Products.CMFCore.PortalFolder import PortalFolder
00070 
00071         SecurityTest.setUp(self)
00072         sm = getSiteManager()
00073         sm.registerUtility(self._getTargetObject(), IFactory, 'cmf.folder')
00074         self.site = DummySite('site').__of__(self.root)
00075         acl_users = self.site._setObject('acl_users', DummyUserFolder())
00076         newSecurityManager(None, acl_users.all_powerful_Oz)
00077 
00078         ttool = self.site._setObject('portal_types', TypesTool())
00079         ttool._setObject(self._PORTAL_TYPE,
00080                          FTI(id=self._PORTAL_TYPE,
00081                              title='Folder or Directory',
00082                              meta_type=PortalFolder.meta_type,
00083                              factory='cmf.folder',
00084                              filter_content_types=0))
00085         ttool._setObject('Dummy Content', FTI(**FTIDATA_DUMMY[0].copy()))
00086 
00087         self.f = self.site._setObject('container', PortalFolder('container'))
00088         self.f._setPortalTypeName(self._PORTAL_TYPE)
00089 
00090     def test_invokeFactory(self):
00091         f = self.f
00092         self.failIf( 'foo' in f.objectIds() )
00093 
00094         f.manage_addProduct = {'FooProduct': DummyFactoryDispatcher(f)}
00095         f.invokeFactory( type_name='Dummy Content', id='foo' )
00096 
00097         self.failUnless( 'foo' in f.objectIds() )
00098         foo = f.foo
00099         self.assertEqual( foo.getId(), 'foo' )
00100         self.assertEqual( foo.getPortalTypeName(), 'Dummy Content' )
00101         self.assertEqual( foo.Type(), 'Dummy Content Title' )
00102 
00103     def test_invokeFactory_disallowed_type(self):
00104         f = self.f
00105         ftype = getattr(self.site.portal_types, self._PORTAL_TYPE)
00106         ftype.filter_content_types = 1
00107         self.assertRaises(ValueError,
00108                           f.invokeFactory, self._PORTAL_TYPE, 'sub')
00109 
00110         ftype.allowed_content_types = (self._PORTAL_TYPE,)
00111         f.invokeFactory(self._PORTAL_TYPE, id='sub')
00112         self.failUnless('sub' in f.objectIds())
00113         self.assertRaises(ValueError, f.invokeFactory, 'Dummy Content', 'foo')
00114 
00115 
00116 class PortalFolderTests(ConformsToFolder, SecurityTest):
00117 
00118     layer = FunctionalZCMLLayer
00119 
00120     def _getTargetClass(self):
00121         from Products.CMFCore.PortalFolder import PortalFolder
00122 
00123         return PortalFolder
00124 
00125     def _makeOne(self, id, *args, **kw):
00126         return self.site._setObject(id,
00127                                     self._getTargetClass()(id, *args, **kw))
00128 
00129     def setUp(self):
00130         SecurityTest.setUp(self)
00131         self.site = DummySite('site').__of__(self.root)
00132 
00133     def test_z2interfaces(self):
00134         from Interface.Verify import verifyClass
00135         from OFS.IOrderSupport import IOrderedContainer
00136 
00137         verifyClass(IOrderedContainer, self._getTargetClass())
00138 
00139     def test_z3interfaces(self):
00140         from zope.interface.verify import verifyClass
00141         from OFS.interfaces import IOrderedContainer
00142 
00143         verifyClass(IOrderedContainer, self._getTargetClass())
00144 
00145     def test_contents_methods(self):
00146         ttool = self.site._setObject( 'portal_types', TypesTool() )
00147         f = self._makeOne('foo')
00148         self.assertEqual( f.objectValues(), [] )
00149         self.assertEqual( f.contentIds(), [] )
00150         self.assertEqual( f.contentItems(), [] )
00151         self.assertEqual( f.contentValues(), [] )
00152         self.assertEqual( f.listFolderContents(), [] )
00153         self.assertEqual( f.listDAVObjects(), [] )
00154 
00155         f._setObject('sub1', DummyContent('sub1') )
00156         self.assertEqual( f.objectValues(), [f.sub1] )
00157         self.assertEqual( f.contentIds(), [] )
00158         self.assertEqual( f.contentItems(), [] )
00159         self.assertEqual( f.contentValues(), [] )
00160         self.assertEqual( f.listFolderContents(), [] )
00161         self.assertEqual( f.listDAVObjects(), [f.sub1] )
00162 
00163         fti = FTIDATA_DUMMY[0].copy()
00164         ttool._setObject( 'Dummy Content', FTI(**fti) )
00165         self.assertEqual( f.objectValues(), [f.sub1] )
00166         self.assertEqual( f.contentIds(), ['sub1'] )
00167         self.assertEqual( f.contentItems(), [ ('sub1', f.sub1) ] )
00168         self.assertEqual( f.contentValues(), [f.sub1] )
00169         self.assertEqual( f.listFolderContents(), [f.sub1] )
00170         self.assertEqual( f.listDAVObjects(), [f.sub1] )
00171 
00172         f._setObject('hidden_sub2', DummyContent('hidden_sub2') )
00173         self.assertEqual( f.objectValues(), [f.sub1, f.hidden_sub2] )
00174         self.assertEqual( f.contentIds(), ['sub1', 'hidden_sub2'] )
00175         self.assertEqual( f.contentItems(), [ ('sub1', f.sub1),
00176                                             ('hidden_sub2', f.hidden_sub2) ] )
00177         self.assertEqual( f.contentValues(), [f.sub1, f.hidden_sub2] )
00178         self.assertEqual( f.listFolderContents(), [f.sub1] )
00179         self.assertEqual( f.listDAVObjects(), [f.sub1, f.hidden_sub2] )
00180 
00181     def test_deletePropagation(self):
00182         test = self._makeOne('test')
00183         foo = DummyContent('foo')
00184         foo.reset()
00185         self.failIf( foo.after_add_called )
00186         self.failIf( foo.before_delete_called )
00187 
00188         test._setObject('foo', foo)
00189         self.failUnless( foo.after_add_called )
00190         self.failIf( foo.before_delete_called )
00191 
00192         foo.reset()
00193         test._delObject('foo')
00194         self.failIf( foo.after_add_called )
00195         self.failUnless( foo.before_delete_called )
00196 
00197         foo.reset()
00198         test._setObject('foo', foo)
00199         test._delOb('foo')    # doesn't propagate
00200         self.failUnless( foo.after_add_called )
00201         self.failIf( foo.before_delete_called )
00202 
00203     def test_manageDelObjects(self):
00204         test = self._makeOne('test')
00205         foo = DummyContent('foo')
00206 
00207         test._setObject('foo', foo)
00208         foo.reset()
00209         test.manage_delObjects( ids=['foo'] )
00210         self.failIf( foo.after_add_called )
00211         self.failUnless( foo.before_delete_called )
00212 
00213     def test_catalogUnindexAndIndex(self):
00214         #
00215         # Test is a new object does get cataloged upon _setObject
00216         # and uncataloged upon manage_deleteObjects
00217         #
00218         test = self._makeOne('test')
00219         ttool = self.site._setObject( 'portal_types', TypesTool() )
00220         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00221         self.assertEqual( len(ctool), 0 )
00222 
00223         test._setObject( 'foo', DummyContent( 'foo' , catalog=1 ) )
00224         foo = test.foo
00225         self.failUnless( foo.after_add_called )
00226         self.failIf( foo.before_delete_called )
00227         self.assertEqual( len(ctool), 1 )
00228 
00229         foo.reset()
00230         test._delObject('foo')
00231         self.failIf( foo.after_add_called )
00232         self.failUnless( foo.before_delete_called )
00233         self.assertEqual( len(ctool), 0 )
00234 
00235     def test_portalfolder_cataloging(self):
00236         #
00237         # Test to ensure a portal folder itself is *not* cataloged upon
00238         # instantiation (Tracker issue 309)
00239         #
00240         ttool = self.site._setObject( 'portal_types', TypesTool() )
00241         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00242         wftool = self.site._setObject( 'portal_workflow', WorkflowTool() )
00243         test = self._makeOne('test')
00244         wftool.notifyCreated(test)
00245         self.assertEqual( len(ctool), 0 )
00246 
00247     def test_tracker261(self):
00248         #
00249         #   Tracker issue #261 says that content in a deleted folder
00250         #   is not being uncatalogued.  Try creating a subfolder with
00251         #   content object, and test.
00252         #
00253         from Products.CMFCore.PortalFolder import PortalFolder
00254 
00255         test = self._makeOne('test')
00256         ttool = self.site._setObject( 'portal_types', TypesTool() )
00257         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00258         self.assertEqual( len(ctool), 0 )
00259 
00260         test._setObject( 'sub', PortalFolder( 'sub', '' ) )
00261         sub = test.sub
00262 
00263         sub._setObject( 'foo', DummyContent( 'foo', catalog=1 ) )
00264         foo = sub.foo
00265 
00266         self.failUnless( foo.after_add_called )
00267         self.failIf( foo.before_delete_called )
00268         self.assertEqual( len(ctool), 1 )
00269 
00270         foo.reset()
00271         test._delObject('sub')
00272         self.failIf( foo.after_add_called )
00273         self.failUnless( foo.before_delete_called )
00274         self.assertEqual( len(ctool), 0 )
00275 
00276     def test_manageAddFolder(self):
00277         #
00278         #   Does MKDIR/MKCOL intercept work?
00279         #
00280         from Products.CMFCore.PortalFolder import PortalFolder
00281 
00282         test = self._makeOne('test')
00283 
00284         ttool = self.site._setObject( 'portal_types', TypesTool() )
00285         ttool._setObject( 'Folder'
00286                         , FTI( id='Folder'
00287                              , title='Folder or Directory'
00288                              , meta_type=PortalFolder.meta_type
00289                              , factory='cmf.folder'
00290                              , filter_content_types=0
00291                              )
00292                         )
00293         ttool._setObject( 'Grabbed'
00294                         , FTI( 'Grabbed'
00295                              , title='Grabbed Content'
00296                              , meta_type=PortalFolder.meta_type
00297                              , factory='cmf.folder'
00298                              )
00299                         )
00300 
00301         # First, test default behavior
00302         test.manage_addFolder(id='simple', title='Simple')
00303         self.assertEqual( test.simple.getPortalTypeName(), 'Folder' )
00304         self.assertEqual( test.simple.Type(), 'Folder or Directory' )
00305         self.assertEqual( test.simple.getId(), 'simple' )
00306         self.assertEqual( test.simple.Title(), 'Simple' )
00307 
00308         # Now, test overridden behavior
00309         ttool.Folder.setMethodAliases( {'mkdir': 'grabbed'} )
00310 
00311         class Grabbed:
00312 
00313             _grabbed_with = None
00314 
00315             def __init__( self, context ):
00316                 self._context = context
00317 
00318             def __call__( self, id ):
00319                 self._grabbed_with = id
00320                 self._context._setOb( id, PortalFolder( id ) )
00321                 self._context._getOb( id )._setPortalTypeName( 'Grabbed' )
00322 
00323         self.root.grabbed = Grabbed(test)
00324 
00325         test.manage_addFolder(id='indirect', title='Indirect')
00326         self.assertEqual( test.indirect.getPortalTypeName(), 'Grabbed' )
00327         self.assertEqual( test.indirect.Type(), 'Grabbed Content' )
00328         self.assertEqual( test.indirect.getId(), 'indirect' )
00329         self.assertEqual( test.indirect.Title(), 'Indirect' )
00330 
00331     def test_contentPasteAllowedTypes(self):
00332         #
00333         #   _verifyObjectPaste() should honor allowed content types
00334         #
00335         ttool = self.site._setObject( 'portal_types', TypesTool() )
00336         fti = FTIDATA_DUMMY[0].copy()
00337         ttool._setObject( 'Dummy Content', FTI(**fti) )
00338         ttool._setObject( 'Folder', FTI(**fti) )
00339         sub1 = self._makeOne('sub1')
00340         sub1._setObject( 'dummy', DummyContent( 'dummy' ) )
00341         sub2 = self._makeOne('sub2')
00342         sub2.all_meta_types = extra_meta_types()
00343 
00344         # Allow adding of Dummy Content
00345         ttool.Folder.manage_changeProperties(filter_content_types=False)
00346 
00347         # Copy/paste should work fine
00348         cookie = sub1.manage_copyObjects( ids = ['dummy'] )
00349         sub2.manage_pasteObjects( cookie )
00350 
00351         # Disallow adding of Dummy Content
00352         ttool.Folder.manage_changeProperties(filter_content_types=True)
00353 
00354         # Now copy/paste should raise a ValueError
00355         cookie = sub1.manage_copyObjects( ids = ( 'dummy', ) )
00356         self.assertRaises( ValueError, sub2.manage_pasteObjects, cookie )
00357 
00358     def test_setObjectRaisesBadRequest(self):
00359         #
00360         #   _setObject() should raise BadRequest on duplicate id
00361         #
00362         test = self._makeOne('test')
00363         test._setObject('foo', DummyContent('foo'))
00364         self.assertRaises(BadRequest, test._setObject, 'foo',
00365                                       DummyContent('foo'))
00366 
00367     def test__checkId_Duplicate(self):
00368         #
00369         #   _checkId() should raise BadRequest on duplicate id
00370         #
00371         test = self._makeOne('test')
00372         test._setObject('foo', DummyContent('foo'))
00373         self.assertRaises(BadRequest, test._checkId, 'foo')
00374 
00375     def test__checkId_PortalRoot(self):
00376         test = self._makeOne('test')
00377         acl_users = self.site._setObject('acl_users', DummyUserFolder())
00378         test._checkId('acl_users')
00379         newSecurityManager(None, acl_users.user_foo)
00380         self.assertRaises(BadRequest, test._checkId, 'acl_users')
00381 
00382     def test__checkId_MethodAlias(self):
00383         test = self._makeOne('test')
00384         test._setPortalTypeName('Dummy Content 15')
00385         ttool = self.site._setObject('portal_types', TypesTool())
00386         ttool._setObject('Dummy Content 15', FTI(**FTIDATA_CMF15[0]))
00387         acl_users = self.site._setObject('acl_users', DummyUserFolder())
00388         test._checkId('view.html')
00389         newSecurityManager(None, acl_users.user_foo)
00390         self.assertRaises(BadRequest, test._checkId, 'view.html')
00391 
00392     def test__checkId_starting_with_dot(self):
00393         #
00394         # doted prefixed names at the root of the portal can be overriden
00395         #
00396 
00397         # Create a .foo at the root
00398         self.site._setObject('.foo', DummyContent('.foo'))
00399 
00400         # Create a sub-folder
00401         sub = self._makeOne('sub')
00402 
00403         # It should be possible to create another .foo object in the
00404         # sub-folder
00405         acl_users = self.site._setObject('acl_users', DummyUserFolder())
00406         newSecurityManager(None, acl_users.user_foo)
00407 
00408         self.assert_(sub.checkIdAvailable('.foo'))
00409 
00410     def test__checkId_Five(self):
00411         test = self._makeOne('test')
00412         self.assertRaises(BadRequest, test._checkId, '@@view.html')
00413         self.assertRaises(BadRequest, test._checkId, '++resource++icon.png')
00414 
00415     def test_checkIdAvailableCatchesBadRequest(self):
00416         #
00417         #   checkIdAvailable() should catch BadRequest
00418         #
00419         test = self._makeOne('test')
00420         test._setObject('foo', DummyContent('foo'))
00421         self.failIf(test.checkIdAvailable('foo'))
00422 
00423 
00424 class PortalFolderMoveTests(SecurityTest):
00425 
00426     layer = TraversingEventZCMLLayer
00427 
00428     def setUp(self):
00429         SecurityTest.setUp(self)
00430         self.root._setObject( 'site', DummySite('site') )
00431         self.site = self.root.site
00432 
00433     def _makeOne(self, id, *args, **kw):
00434         from Products.CMFCore.PortalFolder import PortalFolder
00435 
00436         return self.site._setObject( id, PortalFolder(id, *args, **kw) )
00437 
00438     def test_folderMove(self):
00439         #
00440         #   Does the catalog stay synched when folders are moved?
00441         #
00442         from Products.CMFCore.PortalFolder import PortalFolder
00443 
00444         ttool = self.site._setObject( 'portal_types', TypesTool() )
00445         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00446         ctool.addIndex('getId', 'FieldIndex')
00447         self.assertEqual( len(ctool), 0 )
00448 
00449         folder = self._makeOne('folder')
00450         folder._setObject( 'sub', PortalFolder( 'sub', '' ) )
00451         folder.sub._setObject( 'foo', DummyContent( 'foo', catalog=1 ) )
00452         self.assertEqual( len(ctool), 1 )
00453         self.failUnless( 'foo' in ctool.uniqueValuesFor('getId') )
00454         self.failUnless( has_path(ctool._catalog,
00455                                   '/bar/site/folder/sub/foo') )
00456 
00457         transaction.savepoint(optimistic=True)
00458         folder.manage_renameObject(id='sub', new_id='new_sub')
00459         self.assertEqual( len(ctool), 1 )
00460         self.failUnless( 'foo' in ctool.uniqueValuesFor('getId') )
00461         self.failUnless( has_path(ctool._catalog,
00462                                   '/bar/site/folder/new_sub/foo') )
00463 
00464         folder._setObject( 'bar', DummyContent( 'bar', catalog=1 ) )
00465         self.assertEqual( len(ctool), 2 )
00466         self.failUnless( 'bar' in ctool.uniqueValuesFor('getId') )
00467         self.failUnless( has_path(ctool._catalog, '/bar/site/folder/bar') )
00468 
00469         folder._setObject( 'sub2', PortalFolder( 'sub2', '' ) )
00470         sub2 = folder.sub2
00471         # Waaa! force sub2 to allow paste of Dummy object.
00472         sub2.all_meta_types = []
00473         sub2.all_meta_types.extend( sub2.all_meta_types )
00474         sub2.all_meta_types.extend( extra_meta_types() )
00475 
00476         transaction.savepoint(optimistic=True)
00477         cookie = folder.manage_cutObjects(ids=['bar'])
00478         sub2.manage_pasteObjects(cookie)
00479 
00480         self.failUnless( 'foo' in ctool.uniqueValuesFor('getId') )
00481         self.failUnless( 'bar' in ctool.uniqueValuesFor('getId') )
00482         self.assertEqual( len(ctool), 2 )
00483         self.failUnless( has_path(ctool._catalog,
00484                                   '/bar/site/folder/sub2/bar') )
00485 
00486     def test_contentPaste(self):
00487         #
00488         #   Does copy / paste work?
00489         #
00490         ctool = self.site._setObject( 'portal_catalog', CatalogTool() )
00491         ttool = self.site._setObject( 'portal_types', TypesTool() )
00492         fti = FTIDATA_DUMMY[0].copy()
00493         ttool._setObject( 'Dummy Content', FTI(**fti) )
00494         sub1 = self._makeOne('sub1')
00495         sub2 = self._makeOne('sub2')
00496         sub3 = self._makeOne('sub3')
00497         self.assertEqual( len(ctool), 0 )
00498 
00499         sub1._setObject( 'dummy', DummyContent( 'dummy', catalog=1 ) )
00500         self.failUnless( 'dummy' in sub1.objectIds() )
00501         self.failUnless( 'dummy' in sub1.contentIds() )
00502         self.failIf( 'dummy' in sub2.objectIds() )
00503         self.failIf( 'dummy' in sub2.contentIds() )
00504         self.failIf( 'dummy' in sub3.objectIds() )
00505         self.failIf( 'dummy' in sub3.contentIds() )
00506         self.failUnless( has_path(ctool._catalog, '/bar/site/sub1/dummy') )
00507         self.failIf( has_path(ctool._catalog, '/bar/site/sub2/dummy') )
00508         self.failIf( has_path(ctool._catalog, '/bar/site/sub3/dummy') )
00509 
00510         cookie = sub1.manage_copyObjects( ids = ( 'dummy', ) )
00511         # Waaa! force sub2 to allow paste of Dummy object.
00512         sub2.all_meta_types = []
00513         sub2.all_meta_types.extend( sub2.all_meta_types )
00514         sub2.all_meta_types.extend( extra_meta_types() )
00515         sub2.manage_pasteObjects( cookie )
00516         self.failUnless( 'dummy' in sub1.objectIds() )
00517         self.failUnless( 'dummy' in sub1.contentIds() )
00518         self.failUnless( 'dummy' in sub2.objectIds() )
00519         self.failUnless( 'dummy' in sub2.contentIds() )
00520         self.failIf( 'dummy' in sub3.objectIds() )
00521         self.failIf( 'dummy' in sub3.contentIds() )
00522         self.failUnless( has_path(ctool._catalog, '/bar/site/sub1/dummy') )
00523         self.failUnless( has_path(ctool._catalog, '/bar/site/sub2/dummy') )
00524         self.failIf( has_path(ctool._catalog, '/bar/site/sub3/dummy') )
00525 
00526         transaction.savepoint(optimistic=True)
00527         cookie = sub1.manage_cutObjects( ids = ('dummy',) )
00528         # Waaa! force sub2 to allow paste of Dummy object.
00529         sub3.all_meta_types = []
00530         sub3.all_meta_types.extend(sub3.all_meta_types)
00531         sub3.all_meta_types.extend( extra_meta_types() )
00532         sub3.manage_pasteObjects(cookie)
00533         self.failIf( 'dummy' in sub1.objectIds() )
00534         self.failIf( 'dummy' in sub1.contentIds() )
00535         self.failUnless( 'dummy' in sub2.objectIds() )
00536         self.failUnless( 'dummy' in sub2.contentIds() )
00537         self.failUnless( 'dummy' in sub3.objectIds() )
00538         self.failUnless( 'dummy' in sub3.contentIds() )
00539         self.failIf( has_path(ctool._catalog, '/bar/site/sub1/dummy') )
00540         self.failUnless( has_path(ctool._catalog, '/bar/site/sub2/dummy') )
00541         self.failUnless( has_path(ctool._catalog, '/bar/site/sub3/dummy') )
00542 
00543 
00544 class ContentFilterTests(unittest.TestCase):
00545 
00546     def setUp( self ):
00547         self.dummy=DummyContent('Dummy')
00548 
00549     def test_empty( self ):
00550 
00551         from Products.CMFCore.PortalFolder import ContentFilter
00552 
00553         cfilter = ContentFilter()
00554         dummy = self.dummy
00555         assert cfilter( dummy )
00556         desc = str( cfilter )
00557         lines = filter( None, desc.split('; ') )
00558         assert not lines
00559 
00560     def test_Type( self ):
00561 
00562         from Products.CMFCore.PortalFolder import ContentFilter
00563 
00564         cfilter = ContentFilter( Type='foo' )
00565         dummy = self.dummy
00566         assert not cfilter( dummy )
00567         cfilter = ContentFilter( Type='Dummy Content Title' )
00568         assert cfilter( dummy )
00569         desc = str( cfilter )
00570         lines = desc.split('; ')
00571         assert len( lines ) == 1
00572         assert lines[0] == 'Type: Dummy Content Title'
00573 
00574         cfilter = ContentFilter( Type=( 'foo', 'bar' ) )
00575         dummy = self.dummy
00576         assert not cfilter( dummy )
00577         cfilter = ContentFilter( Type=( 'Dummy Content Title',
00578                                         'something else' ) )
00579         assert cfilter( dummy )
00580         desc = str( cfilter )
00581         lines = desc.split('; ')
00582         assert len( lines ) == 1
00583         assert lines[0] == 'Type: Dummy Content Title, something else'
00584 
00585     def test_portal_type( self ):
00586 
00587         from Products.CMFCore.PortalFolder import ContentFilter
00588 
00589         cfilter = ContentFilter( portal_type='some_pt' )
00590         dummy = self.dummy
00591         assert not cfilter( dummy )
00592         dummy.portal_type = 'asdf'
00593         assert not cfilter( dummy )
00594         dummy.portal_type = 'some_ptyyy'
00595         assert not cfilter( dummy )
00596         dummy.portal_type = 'xxxsome_ptyyy'
00597         assert not cfilter( dummy )
00598         dummy.portal_type = 'some_pt'
00599         assert cfilter( dummy )
00600         desc = str( cfilter )
00601         lines = desc.split('; ')
00602         assert len( lines ) == 1
00603         assert lines[0] == 'Portal Type: some_pt'
00604 
00605     def test_Title( self ):
00606 
00607         from Products.CMFCore.PortalFolder import ContentFilter
00608 
00609         cfilter = ContentFilter( Title='foo' )
00610         dummy = self.dummy
00611         assert not cfilter( dummy )
00612         dummy.title = 'asdf'
00613         assert not cfilter( dummy )
00614         dummy.title = 'foolish'
00615         assert cfilter( dummy )
00616         dummy.title = 'ohsofoolish'
00617         assert cfilter( dummy )
00618         desc = str( cfilter )
00619         lines = desc.split('; ')
00620         assert len( lines ) == 1
00621         assert lines[0] == 'Title: foo'
00622 
00623     def test_Creator( self ):
00624 
00625         from Products.CMFCore.PortalFolder import ContentFilter
00626 
00627         cfilter = ContentFilter( Creator='moe' )
00628         dummy = self.dummy
00629         self.failIf( cfilter(dummy) )
00630         dummy.creators = ('curly',)
00631         self.failIf( cfilter(dummy) )
00632         dummy.creators = ('moe',)
00633         self.failUnless( cfilter(dummy) )
00634         dummy.creators = ('moe', 'curly')
00635         self.failUnless( cfilter(dummy) )
00636         desc = str( cfilter )
00637         lines = desc.split('; ')
00638         self.assertEqual(len( lines ),1)
00639         self.assertEqual(lines[0],'Creator: moe')
00640 
00641     def test_Description( self ):
00642 
00643         from Products.CMFCore.PortalFolder import ContentFilter
00644 
00645         cfilter = ContentFilter( Description='funny' )
00646         dummy = self.dummy
00647         assert not cfilter( dummy )
00648         dummy.description = 'sad'
00649         assert not cfilter( dummy )
00650         dummy.description = 'funny'
00651         assert cfilter( dummy )
00652         dummy.description = 'it is funny you should mention it...'
00653         assert cfilter( dummy )
00654         desc = str( cfilter )
00655         lines = desc.split('; ')
00656         assert len( lines ) == 1
00657         assert lines[0] == 'Description: funny'
00658 
00659     def test_Subject( self ):
00660 
00661         from Products.CMFCore.PortalFolder import ContentFilter
00662 
00663         cfilter = ContentFilter( Subject=('foo',) )
00664         dummy = self.dummy
00665         assert not cfilter( dummy )
00666         dummy.subject = ( 'bar', )
00667         assert not cfilter( dummy )
00668         dummy.subject = ( 'foo', )
00669         assert cfilter( dummy )
00670         dummy.subject = ( 'foo', 'bar', )
00671         assert cfilter( dummy )
00672         desc = str( cfilter )
00673         lines = desc.split('; ')
00674         assert len( lines ) == 1
00675         assert lines[0] == 'Subject: foo'
00676 
00677     def test_Subject2( self ):
00678         # Now test with mutli-valued
00679 
00680         from Products.CMFCore.PortalFolder import ContentFilter
00681 
00682         cfilter = ContentFilter( Subject=('foo', 'bar' ) )
00683         dummy = self.dummy
00684         assert not cfilter( dummy )
00685         dummy.subject = ( 'baz', )
00686         assert not cfilter( dummy )
00687         dummy.subject = ( 'bar', )
00688         assert cfilter( dummy )
00689         dummy.subject = ( 'foo', )
00690         assert cfilter( dummy )
00691         dummy.subject = ( 'foo', 'bar', )
00692         assert cfilter( dummy )
00693         desc = str( cfilter )
00694         lines = desc.split('; ')
00695         assert len( lines ) == 1
00696         assert lines[0] == 'Subject: foo, bar'
00697 
00698     def test_created( self ):
00699 
00700         from Products.CMFCore.PortalFolder import ContentFilter
00701 
00702         cfilter = ContentFilter( created=DateTime( '2001/01/01' )
00703                                , created_usage='range:min' )
00704         dummy = self.dummy
00705         assert not cfilter( dummy )
00706         dummy.created_date = DateTime( '2000/12/31' )
00707         assert not cfilter( dummy )
00708         dummy.created_date = DateTime( '2001/12/31' )
00709         assert cfilter( dummy )
00710         dummy.created_date = DateTime( '2001/01/01' )
00711         assert cfilter( dummy )
00712         desc = str( cfilter )
00713         lines = desc.split('; ')
00714         assert len( lines ) == 1
00715         assert lines[0] == 'Created since: 2001/01/01'
00716 
00717     def test_created2( self ):
00718 
00719         from Products.CMFCore.PortalFolder import ContentFilter
00720 
00721         cfilter = ContentFilter( created=DateTime( '2001/01/01' )
00722                                , created_usage='range:max' )
00723 
00724         dummy = self.dummy
00725         assert not cfilter( dummy )
00726         dummy.created_date = DateTime( '2000/12/31' )
00727         assert cfilter( dummy )
00728         dummy.created_date = DateTime( '2001/12/31' )
00729         assert not cfilter( dummy )
00730         dummy.created_date = DateTime( '2001/01/01' )
00731         assert cfilter( dummy )
00732         desc = str( cfilter )
00733         lines = desc.split('; ')
00734         assert len( lines ) == 1
00735         assert lines[0] == 'Created before: 2001/01/01'
00736 
00737     def test_modified( self ):
00738 
00739         from Products.CMFCore.PortalFolder import ContentFilter
00740 
00741         cfilter = ContentFilter( modified=DateTime( '2001/01/01' )
00742                                , modified_usage='range:min' )
00743         dummy = self.dummy
00744         assert not cfilter( dummy )
00745         dummy.modified_date = DateTime( '2000/12/31' )
00746         assert not cfilter( dummy )
00747         dummy.modified_date = DateTime( '2001/12/31' )
00748         assert cfilter( dummy )
00749         dummy.modified_date = DateTime( '2001/01/01' )
00750         assert cfilter( dummy )
00751         desc = str( cfilter )
00752         lines = desc.split('; ')
00753         assert len( lines ) == 1
00754         assert lines[0] == 'Modified since: 2001/01/01'
00755 
00756     def test_modified2( self ):
00757 
00758         from Products.CMFCore.PortalFolder import ContentFilter
00759 
00760         cfilter = ContentFilter( modified=DateTime( '2001/01/01' )
00761                                , modified_usage='range:max' )
00762         dummy = self.dummy
00763         assert not cfilter( dummy )
00764         dummy.modified_date = DateTime( '2000/12/31' )
00765         assert cfilter( dummy )
00766         dummy.modified_date = DateTime( '2001/12/31' )
00767         assert not cfilter( dummy )
00768         dummy.modified_date = DateTime( '2001/01/01' )
00769         assert cfilter( dummy )
00770         desc = str( cfilter )
00771         lines = desc.split('; ')
00772         assert len( lines ) == 1
00773         assert lines[0] == 'Modified before: 2001/01/01'
00774 
00775     def test_mixed( self ):
00776 
00777         from Products.CMFCore.PortalFolder import ContentFilter
00778 
00779         cfilter = ContentFilter( created=DateTime( '2001/01/01' )
00780                                , created_usage='range:max'
00781                                , Title='foo'
00782                                )
00783 
00784         dummy = self.dummy
00785         assert not cfilter( dummy )
00786         dummy.created_date = DateTime( '2000/12/31' )
00787         assert not cfilter( dummy )
00788         dummy.created_date = DateTime( '2001/12/31' )
00789         assert not cfilter( dummy )
00790         dummy.created_date = DateTime( '2001/01/01' )
00791         assert not cfilter( dummy )
00792 
00793         dummy.title = 'ohsofoolish'
00794         del dummy.created_date
00795         assert not cfilter( dummy )
00796         dummy.created_date = DateTime( '2000/12/31' )
00797         assert cfilter( dummy )
00798         dummy.created_date = DateTime( '2001/12/31' )
00799         assert not cfilter( dummy )
00800         dummy.created_date = DateTime( '2001/01/01' )
00801         assert cfilter( dummy )
00802 
00803         desc = str( cfilter )
00804         lines = desc.split('; ')
00805         assert len( lines ) == 2, lines
00806         assert 'Created before: 2001/01/01' in lines
00807         assert 'Title: foo' in lines
00808 
00809 
00810 #------------------------------------------------------------------------------
00811 #   Tests for security-related CopySupport lifted from the Zope 2.7
00812 #   / head OFS.tests.testCopySupport (see Collector #259).
00813 #------------------------------------------------------------------------------
00814 ADD_IMAGES_AND_FILES = 'Add images and files'
00815 FILE_META_TYPES = ( { 'name'        : 'File'
00816                     , 'action'      : 'manage_addFile'
00817                     , 'permission'  : ADD_IMAGES_AND_FILES
00818                     }
00819                   ,
00820                   )
00821 class _SensitiveSecurityPolicy:
00822 
00823     def __init__( self, validate_lambda, checkPermission_lambda ):
00824         self._lambdas = ( validate_lambda, checkPermission_lambda )
00825 
00826     def validate( self, *args, **kw ):
00827         if self._lambdas[ 0 ]( *args, **kw ):
00828             return True
00829         raise Unauthorized
00830 
00831     def checkPermission( self, *args, **kw ) :
00832         return self._lambdas[ 1 ]( *args, **kw )
00833 
00834 class _AllowedUser( Implicit ):
00835 
00836     def __init__( self, allowed_lambda ):
00837         self._lambdas = ( allowed_lambda, )
00838 
00839     def getId( self ):
00840         return 'unit_tester'
00841 
00842     getUserName = getId
00843 
00844     def allowed( self, object, object_roles=None ):
00845         return self._lambdas[ 0 ]( object, object_roles )
00846 
00847 
00848 class PortalFolderCopySupportTests(SecurityRequestTest):
00849 
00850     layer = FunctionalZCMLLayer
00851 
00852     def _initFolders(self):
00853         from Products.CMFCore.PortalFolder import PortalFolder
00854 
00855         self.app._setObject( 'folder1', PortalFolder( 'folder1' ) )
00856         self.app._setObject( 'folder2', PortalFolder( 'folder2' ) )
00857         folder1 = getattr( self.app, 'folder1' )
00858         folder2 = getattr( self.app, 'folder2' )
00859         manage_addFile(folder1, 'file', file='', content_type='text/plain')
00860 
00861         # Hack, we need a _p_mtime for the file, so we make sure that it
00862         # has one. We use a subtransaction, which means we can rollback
00863         # later and pretend we didn't touch the ZODB.
00864         transaction.savepoint(optimistic=True)
00865         return self.app._getOb( 'folder1' ), self.app._getOb( 'folder2' )
00866 
00867     def _assertCopyErrorUnauth( self, callable, *args, **kw ):
00868 
00869         import re
00870         from zExceptions import Unauthorized
00871         from OFS.CopySupport import CopyError
00872 
00873         ce_regex = kw.get( 'ce_regex' )
00874         if ce_regex is not None:
00875             del kw[ 'ce_regex' ]
00876 
00877         try:
00878             callable( *args, **kw )
00879 
00880         except CopyError, e:
00881 
00882             if ce_regex is not None:
00883 
00884                 pattern = re.compile( ce_regex, re.DOTALL )
00885                 if pattern.search( e ) is None:
00886                     self.fail( "Paste failed; didn't match pattern:\n%s" % e )
00887 
00888             else:
00889                 self.fail( "Paste failed; no pattern:\n%s" % e )
00890 
00891         except Unauthorized, e:
00892             pass
00893 
00894         else:
00895             self.fail( "Paste allowed unexpectedly." )
00896 
00897     def _initPolicyAndUser( self
00898                           , a_lambda=None
00899                           , v_lambda=None
00900                           , c_lambda=None
00901                           ):
00902         def _promiscuous( *args, **kw ):
00903             return 1
00904 
00905         if a_lambda is None:
00906             a_lambda = _promiscuous
00907 
00908         if v_lambda is None:
00909             v_lambda = _promiscuous
00910 
00911         if c_lambda is None:
00912             c_lambda = _promiscuous
00913 
00914         scp = _SensitiveSecurityPolicy( v_lambda, c_lambda )
00915         SecurityManager.setSecurityPolicy( scp )
00916 
00917         newSecurityManager( None
00918                           , _AllowedUser(a_lambda).__of__(self.app.acl_users))
00919 
00920     def test_copy_baseline( self ):
00921 
00922         folder1, folder2 = self._initFolders()
00923         folder2.all_meta_types = FILE_META_TYPES
00924 
00925         self._initPolicyAndUser()
00926 
00927         self.failUnless( 'file' in folder1.objectIds() )
00928         self.failIf( 'file' in folder2.objectIds() )
00929 
00930         cookie = folder1.manage_copyObjects( ids=( 'file', ) )
00931         folder2.manage_pasteObjects( cookie )
00932 
00933         self.failUnless( 'file' in folder1.objectIds() )
00934         self.failUnless( 'file' in folder2.objectIds() )
00935 
00936     def test_copy_cant_read_source( self ):
00937 
00938         folder1, folder2 = self._initFolders()
00939         folder2.all_meta_types = FILE_META_TYPES
00940 
00941         a_file = folder1._getOb( 'file' )
00942 
00943         def _validate( a, c, n, v, *args, **kw ):
00944             return aq_base( v ) is not aq_base( a_file )
00945 
00946         self._initPolicyAndUser( v_lambda=_validate )
00947 
00948         cookie = folder1.manage_copyObjects( ids=( 'file', ) )
00949         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
00950                                    , cookie
00951                                    , ce_regex='Insufficient privileges'
00952                                    )
00953 
00954     def test_copy_cant_create_target_metatype_not_supported( self ):
00955         folder1, folder2 = self._initFolders()
00956         folder2.all_meta_types = ()
00957 
00958         self._initPolicyAndUser()
00959 
00960         cookie = folder1.manage_copyObjects( ids=( 'file', ) )
00961         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
00962                                    , cookie
00963                                    , ce_regex='Not Supported'
00964                                    )
00965 
00966     def test_move_baseline( self ):
00967 
00968         folder1, folder2 = self._initFolders()
00969         folder2.all_meta_types = FILE_META_TYPES
00970 
00971         self.failUnless( 'file' in folder1.objectIds() )
00972         self.failIf( 'file' in folder2.objectIds() )
00973 
00974         self._initPolicyAndUser()
00975 
00976         cookie = folder1.manage_cutObjects( ids=( 'file', ) )
00977         folder2.manage_pasteObjects( cookie )
00978 
00979         self.failIf( 'file' in folder1.objectIds() )
00980         self.failUnless( 'file' in folder2.objectIds() )
00981 
00982     def test_move_cant_read_source( self ):
00983         folder1, folder2 = self._initFolders()
00984         folder2.all_meta_types = FILE_META_TYPES
00985 
00986         a_file = folder1._getOb( 'file' )
00987 
00988         def _validate( a, c, n, v, *args, **kw ):
00989             return aq_base( v ) is not aq_base( a_file )
00990 
00991         self._initPolicyAndUser( v_lambda=_validate )
00992 
00993         cookie = folder1.manage_cutObjects( ids=( 'file', ) )
00994         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
00995                                    , cookie
00996                                    , ce_regex='Insufficient privileges'
00997                                    )
00998 
00999     def test_move_cant_create_target_metatype_not_supported( self ):
01000         folder1, folder2 = self._initFolders()
01001         folder2.all_meta_types = ()
01002 
01003         self._initPolicyAndUser()
01004 
01005         cookie = folder1.manage_cutObjects( ids=( 'file', ) )
01006         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
01007                                    , cookie
01008                                    , ce_regex='Not Supported'
01009                                    )
01010 
01011     def test_move_cant_create_target_metatype_not_allowed( self ):
01012 
01013         #
01014         #   This test can't succeed on Zope's earlier than 2.7.3 because
01015         #   of the DWIM'y behavior of 'guarded_getattr', which tries to
01016         #   filter acquired-but-inaccessible objects, rather than raising
01017         #   Unauthorized.
01018         #
01019         #   If you are running with such a Zope, this test will error out
01020         #   with an AttributeError (instead of the expected Unauthorized).
01021         #
01022         folder1, folder2 = self._initFolders()
01023         folder2.all_meta_types = FILE_META_TYPES
01024 
01025         def _no_manage_addFile( a, c, n, v, *args, **kw ):
01026             return n != 'manage_addFile'
01027 
01028         def _no_add_images_and_files(permission, object, context):
01029             return permission != ADD_IMAGES_AND_FILES
01030 
01031         self._initPolicyAndUser( v_lambda=_no_manage_addFile,
01032                                  c_lambda=_no_add_images_and_files )
01033 
01034         cookie = folder1.manage_cutObjects( ids=( 'file', ) )
01035         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
01036                                    , cookie
01037                                    , ce_regex='Insufficient Privileges'
01038                                              + '.*%s' % ADD_IMAGES_AND_FILES
01039                                    )
01040 
01041     def test_move_cant_delete_source( self ):
01042 
01043         #
01044         #   This test fails on Zope's earlier than 2.7.3 because of the
01045         #   changes required to 'OFS.CopytSupport.manage_pasteObjects'
01046         #   which must pass 'validate_src' of 2 to '_verifyObjectPaste'
01047         #   to indicate that the object is being moved, rather than
01048         #   simply copied.
01049         #
01050         #   If you are running with such a Zope, this test will fail,
01051         #   because the move (which should raise Unauthorized) will be
01052         #   allowed.
01053         #
01054         from AccessControl.Permissions import delete_objects as DeleteObjects
01055         from Products.CMFCore.PortalFolder import PortalFolder
01056 
01057         folder1, folder2 = self._initFolders()
01058         folder1.manage_permission( DeleteObjects, roles=(), acquire=0 )
01059 
01060         folder1._setObject( 'sub', PortalFolder( 'sub' ) )
01061         transaction.savepoint(optimistic=True) # get a _p_jar for 'sub'
01062 
01063         self.app.portal_types = DummyTypesTool()
01064 
01065         def _no_delete_objects(permission, object, context):
01066             return permission != DeleteObjects
01067 
01068         self._initPolicyAndUser( c_lambda=_no_delete_objects )
01069 
01070         cookie = folder1.manage_cutObjects( ids=( 'sub', ) )
01071         self._assertCopyErrorUnauth( folder2.manage_pasteObjects
01072                                    , cookie
01073                                    , ce_regex='Insufficient Privileges'
01074                                              + '.*%s' % DeleteObjects
01075                                    )
01076 
01077     def test_paste_with_restricted_item_content_type_not_allowed(self):
01078 
01079         #   Test from CMF Collector #216 (Plone #2186), for the case
01080         #   in which the item being pasted does not allow adding such
01081         #   objects to containers which do not explicitly grant access.
01082         from Products.CMFCore.PortalFolder import PortalFolder
01083 
01084         RESTRICTED_TYPE = 'Restricted Item'
01085         UNRESTRICTED_TYPE = 'Unrestricted Container'
01086 
01087         folder1, folder2 = self._initFolders()
01088         folder1.portal_type = UNRESTRICTED_TYPE
01089         folder2.portal_type = RESTRICTED_TYPE
01090 
01091         self._initPolicyAndUser() # ensure that sec. machinery allows paste
01092 
01093         self.app._setObject( 'portal_types', TypesTool() )
01094         types_tool = self.app.portal_types
01095         types_tool._setObject( RESTRICTED_TYPE
01096                              , FTI( id=RESTRICTED_TYPE
01097                                   , title=RESTRICTED_TYPE
01098                                   , meta_type=PortalFolder.meta_type
01099                                   , product='CMFCore'
01100                                   , factory='manage_addPortalFolder'
01101                                   , global_allow=0
01102                                   )
01103                              )
01104         types_tool._setObject( UNRESTRICTED_TYPE
01105                              , FTI( id=UNRESTRICTED_TYPE
01106                                   , title=UNRESTRICTED_TYPE
01107                                   , meta_type=PortalFolder.meta_type
01108                                   , product='CMFCore'
01109                                   , factory='manage_addPortalFolder'
01110                                   , filter_content_types=0
01111                                   )
01112                              )
01113 
01114         # copy and pasting the object into the folder should raise
01115         # an exception
01116         copy_cookie = self.app.manage_copyObjects( ids=[ 'folder2' ] )
01117         self.assertRaises( ValueError
01118                          , folder1.manage_pasteObjects
01119                          , copy_cookie
01120                          )
01121 
01122     def test_paste_with_restricted_item_content_type_allowed(self):
01123 
01124         #   Test from CMF Collector #216 (Plone #2186), for the case
01125         #   in which the item being pasted *does8 allow adding such
01126         #   objects to containers which *do* explicitly grant access.
01127         from Products.CMFCore.PortalFolder import PortalFolder
01128 
01129         RESTRICTED_TYPE = 'Restricted Item'
01130         UNRESTRICTED_TYPE = 'Unrestricted Container'
01131 
01132         folder1, folder2 = self._initFolders()
01133         folder1.portal_type = UNRESTRICTED_TYPE
01134         folder2.portal_type = RESTRICTED_TYPE
01135 
01136         self._initPolicyAndUser() # ensure that sec. machinery allows paste
01137 
01138         self.app._setObject( 'portal_types', TypesTool() )
01139         types_tool = self.app.portal_types
01140         types_tool._setObject( RESTRICTED_TYPE
01141                              , FTI( id=RESTRICTED_TYPE
01142                                   , title=RESTRICTED_TYPE
01143                                   , meta_type=PortalFolder.meta_type
01144                                   , product='CMFCore'
01145                                   , factory='manage_addPortalFolder'
01146                                   , global_allow=0
01147                                   )
01148                              )
01149         types_tool._setObject( UNRESTRICTED_TYPE
01150                              , FTI( id=UNRESTRICTED_TYPE
01151                                   , title=UNRESTRICTED_TYPE
01152                                   , meta_type=PortalFolder.meta_type
01153                                   , product='CMFCore'
01154                                   , factory='manage_addPortalFolder'
01155                                   , filter_content_types=1
01156                                   , allowed_content_types=[ RESTRICTED_TYPE ]
01157                                   )
01158                              )
01159 
01160         # copy and pasting the object into the folder should *not* raise
01161         # an exception, because the folder's type allows it.
01162         copy_cookie = self.app.manage_copyObjects( ids=[ 'folder2' ] )
01163         folder1.manage_pasteObjects( copy_cookie )
01164         self.failUnless( 'folder2' in folder1.objectIds() )
01165 
01166     def test_paste_with_restricted_container_content_type(self):
01167 
01168         #   Test from CMF Collector #216 (Plone #2186), for the case
01169         #   in which the container does not allow adding items of the
01170         #   type being pasted.
01171         from Products.CMFCore.PortalFolder import PortalFolder
01172 
01173         RESTRICTED_TYPE = 'Restricted Container'
01174         UNRESTRICTED_TYPE = 'Unrestricted Item'
01175 
01176         folder1, folder2 = self._initFolders()
01177         folder1.portal_type = RESTRICTED_TYPE
01178         folder2.portal_type = UNRESTRICTED_TYPE
01179 
01180         self._initPolicyAndUser() # ensure that sec. machinery allows paste
01181 
01182         self.app._setObject( 'portal_types', TypesTool() )
01183         types_tool = self.app.portal_types
01184         types_tool._setObject( RESTRICTED_TYPE
01185                              , FTI( id=RESTRICTED_TYPE
01186                                   , title=RESTRICTED_TYPE
01187                                   , meta_type=PortalFolder.meta_type
01188                                   , product='CMFCore'
01189                                   , factory='manage_addPortalFolder'
01190                                   , filter_content_types=1
01191                                   , allowed_content_types=()
01192                                   )
01193                              )
01194         types_tool._setObject( UNRESTRICTED_TYPE
01195                              , FTI( id=UNRESTRICTED_TYPE
01196                                   , title=UNRESTRICTED_TYPE
01197                                   , meta_type=PortalFolder.meta_type
01198                                   , product='CMFCore'
01199                                   , factory='manage_addPortalFolder'
01200                                   , global_allow=1
01201                                   )
01202                              )
01203 
01204         # copy and pasting the object into the folder should raise
01205         # an exception
01206         copy_cookie = self.app.manage_copyObjects( ids=[ 'folder2' ] )
01207         self.assertRaises( ValueError
01208                          , folder1.manage_pasteObjects
01209                          , copy_cookie
01210                          )
01211 
01212 class DummyTypeInfo:
01213 
01214     def allowType( self, portal_type ):
01215         return True
01216 
01217 class DummyTypesTool( Implicit ):
01218 
01219     implements(ITypesTool)
01220 
01221     def getTypeInfo( self, portal_type ):
01222 
01223         return DummyTypeInfo()
01224 
01225 
01226 def test_suite():
01227     return unittest.TestSuite((
01228         unittest.makeSuite(PortalFolderFactoryTests),
01229         unittest.makeSuite(PortalFolderTests),
01230         unittest.makeSuite(PortalFolderMoveTests),
01231         unittest.makeSuite(ContentFilterTests),
01232         unittest.makeSuite(PortalFolderCopySupportTests),
01233         ))
01234 
01235 if __name__ == '__main__':
01236     from Products.CMFCore.testing import run
01237     run(test_suite())