changeset 1117:6eb5bb24a948 beta

Major rewrite of auth objects. Moved parts of filling user data into user model. Rewrote AuthUser adding access by api key.
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 09 Mar 2011 16:34:29 +0100
parents 716911af91e1
children b0e2c949c34b
files rhodecode/controllers/admin/users.py rhodecode/controllers/admin/users_groups.py rhodecode/controllers/journal.py rhodecode/controllers/login.py rhodecode/lib/auth.py rhodecode/lib/base.py rhodecode/model/user.py
diffstat 7 files changed, 253 insertions(+), 206 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/admin/users.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/controllers/admin/users.py	Wed Mar 09 16:34:29 2011 +0100
@@ -36,8 +36,7 @@
 
 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
 from rhodecode.lib import helpers as h
-from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
-    fill_perms
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 from rhodecode.lib.base import BaseController, render
 
 from rhodecode.model.db import User
@@ -157,14 +156,15 @@
     def edit(self, id, format='html'):
         """GET /users/id/edit: Form to edit an existing item"""
         # url('edit_user', id=ID)
-        c.user = self.sa.query(User).get(id)
+        user_model = UserModel()
+        c.user = user_model.get(id)
         if not c.user:
             return redirect(url('users'))
         if c.user.username == 'default':
             h.flash(_("You can't edit this user"), category='warning')
             return redirect(url('users'))
         c.user.permissions = {}
-        c.granted_permissions = fill_perms(c.user).permissions['global']
+        c.granted_permissions = user_model.fill_perms(c.user).permissions['global']
 
         defaults = c.user.get_dict()
 
--- a/rhodecode/controllers/admin/users_groups.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/controllers/admin/users_groups.py	Wed Mar 09 16:34:29 2011 +0100
@@ -36,8 +36,7 @@
 
 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
 from rhodecode.lib import helpers as h
-from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
-    fill_perms
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 from rhodecode.lib.base import BaseController, render
 
 from rhodecode.model.db import User, UsersGroup
--- a/rhodecode/controllers/journal.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/controllers/journal.py	Wed Mar 09 16:34:29 2011 +0100
@@ -49,6 +49,7 @@
     @LoginRequired()
     def __before__(self):
         super(JournalController, self).__before__()
+        c.rhodecode_user = self.rhodecode_user
         self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
         self.language = 'en-us'
         self.ttl = "5"
@@ -60,7 +61,7 @@
         p = int(request.params.get('page', 1))
 
         c.following = self.sa.query(UserFollowing)\
-            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
             .options(joinedload(UserFollowing.follows_repository))\
             .all()
 
@@ -126,7 +127,7 @@
             if user_id:
                 try:
                     self.scm_model.toggle_following_user(user_id,
-                                                    c.rhodecode_user.user_id)
+                                                    self.rhodecode_user.user_id)
                     return 'ok'
                 except:
                     raise HTTPInternalServerError()
@@ -135,7 +136,7 @@
             if repo_id:
                 try:
                     self.scm_model.toggle_following_repo(repo_id,
-                                                    c.rhodecode_user.user_id)
+                                                    self.rhodecode_user.user_id)
                     return 'ok'
                 except:
                     raise HTTPInternalServerError()
@@ -152,7 +153,7 @@
         p = int(request.params.get('page', 1))
 
         c.following = self.sa.query(UserFollowing)\
-            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
             .options(joinedload(UserFollowing.follows_repository))\
             .all()
 
@@ -174,7 +175,7 @@
         Produce an atom-1.0 feed via feedgenerator module
         """
         c.following = self.sa.query(UserFollowing)\
-            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
             .options(joinedload(UserFollowing.follows_repository))\
             .all()
 
@@ -207,7 +208,7 @@
         Produce an rss2 feed via feedgenerator module
         """
         c.following = self.sa.query(UserFollowing)\
-            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
+            .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
             .options(joinedload(UserFollowing.follows_repository))\
             .all()
 
--- a/rhodecode/controllers/login.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/controllers/login.py	Wed Mar 09 16:34:29 2011 +0100
@@ -62,19 +62,17 @@
             login_form = LoginForm()
             try:
                 c.form_result = login_form.to_python(dict(request.POST))
+                #form checks for username/password, now we're authenticated
                 username = c.form_result['username']
-                user = UserModel().get_by_username(username, case_insensitive=True)
-                auth_user = AuthUser()
-                auth_user.username = user.username
-                auth_user.is_authenticated = True
-                auth_user.is_admin = user.admin
-                auth_user.user_id = user.user_id
-                auth_user.name = user.name
-                auth_user.lastname = user.lastname
+                user = UserModel().get_by_username(username,
+                                                   case_insensitive=True)
+                auth_user = AuthUser(user.user_id)
+                auth_user.set_authenticated()
                 session['rhodecode_user'] = auth_user
                 session.save()
