##// END OF EJS Templates
feat(configs): deprecared old hooks protocol and ssh wrapper....
feat(configs): deprecared old hooks protocol and ssh wrapper. New defaults are now set on v2 keys, so previous installation are automatically set to new keys. Fallback mode is still available.

File last commit:

r5356:99a91100 default
r5496:cab50adf default
Show More
repo_group.py
886 lines | 34.9 KiB | text/x-python | PythonLexer
copyrights: updated for 2023
r5088 # Copyright (C) 2011-2023 RhodeCode GmbH
project: added all source files and assets
r1 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
repo group model for RhodeCode
"""
repo-groups: implemented default personal repo groups logic....
r1094 import os
project: added all source files and assets
r1 import datetime
import itertools
import logging
import shutil
admin: fixed problems with generating last change in admin panels....
r4000 import time
project: added all source files and assets
r1 import traceback
repo-groups: implemented default personal repo groups logic....
r1094 import string
project: added all source files and assets
r1
from zope.cachedescriptors.property import Lazy as LazyProperty
Martin Bornhold
events: Trigger repository group events (create/update/delete)
r557 from rhodecode import events
project: added all source files and assets
r1 from rhodecode.model import BaseModel
exported get_repos_as_dict for new grids
r4147 from rhodecode.model.db import (_hash_key, func, or_, in_filter_generator,
Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
project: added all source files and assets
r1 UserGroup, Repository)
permissions: flush permissions on owner changes for repo and repo groups.
r4662 from rhodecode.model.permission import PermissionModel
repo-groups: implemented default personal repo groups logic....
r1094 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
project: added all source files and assets
r1 from rhodecode.lib.caching_query import FromCache
descriptions: fixed rendering problem with certain meta-tags....
r4223 from rhodecode.lib.utils2 import action_logger_generic
project: added all source files and assets
r1
log = logging.getLogger(__name__)
class RepoGroupModel(BaseModel):
cls = RepoGroup
meta-tags: fixes #4305, metatags are not taken into account when truncating output....
r1102 PERSONAL_GROUP_DESC = 'personal repo group of user `%(username)s`'
repo-groups: implemented default personal repo groups logic....
r1094 PERSONAL_GROUP_PATTERN = '${username}' # default
project: added all source files and assets
r1
def _get_user_group(self, users_group):
return self._get_instance(UserGroup, users_group,
callback=UserGroup.get_by_group_name)
def _get_repo_group(self, repo_group):
return self._get_instance(RepoGroup, repo_group,
callback=RepoGroup.get_by_group_name)
file-store: changed for stream upload endpoint.
r4611 def get_repo_group(self, repo_group):
return self._get_repo_group(repo_group)
project: added all source files and assets
r1 def get_by_group_name(self, repo_group_name, cache=None):
repo = self.sa.query(RepoGroup) \
.filter(RepoGroup.group_name == repo_group_name)
if cache:
caches: ensure we don't use non-ascii characters in cache keys....
r1749 name_key = _hash_key(repo_group_name)
repo = repo.options(
caches: cleanup code...
r5009 FromCache("sql_cache_short", f"get_repo_group_{name_key}"))
project: added all source files and assets
r1 return repo.scalar()
repo-groups: implemented default personal repo groups logic....
r1094 def get_default_create_personal_repo_group(self):
value = SettingsModel().get_setting_by_name(
'create_personal_repo_group')
return value.app_settings_value if value else None or False
def get_personal_group_name_pattern(self):
value = SettingsModel().get_setting_by_name(
'personal_repo_group_pattern')
val = value.app_settings_value if value else None
group_template = val or self.PERSONAL_GROUP_PATTERN
group_template = group_template.lstrip('/')
return group_template
def get_personal_group_name(self, user):
template = self.get_personal_group_name_pattern()
return string.Template(template).safe_substitute(
username=user.username,
user_id=user.user_id,
users: personal repo group template also can use first/last names for an user
r3659 first_name=user.first_name,
last_name=user.last_name,
repo-groups: implemented default personal repo groups logic....
r1094 )
def create_personal_repo_group(self, user, commit_early=True):
desc = self.PERSONAL_GROUP_DESC % {'username': user.username}
personal_repo_group_name = self.get_personal_group_name(user)
# create a new one
RepoGroupModel().create(
group_name=personal_repo_group_name,
group_description=desc,
owner=user.username,
personal=True,
commit_early=commit_early)
project: added all source files and assets
r1 def _create_default_perms(self, new_group):
# create default permission
default_perm = 'group.read'
def_user = User.get_default_user()
for p in def_user.user_perms:
if p.permission.permission_name.startswith('group.'):
default_perm = p.permission.permission_name
break
repo_group_to_perm = UserRepoGroupToPerm()
repo_group_to_perm.permission = Permission.get_by_key(default_perm)
repo_group_to_perm.group = new_group
models: major update for python3,...
r5070 repo_group_to_perm.user = def_user
project: added all source files and assets
r1 return repo_group_to_perm
repo-group-model: add flag to return proper object along the exported names.
r1151 def _get_group_name_and_parent(self, group_name_full, repo_in_path=False,
get_object=False):
project: added all source files and assets
r1 """
Get's the group name and a parent group name from given group name.
If repo_in_path is set to truth, we asume the full path also includes
repo name, in such case we clean the last element.
:param group_name_full:
"""
split_paths = 1
if repo_in_path:
split_paths = 2
_parts = group_name_full.rsplit(RepoGroup.url_sep(), split_paths)
if repo_in_path and len(_parts) > 1:
# such case last element is the repo_name
_parts.pop(-1)
group_name_cleaned = _parts[-1] # just the group name
parent_repo_group_name = None
if len(_parts) > 1:
parent_repo_group_name = _parts[0]
repo-group-model: add flag to return proper object along the exported names.
r1151 parent_group = None
project: added all source files and assets
r1 if parent_repo_group_name:
parent_group = RepoGroup.get_by_group_name(parent_repo_group_name)
repo-group-model: add flag to return proper object along the exported names.
r1151 if get_object:
return group_name_cleaned, parent_repo_group_name, parent_group
project: added all source files and assets
r1 return group_name_cleaned, parent_repo_group_name
def check_exist_filesystem(self, group_name, exc_on_failure=True):
create_path = os.path.join(self.repos_path, group_name)
log.debug('creating new group in %s', create_path)
if os.path.isdir(create_path):
if exc_on_failure:
repo-group: add path to exception when directory under which repo group should be created already exists.
r1152 abs_create_path = os.path.abspath(create_path)
modernize: python3 updates
r5096 raise Exception(f'Directory `{abs_create_path}` already exists !')
project: added all source files and assets
r1 return False
return True
def _create_group(self, group_name):
"""
makes repository group on filesystem
:param repo_name:
:param parent_id:
"""
self.check_exist_filesystem(group_name)
create_path = os.path.join(self.repos_path, group_name)
log.debug('creating new group in %s', create_path)
code: fixed deprecated octal calls for py3 compat.
r3268 os.makedirs(create_path, mode=0o755)
project: added all source files and assets
r1 log.debug('created group in %s', create_path)
def _rename_group(self, old, new):
"""
Renames a group on filesystem
:param group_name:
"""
if old == new:
log.debug('skipping group rename')
return
log.debug('renaming repository 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)
if os.path.isdir(new_path):
raise Exception('Was trying to rename to already '
'existing dir %s' % new_path)
shutil.move(old_path, new_path)
def _delete_filesystem_group(self, group, force_delete=False):
"""
Deletes a group from a filesystem
:param group: instance of group from database
:param force_delete: use shutil rmtree to remove all objects
"""
paths = group.full_path.split(RepoGroup.url_sep())
paths = os.sep.join(paths)
rm_path = os.path.join(self.repos_path, paths)
log.info("Removing group %s", rm_path)
# delete only if that path really exists
if os.path.isdir(rm_path):
if force_delete:
shutil.rmtree(rm_path)
else:
# archive that group`
_now = datetime.datetime.now()
_ms = str(_now.microsecond).rjust(6, '0')
modernize: python3 updates
r5096 _d = 'rm__{}_GROUP_{}'.format(
project: added all source files and assets
r1 _now.strftime('%Y%m%d_%H%M%S_' + _ms), group.name)
shutil.move(rm_path, os.path.join(self.repos_path, _d))
def create(self, group_name, group_description, owner, just_db=False,
repo-groups: implemented default personal repo groups logic....
r1094 copy_permissions=False, personal=None, commit_early=True):
project: added all source files and assets
r1
(group_name_cleaned,
parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name)
parent_group = None
if parent_group_name:
parent_group = self._get_repo_group(parent_group_name)
repo-groups: implemented default personal repo groups logic....
r1094 if not parent_group:
# we tried to create a nested group, but the parent is not
# existing
raise ValueError(
'Parent group `%s` given in `%s` group name '
'is not yet existing.' % (parent_group_name, group_name))
project: added all source files and assets
r1
repo-groups: implemented default personal repo groups logic....
r1094 # because we are doing a cleanup, we need to check if such directory
# already exists. If we don't do that we can accidentally delete
# existing directory via cleanup that can cause data issues, since
# delete does a folder rename to special syntax later cleanup
# functions can delete this
project: added all source files and assets
r1 cleanup_group = self.check_exist_filesystem(group_name,
exc_on_failure=False)
repo-groups: moved to pyramid
r2175 user = self._get_user(owner)
if not user:
raise ValueError('Owner %s not found as rhodecode user', owner)
project: added all source files and assets
r1 try:
new_repo_group = RepoGroup()
new_repo_group.user = user
new_repo_group.group_description = group_description or group_name
new_repo_group.parent_group = parent_group
new_repo_group.group_name = group_name
repo-groups: implemented default personal repo groups logic....
r1094 new_repo_group.personal = personal
project: added all source files and assets
r1
self.sa.add(new_repo_group)
# create an ADMIN permission for owner except if we're super admin,
# later owner should go into the owner field of groups
if not user.is_admin:
self.grant_user_permission(repo_group=new_repo_group,
user=owner, perm='group.admin')
if parent_group and copy_permissions:
# copy permissions from parent
user_perms = UserRepoGroupToPerm.query() \
.filter(UserRepoGroupToPerm.group == parent_group).all()
group_perms = UserGroupRepoGroupToPerm.query() \
.filter(UserGroupRepoGroupToPerm.group == parent_group).all()
for perm in user_perms:
# don't copy over the permission for user who is creating
# this group, if he is not super admin he get's admin
# permission set above
if perm.user != user or user.is_admin:
UserRepoGroupToPerm.create(
perm.user, new_repo_group, perm.permission)
for perm in group_perms:
UserGroupRepoGroupToPerm.create(
perm.users_group, new_repo_group, perm.permission)
else:
perm_obj = self._create_default_perms(new_repo_group)
self.sa.add(perm_obj)
# now commit the changes, earlier so we are sure everything is in
# the database.
if commit_early:
self.sa.commit()
if not just_db:
self._create_group(new_repo_group.group_name)
# trigger the post hook
comments: added rcextensions hoooks for comment editing, and renamed methods to remove odd log_ prefix which...
r4445 from rhodecode.lib import hooks_base
project: added all source files and assets
r1 repo_group = RepoGroup.get_by_group_name(group_name)
feat: changed last change of repo group to be commit of a latest repository.
r3689
# update repo group commit caches initially
repo_group.update_commit_cache()
comments: added rcextensions hoooks for comment editing, and renamed methods to remove odd log_ prefix which...
r4445 hooks_base.create_repository_group(
project: added all source files and assets
r1 created_by=user.username, **repo_group.get_dict())
Martin Bornhold
events: Trigger repository group events (create/update/delete)
r557 # Trigger create event.
events.trigger(events.RepoGroupCreateEvent(repo_group))
project: added all source files and assets
r1 return new_repo_group
except Exception:
self.sa.rollback()
log.exception('Exception occurred when creating repository group, '
'doing cleanup...')
# rollback things manually !
repo_group = RepoGroup.get_by_group_name(group_name)
if repo_group:
RepoGroup.delete(repo_group.group_id)
self.sa.commit()
if cleanup_group:
RepoGroupModel()._delete_filesystem_group(repo_group)
raise
def update_permissions(
self, repo_group, perm_additions=None, perm_updates=None,
perm_deletions=None, recursive=None, check_perms=True,
cur_user=None):
from rhodecode.model.repo import RepoModel
from rhodecode.lib.auth import HasUserGroupPermissionAny
if not perm_additions:
perm_additions = []
if not perm_updates:
perm_updates = []
if not perm_deletions:
perm_deletions = []
req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
audit-logs: added action logs for repository groups.
r1799 changes = {
'added': [],
'updated': [],
dan
permissions: flush all user permissions in case of default user permission changes....
r4187 'deleted': [],
'default_user_changed': None
audit-logs: added action logs for repository groups.
r1799 }
project: added all source files and assets
r1 def _set_perm_user(obj, user, perm):
if isinstance(obj, RepoGroup):
self.grant_user_permission(
repo_group=obj, user=user, perm=perm)
elif isinstance(obj, Repository):
# private repos will not allow to change the default
# permissions using recursive mode
if obj.private and user == User.DEFAULT_USER:
return
# we set group permission but we have to switch to repo
# permission
perm = perm.replace('group.', 'repository.')
RepoModel().grant_user_permission(
repo=obj, user=user, perm=perm)
def _set_perm_group(obj, users_group, perm):
if isinstance(obj, RepoGroup):
self.grant_user_group_permission(
repo_group=obj, group_name=users_group, perm=perm)
elif isinstance(obj, Repository):
# we set group permission but we have to switch to repo
# permission
perm = perm.replace('group.', 'repository.')
RepoModel().grant_user_group_permission(
repo=obj, group_name=users_group, perm=perm)
def _revoke_perm_user(obj, user):
if isinstance(obj, RepoGroup):
self.revoke_user_permission(repo_group=obj, user=user)
elif isinstance(obj, Repository):
RepoModel().revoke_user_permission(repo=obj, user=user)
def _revoke_perm_group(obj, user_group):
if isinstance(obj, RepoGroup):
self.revoke_user_group_permission(
repo_group=obj, group_name=user_group)
elif isinstance(obj, Repository):
RepoModel().revoke_user_group_permission(
repo=obj, group_name=user_group)
# start updates
log.debug('Now updating permissions for %s in recursive mode:%s',
repo_group, recursive)
# initialize check function, we'll call that multiple times
has_group_perm = HasUserGroupPermissionAny(*req_perms)
for obj in repo_group.recursive_groups_and_repos():
# iterated obj is an instance of a repos group or repository in
# that group, recursive option can be: none, repos, groups, all
if recursive == 'all':
obj = obj
elif recursive == 'repos':
# skip groups, other than this one
if isinstance(obj, RepoGroup) and not obj == repo_group:
continue
elif recursive == 'groups':
# skip repos
if isinstance(obj, Repository):
continue
else: # recursive == 'none':
# DEFAULT option - don't apply to iterated objects
# also we do a break at the end of this loop. if we are not
# in recursive mode
obj = repo_group
audit-logs: added action logs for repository groups.
r1799 change_obj = obj.get_api_data()
project: added all source files and assets
r1 # update permissions
for member_id, perm, member_type in perm_updates:
member_id = int(member_id)
if member_type == 'user':
audit-logs: added action logs for repository groups.
r1799 member_name = User.get(member_id).username
dan
permissions: flush all user permissions in case of default user permission changes....
r4187 if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER:
# NOTE(dan): detect if we changed permissions for default user
perm_obj = self.sa.query(UserRepoGroupToPerm) \
.filter(UserRepoGroupToPerm.user_id == member_id) \
.filter(UserRepoGroupToPerm.group == repo_group) \
.scalar()
if perm_obj and perm_obj.permission.permission_name != perm:
changes['default_user_changed'] = True
project: added all source files and assets
r1 # this updates also current one if found
_set_perm_user(obj, user=member_id, perm=perm)
tests: added tests for permission update views to catch obvious form errors.
r2827 elif member_type == 'user_group':
project: added all source files and assets
r1 member_name = UserGroup.get(member_id).users_group_name
if not check_perms or has_group_perm(member_name,
user=cur_user):
_set_perm_group(obj, users_group=member_id, perm=perm)
tests: added tests for permission update views to catch obvious form errors.
r2827 else:
raise ValueError("member_type must be 'user' or 'user_group' "
"got {} instead".format(member_type))
project: added all source files and assets
r1
audit-logs: added action logs for repository groups.
r1799 changes['updated'].append(
{'change_obj': change_obj, 'type': member_type,
'id': member_id, 'name': member_name, 'new_perm': perm})
project: added all source files and assets
r1 # set new permissions
for member_id, perm, member_type in perm_additions:
member_id = int(member_id)
if member_type == 'user':
audit-logs: added action logs for repository groups.
r1799 member_name = User.get(member_id).username
project: added all source files and assets
r1 _set_perm_user(obj, user=member_id, perm=perm)
tests: added tests for permission update views to catch obvious form errors.
r2827 elif member_type == 'user_group':
project: added all source files and assets
r1 # check if we have permissions to alter this usergroup
member_name = UserGroup.get(member_id).users_group_name
if not check_perms or has_group_perm(member_name,
user=cur_user):
_set_perm_group(obj, users_group=member_id, perm=perm)
tests: added tests for permission update views to catch obvious form errors.
r2827 else:
raise ValueError("member_type must be 'user' or 'user_group' "
"got {} instead".format(member_type))
project: added all source files and assets
r1
audit-logs: added action logs for repository groups.
r1799 changes['added'].append(
{'change_obj': change_obj, 'type': member_type,
'id': member_id, 'name': member_name, 'new_perm': perm})
project: added all source files and assets
r1 # delete permissions
for member_id, perm, member_type in perm_deletions:
member_id = int(member_id)
if member_type == 'user':
audit-logs: added action logs for repository groups.
r1799 member_name = User.get(member_id).username
project: added all source files and assets
r1 _revoke_perm_user(obj, user=member_id)
tests: added tests for permission update views to catch obvious form errors.
r2827 elif member_type == 'user_group':
project: added all source files and assets
r1 # check if we have permissions to alter this usergroup
member_name = UserGroup.get(member_id).users_group_name
if not check_perms or has_group_perm(member_name,
user=cur_user):
_revoke_perm_group(obj, user_group=member_id)
tests: added tests for permission update views to catch obvious form errors.
r2827 else:
raise ValueError("member_type must be 'user' or 'user_group' "
"got {} instead".format(member_type))
project: added all source files and assets
r1
audit-logs: added action logs for repository groups.
r1799 changes['deleted'].append(
{'change_obj': change_obj, 'type': member_type,
'id': member_id, 'name': member_name, 'new_perm': perm})
project: added all source files and assets
r1 # if it's not recursive call for all,repos,groups
# break the loop and don't proceed with other changes
if recursive not in ['all', 'repos', 'groups']:
break
audit-logs: added action logs for repository groups.
r1799 return changes
project: added all source files and assets
r1
def update(self, repo_group, form_data):
try:
repo_group = self._get_repo_group(repo_group)
old_path = repo_group.full_path
# change properties
if 'group_description' in form_data:
repo_group.group_description = form_data['group_description']
if 'enable_locking' in form_data:
repo_group.enable_locking = form_data['enable_locking']
if 'group_parent_id' in form_data:
parent_group = (
self._get_repo_group(form_data['group_parent_id']))
repo_group.group_parent_id = (
parent_group.group_id if parent_group else None)
repo_group.parent_group = parent_group
# mikhail: to update the full_path, we have to explicitly
# update group_name
group_name = form_data.get('group_name', repo_group.name)
repo_group.group_name = repo_group.get_new_name(group_name)
new_path = repo_group.full_path
permissions: flush permissions on owner changes for repo and repo groups.
r4662 affected_user_ids = []
project: added all source files and assets
r1 if 'user' in form_data:
permissions: flush permissions on owner changes for repo and repo groups.
r4662 old_owner_id = repo_group.user.user_id
new_owner = User.get_by_username(form_data['user'])
repo_group.user = new_owner
if old_owner_id != new_owner.user_id:
affected_user_ids = [new_owner.user_id, old_owner_id]
admin: fixed problems with generating last change in admin panels....
r4000
project: added all source files and assets
r1 self.sa.add(repo_group)
# iterate over all members of this groups and do fixes
# set locking if given
# if obj is a repoGroup also fix the name of the group according
# to the parent
# if obj is a Repo fix it's name
# this can be potentially heavy operation
for obj in repo_group.recursive_groups_and_repos():
# set the value from it's parent
obj.enable_locking = repo_group.enable_locking
if isinstance(obj, RepoGroup):
new_name = obj.get_new_name(obj.name)
log.debug('Fixing group %s to new name %s',
obj.group_name, new_name)
obj.group_name = new_name
admin: fixed problems with generating last change in admin panels....
r4000
project: added all source files and assets
r1 elif isinstance(obj, Repository):
# we need to get all repositories from this new group and
# rename them accordingly to new group path
new_name = obj.get_new_name(obj.just_name)
log.debug('Fixing repo %s to new name %s',
obj.repo_name, new_name)
obj.repo_name = new_name
admin: fixed problems with generating last change in admin panels....
r4000
project: added all source files and assets
r1 self.sa.add(obj)
self._rename_group(old_path, new_path)
Martin Bornhold
events: Trigger repository group events (create/update/delete)
r557 # Trigger update event.
events.trigger(events.RepoGroupUpdateEvent(repo_group))
permissions: flush permissions on owner changes for repo and repo groups.
r4662 if affected_user_ids:
PermissionModel().trigger_permission_flush(affected_user_ids)
project: added all source files and assets
r1 return repo_group
except Exception:
log.error(traceback.format_exc())
raise
def delete(self, repo_group, force_delete=False, fs_remove=True):
repo_group = self._get_repo_group(repo_group)
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 if not repo_group:
return False
project: added all source files and assets
r1 try:
self.sa.delete(repo_group)
if fs_remove:
self._delete_filesystem_group(repo_group, force_delete)
else:
log.debug('skipping removal from filesystem')
Martin Bornhold
events: Trigger repository group events (create/update/delete)
r557 # Trigger delete event.
events.trigger(events.RepoGroupDeleteEvent(repo_group))
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 return True
Martin Bornhold
events: Trigger repository group events (create/update/delete)
r557
project: added all source files and assets
r1 except Exception:
log.error('Error removing repo_group %s', repo_group)
raise
def grant_user_permission(self, repo_group, user, perm):
"""
Grant permission for user on given repository group, or update
existing one if found
:param repo_group: Instance of RepoGroup, repositories_group_id,
or repositories_group name
:param user: Instance of User, user_id or username
:param perm: Instance of Permission, or permission_name
"""
repo_group = self._get_repo_group(repo_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 == repo_group)\
.scalar()
if obj is None:
# create new !
obj = UserRepoGroupToPerm()
obj.group = repo_group
obj.user = user
obj.permission = permission
self.sa.add(obj)
log.debug('Granted perm %s to %s on %s', perm, user, repo_group)
action_logger_generic(
'granted permission: {} to user: {} on repogroup: {}'.format(
perm, user, repo_group), namespace='security.repogroup')
return obj
def revoke_user_permission(self, repo_group, user):
"""
Revoke permission for user on given repository group
:param repo_group: Instance of RepoGroup, repositories_group_id,
or repositories_group name
:param user: Instance of User, user_id or username
"""
repo_group = self._get_repo_group(repo_group)
user = self._get_user(user)
obj = self.sa.query(UserRepoGroupToPerm)\
.filter(UserRepoGroupToPerm.user == user)\
.filter(UserRepoGroupToPerm.group == repo_group)\
.scalar()
if obj:
self.sa.delete(obj)
log.debug('Revoked perm on %s on %s', repo_group, user)
action_logger_generic(
'revoked permission from user: {} on repogroup: {}'.format(
user, repo_group), namespace='security.repogroup')
def grant_user_group_permission(self, repo_group, group_name, perm):
"""
Grant permission for user group on given repository group, or update
existing one if found
:param repo_group: Instance of RepoGroup, repositories_group_id,
or repositories_group name
:param group_name: Instance of UserGroup, users_group_id,
or user group name
:param perm: Instance of Permission, or permission_name
"""
repo_group = self._get_repo_group(repo_group)
group_name = self._get_user_group(group_name)
permission = self._get_perm(perm)
# check if we have that permission already
obj = self.sa.query(UserGroupRepoGroupToPerm)\
.filter(UserGroupRepoGroupToPerm.group == repo_group)\
.filter(UserGroupRepoGroupToPerm.users_group == group_name)\
.scalar()
if obj is None:
# create new
obj = UserGroupRepoGroupToPerm()
obj.group = repo_group
obj.users_group = group_name
obj.permission = permission
self.sa.add(obj)
log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group)
action_logger_generic(
'granted permission: {} to usergroup: {} on repogroup: {}'.format(
perm, group_name, repo_group), namespace='security.repogroup')
return obj
def revoke_user_group_permission(self, repo_group, group_name):
"""
Revoke permission for user group on given repository group
:param repo_group: Instance of RepoGroup, repositories_group_id,
or repositories_group name
:param group_name: Instance of UserGroup, users_group_id,
or user group name
"""
repo_group = self._get_repo_group(repo_group)
group_name = self._get_user_group(group_name)
obj = self.sa.query(UserGroupRepoGroupToPerm)\
.filter(UserGroupRepoGroupToPerm.group == repo_group)\
.filter(UserGroupRepoGroupToPerm.users_group == group_name)\
.scalar()
if obj:
self.sa.delete(obj)
log.debug('Revoked perm to %s on %s', repo_group, group_name)
action_logger_generic(
'revoked permission from usergroup: {} on repogroup: {}'.format(
group_name, repo_group), namespace='security.repogroup')
feat: changed last change of repo group to be commit of a latest repository.
r3689 @classmethod
def update_commit_cache(cls, repo_groups=None):
if not repo_groups:
repo_groups = RepoGroup.getAll()
for repo_group in repo_groups:
repo_group.update_commit_cache()
project: added all source files and assets
r1 def get_repo_groups_as_dict(self, repo_group_list=None, admin=False,
super_user_actions=False):
core: use new style pyramid partial renderer where possible.
r1897 from pyramid.threadlocal import get_current_request
_render = get_current_request().get_partial_renderer(
partial-renderer: use package resource format for templates....
r2313 'rhodecode:templates/data_table/_dt_elements.mako')
core: use new style pyramid partial renderer where possible.
r1897 c = _render.get_call_context()
h = _render.get_helpers()
project: added all source files and assets
r1
def quick_menu(repo_group_name):
return _render('quick_repo_group_menu', repo_group_name)
def repo_group_lnk(repo_group_name):
return _render('repo_group_name', repo_group_name)
repository-groups: introduce last change for repository groups.
r1940 def last_change(last_change):
if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
admin: fixed problems with generating last change in admin panels....
r4000 ts = time.time()
utc_offset = (datetime.datetime.fromtimestamp(ts)
- datetime.datetime.utcfromtimestamp(ts)).total_seconds()
last_change = last_change + datetime.timedelta(seconds=utc_offset)
repository-groups: introduce last change for repository groups.
r1940 return _render("last_change", last_change)
meta-tags: fixes #4305, metatags are not taken into account when truncating output....
r1102 def desc(desc, personal):
meta-tags: cleanup support for metatags....
r2091 return _render(
'repo_group_desc', desc, personal, c.visual.stylify_metatags)
project: added all source files and assets
r1
def repo_group_actions(repo_group_id, repo_group_name, gr_count):
return _render(
'repo_group_actions', repo_group_id, repo_group_name, gr_count)
def repo_group_name(repo_group_name, children_groups):
return _render("repo_group_name", repo_group_name, children_groups)
def user_profile(username):
return _render('user_profile', username)
repo_group_data = []
for group in repo_group_list:
exported get_repos_as_dict for new grids
r4147 # NOTE(marcink): because we use only raw column we need to load it like that
changeset_cache = RepoGroup._load_changeset_cache(
'', group._changeset_cache)
last_commit_change = RepoGroup._load_commit_change(changeset_cache)
project: added all source files and assets
r1 row = {
"menu": quick_menu(group.group_name),
"name": repo_group_lnk(group.group_name),
"name_raw": group.group_name,
exported get_repos_as_dict for new grids
r4147
"last_change": last_change(last_commit_change),
ui: normalize main grid sizes and columns
r3557
"last_changeset": "",
"last_changeset_raw": "",
descriptions: fixed rendering problem with certain meta-tags....
r4223 "desc": desc(h.escape(group.group_description), group.personal),
project: added all source files and assets
r1 "top_level_repos": 0,
exported get_repos_as_dict for new grids
r4147 "owner": user_profile(group.User.username)
project: added all source files and assets
r1 }
if admin:
repo_count = group.repositories.count()
models: major update for python3,...
r5070 children_groups = list(map(
h.safe_str,
project: added all source files and assets
r1 itertools.chain((g.name for g in group.parents),
models: major update for python3,...
r5070 (x.name for x in [group]))))
project: added all source files and assets
r1 row.update({
"action": repo_group_actions(
group.group_id, group.group_name, repo_count),
"top_level_repos": repo_count,
"name": repo_group_name(group.group_name, children_groups),
})
repo_group_data.append(row)
return repo_group_data
repo-groups: moved to pyramid
r2175
dashboard: main page grids async load....
r4148 def get_repo_groups_data_table(
self, draw, start, limit,
search_q, order_by, order_dir,
auth_user, repo_group_id):
from rhodecode.model.scm import RepoGroupList
_perms = ['group.read', 'group.write', 'group.admin']
repo_groups = RepoGroup.query() \
.filter(RepoGroup.group_parent_id == repo_group_id) \
.all()
auth_repo_group_list = RepoGroupList(
repo_groups, perm_set=_perms,
extra_kwargs=dict(user=auth_user))
allowed_ids = [-1]
for repo_group in auth_repo_group_list:
allowed_ids.append(repo_group.group_id)
repo_groups_data_total_count = RepoGroup.query() \
.filter(RepoGroup.group_parent_id == repo_group_id) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(RepoGroup.group_id, allowed_ids))
) \
.count()
base_q = Session.query(
RepoGroup.group_name,
RepoGroup.group_name_hash,
RepoGroup.group_description,
RepoGroup.group_id,
RepoGroup.personal,
RepoGroup.updated_on,
RepoGroup._changeset_cache,
User,
) \
.filter(RepoGroup.group_parent_id == repo_group_id) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(RepoGroup.group_id, allowed_ids))
) \
.join(User, User.user_id == RepoGroup.user_id) \
.group_by(RepoGroup, User)
repo_groups_data_total_filtered_count = base_q.count()
sort_defined = False
if order_by == 'group_name':
sort_col = func.lower(RepoGroup.group_name)
sort_defined = True
elif order_by == 'user_username':
sort_col = User.username
else:
sort_col = getattr(RepoGroup, order_by, None)
if sort_defined or sort_col:
if order_dir == 'asc':
sort_col = sort_col.asc()
else:
sort_col = sort_col.desc()
base_q = base_q.order_by(sort_col)
base_q = base_q.offset(start).limit(limit)
repo_group_list = base_q.all()
repo_groups_data = RepoGroupModel().get_repo_groups_as_dict(
repo_group_list=repo_group_list, admin=False)
data = ({
'draw': draw,
'data': repo_groups_data,
'recordsTotal': repo_groups_data_total_count,
'recordsFiltered': repo_groups_data_total_filtered_count,
})
return data
repo-groups: moved to pyramid
r2175 def _get_defaults(self, repo_group_name):
repo_group = RepoGroup.get_by_group_name(repo_group_name)
if repo_group is None:
return None
defaults = repo_group.get_dict()
defaults['repo_group_name'] = repo_group.name
defaults['repo_group_description'] = repo_group.group_description
defaults['repo_group_enable_locking'] = repo_group.enable_locking
# we use -1 as this is how in HTML, we mark an empty group
defaults['repo_group'] = defaults['group_parent_id'] or -1
# fill owner
if repo_group.user:
defaults.update({'user': repo_group.user.username})
else:
replacement_user = User.get_first_super_admin().username
defaults.update({'user': replacement_user})
return defaults