diff pylons_app/lib/auth.py @ 239:b18f89d6d17f

Adde draft for permissions systems, made all needed decorators, and checks. For future usage in the system.
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 30 May 2010 19:49:40 +0200
parents a0116e944da1
children 3782a6d698af
line wrap: on
line diff
--- a/pylons_app/lib/auth.py	Sun May 30 17:55:56 2010 +0200
+++ b/pylons_app/lib/auth.py	Sun May 30 19:49:40 2010 +0200
@@ -1,5 +1,5 @@
 from functools import wraps
-from pylons import session, url
+from pylons import session, url, app_globals as g
 from pylons.controllers.util import abort, redirect
 from pylons_app.model import meta
 from pylons_app.model.db import User
@@ -47,7 +47,26 @@
     
     def __init__(self):
         pass
-    
+
+
+
+def set_available_permissions(config):
+    """
+    This function will propagate pylons globals with all available defined
+    permission given in db. We don't wannt to check each time from db for new 
+    permissions since adding a new permission also requires application restart
+    ie. to decorate new views with the newly created permission
+    @param config:
+    """
+    from pylons_app.model.meta import Session
+    from pylons_app.model.db import Permission
+    logging.info('getting information about all available permissions')
+    sa = Session()
+    all_perms = sa.query(Permission).all()
+    config['pylons.app_globals'].available_permissions = [x.permission_name for x in all_perms]
+
+
+        
 #===============================================================================
 # DECORATORS
 #===============================================================================
@@ -73,3 +92,62 @@
                 return redirect(url('login_home'))
 
         return _wrapper
+
+class PermsDecorator(object):
+    
+    def __init__(self, *perms):
+        available_perms = g.available_permissions
+        for perm in perms:
+            if perm not in available_perms:
+                raise Exception("'%s' permission in not defined" % perm)
+        self.required_perms = set(perms)
+        self.user_perms = set([])#propagate this list from somewhere.
+        
+    def __call__(self, func):        
+        @wraps(func)
+        def _wrapper(*args, **kwargs):
+            logging.info('checking %s permissions %s for %s',
+               self.__class__.__name__[-3:], self.required_perms, func.__name__)            
+            
+            if self.check_permissions():
+                logging.info('Permission granted for %s', func.__name__)
+                return func(*args, **kwargs)
+            
+            else:
+                logging.warning('Permission denied for %s', func.__name__)
+                #redirect with forbidden ret code
+                return redirect(url('access_denied'), 403) 
+        return _wrapper
+        
+        
+    def check_permissions(self):
+        """
+        Dummy function for overiding
+        """
+        raise Exception('You have to write this function in child class')
+
+class CheckPermissionAll(PermsDecorator):
+    """
+    Checks for access permission for all given predicates. All of them have to
+    be meet in order to fulfill the request
+    """
+        
+    def check_permissions(self):
+        if self.required_perms.issubset(self.user_perms):
+            return True
+        return False
+            
+
+class CheckPermissionAny(PermsDecorator):
+    """
+    Checks for access permission for any of given predicates. In order to 
+    fulfill the request any of predicates must be meet
+    """
+    
+    def check_permissions(self):
+        if self.required_perms.intersection(self.user_perms):
+            return True
+        return False
+
+
+