-                log.info('user %s is now authenticated', username)
 
+                log.info('user %s is now authenticated and stored in session',
+                         username)
                 user.update_lastlogin()
 
                 if c.came_from:
@@ -146,7 +144,7 @@
         return render('/password_reset.html')
 
     def logout(self):
-        session['rhodecode_user'] = AuthUser()
+        del session['rhodecode_user']
         session.save()
         log.info('Logging out and setting user as Empty')
         redirect(url('home'))
--- a/rhodecode/lib/auth.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/lib/auth.py	Wed Mar 09 16:34:29 2011 +0100
@@ -42,19 +42,11 @@
 
 from rhodecode.model import meta
 from rhodecode.model.user import UserModel
-from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
-    UserToPerm, UsersGroupToPerm, UsersGroupMember
+from rhodecode.model.db import Permission
 
 
 log = logging.getLogger(__name__)
 
-
-PERM_WEIGHTS = {'repository.none':0,
-                'repository.read':1,
-                'repository.write':3,
-                'repository.admin':3}
-
-
 class PasswordGenerator(object):
     """This is a simple class for generating password from
         different sets of characters
@@ -185,21 +177,66 @@
     return False
 
 class  AuthUser(object):
-    """A simple object that handles a mercurial username for authentication
+    """
+    A simple object that handles all attributes of user in RhodeCode
+    
+    It does lookup based on API key,given user, or user present in session
+    Then it fills all required information for such user. It also checks if 
+    anonymous access is enabled and if so, it returns default user as logged
+    in
     """
 
-    def __init__(self):
+    def __init__(self, user_id=None, api_key=None):
+
+        self.user_id = user_id
+        self.api_key = api_key
+
         self.username = 'None'
         self.name = ''
         self.lastname = ''
         self.email = ''
-        self.user_id = None
         self.is_authenticated = False
-        self.is_admin = False
+        self.admin = False
         self.permissions = {}
+        self.propagate_data()
+
+
+    def propagate_data(self):
+        user_model = UserModel()
+        if self.api_key:
+            #try go get user by api key
+            log.debug('Auth User lookup by API KEY %s', self.api_key)
+            user_model.fill_data(self, api_key=self.api_key)
+        else:
+            log.debug('Auth User lookup by USER ID %s', self.user_id)
+            self.anonymous_user = user_model.get_by_username('default', cache=True)
+
+            if self.user_id is not None and self.user_id != self.anonymous_user.user_id:
+                user_model.fill_data(self, user_id=self.user_id)
+            else:
+                if self.anonymous_user.active is True:
+                    user_model.fill_data(self, user_id=self.anonymous_user.user_id)
+                    #then we set this user is logged in
+                    self.is_authenticated = True
+                else:
+                    self.is_authenticated = False
+
+        log.debug('Auth User is now %s', self)
+        user_model.fill_perms(self)
+
+    @property
+    def is_admin(self):
+        return self.admin
 
     def __repr__(self):
