Mercurial > kallithea
diff rhodecode/model/user.py @ 2776:63e58ef80ef1
Merge beta branch into stable
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 02 Sep 2012 21:19:54 +0200 |
parents | b8d5a5c9f66d d2d35cf2b351 |
children | f7a52d548fd0 |
line wrap: on
line diff
--- a/rhodecode/model/user.py Sat May 19 14:54:50 2012 +0200 +++ b/rhodecode/model/user.py Sun Sep 02 21:19:54 2012 +0200 @@ -25,48 +25,31 @@ import logging import traceback - +import itertools from pylons import url from pylons.i18n.translation import _ +from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm import joinedload + from rhodecode.lib.utils2 import safe_unicode, generate_api_key from rhodecode.lib.caching_query import FromCache - from rhodecode.model import BaseModel from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \ UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \ - Notification, RepoGroup, UserRepoGroupToPerm, UsersGroup,\ - UsersGroupRepoGroupToPerm + Notification, RepoGroup, UserRepoGroupToPerm, UsersGroupRepoGroupToPerm, \ + UserEmailMap from rhodecode.lib.exceptions import DefaultUserException, \ UserOwnsReposException -from sqlalchemy.exc import DatabaseError - -from sqlalchemy.orm import joinedload log = logging.getLogger(__name__) - -PERM_WEIGHTS = { - 'repository.none': 0, - 'repository.read': 1, - 'repository.write': 3, - 'repository.admin': 4, - 'group.none': 0, - 'group.read': 1, - 'group.write': 3, - 'group.admin': 4, -} +PERM_WEIGHTS = Permission.PERM_WEIGHTS class UserModel(BaseModel): - - def __get_user(self, user): - return self._get_instance(User, user, callback=User.get_by_username) - - def __get_perm(self, permission): - return self._get_instance(Permission, permission, - callback=Permission.get_by_key) + cls = User def get(self, user_id, cache=False): user = self.sa.query(User) @@ -76,7 +59,7 @@ return user.get(user_id) def get_user(self, user): - return self.__get_user(user) + return self._get_user(user) def get_by_username(self, username, cache=False, case_insensitive=False): @@ -90,13 +73,21 @@ "get_user_%s" % username)) return user.scalar() + def get_by_email(self, email, cache=False, case_insensitive=False): + return User.get_by_email(email, case_insensitive, cache) + def get_by_api_key(self, api_key, cache=False): return User.get_by_api_key(api_key, cache) def create(self, form_data): + from rhodecode.lib.auth import get_crypt_password try: new_user = User() for k, v in form_data.items(): + if k == 'password': + v = get_crypt_password(v) + if k == 'firstname': + k = 'name' setattr(new_user, k, v) new_user.api_key = generate_api_key(form_data['username']) @@ -106,8 +97,8 @@ log.error(traceback.format_exc()) raise - def create_or_update(self, username, password, email, name, lastname, - active=True, admin=False, ldap_dn=None): + def create_or_update(self, username, password, email, firstname='', + lastname='', active=True, admin=False, ldap_dn=None): """ Creates a new instance if not found, or updates current one @@ -115,7 +106,7 @@ :param password: :param email: :param active: - :param name: + :param firstname: :param lastname: :param active: :param admin: @@ -129,19 +120,23 @@ if user is None: log.debug('creating new user %s' % username) new_user = User() + edit = False else: log.debug('updating user %s' % username) new_user = user + edit = True try: new_user.username = username new_user.admin = admin - new_user.password = get_crypt_password(password) - new_user.api_key = generate_api_key(username) + # set password only if creating an user or password is changed + if edit is False or user.password != password: + new_user.password = get_crypt_password(password) + new_user.api_key = generate_api_key(username) new_user.email = email new_user.active = active new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None - new_user.name = name + new_user.name = firstname new_user.lastname = lastname self.sa.add(new_user) return new_user @@ -252,6 +247,7 @@ raise def update(self, user_id, form_data): + from rhodecode.lib.auth import get_crypt_password try: user = self.get(user_id, cache=False) if user.username == 'default': @@ -260,29 +256,56 @@ " crucial for entire application")) for k, v in form_data.items(): - if k == 'new_password' and v != '': - user.password = v + if k == 'new_password' and v: + user.password = get_crypt_password(v) user.api_key = generate_api_key(user.username) else: + if k == 'firstname': + k = 'name' setattr(user, k, v) + self.sa.add(user) + except: + log.error(traceback.format_exc()) + raise + def update_user(self, user, **kwargs): + from rhodecode.lib.auth import get_crypt_password + try: + user = self._get_user(user) + if user.username == 'default': + raise DefaultUserException( + _("You can't Edit this user since it's" + " crucial for entire application") + ) + + for k, v in kwargs.items(): + if k == 'password' and v: + v = get_crypt_password(v) + user.api_key = generate_api_key(user.username) + + setattr(user, k, v) self.sa.add(user) + return user except: log.error(traceback.format_exc()) raise def update_my_account(self, user_id, form_data): + from rhodecode.lib.auth import get_crypt_password try: user = self.get(user_id, cache=False) if user.username == 'default': raise DefaultUserException( - _("You can't Edit this user since it's" - " crucial for entire application")) + _("You can't Edit this user since it's" + " crucial for entire application") + ) for k, v in form_data.items(): - if k == 'new_password' and v != '': - user.password = v + if k == 'new_password' and v: + user.password = get_crypt_password(v) user.api_key = generate_api_key(user.username) else: + if k == 'firstname': + k = 'name' if k not in ['admin', 'active']: setattr(user, k, v) @@ -292,7 +315,7 @@ raise def delete(self, user): - user = self.__get_user(user) + user = self._get_user(user) try: if user.username == 'default': @@ -399,11 +422,11 @@ return user #================================================================== - # set default permissions first for repositories and groups + # SET DEFAULTS GLOBAL, REPOS, REPOS GROUPS #================================================================== uid = user.user_id - # default global permissions + # default global permissions taken fron the default user default_global_perms = self.sa.query(UserToPerm)\ .filter(UserToPerm.user_id == default_user_id) @@ -431,25 +454,89 @@ p = perm.Permission.permission_name user.permissions[GK][rg_k] = p - #================================================================== - # overwrite defaults with user permissions if any found - #================================================================== + #====================================================================== + # !! OVERRIDE GLOBALS !! with user permissions if any found + #====================================================================== + # those can be configured from groups or users explicitly + _configurable = set(['hg.fork.none', 'hg.fork.repository', + 'hg.create.none', 'hg.create.repository']) - # user global permissions + # USER GROUPS comes first + # users group global permissions + user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ + .options(joinedload(UsersGroupToPerm.permission))\ + .join((UsersGroupMember, UsersGroupToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid)\ + .order_by(UsersGroupToPerm.users_group_id)\ + .all() + #need to group here by groups since user can be in more than one group + _grouped = [[x, list(y)] for x, y in + itertools.groupby(user_perms_from_users_groups, + lambda x:x.users_group)] + for gr, perms in _grouped: + # since user can be in multiple groups iterate over them and + # select the lowest permissions first (more explicit) + ##TODO: do this^^ + if not gr.inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + user.permissions[GLOBAL] = user.permissions[GLOBAL]\ + .difference(_configurable) + for perm in perms: + user.permissions[GLOBAL].add(perm.permission.permission_name) + + # user specific global permissions user_perms = self.sa.query(UserToPerm)\ .options(joinedload(UserToPerm.permission))\ .filter(UserToPerm.user_id == uid).all() - for perm in user_perms: - user.permissions[GLOBAL].add(perm.permission.permission_name) + if not user.inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + user.permissions[GLOBAL] = user.permissions[GLOBAL]\ + .difference(_configurable) + + for perm in user_perms: + user.permissions[GLOBAL].add(perm.permission.permission_name) + + #====================================================================== + # !! REPO PERMISSIONS !! + #====================================================================== + #====================================================================== + # check if user is part of user groups for this repository and + # fill in (or NOT replace with higher `or 1` permissions + #====================================================================== + # users group for repositories permissions + user_repo_perms_from_users_groups = \ + self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\ + .join((Repository, UsersGroupRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UsersGroupRepoToPerm.permission_id == + Permission.permission_id))\ + .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid)\ + .all() + + for perm in user_repo_perms_from_users_groups: + r_k = perm.UsersGroupRepoToPerm.repository.repo_name + p = perm.Permission.permission_name + cur_perm = user.permissions[RK][r_k] + # overwrite permission only if it's greater than permission + # given from other sources + if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check + user.permissions[RK][r_k] = p # user explicit permissions for repositories user_repo_perms = \ self.sa.query(UserRepoToPerm, Permission, Repository)\ - .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, UserRepoToPerm.permission_id == Permission.permission_id))\ - .filter(UserRepoToPerm.user_id == uid)\ - .all() + .join((Repository, UserRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UserRepoToPerm.permission_id == + Permission.permission_id))\ + .filter(UserRepoToPerm.user_id == uid)\ + .all() for perm in user_repo_perms: # set admin if owner @@ -460,40 +547,6 @@ p = perm.Permission.permission_name user.permissions[RK][r_k] = p - # USER GROUP - #================================================================== - # check if user is part of user groups for this repository and - # fill in (or replace with higher) permissions - #================================================================== - - # users group global - user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ - .options(joinedload(UsersGroupToPerm.permission))\ - .join((UsersGroupMember, UsersGroupToPerm.users_group_id == - UsersGroupMember.users_group_id))\ - .filter(UsersGroupMember.user_id == uid).all() - - for perm in user_perms_from_users_groups: - user.permissions[GLOBAL].add(perm.permission.permission_name) - - # users group for repositories permissions - user_repo_perms_from_users_groups = \ - self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\ - .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\ - .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\ - .filter(UsersGroupMember.user_id == uid)\ - .all() - - for perm in user_repo_perms_from_users_groups: - r_k = perm.UsersGroupRepoToPerm.repository.repo_name - p = perm.Permission.permission_name - cur_perm = user.permissions[RK][r_k] - # overwrite permission only if it's greater than permission - # given from other sources - if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: - user.permissions[RK][r_k] = p - # REPO GROUP #================================================================== # get access for this user for repos group and override defaults @@ -541,11 +594,8 @@ return user def has_perm(self, user, perm): - if not isinstance(perm, Permission): - raise Exception('perm needs to be an instance of Permission class ' - 'got %s instead' % type(perm)) - - user = self.__get_user(user) + perm = self._get_perm(perm) + user = self._get_user(user) return UserToPerm.query().filter(UserToPerm.user == user)\ .filter(UserToPerm.permission == perm).scalar() is not None @@ -557,8 +607,8 @@ :param user: :param perm: """ - user = self.__get_user(user) - perm = self.__get_perm(perm) + user = self._get_user(user) + perm = self._get_perm(perm) # if this permission is already granted skip it _perm = UserToPerm.query()\ .filter(UserToPerm.user == user)\ @@ -578,8 +628,8 @@ :param user: :param perm: """ - user = self.__get_user(user) - perm = self.__get_perm(perm) + user = self._get_user(user) + perm = self._get_perm(perm) obj = UserToPerm.query()\ .filter(UserToPerm.user == user)\ @@ -587,3 +637,33 @@ .scalar() if obj: self.sa.delete(obj) + + def add_extra_email(self, user, email): + """ + Adds email address to UserEmailMap + + :param user: + :param email: + """ + from rhodecode.model import forms + form = forms.UserExtraEmailForm()() + data = form.to_python(dict(email=email)) + user = self._get_user(user) + + obj = UserEmailMap() + obj.user = user + obj.email = data['email'] + self.sa.add(obj) + return obj + + def delete_extra_email(self, user, email_id): + """ + Removes email address from UserEmailMap + + :param user: + :param email_id: + """ + user = self._get_user(user) + obj = UserEmailMap.query().get(email_id) + if obj: + self.sa.delete(obj)