diff --git a/rhodecode/model/repos_group.py b/rhodecode/model/repos_group.py --- a/rhodecode/model/repos_group.py +++ b/rhodecode/model/repos_group.py @@ -7,7 +7,7 @@ :created_on: Jan 25, 2011 :author: marcink - :copyright: (C) 2009-2011 Marcin Kuzminski + :copyright: (C) 2011-2012 Marcin Kuzminski :license: GPLv3, see COPYING for more details. """ # This program is free software: you can redistribute it and/or modify @@ -28,19 +28,32 @@ import logging import traceback import shutil -from pylons.i18n.translation import _ - -from vcs.utils.lazy import LazyProperty +from rhodecode.lib import LazyProperty from rhodecode.model import BaseModel -from rhodecode.model.caching_query import FromCache -from rhodecode.model.db import Group, RhodeCodeUi +from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \ + User, Permission, UsersGroupRepoGroupToPerm, UsersGroup log = logging.getLogger(__name__) class ReposGroupModel(BaseModel): + def __get_user(self, user): + return self._get_instance(User, user, callback=User.get_by_username) + + def __get_users_group(self, users_group): + return self._get_instance(UsersGroup, users_group, + callback=UsersGroup.get_by_group_name) + + def __get_repos_group(self, repos_group): + return self._get_instance(RepoGroup, repos_group, + callback=RepoGroup.get_by_group_name) + + def __get_perm(self, permission): + return self._get_instance(Permission, permission, + callback=Permission.get_by_key) + @LazyProperty def repos_path(self): """ @@ -50,6 +63,24 @@ class ReposGroupModel(BaseModel): q = RhodeCodeUi.get_by_key('/').one() return q.ui_value + def _create_default_perms(self, new_group): + # create default permission + repo_group_to_perm = UserRepoGroupToPerm() + default_perm = 'group.read' + for p in User.get_by_username('default').user_perms: + if p.permission.permission_name.startswith('group.'): + default_perm = p.permission.permission_name + break + + repo_group_to_perm.permission_id = self.sa.query(Permission)\ + .filter(Permission.permission_name == default_perm)\ + .one().permission_id + + repo_group_to_perm.group = new_group + repo_group_to_perm.user_id = User.get_by_username('default').user_id + + self.sa.add(repo_group_to_perm) + def __create_group(self, group_name): """ makes repositories group on filesystem @@ -59,7 +90,7 @@ class ReposGroupModel(BaseModel): """ create_path = os.path.join(self.repos_path, group_name) - log.debug('creating new group in %s', create_path) + log.debug('creating new group in %s' % create_path) if os.path.isdir(create_path): raise Exception('That directory already exists !') @@ -69,7 +100,7 @@ class ReposGroupModel(BaseModel): def __rename_group(self, old, new): """ Renames a group on filesystem - + :param group_name: """ @@ -77,13 +108,12 @@ class ReposGroupModel(BaseModel): log.debug('skipping group rename') return - log.debug('renaming repos group from %s to %s', old, new) - + log.debug('renaming repos group from %s to %s' % (old, new)) old_path = os.path.join(self.repos_path, old) new_path = os.path.join(self.repos_path, new) - log.debug('renaming repos paths from %s to %s', old_path, new_path) + log.debug('renaming repos paths from %s to %s' % (old_path, new_path)) if os.path.isdir(new_path): raise Exception('Was trying to rename to already ' @@ -93,10 +123,10 @@ class ReposGroupModel(BaseModel): def __delete_group(self, group): """ Deletes a group from a filesystem - + :param group: instance of group from database """ - paths = group.full_path.split(Group.url_sep()) + paths = group.full_path.split(RepoGroup.url_sep()) paths = os.sep.join(paths) rm_path = os.path.join(self.repos_path, paths) @@ -104,33 +134,59 @@ class ReposGroupModel(BaseModel): # delete only if that path really exists os.rmdir(rm_path) - def create(self, form_data): + def create(self, group_name, group_description, parent, just_db=False): try: - new_repos_group = Group() - new_repos_group.group_description = form_data['group_description'] - new_repos_group.parent_group = Group.get(form_data['group_parent_id']) - new_repos_group.group_name = new_repos_group.get_new_name(form_data['group_name']) + new_repos_group = RepoGroup() + new_repos_group.group_description = group_description + new_repos_group.parent_group = self.__get_repos_group(parent) + new_repos_group.group_name = new_repos_group.get_new_name(group_name) self.sa.add(new_repos_group) + self._create_default_perms(new_repos_group) - self.__create_group(new_repos_group.group_name) + if not just_db: + # we need to flush here, in order to check if database won't + # throw any exceptions, create filesystem dirs at the very end + self.sa.flush() + self.__create_group(new_repos_group.group_name) - self.sa.commit() return new_repos_group except: log.error(traceback.format_exc()) - self.sa.rollback() raise def update(self, repos_group_id, form_data): try: - repos_group = Group.get(repos_group_id) + repos_group = RepoGroup.get(repos_group_id) + + # update permissions + for member, perm, member_type in form_data['perms_updates']: + if member_type == 'user': + # this updates also current one if found + ReposGroupModel().grant_user_permission( + repos_group=repos_group, user=member, perm=perm + ) + else: + ReposGroupModel().grant_users_group_permission( + repos_group=repos_group, group_name=member, perm=perm + ) + # set new permissions + for member, perm, member_type in form_data['perms_new']: + if member_type == 'user': + ReposGroupModel().grant_user_permission( + repos_group=repos_group, user=member, perm=perm + ) + else: + ReposGroupModel().grant_users_group_permission( + repos_group=repos_group, group_name=member, perm=perm + ) + old_path = repos_group.full_path - + # change properties repos_group.group_description = form_data['group_description'] - repos_group.parent_group = Group.get(form_data['group_parent_id']) + repos_group.parent_group = RepoGroup.get(form_data['group_parent_id']) repos_group.group_name = repos_group.get_new_name(form_data['group_name']) new_path = repos_group.full_path @@ -139,26 +195,116 @@ class ReposGroupModel(BaseModel): self.__rename_group(old_path, new_path) - # we need to get all repositories from this new group and + # we need to get all repositories from this new group and # rename them accordingly to new group path for r in repos_group.repositories: r.repo_name = r.get_new_name(r.just_name) self.sa.add(r) - self.sa.commit() return repos_group except: log.error(traceback.format_exc()) - self.sa.rollback() raise def delete(self, users_group_id): try: - users_group = Group.get(users_group_id) + users_group = RepoGroup.get(users_group_id) self.sa.delete(users_group) self.__delete_group(users_group) - self.sa.commit() except: log.error(traceback.format_exc()) - self.sa.rollback() raise + + def grant_user_permission(self, repos_group, user, perm): + """ + Grant permission for user on given repositories group, or update + existing one if found + + :param repos_group: Instance of ReposGroup, repositories_group_id, + or repositories_group name + :param user: Instance of User, user_id or username + :param perm: Instance of Permission, or permission_name + """ + + repos_group = self.__get_repos_group(repos_group) + user = self.__get_user(user) + permission = self.__get_perm(perm) + + # check if we have that permission already + obj = self.sa.query(UserRepoGroupToPerm)\ + .filter(UserRepoGroupToPerm.user == user)\ + .filter(UserRepoGroupToPerm.group == repos_group)\ + .scalar() + if obj is None: + # create new ! + obj = UserRepoGroupToPerm() + obj.group = repos_group + obj.user = user + obj.permission = permission + self.sa.add(obj) + + def revoke_user_permission(self, repos_group, user): + """ + Revoke permission for user on given repositories group + + :param repos_group: Instance of ReposGroup, repositories_group_id, + or repositories_group name + :param user: Instance of User, user_id or username + """ + + repos_group = self.__get_repos_group(repos_group) + user = self.__get_user(user) + + obj = self.sa.query(UserRepoGroupToPerm)\ + .filter(UserRepoGroupToPerm.user == user)\ + .filter(UserRepoGroupToPerm.group == repos_group)\ + .one() + self.sa.delete(obj) + + def grant_users_group_permission(self, repos_group, group_name, perm): + """ + Grant permission for users group on given repositories group, or update + existing one if found + + :param repos_group: Instance of ReposGroup, repositories_group_id, + or repositories_group name + :param group_name: Instance of UserGroup, users_group_id, + or users group name + :param perm: Instance of Permission, or permission_name + """ + repos_group = self.__get_repos_group(repos_group) + group_name = self.__get_users_group(group_name) + permission = self.__get_perm(perm) + + # check if we have that permission already + obj = self.sa.query(UsersGroupRepoGroupToPerm)\ + .filter(UsersGroupRepoGroupToPerm.group == repos_group)\ + .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\ + .scalar() + + if obj is None: + # create new + obj = UsersGroupRepoGroupToPerm() + + obj.group = repos_group + obj.users_group = group_name + obj.permission = permission + self.sa.add(obj) + + def revoke_users_group_permission(self, repos_group, group_name): + """ + Revoke permission for users group on given repositories group + + :param repos_group: Instance of ReposGroup, repositories_group_id, + or repositories_group name + :param group_name: Instance of UserGroup, users_group_id, + or users group name + """ + repos_group = self.__get_repos_group(repos_group) + group_name = self.__get_users_group(group_name) + + obj = self.sa.query(UsersGroupRepoGroupToPerm)\ + .filter(UsersGroupRepoGroupToPerm.group == repos_group)\ + .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\ + .one() + self.sa.delete(obj)