-        return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
+        return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
+                                              self.is_authenticated)
+
+    def set_authenticated(self, authenticated=True):
+
+        if self.user_id != self.anonymous_user.user_id:
+            self.is_authenticated = authenticated
+
 
 def set_available_permissions(config):
     """This function will propagate pylons globals with all available defined
@@ -221,144 +258,42 @@
 
     config['available_permissions'] = [x.permission_name for x in all_perms]
 
-def fill_perms(user):
-    """Fills user permission attribute with permissions taken from database
-    works for permissions given for repositories, and for permissions that
-    as part of beeing group member
-    
-    :param user: user instance to fill his perms
-    """
-
-    sa = meta.Session()
-    user.permissions['repositories'] = {}
-    user.permissions['global'] = set()
-
-    #===========================================================================
-    # fetch default permissions
-    #===========================================================================
-    default_user = UserModel().get_by_username('default', cache=True)
-
-    default_perms = sa.query(RepoToPerm, Repository, Permission)\
-        .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
-        .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
-        .filter(RepoToPerm.user == default_user).all()
-
-    if user.is_admin:
-        #=======================================================================
-        # #admin have all default rights set to admin        
-        #=======================================================================
-        user.permissions['global'].add('hg.admin')
-
-        for perm in default_perms:
-            p = 'repository.admin'
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
-
-    else:
-        #=======================================================================
-        # set default permissions
-        #=======================================================================
-
-        #default global
-        default_global_perms = sa.query(UserToPerm)\
-            .filter(UserToPerm.user == sa.query(User)\
-                   .filter(User.username == 'default').one())
-
-        for perm in default_global_perms:
-            user.permissions['global'].add(perm.permission.permission_name)
-
-        #default for repositories
-        for perm in default_perms:
-            if perm.Repository.private and not perm.Repository.user_id == user.user_id:
-                #disable defaults for private repos,
-                p = 'repository.none'
-            elif perm.Repository.user_id == user.user_id:
-                #set admin if owner
-                p = 'repository.admin'
-            else:
-                p = perm.Permission.permission_name
-
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
-
-        #=======================================================================
-        # overwrite default with user permissions if any
-        #=======================================================================
-        user_perms = sa.query(RepoToPerm, Permission, Repository)\
-            .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
-            .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
-            .filter(RepoToPerm.user_id == user.user_id).all()
-
-        for perm in user_perms:
-            if perm.Repository.user_id == user.user_id:#set admin if owner
-                p = 'repository.admin'
-            else:
-                p = perm.Permission.permission_name
-            user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
-
-
-        #=======================================================================
-        # check if user is part of groups for this repository and fill in 
-        # (or replace with higher) permissions
-        #=======================================================================
-        user_perms_from_users_groups = sa.query(UsersGroupToPerm, Permission, Repository,)\
-            .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
-            .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
-            .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
-            .filter(UsersGroupMember.user_id == user.user_id).all()
-
-        for perm in user_perms_from_users_groups:
-            p = perm.Permission.permission_name
-            cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
-            #overwrite permission only if it's greater than permission given from other sources
-            if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
-                user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
-
-    meta.Session.remove()
-    return user
-
-def get_user(session):
-    """Gets user from session, and wraps permissions into user
-    
-    :param session:
-    """
-    user = session.get('rhodecode_user', AuthUser())
-    #if the user is not logged in we check for anonymous access
-    #if user is logged and it's a default user check if we still have anonymous
-    #access enabled
-    if user.user_id is None or user.username == 'default':
-        anonymous_user = UserModel().get_by_username('default', cache=True)
-        if anonymous_user.active is True:
-            #then we set this user is logged in
-            user.is_authenticated = True
-            user.user_id = anonymous_user.user_id
-        else:
-            user.is_authenticated = False
-
-    if user.is_authenticated:
-        user = UserModel().fill_data(user)
-
-    user = fill_perms(user)
-    session['rhodecode_user'] = user
-    session.save()
-    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
+    
+    :param api_access: if enabled this checks only for valid auth token
+        and grants access based on valid token
+    """
+
+    def __init__(self, api_access=False):
+        self.api_access = api_access
 
     def __call__(self, func):
         return decorator(self.__wrapper, func)
 
     def __wrapper(self, func, *fargs, **fkwargs):
-        user = session.get('rhodecode_user', AuthUser())
-        log.debug('Checking login required for user:%s', user.username)
-        if user.is_authenticated:
+        cls = fargs[0]
+        user = cls.rhodecode_user
+
+        api_access_ok = False
+        if self.api_access:
+            log.debug('Checking API KEY access for %s', cls)
+            if user.api_key == request.GET.get('api_key'):
+                api_access_ok = True
+            else:
+                log.debug("API KEY token not valid")
+
+        log.debug('Checking if %s is authenticated @ %s', user.username, cls)
+        if user.is_authenticated or api_access_ok:
             log.debug('user %s is authenticated', user.username)
             return func(*fargs, **fkwargs)
         else:
-            log.warn('user %s not authenticated', user.username)
+            log.warn('user %s NOT authenticated', user.username)
 
             p = ''
             if request.environ.get('SCRIPT_NAME') != '/':
@@ -379,10 +314,12 @@
         return decorator(self.__wrapper, func)
 
     def __wrapper(self, func, *fargs, **fkwargs):
-        user = session.get('rhodecode_user', AuthUser())
-        log.debug('Checking if user is not anonymous')
+        cls = fargs[0]
+        self.user = cls.rhodecode_user
 
-        anonymous = user.username == 'default'
+        log.debug('Checking if user is not anonymous @%s', cls)
+
+        anonymous = self.user.username == 'default'
 
         if anonymous:
             p = ''
@@ -401,7 +338,7 @@
             return func(*fargs, **fkwargs)
 
 class PermsDecorator(object):
-    """Base class for decorators"""
+    """Base class for controller decorators"""
 
     def __init__(self, *required_perms):
         available_perms = config['available_permissions']
