From 3ebdd456ecb2da99a8b8f0dbb93ba1933cc89266 Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Mon, 27 May 2019 08:14:15 +0200 Subject: [PATCH] Implement the suggestion of @davisagli. --- src/Products/Five/browser/metaconfigure.py | 28 +++++++++++++++---- src/Products/Five/browser/tests/test_pages.py | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/Products/Five/browser/metaconfigure.py b/src/Products/Five/browser/metaconfigure.py index ad9b13a129..4d0f090129 100644 --- a/src/Products/Five/browser/metaconfigure.py +++ b/src/Products/Five/browser/metaconfigure.py @@ -25,6 +25,7 @@ import zope.browserpage.metaconfigure import zope.browserpage.simpleviewclass import zope.publisher.browser +from AccessControl import ClassSecurityInfo from AccessControl.class_init import InitializeClass from AccessControl.security import CheckerPrivateId from AccessControl.security import getSecurityInfo @@ -459,6 +460,27 @@ def __call__(self): return getattr(self, attr) +class DeferredAttrAuthProxy(object): + """Proxy to defer the authorization from traversal to object access.""" + + security = ClassSecurityInfo() + + def __init__(self, context, name): + self.context = context + self.name = name + + @security.public + def __call__(self, *args, **kw): + try: + attr = guarded_getattr(self.context, self.name) + except (AttributeError, Unauthorized): + raise NotFound(self.context, self.name) + return attr(*args, **kw) + + +InitializeClass(DeferredAttrAuthProxy) + + @zope.interface.implementer(IPublishTraverse) @zope.component.adapter(simple, IBrowserRequest) class SimplePublishTraverse(object): @@ -469,11 +491,7 @@ def __init__(self, context, request): self.request = request def publishTraverse(self, request, name): - try: - return guarded_getattr(self.context, name) - except Unauthorized: - # attribute exists but is not published, so hide it from access: - raise AttributeError(name) + return DeferredAttrAuthProxy(self.context, name) class ViewMixinForTemplates(zope.browserpage.simpleviewclass.simple): diff --git a/src/Products/Five/browser/tests/test_pages.py b/src/Products/Five/browser/tests/test_pages.py index 64c3938d60..74e7153334 100644 --- a/src/Products/Five/browser/tests/test_pages.py +++ b/src/Products/Five/browser/tests/test_pages.py @@ -110,7 +110,7 @@ def test_publishTraverse_to_allowed_name(self): self.browser.open( 'http://localhost/test_folder_1_/testoid/eagle.method/eagle') - self.assertEqual('The eagle has landed', browser.contents) + self.assertEqual('The eagle has landed', self.browser.contents) def test_publishTraverse_to_not_allowed_name(self): # The ``eagle.method`` view has a method ``mouse`` but it is not