##// 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:

r5088:8f6d1ed6 default
r5365:ae8a165b default
Show More
user_groups.py
252 lines | 9.6 KiB | text/x-python | PythonLexer
apps: removed utf8 marker
r5053
user-groups: moved the display of user group into a pyramid view
r1980
copyrights: updated for 2023
r5088 # Copyright (C) 2016-2023 RhodeCode GmbH
user-groups: moved the display of user group into a pyramid view
r1980 #
# 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
user-groups: rewrote the app to pyramid...
r2068 import formencode
import formencode.htmlfill
user-groups: moved the display of user group into a pyramid view
r1980 from pyramid.httpexceptions import HTTPFound
application: not use config.scan(), and replace all @add_view decorator into a explicit add_view call for faster app start.
r4610
user-groups: rewrote the app to pyramid...
r2068 from pyramid.response import Response
from pyramid.renderers import render
user-groups: moved the display of user group into a pyramid view
r1980
caches: flush cache when adding new objects so we can access them right away.
r2852 from rhodecode import events
user-groups: moved the display of user group into a pyramid view
r1980 from rhodecode.apps._base import BaseAppView, DataGridAppView
from rhodecode.lib.auth import (
user-groups: rewrote the app to pyramid...
r2068 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
from rhodecode.lib import helpers as h, audit_logger
core: multiple fixes to unicode vs str usage...
r5065 from rhodecode.lib.str_utils import safe_str
user-groups: rewrote the app to pyramid...
r2068
from rhodecode.model.forms import UserGroupForm
from rhodecode.model.permission import PermissionModel
users/user_groups: ported permission summary pages into pyramid....
r1998 from rhodecode.model.db import (
user-groups: fixed in_ filters for large ammount of data.
r3624 or_, count, User, UserGroup, UserGroupMember, in_filter_generator)
user-groups: moved the display of user group into a pyramid view
r1980 from rhodecode.model.meta import Session
user-groups: rewrote the app to pyramid...
r2068 from rhodecode.model.user_group import UserGroupModel
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 from rhodecode.model.db import true
user-groups: moved the display of user group into a pyramid view
r1980
log = logging.getLogger(__name__)
class AdminUserGroupsView(BaseAppView, DataGridAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
user-groups: rewrote the app to pyramid...
r2068 PermissionModel().set_global_permission_choices(
c, gettext_translator=self.request.translate)
user-groups: moved the display of user group into a pyramid view
r1980 return c
# permission check in data loading of
# `user_groups_list_data` via UserGroupList
auth: added @LoginRequired() decorators for user/user_group views....
r2001 @LoginRequired()
user-groups: moved the display of user group into a pyramid view
r1980 @NotAnonymous()
def user_groups_list(self):
c = self.load_default_context()
return self._get_template_context(c)
# permission check inside
auth: added @LoginRequired() decorators for user/user_group views....
r2001 @LoginRequired()
user-groups: moved the display of user group into a pyramid view
r1980 @NotAnonymous()
def user_groups_list_data(self):
views: load template context for XHR views....
r2308 self.load_default_context()
user-groups: moved the display of user group into a pyramid view
r1980 column_map = {
'active': 'users_group_active',
'description': 'user_group_description',
'members': 'members_total',
'owner': 'user_username',
'sync': 'group_data'
}
draw, start, limit = self._extract_chunk(self.request)
search_q, order_by, order_dir = self._extract_ordering(
self.request, column_map=column_map)
user-groups: use request partial renderer and not the pylons one.
r2109 _render = self.request.get_partial_renderer(
partial-renderer: use package resource format for templates....
r2313 'rhodecode:templates/data_table/_dt_elements.mako')
user-groups: moved the display of user group into a pyramid view
r1980
user-groups: on admin view redirect links to public profile. We have an explicit...
r2639 def user_group_name(user_group_name):
return _render("user_group_name", user_group_name)
user-groups: moved the display of user group into a pyramid view
r1980
def user_group_actions(user_group_id, user_group_name):
return _render("user_group_actions", user_group_id, user_group_name)
def user_profile(username):
return _render('user_profile', username)
admin: made all grids use same partial loading logic...
r4146 _perms = ['usergroup.admin']
allowed_ids = [-1] + self._rhodecode_user.user_group_acl_ids_from_stack(_perms)
user-group-admin: use a proper auth filter....
r1986
user_groups_data_total_count = UserGroup.query()\
user-groups: fixed in_ filters for large ammount of data.
r3624 .filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(UserGroup.users_group_id, allowed_ids)
))\
user-group-admin: use a proper auth filter....
r1986 .count()
user-groups: moved the display of user group into a pyramid view
r1980
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 user_groups_data_total_inactive_count = UserGroup.query()\
user-groups: fixed in_ filters for large ammount of data.
r3624 .filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(UserGroup.users_group_id, allowed_ids)
))\
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 .filter(UserGroup.users_group_active != true()).count()
user-groups: moved the display of user group into a pyramid view
r1980 member_count = count(UserGroupMember.user_id)
base_q = Session.query(
UserGroup.users_group_name,
UserGroup.user_group_description,
UserGroup.users_group_active,
UserGroup.users_group_id,
UserGroup.group_data,
User,
member_count.label('member_count')
user-groups: fixed in_ filters for large ammount of data.
r3624 ) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(UserGroup.users_group_id, allowed_ids)
)) \
db: use more consistent sorting using real objects, strings are deprecated in laters sqlalchemy query syntax.
r3949 .outerjoin(UserGroupMember, UserGroupMember.users_group_id == UserGroup.users_group_id) \
user-groups: fixed in_ filters for large ammount of data.
r3624 .join(User, User.user_id == UserGroup.user_id) \
.group_by(UserGroup, User)
user-groups: moved the display of user group into a pyramid view
r1980
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
user-groups: moved the display of user group into a pyramid view
r1980 if search_q:
core: multiple fixes to unicode vs str usage...
r5065 like_expression = u'%{}%'.format(safe_str(search_q))
user-groups: moved the display of user group into a pyramid view
r1980 base_q = base_q.filter(or_(
UserGroup.users_group_name.ilike(like_expression),
))
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
user-groups: moved the display of user group into a pyramid view
r1980
user_groups_data_total_filtered_count = base_q.count()
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 user_groups_data_total_filtered_inactive_count = base_q_inactive.count()
user-groups: moved the display of user group into a pyramid view
r1980
user-groups: fixed in_ filters for large ammount of data.
r3624 sort_defined = False
user-groups: moved the display of user group into a pyramid view
r1980 if order_by == 'members_total':
sort_col = member_count
user-groups: fixed in_ filters for large ammount of data.
r3624 sort_defined = True
user-groups: moved the display of user group into a pyramid view
r1980 elif order_by == 'user_username':
sort_col = User.username
else:
sort_col = getattr(UserGroup, order_by, None)
user-groups: fixed in_ filters for large ammount of data.
r3624 if sort_defined or sort_col:
user-groups: moved the display of user group into a pyramid view
r1980 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)
# authenticated access to user groups
user-group-admin: use a proper auth filter....
r1986 auth_user_group_list = base_q.all()
user-groups: moved the display of user group into a pyramid view
r1980
user_groups_data = []
for user_gr in auth_user_group_list:
user-groups: fixed in_ filters for large ammount of data.
r3624 row = {
user-groups: on admin view redirect links to public profile. We have an explicit...
r2639 "users_group_name": user_group_name(user_gr.users_group_name),
user-groups: moved the display of user group into a pyramid view
r1980 "description": h.escape(user_gr.user_group_description),
"members": user_gr.member_count,
# NOTE(marcink): because of advanced query we
# need to load it like that
user-groups: fix sync flag extraction.
r2672 "sync": UserGroup._load_sync(
UserGroup._load_group_data(user_gr.group_data)),
user-groups: moved the display of user group into a pyramid view
r1980 "active": h.bool2icon(user_gr.users_group_active),
"owner": user_profile(user_gr.User.username),
"action": user_group_actions(
user_gr.users_group_id, user_gr.users_group_name)
user-groups: fixed in_ filters for large ammount of data.
r3624 }
user_groups_data.append(row)
user-groups: moved the display of user group into a pyramid view
r1980
data = ({
'draw': draw,
'data': user_groups_data,
'recordsTotal': user_groups_data_total_count,
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 'recordsTotalInactive': user_groups_data_total_inactive_count,
user-groups: moved the display of user group into a pyramid view
r1980 'recordsFiltered': user_groups_data_total_filtered_count,
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 'recordsFilteredInactive': user_groups_data_total_filtered_inactive_count,
user-groups: moved the display of user group into a pyramid view
r1980 })
return data
@LoginRequired()
user-groups: rewrote the app to pyramid...
r2068 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
def user_groups_new(self):
users/user_groups: ported permission summary pages into pyramid....
r1998 c = self.load_default_context()
return self._get_template_context(c)
@LoginRequired()
user-groups: rewrote the app to pyramid...
r2068 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
@CSRFRequired()
def user_groups_create(self):
_ = self.request.translate
c = self.load_default_context()
pylons: remove pylons as dependency...
r2351 users_group_form = UserGroupForm(self.request.translate)()
user-groups: rewrote the app to pyramid...
r2068
user_group_name = self.request.POST.get('users_group_name')
try:
form_result = users_group_form.to_python(dict(self.request.POST))
user_group = UserGroupModel().create(
name=form_result['users_group_name'],
description=form_result['user_group_description'],
owner=self._rhodecode_user.user_id,
active=form_result['users_group_active'])
Session().flush()
creation_data = user_group.get_api_data()
user_group_name = form_result['users_group_name']
audit_logger.store_web(
'user_group.create', action_data={'data': creation_data},
user=self._rhodecode_user)
users/user_groups: ported permission summary pages into pyramid....
r1998
user-groups: rewrote the app to pyramid...
r2068 user_group_link = h.link_to(
h.escape(user_group_name),
h.route_path(
'edit_user_group', user_group_id=user_group.users_group_id))
h.flash(h.literal(_('Created user group %(user_group_link)s')
% {'user_group_link': user_group_link}),
category='success')
Session().commit()
user_group_id = user_group.users_group_id
except formencode.Invalid as errors:
users/user_groups: ported permission summary pages into pyramid....
r1998
user-groups: rewrote the app to pyramid...
r2068 data = render(
'rhodecode:templates/admin/user_groups/user_group_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 {},
user-groups: rewrote the app to pyramid...
r2068 prefix_error=False,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
except Exception:
log.exception("Exception creating user group")
h.flash(_('Error occurred during creation of user group %s') \
% user_group_name, category='error')
raise HTTPFound(h.route_path('user_groups_new'))
permissions: flush all users permissions when creating a new user group....
r4727 PermissionModel().trigger_permission_flush()
permissions: properly flush user cache permissions in more cases of permission changes....
r3824
user-groups: rewrote the app to pyramid...
r2068 raise HTTPFound(
h.route_path('edit_user_group', user_group_id=user_group_id))