@@ -416,22 +353,19 @@
 
 
     def __wrapper(self, func, *fargs, **fkwargs):
-#        _wrapper.__name__ = func.__name__
-#        _wrapper.__dict__.update(func.__dict__)
-#        _wrapper.__doc__ = func.__doc__
-        self.user = session.get('rhodecode_user', AuthUser())
+        cls = fargs[0]
+        self.user = cls.rhodecode_user
         self.user_perms = self.user.permissions
         log.debug('checking %s permissions %s for %s %s',
-           self.__class__.__name__, self.required_perms, func.__name__,
+           self.__class__.__name__, self.required_perms, cls,
                self.user)
 
         if self.check_permissions():
-            log.debug('Permission granted for %s %s', func.__name__, self.user)
-
+            log.debug('Permission granted for %s %s', cls, self.user)
             return func(*fargs, **fkwargs)
 
         else:
-            log.warning('Permission denied for %s %s', func.__name__, self.user)
+            log.warning('Permission denied for %s %s', cls, self.user)
             #redirect with forbidden ret code
             return abort(403)
 
@@ -516,18 +450,18 @@
         if not user:
             return False
         self.user_perms = user.permissions
-        self.granted_for = user.username
+        self.granted_for = user
         log.debug('checking %s %s %s', self.__class__.__name__,
                   self.required_perms, user)
 
         if self.check_permissions():
-            log.debug('Permission granted for %s @ %s %s', self.granted_for,
-                      check_Location, user)
+            log.debug('Permission granted %s @ %s', self.granted_for,
+                      check_Location or 'unspecified location')
             return True
 
         else:
-            log.warning('Permission denied for %s @ %s %s', self.granted_for,
-                        check_Location, user)
+            log.warning('Permission denied for %s @ %s', self.granted_for,
+                        check_Location or 'unspecified location')
             return False
 
     def check_permissions(self):
@@ -595,14 +529,9 @@
         self.required_perms = set(perms)
 
     def __call__(self, user, repo_name):
-        usr = AuthUser()
-        usr.user_id = user.user_id
-        usr.username = user.username
-        usr.is_admin = user.admin
-
+        usr = AuthUser(user.user_id)
         try:
-            self.user_perms = set([fill_perms(usr)\
-                                   .permissions['repositories'][repo_name]])
+            self.user_perms = set([usr.permissions['repositories'][repo_name]])
         except:
             self.user_perms = set()
         self.granted_for = ''
--- a/rhodecode/lib/base.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/lib/base.py	Wed Mar 09 16:34:29 2011 +0100
@@ -6,7 +6,7 @@
 from pylons.controllers import WSGIController
 from pylons.templating import render_mako as render
 from rhodecode import __version__
-from rhodecode.lib import auth
+from rhodecode.lib.auth import AuthUser
 from rhodecode.lib.utils import get_repo_slug
 from rhodecode.model import meta
 from rhodecode.model.scm import ScmModel
@@ -34,7 +34,14 @@
         # available in environ['pylons.routes_dict']
         try:
             #putting this here makes sure that we update permissions every time
-            self.rhodecode_user = c.rhodecode_user = auth.get_user(session)
+            api_key = request.GET.get('api_key')
+            user_id = getattr(session.get('rhodecode_user'), 'user_id', None)
+            self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key)
+            self.rhodecode_user.set_authenticated(
+                                        getattr(session.get('rhodecode_user'),
+                                       'is_authenticated', False))
+            session['rhodecode_user'] = self.rhodecode_user
+            session.save()
             return WSGIController.__call__(self, environ, start_response)
         finally:
             meta.Session.remove()
--- a/rhodecode/model/user.py	Sun Mar 06 00:06:28 2011 +0100
+++ b/rhodecode/model/user.py	Wed Mar 09 16:34:29 2011 +0100
@@ -32,8 +32,8 @@
 
 from rhodecode.model import BaseModel
 from rhodecode.model.caching_query import FromCache
-from rhodecode.model.db import User
-
+from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
+    UserToPerm, UsersGroupToPerm, UsersGroupMember
 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
 
 from sqlalchemy.exc import DatabaseError
@@ -41,6 +41,11 @@
 
 log = logging.getLogger(__name__)
 
+PERM_WEIGHTS = {'repository.none':0,
+                'repository.read':1,
+                'repository.write':3,
+                'repository.admin':3}
+
 class UserModel(BaseModel):
 
     def get(self, user_id, cache=False):
@@ -63,6 +68,16 @@
                                           "get_user_%s" % username))
         return user.scalar()
 
+
+    def get_by_api_key(self, api_key, cache=False):
+
+        user = self.sa.query(User)\
+                .filter(User.api_key == api_key)
+        if cache:
+            user = user.options(FromCache("sql_cache_short",
+                                          "get_user_%s" % api_key))
+        return user.scalar()
+
     def create(self, form_data):
         try:
             new_user = User()
@@ -204,27 +219,125 @@
         run_task(tasks.reset_user_password, data['email'])
 
 
-    def fill_data(self, user):
+    def fill_data(self, auth_user, user_id=None, api_key=None):
         """
-        Fills user data with those from database and log out user if not 
+        Fetches auth_user by user_id,or api_key if present.
+        Fills auth_user attributes with those taken from database.
+        Additionally set's is_authenitated if lookup fails 
         present in database
-        :param user:
+        
+        :param auth_user: instance of user to set attributes
+        :param user_id: user id to fetch by
+        :param api_key: api key to fetch by
         """
+        if not user_id and not not api_key:
+            raise Exception('You need to pass user_id or api_key')
 
-        if not hasattr(user, 'user_id') or user.user_id is None:
-            raise Exception('passed in user has to have the user_id attribute')
+        try:
+            if api_key:
+                dbuser = self.get_by_api_key(api_key)
+            else:
+                dbuser = self.get(user_id)
+
+            log.debug('filling %s data', dbuser)
+            for k, v in dbuser.get_dict().items():
+                setattr(auth_user, k, v)
+
+        except:
+            log.error(traceback.format_exc())
+            auth_user.is_authenticated = False
+
+        return auth_user
 
 
-        log.debug('filling auth user data')
-        try:
-            dbuser = self.get(user.user_id)
-            user.username = dbuser.username
-            user.is_admin = dbuser.admin
-            user.name = dbuser.name
-            user.lastname = dbuser.lastname
-            user.email = dbuser.email
-        except:
-            log.error(traceback.format_exc())
-            user.is_authenticated = False
+    def fill_perms(self, user):
+        """Fills user permission attribute with permissions taken from database
+        works for permissions given for repositories, and for permissions that
+        as part of beeing group member
+        
+        :param user: user instance to fill his perms
+        """
+
+        user.permissions['repositories'] = {}
+        user.permissions['global'] = set()
+
+        #===========================================================================
+        # fetch default permissions
+        #===========================================================================
+        default_user = self.get_by_username('default', cache=True)
+
+        default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
+            .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
+            .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
+            .filter(RepoToPerm.user == default_user).all()
+
+        if user.is_admin:
+            #=======================================================================
+            # #admin have all default rights set to admin        
+            #=======================================================================
+            user.permissions['global'].add('hg.admin')
+
+            for perm in default_perms:
+                p = 'repository.admin'
+                user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
+
+        else:
+            #=======================================================================
+            # set default permissions
+            #=======================================================================
+
+            #default global
+            default_global_perms = self.sa.query(UserToPerm)\
+                .filter(UserToPerm.user == self.sa.query(User)\
+                       .filter(User.username == 'default').one())
+
+            for perm in default_global_perms:
+                user.permissions['global'].add(perm.permission.permission_name)
+
+            #default for repositories
+            for perm in default_perms:
+                if perm.Repository.private and not perm.Repository.user_id == user.user_id:
+                    #diself.sable defaults for private repos,
+                    p = 'repository.none'
+                elif perm.Repository.user_id == user.user_id:
+                    #set admin if owner
+                    p = 'repository.admin'
+                else:
+                    p = perm.Permission.permission_name
+
+                user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
+
+            #=======================================================================
+            # overwrite default with user permissions if any
+            #=======================================================================
+            user_perms = self.sa.query(RepoToPerm, Permission, Repository)\
+                .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
+                .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
+                .filter(RepoToPerm.user_id == user.user_id).all()
+
+            for perm in user_perms:
+                if perm.Repository.user_id == user.user_id:#set admin if owner
+                    p = 'repository.admin'
+                else:
+                    p = perm.Permission.permission_name
+                user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
+
+
+            #=======================================================================
+            # check if user is part of groups for this repository and fill in 
+            # (or replace with higher) permissions
+            #=======================================================================
+            user_perms_from_users_groups = self.sa.query(UsersGroupToPerm, Permission, Repository,)\
+                .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
+                .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
+                .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
+                .filter(UsersGroupMember.user_id == user.user_id).all()
+
+            for perm in user_perms_from_users_groups:
+                p = perm.Permission.permission_name
+                cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
+                #overwrite permission only if it's greater than permission given from other sources
+                if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
+                    user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
 
         return user