src/pyams_security/utility.py
changeset 2 94e76f8e9828
parent 0 f04e1d0a0723
child 12 f227ffa9e824
--- a/src/pyams_security/utility.py	Sun Feb 22 14:52:32 2015 +0100
+++ b/src/pyams_security/utility.py	Mon Feb 23 17:55:05 2015 +0100
@@ -17,15 +17,17 @@
 
 # import interfaces
 from pyams_security.interfaces import ISecurityManager, ICredentialsPlugin, IAuthenticationPlugin, \
-    IDirectoryPlugin, AuthenticatedPrincipalEvent
+    IDirectoryPlugin, AuthenticatedPrincipalEvent, IProtectedObject
 from pyramid.interfaces import IAuthenticationPolicy
 
 # import packages
 from pyams_security.principal import UnknownPrincipal, MissingPrincipal
 from pyams_utils.registry import query_utility
 from pyams_utils.request import check_request
+from pyams_utils.wsgi import wsgi_environ_cache
 from pyramid.authentication import AuthTktCookieHelper
 from pyramid.decorator import reify
+from pyramid.location import lineage
 from pyramid.security import Everyone, Authenticated
 from zope.container.folder import Folder
 from zope.interface import implementer
@@ -37,6 +39,7 @@
     """Security manager utility"""
 
     enable_social_login = FieldProperty(ISecurityManager['enable_social_login'])
+    social_users_folder = FieldProperty(ISecurityManager['social_users_folder'])
     authomatic_secret = FieldProperty(ISecurityManager['authomatic_secret'])
     social_login_use_popup = FieldProperty(ISecurityManager['social_login_use_popup'])
     open_registration = FieldProperty(ISecurityManager['open_registration'])
@@ -61,9 +64,9 @@
     def __delitem__(self, key):
         super(SecurityManager, self).__delitem__(key)
         if key in self.authentication_plugins_names:
-            del self.authentication_plugins_names[self.authentication_plugins_names.index(key)]
+            self.authentication_plugins_names = tuple(filter(lambda x: x != key, self.authentication_plugins_names))
         if key in self.directory_plugins_names:
-            del self.directory_plugins_names[self.directory_plugins_names.index(key)]
+            self.directory_plugins_names = tuple(filter(lambda x: x != key, self.directory_plugins_names))
 
     def get_plugin(self, name):
         if name in self.credentials_plugins_names:
@@ -115,10 +118,23 @@
             if principal is not None:
                 return principal.id
 
-    def effective_principals(self, principal_id):
+    def effective_principals(self, principal_id, request=None):
         principals = set()
         for plugin in self.get_directory_plugins():
             principals |= set(plugin.get_all_principals(principal_id))
+        if request is None:
+            request = check_request()
+        # add context roles granted to principal
+        context = request.context
+        if context is not None:
+            for parent in lineage(context):
+                protection = IProtectedObject(parent, None)
+                if protection is not None:
+                    for principal_id in principals.copy():
+                        principals |= set(map(lambda x: 'role:{0}'.format(x),
+                                              protection.get_roles(principal_id)))
+                    if not protection.inherit_parent_roles:
+                        break
         return principals
 
     # IDirectoryPlugin interface methods
@@ -134,7 +150,7 @@
     def find_principals(self, query):
         principals = set()
         for plugin in self.get_directory_plugins():
-            principals |= set(plugin.find_principals(query) or set())
+            principals |= set(plugin.find_principals(query))
         return sorted(principals, key=lambda x: x.title)
 
 
@@ -153,7 +169,7 @@
     """
 
     def __init__(self, secret,
-                 credentials=('http', 'session'),
+                 credentials=('http', ),
                  cookie_name='auth_ticket',
                  secure=False,
                  include_ip=False,
@@ -189,6 +205,7 @@
     def _get_security_manager(self, request):
         return query_utility(ISecurityManager)
 
+    @wsgi_environ_cache('pyams_security.unauthenticated_userid')
     def unauthenticated_userid(self, request):
         result = self.cookie.identify(request)
         if result:
@@ -199,6 +216,7 @@
                 if credentials is not None:
                     return credentials.id
 
+    @wsgi_environ_cache('pyams_security.authenticated_userid')
     def authenticated_userid(self, request):
         principal_id = self.unauthenticated_userid(request)
         if principal_id:
@@ -207,10 +225,12 @@
         if manager is not None:
             return manager.authenticated_userid(request)
 
+    @wsgi_environ_cache('pyams_security.effective_principals')
     def effective_principals(self, request):
         principals = {Everyone}
         principal_id = self.unauthenticated_userid(request)
         if principal_id:
+            # get authenticated user principals
             principals.add(Authenticated)
             principals.add(principal_id)
             manager = self._get_security_manager(request)