[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Security - ZopeSecurityPolicy.py:1.1.2.13.2.5

Casey Duncan casey_duncan@yahoo.com
Tue, 12 Feb 2002 10:34:37 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/Security
In directory cvs.zope.org:/tmp/cvs-serv31197

Modified Files:
      Tag: Zope-3x-security_defactor-branch
	ZopeSecurityPolicy.py 
Log Message:
Additional refactoring of ZopeSecurityPolicy. Conflicting role permissions are now handled correctly (deny always wins). Role computation is now inlined and combined with principal permission checking, this allows principal permissions to be asserted sooner so they Read from remote host cvs.zope.org: Connection reset by peera bit easier to follow.


=== Zope3/lib/python/Zope/App/Security/ZopeSecurityPolicy.py 1.1.2.13.2.4 => 1.1.2.13.2.5 ===
 
     def checkPermission( self, permission, object, context ):
+        # XXX We aren't really handling multiple principals yet
 
         principals = { context.user : 1 }
-        roles      = {}
-        placeful_setting = None
-        all_roles = self._listAllRoles(object, context)
+        assigned_roles = {}
+        roles = {}
+        seen_allow = 0
 
-        # XXX We aren't really handling multiple principals below
+        # Check the placeful principal permissions and aggregate the
+        # Roles in this context
+        for c in ContainmentIterator(object):
+            ppm = getAdapter(c, IPrincipalPermissionManager, None)
+            if ppm is not None: 
+                for principal in principals.keys():
+                    setting = ppm.getSetting(permission, principal)
+                    if setting is Deny:
+                        return 0 # Explicit deny on principal
+                    elif setting is Allow:
+                        return 1 # Explicit allow on principal
+                    
+            prm = getAdapter(c, IPrincipalRoleManager, None)
+            if prm is not None:
+                for principal in principals.keys():
+                    for role, setting in prm.getRolesForPrincipal(principal):
+                        if not roles.has_key(role):
+                            roles[role] = 1
+                            if setting is Assign:
+                                assigned_roles[role] = 1
         
-        # Check the placeful permissions settings first
-        try:
-            for c in ContainmentIterator(object):
-                ppm = getAdapter(c, IPrincipalPermissionManager, None)
-                if ppm is not None: 
-                    for principal in principals.keys():
-                        setting = ppm.getSetting(permission, principal)
-                        if setting is Deny:
-                            return 0 # Explicit deny on principal
-                        elif setting is Allow:
-                            return 1 # Explicit allow on principal
-                        
-                rpm = getAdapter(c, IRolePermissionManager, None)
-                if rpm is not None:
-                    for role in all_roles:
-                        placeful_setting = rpm.getSetting(permission, role)
-                        if placeful_setting and \
-                            placeful_setting is not Unset:
-                            raise 'BreakOut' 
-        except 'BreakOut':
-            pass
-
         # now check the global principal permissions
         getSetting = principalPermissionManager.getSetting
         for principal in principals.keys():
@@ -125,29 +123,40 @@
                 return 1 # Explicit allow on global principal
             elif setting is Deny:
                 return 0 # Explicit deny on global principal
-
-        # See if the placeful role permission checks yielded an answer
-        if placeful_setting is Allow:
-            return 1 # Allow on placeful role
-        elif placeful_setting is Deny:
-            return 0 # deny on placeful role
-
+                                    
+        # aggregate global roles
+        global_roles = principalRoleManager.getRolesForPrincipal(principal)
+        for principal in principals.keys():
+            for role, setting in global_roles:
+                if not roles.has_key(role):
+                    roles[role] = 1
+                    if setting is Assign:
+                        assigned_roles[role] = 1
+                        
+        # Check the placeful role permissions, checking anonymous first
+        for c in ContainmentIterator(object):
+            rpm = getAdapter(c, IRolePermissionManager, None)
+            if rpm is not None:
+                for role in ['Anonymous'] + assigned_roles.keys():
+                    setting = rpm.getSetting(permission, role)
+                    if setting is Allow:
+                        seen_allow = 1 # Flag allow, but continue processing
+                    elif setting is Deny:
+                        return 0 # Deny on placeful role permission
+                if seen_allow:
+                    return 1 # Allow on placeful role permission
+            
         # Last, check if there are any global role settings
-        seen_allowed = 0
         getSetting = rolePermissionManager.getSetting
-        getGlobalRoles = principalRoleManager.getRolesForPrincipal
         for principal in principals.keys():
-            # Get the global roles for this principal always checking
-            # anonymous first
-            all_roles = [('Anonymous', Assign)] + getGlobalRoles(principal)
-            for role, role_setting in all_roles:
+            for role, role_setting in [('Anonymous', Assign)] + global_roles:
                 if role_setting is Assign:
                     setting = getSetting(permission, role)
                     if setting == Allow:
-                        seen_allowed = 1
+                        seen_allow = 1 # Flag allow and continue
                     elif setting == Deny:
                         return 0 # Deny on global role
-            if seen_allowed:
+            if seen_allow:
                 return 1 # Allow on global role
 
         return 0 # Deny by default
@@ -196,39 +205,6 @@
         roles.sort()
 
         return tuple( roles )
-
-    def _listAllRoles( self, object, context ):
-        """
-            Walk the containment hierarchy of object and accumulate the roles 
-            assigned to the current user in the context.
-        """
-        principals = [context.user]
-        roles = {}
-
-        if object is not None:
-            for c in ContainmentIterator(object):
-                prm = getAdapter(c, IPrincipalRoleManager, None)
-                if prm is not None:
-                    for principal in principals:
-                        for role, setting in \
-                                    prm.getRolesForPrincipal(principal):
-                            if not roles.has_key(role):
-                                roles[role] = setting
-        # non-playful (dour) roles
-        prm = principalRoleManager
-        if prm is not None:
-            for principal in principals:
-                for role, setting in \
-                            prm.getRolesForPrincipal(principal):
-                    if not roles.has_key(role):
-                        roles[role] = setting
-
-        result = [('Anonymous',Assign)] # Always check anonymous
-        for role, setting in roles.items():
-            if setting is Assign:
-                result.append(role)
-
-        return result
 
 zopeSecurityPolicy=ZopeSecurityPolicy()