Commit c00164c0 authored by 's avatar

- reverted workaround in '_verifyObjectPaste'; 'checkPermission' now respects proxy roles

parent 665b04c9
...@@ -26,6 +26,11 @@ Zope Changes ...@@ -26,6 +26,11 @@ Zope Changes
Bugs Fixed Bugs Fixed
- CopySupport: Reverted workaround in '_verifyObjectPaste'.
'checkPermission' now respects proxy roles, so the warkaround
introduced to fix http://www.zope.org/Collectors/Zope/78 is no longer
needed. Meta types listed in all_meta_types need a 'permission' key.
- Collector #1774: Harmonize the implementation of - Collector #1774: Harmonize the implementation of
AccessControl.ZopeSecurityPolicy.checkPermission AccessControl.ZopeSecurityPolicy.checkPermission
with 'validate', checking ownership and proxy roles if an with 'validate', checking ownership and proxy roles if an
......
...@@ -19,6 +19,7 @@ import re, sys, tempfile ...@@ -19,6 +19,7 @@ import re, sys, tempfile
from cgi import escape from cgi import escape
from marshal import loads, dumps from marshal import loads, dumps
from urllib import quote, unquote from urllib import quote, unquote
from warnings import warn
from zlib import compress, decompress from zlib import compress, decompress
import Globals, Moniker, ExtensionClass import Globals, Moniker, ExtensionClass
...@@ -352,7 +353,7 @@ class CopyContainer(ExtensionClass.Base): ...@@ -352,7 +353,7 @@ class CopyContainer(ExtensionClass.Base):
if not hasattr(object, 'meta_type'): if not hasattr(object, 'meta_type'):
raise CopyError, MessageDialog( raise CopyError, MessageDialog(
title = 'Not Supported', title = 'Not Supported',
message = ('The object <EM>%s</EM> does not support this' \ message = ('The object <em>%s</em> does not support this' \
' operation' % escape(absattr(object.id))), ' operation' % escape(absattr(object.id))),
action = 'manage_main') action = 'manage_main')
...@@ -372,35 +373,49 @@ class CopyContainer(ExtensionClass.Base): ...@@ -372,35 +373,49 @@ class CopyContainer(ExtensionClass.Base):
mt_permission = d.get('permission') mt_permission = d.get('permission')
break break
if method_name: if mt_permission is not None:
try: sm = getSecurityManager()
method = self.restrictedTraverse(method_name)
# method_name is e.g. if sm.checkPermission(mt_permission, self):
# "manage_addProduct/PageTemplates/manage_addPageTemplateForm". if validate_src:
# restrictedTraverse will raise Unauthorized if it # Ensure the user is allowed to access the object on the
# can't obtain the factory method by name due to a # clipboard.
# security restriction. We depend on this side effect try:
# here! Note that we use restrictedTraverse as parent = aq_parent(aq_inner(object))
# opposed to checkPermission to take into account the except:
# special security circumstances related to proxy parent = None
# roles. See collector #78.
if not sm.validate(None, parent, None, object):
except Unauthorized: raise Unauthorized(absattr(object.id))
if mt_permission:
if validate_src == 2: # moving
if not sm.checkPermission(DeleteObjects, parent):
raise Unauthorized('Delete not allowed.')
else:
raise CopyError, MessageDialog(
title = 'Insufficient Privileges',
message = ('You do not possess the %s permission in the ' message = ('You do not possess the %s permission in the '
'context of the container into which you are ' 'context of the container into which you are '
'pasting, thus you are not able to perform ' 'pasting, thus you are not able to perform '
'this operation.' % mt_permission) 'this operation.' % mt_permission),
else: action = 'manage_main')
elif method_name:
# BBB: fallback for missing or None permission
warn("The required 'permission' key is not set or None for meta "
"type '%s'. This fallback will be removed in Zope 2.9."
% object.meta_type,
DeprecationWarning)
try:
method = self.restrictedTraverse(method_name)
except Unauthorized:
raise CopyError, MessageDialog(
title = 'Insufficient Privileges',
message = ('You do not possess the permission required ' message = ('You do not possess the permission required '
'to call %s in the context of the container ' 'to call %s in the context of the container '
'into which you are pasting, thus you are not ' 'into which you are pasting, thus you are not '
'able to perform this operation.' % method_name) 'able to perform this operation.'
% method_name),
raise CopyError, MessageDialog( action = 'manage_main')
title = 'Insufficient Privileges',
message = message,
action = 'manage_main')
if validate_src: if validate_src:
...@@ -420,12 +435,12 @@ class CopyContainer(ExtensionClass.Base): ...@@ -420,12 +435,12 @@ class CopyContainer(ExtensionClass.Base):
if not sm.checkPermission(DeleteObjects, parent): if not sm.checkPermission(DeleteObjects, parent):
raise Unauthorized, 'Delete not allowed.' raise Unauthorized, 'Delete not allowed.'
else: # /if method_name else:
raise CopyError, MessageDialog( raise CopyError, MessageDialog(
title = 'Not Supported', title = 'Not Supported',
message = ('The object <EM>%s</EM> does not support this ' message = ('The object <em>%s</em> does not support this '
'operation.' % escape(absattr(object.id))), 'operation.' % escape(absattr(object.id))),
action = 'manage_main') action = 'manage_main')
Globals.default__class_init__(CopyContainer) Globals.default__class_init__(CopyContainer)
......
import unittest import unittest
import cStringIO import cStringIO
from mimetools import Message
from multifile import MultiFile
import transaction import transaction
from AccessControl import SecurityManager from AccessControl import SecurityManager
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
from Acquisition import Implicit
from Acquisition import aq_base from Acquisition import aq_base
from Acquisition import Implicit
from OFS.Application import Application from OFS.Application import Application
from OFS.Folder import manage_addFolder from OFS.Folder import manage_addFolder
from OFS.Image import manage_addFile from OFS.Image import manage_addFile
from Testing.makerequest import makerequest from Testing.makerequest import makerequest
from webdav.common import rfc1123_date
ADD_IMAGES_AND_FILES = 'Add images and files' ADD_IMAGES_AND_FILES = 'Add images and files'
...@@ -334,7 +331,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -334,7 +331,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
except CopyError, e: except CopyError, e:
if ce_regex is not None: if ce_regex is not None:
pattern = re.compile( ce_regex, re.DOTALL ) pattern = re.compile( ce_regex, re.DOTALL )
if pattern.search( e ) is None: if pattern.search( e ) is None:
self.fail( "Paste failed; didn't match pattern:\n%s" % e ) self.fail( "Paste failed; didn't match pattern:\n%s" % e )
...@@ -348,7 +345,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -348,7 +345,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
else: else:
self.fail( "Paste allowed unexpectedly." ) self.fail( "Paste allowed unexpectedly." )
def _initPolicyAndUser( self def _initPolicyAndUser( self
, a_lambda=None , a_lambda=None
, v_lambda=None , v_lambda=None
, c_lambda=None , c_lambda=None
...@@ -406,7 +403,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -406,7 +403,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
) )
def test_copy_cant_create_target_metatype_not_supported( self ): def test_copy_cant_create_target_metatype_not_supported( self ):
from OFS.CopySupport import CopyError from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders() folder1, folder2 = self._initFolders()
...@@ -437,7 +434,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -437,7 +434,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
self.failUnless( 'file' in folder2.objectIds() ) self.failUnless( 'file' in folder2.objectIds() )
def test_move_cant_read_source( self ): def test_move_cant_read_source( self ):
from OFS.CopySupport import CopyError from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders() folder1, folder2 = self._initFolders()
...@@ -457,7 +454,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -457,7 +454,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
) )
def test_move_cant_create_target_metatype_not_supported( self ): def test_move_cant_create_target_metatype_not_supported( self ):
from OFS.CopySupport import CopyError from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders() folder1, folder2 = self._initFolders()
...@@ -472,16 +469,16 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -472,16 +469,16 @@ class TestCopySupportSecurity( CopySupportTestBase ):
) )
def test_move_cant_create_target_metatype_not_allowed( self ): def test_move_cant_create_target_metatype_not_allowed( self ):
from OFS.CopySupport import CopyError from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders() folder1, folder2 = self._initFolders()
folder2.all_meta_types = FILE_META_TYPES folder2.all_meta_types = FILE_META_TYPES
def _no_manage_addFile( a, c, n, v, *args, **kw ): def _no_add_images_and_files(permission, object, context):
return n != 'manage_addFile' return permission != ADD_IMAGES_AND_FILES
self._initPolicyAndUser( v_lambda=_no_manage_addFile ) self._initPolicyAndUser( c_lambda=_no_add_images_and_files )
cookie = folder1.manage_cutObjects( ids=( 'file', ) ) cookie = folder1.manage_cutObjects( ids=( 'file', ) )
self._assertCopyErrorUnauth( folder2.manage_pasteObjects self._assertCopyErrorUnauth( folder2.manage_pasteObjects
...@@ -491,7 +488,7 @@ class TestCopySupportSecurity( CopySupportTestBase ): ...@@ -491,7 +488,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
) )
def test_move_cant_delete_source( self ): def test_move_cant_delete_source( self ):
from OFS.CopySupport import CopyError from OFS.CopySupport import CopyError
from AccessControl.Permissions import delete_objects as DeleteObjects from AccessControl.Permissions import delete_objects as DeleteObjects
...@@ -518,8 +515,5 @@ def test_suite(): ...@@ -518,8 +515,5 @@ def test_suite():
suite.addTest( unittest.makeSuite( TestCopySupportSecurity ) ) suite.addTest( unittest.makeSuite( TestCopySupportSecurity ) )
return suite return suite
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__': if __name__ == '__main__':
main() unittest.main(defaultTest='test_suite')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment