From 038dcbaea40ee6e4526946115cc4c8c9bfb43c2f Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 18 Mar 2013 20:53:14 -0700 Subject: add failing test for callable acl --- pyramid/tests/test_authorization.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyramid/tests/test_authorization.py b/pyramid/tests/test_authorization.py index 27f2a18b4..60b1b0c8d 100644 --- a/pyramid/tests/test_authorization.py +++ b/pyramid/tests/test_authorization.py @@ -215,6 +215,15 @@ class TestACLAuthorizationPolicy(unittest.TestCase): result = sorted( policy.principals_allowed_by_permission(context, 'read')) self.assertEqual(result, []) + + def test_callable_acl(self): + from pyramid.security import Allow + context = DummyContext() + fn = lambda self: [(Allow, 'bob', 'read')] + context.__acl__ = fn.__get__(context, context.__class__) + policy = self._makeOne() + result = policy.permits(context, ['bob'], 'read') + self.assertTrue(result) class DummyContext: -- cgit v1.2.3 From 2d931400b22f4c5764df68c2799be512e60a2de1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 18 Mar 2013 21:00:50 -0700 Subject: support acl as a callable --- CHANGES.txt | 13 +++++++++++++ docs/narr/security.rst | 21 +++++++++++++++++++++ pyramid/authorization.py | 3 +++ 3 files changed, 37 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 85dd3be2a..ae2cafba4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,16 @@ +next release +============ + +Features +-------- + +- ``ACLAuthorizationPolicy`` supports ``__acl__`` as a callable. This + removes the ambiguity between the potential ``AttributeError`` that would + be raised on the ``context`` when the property was not defined and the + ``AttributeError`` that could be raised from any user-defined code within + a dynamic property. It is recommended to define a dynamic ACL as a callable + to avoid this ambiguity. See https://github.com/Pylons/pyramid/issues/735. + 1.4 (2012-12-18) ================ diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 5b79edd19..36c888559 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -270,6 +270,27 @@ resource instances with an ACL (as opposed to just decorating their class) in applications such as "CMS" systems where fine-grained access is required on an object-by-object basis. +Dynamic ACLs are also possible by turning the ACL into a callable on the +resource. This may allow the ACL to dynamically generate rules based on +properties of the instance. + +.. code-block:: python + :linenos: + + from pyramid.security import Allow + from pyramid.security import Everyone + + class Blog(object): + def __acl__(self): + return [ + (Allow, Everyone, 'view'), + (Allow, self.owner, 'edit'), + (Allow, 'group:editors', 'edit'), + ] + + def __init__(self, owner): + self.owner = owner + .. index:: single: ACE single: access control entry diff --git a/pyramid/authorization.py b/pyramid/authorization.py index 943f8bd00..1fd05e244 100644 --- a/pyramid/authorization.py +++ b/pyramid/authorization.py @@ -80,6 +80,9 @@ class ACLAuthorizationPolicy(object): except AttributeError: continue + if acl and callable(acl): + acl = acl() + for ace in acl: ace_action, ace_principal, ace_permissions = ace if ace_principal in principals: -- cgit v1.2.3 From 81e84fe86bee0c2753674fdaead001803936a2ba Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 18 Mar 2013 21:53:35 -0700 Subject: reorder some imports to be alphabetical --- docs/narr/security.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 36c888559..203aa2404 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -234,8 +234,8 @@ class: .. code-block:: python :linenos: - from pyramid.security import Everyone from pyramid.security import Allow + from pyramid.security import Everyone class Blog(object): __acl__ = [ @@ -250,8 +250,8 @@ Or, if your resources are persistent, an ACL might be specified via the .. code-block:: python :linenos: - from pyramid.security import Everyone from pyramid.security import Allow + from pyramid.security import Everyone class Blog(object): pass @@ -303,8 +303,8 @@ Here's an example ACL: .. code-block:: python :linenos: - from pyramid.security import Everyone from pyramid.security import Allow + from pyramid.security import Everyone __acl__ = [ (Allow, Everyone, 'view'), @@ -342,9 +342,9 @@ order dictated by the ACL*. So if you have an ACL like this: .. code-block:: python :linenos: - from pyramid.security import Everyone from pyramid.security import Allow from pyramid.security import Deny + from pyramid.security import Everyone __acl__ = [ (Allow, Everyone, 'view'), @@ -380,8 +380,8 @@ ACE, as below. .. code-block:: python :linenos: - from pyramid.security import Everyone from pyramid.security import Allow + from pyramid.security import Everyone __acl__ = [ (Allow, Everyone, 'view'), -- cgit v1.2.3