Commit c00164c0 authored by 's avatar

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

parent 665b04c9
......@@ -26,6 +26,11 @@ Zope Changes
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
AccessControl.ZopeSecurityPolicy.checkPermission
with 'validate', checking ownership and proxy roles if an
......
......@@ -19,6 +19,7 @@ import re, sys, tempfile
from cgi import escape
from marshal import loads, dumps
from urllib import quote, unquote
from warnings import warn
from zlib import compress, decompress
import Globals, Moniker, ExtensionClass
......@@ -352,7 +353,7 @@ class CopyContainer(ExtensionClass.Base):
if not hasattr(object, 'meta_type'):
raise CopyError, MessageDialog(
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))),
action = 'manage_main')
......@@ -372,35 +373,49 @@ class CopyContainer(ExtensionClass.Base):
mt_permission = d.get('permission')
break
if method_name:
try:
method = self.restrictedTraverse(method_name)
# method_name is e.g.
# "manage_addProduct/PageTemplates/manage_addPageTemplateForm".
# restrictedTraverse will raise Unauthorized if it
# can't obtain the factory method by name due to a
# security restriction. We depend on this side effect
# here! Note that we use restrictedTraverse as
# opposed to checkPermission to take into account the
# special security circumstances related to proxy
# roles. See collector #78.
except Unauthorized:
if mt_permission:
if mt_permission is not None:
sm = getSecurityManager()
if sm.checkPermission(mt_permission, self):
if validate_src:
# Ensure the user is allowed to access the object on the
# clipboard.
try:
parent = aq_parent(aq_inner(object))
except:
parent = None
if not sm.validate(None, parent, None, object):
raise Unauthorized(absattr(object.id))
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 '
'context of the container into which you are '
'pasting, thus you are not able to perform '
'this operation.' % mt_permission)
else:
'this operation.' % mt_permission),
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 '
'to call %s in the context of the container '
'into which you are pasting, thus you are not '
'able to perform this operation.' % method_name)
raise CopyError, MessageDialog(
title = 'Insufficient Privileges',
message = message,
action = 'manage_main')
'able to perform this operation.'
% method_name),
action = 'manage_main')
if validate_src:
......@@ -420,12 +435,12 @@ class CopyContainer(ExtensionClass.Base):
if not sm.checkPermission(DeleteObjects, parent):
raise Unauthorized, 'Delete not allowed.'
else: # /if method_name
else:
raise CopyError, MessageDialog(
title = 'Not Supported',
message = ('The object <EM>%s</EM> does not support this '
'operation.' % escape(absattr(object.id))),
action = 'manage_main')
title = 'Not Supported',
message = ('The object <em>%s</em> does not support this '
'operation.' % escape(absattr(object.id))),
action = 'manage_main')
Globals.default__class_init__(CopyContainer)
......
import unittest
import cStringIO
from mimetools import Message
from multifile import MultiFile
import transaction
from AccessControl import SecurityManager
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
from Acquisition import Implicit
from Acquisition import aq_base
from Acquisition import Implicit
from OFS.Application import Application
from OFS.Folder import manage_addFolder
from OFS.Image import manage_addFile
from Testing.makerequest import makerequest
from webdav.common import rfc1123_date
ADD_IMAGES_AND_FILES = 'Add images and files'
......@@ -334,7 +331,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
except CopyError, e:
if ce_regex is not None:
pattern = re.compile( ce_regex, re.DOTALL )
if pattern.search( e ) is None:
self.fail( "Paste failed; didn't match pattern:\n%s" % e )
......@@ -348,7 +345,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
else:
self.fail( "Paste allowed unexpectedly." )
def _initPolicyAndUser( self
def _initPolicyAndUser( self
, a_lambda=None
, v_lambda=None
, c_lambda=None
......@@ -406,7 +403,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
)
def test_copy_cant_create_target_metatype_not_supported( self ):
from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders()
......@@ -437,7 +434,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
self.failUnless( 'file' in folder2.objectIds() )
def test_move_cant_read_source( self ):
from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders()
......@@ -457,7 +454,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
)
def test_move_cant_create_target_metatype_not_supported( self ):
from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders()
......@@ -472,16 +469,16 @@ class TestCopySupportSecurity( CopySupportTestBase ):
)
def test_move_cant_create_target_metatype_not_allowed( self ):
from OFS.CopySupport import CopyError
folder1, folder2 = self._initFolders()
folder2.all_meta_types = FILE_META_TYPES
def _no_manage_addFile( a, c, n, v, *args, **kw ):
return n != 'manage_addFile'
def _no_add_images_and_files(permission, object, context):
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', ) )
self._assertCopyErrorUnauth( folder2.manage_pasteObjects
......@@ -491,7 +488,7 @@ class TestCopySupportSecurity( CopySupportTestBase ):
)
def test_move_cant_delete_source( self ):
from OFS.CopySupport import CopyError
from AccessControl.Permissions import delete_objects as DeleteObjects
......@@ -518,8 +515,5 @@ def test_suite():
suite.addTest( unittest.makeSuite( TestCopySupportSecurity ) )
return suite
def main():
unittest.TextTestRunner().run(test_suite())
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