Changeset - bd8b25ad058d
[Not reviewed]
default
0 1 0
Marcin Kuzminski - 15 years ago 2010-07-31 18:47:43
marcin@python-works.com
Fixed decorators bug when using them with keyworded arguments,new implementation takes new approach that is more flexible
1 file changed with 33 insertions and 42 deletions:
0 comments (0 inline, 0 general)
pylons_app/lib/auth.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# authentication and permission libraries
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 

	
 
#
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
@@ -14,28 +14,28 @@
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 4, 2010
 

	
 
@author: marcink
 
"""
 
from beaker.cache import cache_region
 
from functools import wraps
 
from pylons import config, session, url, request
 
from pylons.controllers.util import abort, redirect
 
from pylons_app.lib.utils import get_repo_slug
 
from pylons_app.model import meta
 
from pylons_app.model.db import User, Repo2Perm, Repository, Permission
 
from sqlalchemy.exc import OperationalError
 
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 
import crypt
 
from decorator import decorator
 
import logging
 
"""
 
Created on April 4, 2010
 

	
 
@author: marcink
 
"""
 

	
 
log = logging.getLogger(__name__) 
 

	
 
def get_crypt_password(password):
 
    """
 
    Cryptographic function used for password hashing
 
@@ -143,13 +143,13 @@ def fill_perms(user):
 
        #admin have all rights full
 
        for perm in default_perms:
 
            p = 'repository.admin'
 
            user.permissions['repositories'][perm.Repo2Perm.repository.repo_name] = p
 
    
 
    else:
 
        user.permissions['global'].add('')
 
        user.permissions['global'].add('repository.create')
 
        for perm in default_perms:
 
            if perm.Repository.private:
 
                #disable defaults for private repos,
 
                p = 'repository.none'
 
            elif perm.Repository.user_id == user.user_id:
 
                #set admin if owner
 
@@ -189,94 +189,91 @@ def get_user(session):
 
    return user
 
        
 
#===============================================================================
 
# CHECK DECORATORS
 
#===============================================================================
 
class LoginRequired(object):
 
    """
 
    Must be logged in to execute this function else redirect to login page
 
    """
 
    """Must be logged in to execute this function else redirect to login page"""
 
   
 
    def __call__(self, func):
 
        @wraps(func)
 
        def _wrapper(*fargs, **fkwargs):
 
        return decorator(self.__wrapper, func)
 
    
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
            user = session.get('hg_app_user', AuthUser())
 
            log.debug('Checking login required for user:%s', user.username)
 
            if user.is_authenticated:
 
                log.debug('user %s is authenticated', user.username)
 
                func(*fargs)
 
            return func(*fargs, **fkwargs)
 
            else:
 
                log.warn('user %s not authenticated', user.username)
 
                log.debug('redirecting to login page')
 
                return redirect(url('login_home'))
 

	
 
        return _wrapper
 

	
 
class PermsDecorator(object):
 
    """
 
    Base class for decorators
 
    """
 
    """Base class for decorators"""
 
    
 
    def __init__(self, *required_perms):
 
        available_perms = config['available_permissions']
 
        for perm in required_perms:
 
            if perm not in available_perms:
 
                raise Exception("'%s' permission is not defined" % perm)
 
        self.required_perms = set(required_perms)
 
        self.user_perms = None
 
        
 
    def __call__(self, func):
 
        @wraps(func)
 
        def _wrapper(*fargs, **fkwargs):
 
        return decorator(self.__wrapper, func)
 
    
 
    
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
#        _wrapper.__name__ = func.__name__
 
#        _wrapper.__dict__.update(func.__dict__)
 
#        _wrapper.__doc__ = func.__doc__
 

	
 
            self.user_perms = session.get('hg_app_user', AuthUser()).permissions
 
            log.debug('checking %s permissions %s for %s',
 
               self.__class__.__name__, self.required_perms, func.__name__)
 
            
 
            if self.check_permissions():
 
                log.debug('Permission granted for %s', func.__name__)
 
                return func(*fargs)
 
            
 
            return func(*fargs, **fkwargs)
 
            
 
            else:
 
                log.warning('Permission denied for %s', func.__name__)
 
                #redirect with forbidden ret code
 
                return abort(403)
 
        return _wrapper
 

	
 
        
 
        
 
    def check_permissions(self):
 
        """
 
        Dummy function for overriding
 
        """
 
        """Dummy function for overriding"""
 
        raise Exception('You have to write this function in child class')
 

	
 
class HasPermissionAllDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for all given predicates. All of them have to
 
    be meet in order to fulfill the request
 
    """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.get('global')):
 
            return True
 
        return False
 
            
 

	
 
class HasPermissionAnyDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for any of given predicates. In order to 
 
    """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.get('global')):
 
            return True
 
        return False
 

	
 
class HasRepoPermissionAllDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for all given predicates for specific 
 
    """Checks for access permission for all given predicates for specific 
 
    repository. All of them have to be meet in order to fulfill the request
 
    """
 
            
 
    def check_permissions(self):
 
        repo_name = get_repo_slug(request)
 
        try:
 
@@ -286,14 +283,13 @@ class HasRepoPermissionAllDecorator(Perm
 
        if self.required_perms.issubset(user_perms):
 
            return True
 
        return False
 
            
 

	
 
class HasRepoPermissionAnyDecorator(PermsDecorator):
 
    """
 
    Checks for access permission for any of given predicates for specific 
 
    """Checks for access permission for any of given predicates for specific 
 
    repository. In order to fulfill the request any of predicates must be meet
 
    """
 
            
 
    def check_permissions(self):
 
        repo_name = get_repo_slug(request)
 
        
 
@@ -306,15 +302,13 @@ class HasRepoPermissionAnyDecorator(Perm
 
        return False
 
#===============================================================================
 
# CHECK FUNCTIONS
 
#===============================================================================
 

	
 
class PermsFunction(object):
 
    """
 
    Base function for other check functions
 
    """
 
    """Base function for other check functions"""
 
    
 
    def __init__(self, *perms):
 
        available_perms = config['available_permissions']
 
        
 
        for perm in perms:
 
            if perm not in available_perms:
 
@@ -340,15 +334,13 @@ class PermsFunction(object):
 
        else:
 
            log.warning('Permission denied for %s @%s', self.granted_for,
 
                        check_Location)
 
            return False 
 
    
 
    def check_permissions(self):
 
        """
 
        Dummy function for overriding
 
        """
 
        """Dummy function for overriding"""
 
        raise Exception('You have to write this function in child class')
 
        
 
class HasPermissionAll(PermsFunction):
 
    def check_permissions(self):
 
        if self.required_perms.issubset(self.user_perms.get('global')):
 
            return True
 
@@ -379,13 +371,12 @@ class HasRepoPermissionAll(PermsFunction
 
        if self.required_perms.issubset(self.user_perms):
 
            return True
 
        return False
 
            
 
class HasRepoPermissionAny(PermsFunction):
 
    
 
    
 
    def __call__(self, repo_name=None, check_Location=''):
 
        self.repo_name = repo_name
 
        return super(HasRepoPermissionAny, self).__call__(check_Location)
 
        
 
    def check_permissions(self):
 
        if not self.repo_name:
0 comments (0 inline, 0 general)