# HG changeset patch # User Marcin Kuzminski # Date 2019-01-14 19:19:25 # Node ID 2e06ebce85a3c05d6d5907dd6f17ab7e8f8715fe # Parent e6485a6c92c3f3843657fc929d81524a419dc976 permissions: handle more cases for invalidating permission caches - invalidate user permissions on chaning the global permissions - invalidate all users in case of creating new object with "copy permissions" flag - invalidate all users permissions in case of repo/repo group renames - invalidate all user permissions in forked repo with copy flag diff --git a/rhodecode/apps/admin/views/repo_groups.py b/rhodecode/apps/admin/views/repo_groups.py --- a/rhodecode/apps/admin/views/repo_groups.py +++ b/rhodecode/apps/admin/views/repo_groups.py @@ -159,6 +159,7 @@ class AdminRepoGroupsView(BaseAppView, D try: owner = self._rhodecode_user form_result = repo_group_form.to_python(dict(self.request.POST)) + copy_permissions = form_result.get('group_copy_permissions') repo_group = RepoGroupModel().create( group_name=form_result['group_name_full'], group_description=form_result['group_description'], @@ -201,7 +202,14 @@ class AdminRepoGroupsView(BaseAppView, D % repo_group_name, category='error') raise HTTPFound(h.route_path('home')) - events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id])) + affected_user_ids = [self._rhodecode_user.user_id] + if copy_permissions: + user_group_perms = repo_group.permissions(expand_from_user_groups=True) + copy_perms = [perm['user_id'] for perm in user_group_perms] + # also include those newly created by copy + affected_user_ids.extend(copy_perms) + events.trigger(events.UserPermissionsChange(affected_user_ids)) + raise HTTPFound( h.route_path('repo_group_home', repo_group_name=form_result['group_name_full'])) diff --git a/rhodecode/apps/admin/views/repositories.py b/rhodecode/apps/admin/views/repositories.py --- a/rhodecode/apps/admin/views/repositories.py +++ b/rhodecode/apps/admin/views/repositories.py @@ -146,14 +146,14 @@ class AdminReposView(BaseAppView, DataGr form_result = {} self._load_form_data(c) - task_id = None + try: # CanWriteToGroup validators checks permissions of this POST form = RepoForm( self.request.translate, repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)() form_result = form.to_python(dict(self.request.POST)) - + copy_permissions = form_result.get('repo_copy_permissions') # create is done sometimes async on celery, db transaction # management is handled there. task = RepoModel().create(form_result, self._rhodecode_user.user_id) @@ -176,9 +176,19 @@ class AdminReposView(BaseAppView, DataGr h.flash(msg, category='error') raise HTTPFound(h.route_path('home')) - events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id])) + repo_name = form_result.get('repo_name_full') + + affected_user_ids = [self._rhodecode_user.user_id] + if copy_permissions: + repository = Repository.get_by_repo_name(repo_name) + # also include those newly created by copy + user_group_perms = repository.permissions(expand_from_user_groups=True) + copy_perms = [perm['user_id'] for perm in user_group_perms] + # also include those newly created by copy + affected_user_ids.extend(copy_perms) + + events.trigger(events.UserPermissionsChange(affected_user_ids)) raise HTTPFound( - h.route_path('repo_creating', - repo_name=form_result['repo_name_full'], + h.route_path('repo_creating', repo_name=repo_name, _query=dict(task_id=task_id))) diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -28,6 +28,7 @@ from pyramid.view import view_config from pyramid.renderers import render from pyramid.response import Response +from rhodecode import events from rhodecode.apps._base import BaseAppView, DataGridAppView, UserAppView from rhodecode.apps.ssh_support import SshKeyFileChangeEvent from rhodecode.authentication.plugins import auth_rhodecode @@ -573,6 +574,7 @@ class UsersView(UserAppView): # audit_log.store_web('user.edit.permissions') Session().commit() + h.flash(_('User global permissions updated successfully'), category='success') @@ -593,6 +595,9 @@ class UsersView(UserAppView): log.exception("Exception during permissions saving") h.flash(_('An error occurred during permissions saving'), category='error') + + affected_user_ids = [user_id] + events.trigger(events.UserPermissionsChange(affected_user_ids)) raise HTTPFound(h.route_path('user_edit_global_perms', user_id=user_id)) @LoginRequired() diff --git a/rhodecode/apps/repo_group/views/repo_group_settings.py b/rhodecode/apps/repo_group/views/repo_group_settings.py --- a/rhodecode/apps/repo_group/views/repo_group_settings.py +++ b/rhodecode/apps/repo_group/views/repo_group_settings.py @@ -180,10 +180,14 @@ class RepoGroupSettingsView(RepoGroupApp name_changed = old_repo_group_name != new_repo_group_name if name_changed: + current_perms = self.db_repo_group.permissions(expand_from_user_groups=True) + affected_user_ids = [perm['user_id'] for perm in current_perms] + + # NOTE(marcink): also add owner maybe it has changed owner = User.get_by_username(schema_data['repo_group_owner']) owner_id = owner.user_id if owner else self._rhodecode_user.user_id - events.trigger(events.UserPermissionsChange([ - self._rhodecode_user.user_id, owner_id])) + affected_user_ids.extend([self._rhodecode_user.user_id, owner_id]) + events.trigger(events.UserPermissionsChange(affected_user_ids)) raise HTTPFound( h.route_path('edit_repo_group', repo_group_name=new_repo_group_name)) diff --git a/rhodecode/apps/repository/views/repo_forks.py b/rhodecode/apps/repository/views/repo_forks.py --- a/rhodecode/apps/repository/views/repo_forks.py +++ b/rhodecode/apps/repository/views/repo_forks.py @@ -224,6 +224,7 @@ class RepoForksView(RepoAppView, DataGri task_id = None try: form_result = _form.to_python(post_data) + copy_permissions = form_result.get('copy_permissions') # create fork is done sometimes async on celery, db transaction # management is handled there. task = RepoModel().create_fork( @@ -246,18 +247,24 @@ class RepoForksView(RepoAppView, DataGri return Response(html) except Exception: log.exception( - u'Exception while trying to fork the repository %s', - self.db_repo_name) - msg = ( - _('An error occurred during repository forking %s') % ( - self.db_repo_name, )) + u'Exception while trying to fork the repository %s', self.db_repo_name) + msg = _('An error occurred during repository forking %s') % (self.db_repo_name, ) h.flash(msg, category='error') + raise HTTPFound(h.route_path('home')) repo_name = form_result.get('repo_name_full', self.db_repo_name) - events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id])) + affected_user_ids = [self._rhodecode_user.user_id] + if copy_permissions: + repository = Repository.get_by_repo_name(repo_name) + # also include those newly created by copy + user_group_perms = repository.permissions(expand_from_user_groups=True) + copy_perms = [perm['user_id'] for perm in user_group_perms] + # also include those newly created by copy + affected_user_ids.extend(copy_perms) + + events.trigger(events.UserPermissionsChange(affected_user_ids)) raise HTTPFound( - h.route_path('repo_creating', - repo_name=repo_name, + h.route_path('repo_creating', repo_name=repo_name, _query=dict(task_id=task_id))) diff --git a/rhodecode/apps/repository/views/repo_settings.py b/rhodecode/apps/repository/views/repo_settings.py --- a/rhodecode/apps/repository/views/repo_settings.py +++ b/rhodecode/apps/repository/views/repo_settings.py @@ -168,8 +168,8 @@ class RepoSettingsView(RepoAppView): Session().commit() - h.flash(_('Repository `{}` updated successfully').format( - old_repo_name), category='success') + h.flash(_('Repository `{}` updated successfully').format(old_repo_name), + category='success') except Exception: log.exception("Exception during update of repository") h.flash(_('Error occurred during update of repository {}').format( @@ -177,10 +177,14 @@ class RepoSettingsView(RepoAppView): name_changed = old_repo_name != new_repo_name if name_changed: + current_perms = self.db_repo.permissions(expand_from_user_groups=True) + affected_user_ids = [perm['user_id'] for perm in current_perms] + + # NOTE(marcink): also add owner maybe it has changed owner = User.get_by_username(schema_data['repo_owner']) owner_id = owner.user_id if owner else self._rhodecode_user.user_id - events.trigger(events.UserPermissionsChange([ - self._rhodecode_user.user_id, owner_id])) + affected_user_ids.extend([self._rhodecode_user.user_id, owner_id]) + events.trigger(events.UserPermissionsChange(affected_user_ids)) raise HTTPFound( h.route_path('edit_repo', repo_name=new_repo_name)) diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -959,12 +959,14 @@ class User(Base, BaseModel): return user @classmethod - def get_all_super_admins(cls): + def get_all_super_admins(cls, only_active=False): """ Returns all admin accounts sorted by username """ - return User.query().filter(User.admin == true())\ - .order_by(User.username.asc()).all() + qry = User.query().filter(User.admin == true()).order_by(User.username.asc()) + if only_active: + qry = qry.filter(User.active == true()) + return qry.all() @classmethod def get_default_user(cls, cache=False, refresh=False): @@ -1390,7 +1392,8 @@ class UserGroup(Base, BaseModel): FromCache("sql_cache_short", "get_users_group_%s" % user_group_id)) return user_group.get(user_group_id) - def permissions(self, with_admins=True, with_owner=True): + def permissions(self, with_admins=True, with_owner=True, + expand_from_user_groups=False): """ Permissions for user groups """ @@ -1441,19 +1444,29 @@ class UserGroup(Base, BaseModel): # each group perm_rows = sorted(perm_rows, key=display_user_sort) - return super_admin_rows + owner_row + perm_rows - - def permission_user_groups(self): - q = UserGroupUserGroupToPerm.query().filter(UserGroupUserGroupToPerm.target_user_group == self) + user_groups_rows = [] + if expand_from_user_groups: + for ug in self.permission_user_groups(with_members=True): + for user_data in ug.members: + user_groups_rows.append(user_data) + + return super_admin_rows + owner_row + perm_rows + user_groups_rows + + def permission_user_groups(self, with_members=False): + q = UserGroupUserGroupToPerm.query()\ + .filter(UserGroupUserGroupToPerm.target_user_group == self) q = q.options(joinedload(UserGroupUserGroupToPerm.user_group), joinedload(UserGroupUserGroupToPerm.target_user_group), joinedload(UserGroupUserGroupToPerm.permission),) perm_rows = [] for _user_group in q.all(): - usr = AttributeDict(_user_group.user_group.get_dict()) - usr.permission = _user_group.permission.permission_name - perm_rows.append(usr) + entry = AttributeDict(_user_group.user_group.get_dict()) + entry.permission = _user_group.permission.permission_name + if with_members: + entry.members = [x.user.get_dict() + for x in _user_group.users_group.members] + perm_rows.append(entry) perm_rows = sorted(perm_rows, key=display_user_group_sort) return perm_rows @@ -1928,7 +1941,8 @@ class Repository(Base, BaseModel): from rhodecode.lib.utils import make_db_config return make_db_config(clear_session=False, repo=self) - def permissions(self, with_admins=True, with_owner=True): + def permissions(self, with_admins=True, with_owner=True, + expand_from_user_groups=False): """ Permissions for repositories """ @@ -1986,20 +2000,29 @@ class Repository(Base, BaseModel): # each group perm_rows = sorted(perm_rows, key=display_user_sort) - return super_admin_rows + owner_row + perm_rows - - def permission_user_groups(self): - q = UserGroupRepoToPerm.query().filter( - UserGroupRepoToPerm.repository == self) + user_groups_rows = [] + if expand_from_user_groups: + for ug in self.permission_user_groups(with_members=True): + for user_data in ug.members: + user_groups_rows.append(user_data) + + return super_admin_rows + owner_row + perm_rows + user_groups_rows + + def permission_user_groups(self, with_members=True): + q = UserGroupRepoToPerm.query()\ + .filter(UserGroupRepoToPerm.repository == self) q = q.options(joinedload(UserGroupRepoToPerm.repository), joinedload(UserGroupRepoToPerm.users_group), joinedload(UserGroupRepoToPerm.permission),) perm_rows = [] for _user_group in q.all(): - usr = AttributeDict(_user_group.users_group.get_dict()) - usr.permission = _user_group.permission.permission_name - perm_rows.append(usr) + entry = AttributeDict(_user_group.users_group.get_dict()) + entry.permission = _user_group.permission.permission_name + if with_members: + entry.members = [x.user.get_dict() + for x in _user_group.users_group.members] + perm_rows.append(entry) perm_rows = sorted(perm_rows, key=display_user_group_sort) return perm_rows @@ -2641,7 +2664,8 @@ class RepoGroup(Base, BaseModel): self.parent_group else []) return RepoGroup.url_sep().join(path_prefix + [group_name]) - def permissions(self, with_admins=True, with_owner=True): + def permissions(self, with_admins=True, with_owner=True, + expand_from_user_groups=False): """ Permissions for repository groups """ @@ -2692,20 +2716,29 @@ class RepoGroup(Base, BaseModel): # each group perm_rows = sorted(perm_rows, key=display_user_sort) - return super_admin_rows + owner_row + perm_rows - - def permission_user_groups(self): - q = UserGroupRepoGroupToPerm.query().filter( - UserGroupRepoGroupToPerm.group == self) + user_groups_rows = [] + if expand_from_user_groups: + for ug in self.permission_user_groups(with_members=True): + for user_data in ug.members: + user_groups_rows.append(user_data) + + return super_admin_rows + owner_row + perm_rows + user_groups_rows + + def permission_user_groups(self, with_members=False): + q = UserGroupRepoGroupToPerm.query()\ + .filter(UserGroupRepoGroupToPerm.group == self) q = q.options(joinedload(UserGroupRepoGroupToPerm.group), joinedload(UserGroupRepoGroupToPerm.users_group), joinedload(UserGroupRepoGroupToPerm.permission),) perm_rows = [] for _user_group in q.all(): - usr = AttributeDict(_user_group.users_group.get_dict()) - usr.permission = _user_group.permission.permission_name - perm_rows.append(usr) + entry = AttributeDict(_user_group.users_group.get_dict()) + entry.permission = _user_group.permission.permission_name + if with_members: + entry.members = [x.user.get_dict() + for x in _user_group.users_group.members] + perm_rows.append(entry) perm_rows = sorted(perm_rows, key=display_user_group_sort) return perm_rows