##// END OF EJS Templates
fix(caching): fixed problems with Cache query for users....
fix(caching): fixed problems with Cache query for users. The old way of querying caused the user get query to be always cached, and returning old results even in 2fa forms. The new limited query doesn't cache the user object resolving issues

File last commit:

r5242:f8424773 default
r5365:ae8a165b default
Show More
repositories.py
253 lines | 9.3 KiB | text/x-python | PythonLexer
copyrights: updated for 2023
r5088 # Copyright (C) 2016-2023 RhodeCode GmbH
repositories: rewrote whole admin section to pyramid....
r2014 #
# 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/
import logging
import formencode
admin: cleanup imports.
r2079 import formencode.htmlfill
repositories: rewrote whole admin section to pyramid....
r2014
from pyramid.httpexceptions import HTTPFound, HTTPForbidden
application: not use config.scan(), and replace all @add_view decorator into a explicit add_view call for faster app start.
r4610
repositories: rewrote whole admin section to pyramid....
r2014 from pyramid.renderers import render
from pyramid.response import Response
apps: various fixes and improvements for python3
r5072 from sqlalchemy.orm import aliased
repositories: rewrote whole admin section to pyramid....
r2014
caches: flush cache when adding new objects so we can access them right away.
r2852 from rhodecode import events
repositories: rewrote whole admin section to pyramid....
r2014 from rhodecode.apps._base import BaseAppView, DataGridAppView
celery: celery 4.X support. Fixes #4169...
r2359 from rhodecode.lib.celerylib.utils import get_task_id
repositories: rewrote whole admin section to pyramid....
r2014
from rhodecode.lib.auth import (
LoginRequired, CSRFRequired, NotAnonymous,
HasPermissionAny, HasRepoGroupPermissionAny)
from rhodecode.lib import helpers as h
from rhodecode.lib.utils import repo_name_slug
core: multiple fixes to unicode vs str usage...
r5065 from rhodecode.lib.utils2 import safe_int, safe_str
repositories: rewrote whole admin section to pyramid....
r2014 from rhodecode.model.forms import RepoForm
permissions: properly flush user cache permissions in more cases of permission changes....
r3824 from rhodecode.model.permission import PermissionModel
repositories: rewrote whole admin section to pyramid....
r2014 from rhodecode.model.repo import RepoModel
from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
from rhodecode.model.settings import SettingsModel
admin: made all grids use same partial loading logic...
r4146 from rhodecode.model.db import (
in_filter_generator, or_, func, Session, Repository, RepoGroup, User)
repositories: rewrote whole admin section to pyramid....
r2014
log = logging.getLogger(__name__)
class AdminReposView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
return c
def _load_form_data(self, c):
acl_groups = RepoGroupList(RepoGroup.query().all(),
perm_set=['group.write', 'group.admin'])
c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
core: multiple fixes to unicode vs str usage...
r5065 c.repo_groups_choices = list(map(lambda k: safe_str(k[0]), c.repo_groups))
repositories: rewrote whole admin section to pyramid....
r2014 c.personal_repo_group = self._rhodecode_user.personal_repo_group
@LoginRequired()
@NotAnonymous()
repo-forks: security, fix issue when forging fork_repo_id could allow reading...
r2172 # perms check inside
repositories: rewrote whole admin section to pyramid....
r2014 def repository_list(self):
c = self.load_default_context()
admin: made all grids use same partial loading logic...
r4146 return self._get_template_context(c)
repositories: rewrote whole admin section to pyramid....
r2014
admin: made all grids use same partial loading logic...
r4146 @LoginRequired()
@NotAnonymous()
# perms check inside
def repository_list_data(self):
self.load_default_context()
column_map = {
grids: columns and sorting fixes
r4150 'name': 'repo_name',
admin: made all grids use same partial loading logic...
r4146 'desc': 'description',
grids: columns and sorting fixes
r4150 'last_change': 'updated_on',
admin: made all grids use same partial loading logic...
r4146 'owner': 'user_username',
}
draw, start, limit = self._extract_chunk(self.request)
search_q, order_by, order_dir = self._extract_ordering(
self.request, column_map=column_map)
_perms = ['repository.admin']
allowed_ids = [-1] + self._rhodecode_user.repo_acl_ids_from_stack(_perms)
repos_data_total_count = Repository.query() \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(Repository.repo_id, allowed_ids))
) \
.count()
apps: various fixes and improvements for python3
r5072 RepoFork = aliased(Repository)
OwnerUser = aliased(User)
admin: made all grids use same partial loading logic...
r4146 base_q = Session.query(
Repository.repo_id,
Repository.repo_name,
Repository.description,
Repository.repo_type,
Repository.repo_state,
Repository.private,
Repository.archived,
Repository.updated_on,
Repository._changeset_cache,
apps: various fixes and improvements for python3
r5072 RepoFork.repo_name.label('fork_repo_name'),
OwnerUser.username.label('owner_username'),
admin: made all grids use same partial loading logic...
r4146 ) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(Repository.repo_id, allowed_ids))
) \
apps: various fixes and improvements for python3
r5072 .outerjoin(RepoFork, Repository.fork_id == RepoFork.repo_id) \
.join(OwnerUser, Repository.user_id == OwnerUser.user_id)
admin: made all grids use same partial loading logic...
r4146
if search_q:
apps: modernize for python3
r5093 like_expression = f'%{safe_str(search_q)}%'
admin: made all grids use same partial loading logic...
r4146 base_q = base_q.filter(or_(
Repository.repo_name.ilike(like_expression),
))
apps: various fixes and improvements for python3
r5072 #TODO: check if we need group_by here ?
#base_q = base_q.group_by(Repository, User)
admin: made all grids use same partial loading logic...
r4146 repos_data_total_filtered_count = base_q.count()
sort_defined = False
if order_by == 'repo_name':
sort_col = func.lower(Repository.repo_name)
sort_defined = True
elif order_by == 'user_username':
apps: various fixes and improvements for python3
r5072 sort_col = OwnerUser.username
admin: made all grids use same partial loading logic...
r4146 else:
sort_col = getattr(Repository, 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)
repos_list = base_q.all()
repositories: rewrote whole admin section to pyramid....
r2014 repos_data = RepoModel().get_repos_as_dict(
admin: made all grids use same partial loading logic...
r4146 repo_list=repos_list, admin=True, super_user_actions=True)
repositories: rewrote whole admin section to pyramid....
r2014
admin: made all grids use same partial loading logic...
r4146 data = ({
'draw': draw,
'data': repos_data,
'recordsTotal': repos_data_total_count,
'recordsFiltered': repos_data_total_filtered_count,
})
return data
repositories: rewrote whole admin section to pyramid....
r2014
@LoginRequired()
@NotAnonymous()
# perms check inside
def repository_new(self):
c = self.load_default_context()
new_repo = self.request.GET.get('repo', '')
create: fixed case for repo groups that didn't pre-fill the repo group from GET param....
r4424 parent_group_id = safe_int(self.request.GET.get('parent_group'))
_gr = RepoGroup.get(parent_group_id)
repositories: rewrote whole admin section to pyramid....
r2014
if not HasPermissionAny('hg.admin', 'hg.create.repository')():
# you're not super admin nor have global create permissions,
# but maybe you have at least write permission to a parent group ?
gr_name = _gr.group_name if _gr else None
# create repositories with write permission on group is set to true
create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
if not (group_admin or (group_write and create_on_write)):
raise HTTPForbidden()
self._load_form_data(c)
c.new_repo = repo_name_slug(new_repo)
# apply the defaults from defaults page
defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
# set checkbox to autochecked
defaults['repo_copy_permissions'] = True
parent_group_choice = '-1'
if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
parent_group_choice = self._rhodecode_user.personal_repo_group
create: fixed case for repo groups that didn't pre-fill the repo group from GET param....
r4424 if parent_group_id and _gr:
if parent_group_id in [x[0] for x in c.repo_groups]:
apps: various fixes and improvements for python3
r5072 parent_group_choice = safe_str(parent_group_id)
repositories: rewrote whole admin section to pyramid....
r2014
defaults.update({'repo_group': parent_group_choice})
data = render('rhodecode:templates/admin/repos/repo_add.mako',
self._get_template_context(c), self.request)
html = formencode.htmlfill.render(
data,
defaults=defaults,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
@LoginRequired()
@NotAnonymous()
@CSRFRequired()
# perms check inside
def repository_create(self):
c = self.load_default_context()
form_result = {}
celery: celery 4.X support. Fixes #4169...
r2359 self._load_form_data(c)
permissions: handle more cases for invalidating permission caches...
r3411
repositories: rewrote whole admin section to pyramid....
r2014 try:
# CanWriteToGroup validators checks permissions of this POST
pylons: remove pylons as dependency...
r2351 form = RepoForm(
landing-rev: fixes #4102, use branches instead of landing tip refs by default....
r3881 self.request.translate, repo_groups=c.repo_groups_choices)()
celery: celery 4.X support. Fixes #4169...
r2359 form_result = form.to_python(dict(self.request.POST))
permissions: handle more cases for invalidating permission caches...
r3411 copy_permissions = form_result.get('repo_copy_permissions')
repositories: rewrote whole admin section to pyramid....
r2014 # create is done sometimes async on celery, db transaction
# management is handled there.
task = RepoModel().create(form_result, self._rhodecode_user.user_id)
celery: celery 4.X support. Fixes #4169...
r2359 task_id = get_task_id(task)
repositories: rewrote whole admin section to pyramid....
r2014 except formencode.Invalid as errors:
data = render('rhodecode:templates/admin/repos/repo_add.mako',
self._get_template_context(c), self.request)
html = formencode.htmlfill.render(
data,
defaults=errors.value,
forms: fixed error handling in forms
r5018 errors=errors.unpack_errors() or {},
repositories: rewrote whole admin section to pyramid....
r2014 prefix_error=False,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
except Exception as e:
msg = self._log_creation_exception(e, form_result.get('repo_name'))
h.flash(msg, category='error')
raise HTTPFound(h.route_path('home'))
permissions: handle more cases for invalidating permission caches...
r3411 repo_name = form_result.get('repo_name_full')
fix(permissions): use consent cache purge when creating repos, similar as groups and repo groups
r5242 PermissionModel().trigger_permission_flush()
caches: flush cache when adding new objects so we can access them right away.
r2852
repositories: rewrote whole admin section to pyramid....
r2014 raise HTTPFound(
permissions: handle more cases for invalidating permission caches...
r3411 h.route_path('repo_creating', repo_name=repo_name,
repositories: rewrote whole admin section to pyramid....
r2014 _query=dict(task_id=task_id)))