From 2c29335528503f581ecdef4ae865384f892fcd08 Mon Sep 17 00:00:00 2001
From: Jean-Paul Smets <jp@nexedi.com>
Date: Sun, 30 Oct 2005 16:48:24 +0000
Subject: [PATCH] Added PAS patch

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4174 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/ZopePatch.py | 180 ++++++++++++++++++++++++++++++++++
 1 file changed, 180 insertions(+)

diff --git a/product/ERP5Type/ZopePatch.py b/product/ERP5Type/ZopePatch.py
index b7f0435094..ddd33385e6 100755
--- a/product/ERP5Type/ZopePatch.py
+++ b/product/ERP5Type/ZopePatch.py
@@ -1978,3 +1978,183 @@ try:
     AttrDict.has_key = AttrDict_has_key
 except ImportError:
     pass
+
+    
+############################################################################
+# Locale roles acquisition patch for PAS
+
+from Acquisition import aq_inner, aq_parent
+
+try:
+  from PluggableAuthService.PropertiedUser import PropertiedUser
+except ImportError:
+  PropertiedUser = None
+  
+def getRolesInContext( self, object ):
+
+    """ Return the list of roles assigned to the user.
+
+    o Include local roles assigned in context of the passed-in object.
+
+    o Include *both* local roles assigned directly to us *and* those
+      assigned to our groups.
+
+    o Ripped off from AccessControl.User.BasicUser, which provides
+      no other extension mechanism. :(
+    """
+    user_id = self.getId()
+    # [ x.getId() for x in self.getGroups() ]
+    group_ids = self.getGroups()
+
+    principal_ids = list( group_ids )
+    principal_ids.insert( 0, user_id )
+
+    local ={} 
+    object = aq_inner( object )
+
+    while 1:
+
+        local_roles = getattr( object, '__ac_local_roles__', None )
+
+        if local_roles:
+
+            if callable( local_roles ):
+                local_roles = local_roles()
+
+            dict = local_roles or {}
+
+            for principal_id in principal_ids:
+                for role in dict.get( principal_id, [] ):
+                    local[ role ] = 1
+                    
+        # patch by Klaus for LocalRole blocking
+        if hasattr(object, '_getAcquireLocalRoles'):
+            if not object._getAcquireLocalRoles():
+                break
+
+        inner = aq_inner( object )
+        parent = aq_parent( inner )
+
+        if parent is not None:
+            object = parent
+            continue
+
+        new = getattr( object, 'im_self', None )
+
+        if new is not None:
+
+            object = aq_inner( new )
+            continue
+
+        break
+    
+    return list( self.getRoles() ) + local.keys()
+
+def allowed( self, object, object_roles=None ):
+
+    """ Check whether the user has access to object.
+
+    o The user must have one of the roles in object_roles to allow access.
+
+    o Include *both* local roles assigned directly to us *and* those
+      assigned to our groups.
+
+    o Ripped off from AccessControl.User.BasicUser, which provides
+      no other extension mechanism. :(
+    """
+    if object_roles is _what_not_even_god_should_do:
+        return 0
+
+    # Short-circuit the common case of anonymous access.
+    if object_roles is None or 'Anonymous' in object_roles:
+        return 1
+
+    # Provide short-cut access if object is protected by 'Authenticated'
+    # role and user is not nobody
+    if 'Authenticated' in object_roles and (
+        self.getUserName() != 'Anonymous User'):
+        return 1
+
+    # Check for ancient role data up front, convert if found.
+    # This should almost never happen, and should probably be
+    # deprecated at some point.
+    if 'Shared' in object_roles:
+        object_roles = self._shared_roles(object)
+        if object_roles is None or 'Anonymous' in object_roles:
+            return 1
+
+    # Check for a role match with the normal roles given to
+    # the user, then with local roles only if necessary. We
+    # want to avoid as much overhead as possible.
+    user_roles = self.getRoles()
+    for role in object_roles:
+        if role in user_roles:
+            if self._check_context(object):
+                return 1
+            return None
+
+    # Still have not found a match, so check local roles. We do
+    # this manually rather than call getRolesInContext so that
+    # we can incur only the overhead required to find a match.
+    inner_obj = aq_inner( object )
+    user_id = self.getId()
+    # [ x.getId() for x in self.getGroups() ]
+    group_ids = self.getGroups()
+
+    principal_ids = list( group_ids )
+    principal_ids.insert( 0, user_id )
+
+    while 1:
+
+        local_roles = getattr( inner_obj, '__ac_local_roles__', None )
+
+        if local_roles:
+
+            if callable( local_roles ):
+                local_roles = local_roles()
+
+            dict = local_roles or {}
+
+            for principal_id in principal_ids:
+
+                local_roles = dict.get( principal_id, [] )
+
+                for role in object_roles:
+
+                    if role in local_roles:
+
+                        if self._check_context( object ):
+                            return 1
+
+                        return 0
+                    
+        # patch by Klaus for LocalRole blocking
+        if hasattr(object, '_getAcquireLocalRoles'):
+            if not object._getAcquireLocalRoles():
+                break
+
+        inner = aq_inner( inner_obj )
+        parent = aq_parent( inner )
+
+        if parent is not None:
+            inner_obj = parent
+            continue
+
+        new = getattr( inner_obj, 'im_self', None )
+
+        if new is not None:
+            inner_obj = aq_inner( new )
+            continue
+
+        break
+
+    return None
+
+if PropertiedUser is not None:
+  PropertiedUser.getRolesInContext = getRolesInContext
+  PropertiedUser.allowed = allowed
+  
+
+
+    
+    
\ No newline at end of file
-- 
2.30.9