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

r5318:ad20d5fb default
r5365:ae8a165b default
Show More
users.py
1321 lines | 48.5 KiB | text/x-python | PythonLexer
copyrights: updated for 2023
r5088 # Copyright (C) 2016-2023 RhodeCode GmbH
admin: moved auth tokens into pyramid view....
r1518 #
# 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
admin-users: replace the previous nullslast() with db independent solution....
r1630 import datetime
users-admin: moved views into pyramid for editing emails and ips....
r1821 import formencode
admin: cleanup imports.
r2079 import formencode.htmlfill
admin: moved auth tokens into pyramid view....
r1518
from pyramid.httpexceptions import HTTPFound
users: ported controllers from pylons into pyramid views.
r2114 from pyramid.renderers import render
from pyramid.response import Response
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559
permissions: handle more cases for invalidating permission caches...
r3411 from rhodecode import events
users: ported controllers from pylons into pyramid views.
r2114 from rhodecode.apps._base import BaseAppView, DataGridAppView, UserAppView
chore(imports): optimize imports for ssh events
r5318 from rhodecode.apps.ssh_support.events import SshKeyFileChangeEvent
dan
authentication: allow super-admins to change bound authentication for users....
r3988 from rhodecode.authentication.base import get_authn_registry, RhodeCodeExternalAuthPlugin
users: ported controllers from pylons into pyramid views.
r2114 from rhodecode.authentication.plugins import auth_rhodecode
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 from rhodecode.events import trigger
core: added user-notice logic to push notice messages....
r4300 from rhodecode.model.db import true, UserNotice
users-admin: moved views into pyramid for editing emails and ips....
r1821
app: improve logging, and remove DB calls on app startup.
r4548 from rhodecode.lib import audit_logger, rc_cache, auth
users: ported controllers from pylons into pyramid views.
r2114 from rhodecode.lib.exceptions import (
UserCreationError, UserOwnsReposException, UserOwnsRepoGroupsException,
dan
users: added option to detach pull requests for users which we delete....
r4351 UserOwnsUserGroupsException, UserOwnsPullRequestsException,
UserOwnsArtifactsException, DefaultUserException)
json: fixed calls to json after orjson implementation
r4974 from rhodecode.lib import ext_json
admin: moved auth tokens into pyramid view....
r1518 from rhodecode.lib.auth import (
LoginRequired, HasPermissionAllDecorator, CSRFRequired)
from rhodecode.lib import helpers as h
dan
webhelpers: replaced paginate library with custom lib
r4091 from rhodecode.lib.helpers import SqlPage
core: multiple fixes to unicode vs str usage...
r5065 from rhodecode.lib.utils2 import safe_int, safe_str, AttributeDict
admin: moved auth tokens into pyramid view....
r1518 from rhodecode.model.auth_token import AuthTokenModel
users: ported controllers from pylons into pyramid views.
r2114 from rhodecode.model.forms import (
pylons: remove pylons as dependency...
r2351 UserForm, UserIndividualPermissionsForm, UserPermissionsForm,
UserExtraEmailForm, UserExtraIpForm)
users: ported controllers from pylons into pyramid views.
r2114 from rhodecode.model.permission import PermissionModel
from rhodecode.model.repo_group import RepoGroupModel
users: added SSH key management for user admin pages
r1993 from rhodecode.model.ssh_key import SshKeyModel
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559 from rhodecode.model.user import UserModel
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556 from rhodecode.model.user_group import UserGroupModel
users: added SSH key management for user admin pages
r1993 from rhodecode.model.db import (
users: ported controllers from pylons into pyramid views.
r2114 or_, coalesce,IntegrityError, User, UserGroup, UserIpMap, UserEmailMap,
UserApiKeys, UserSshKeys, RepoGroup)
admin: moved auth tokens into pyramid view....
r1518 from rhodecode.model.meta import Session
log = logging.getLogger(__name__)
admin-users: fix wrong class name used.
r1653 class AdminUsersView(BaseAppView, DataGridAppView):
admin: moved auth tokens into pyramid view....
r1518
def load_default_context(self):
c = self._get_local_tmpl_context()
return c
auth: added @LoginRequired() decorators for user/user_group views....
r2001 @LoginRequired()
admin-users: moved grid browsing to pyramid....
r1520 @HasPermissionAllDecorator('hg.admin')
def users_list(self):
c = self.load_default_context()
return self._get_template_context(c)
auth: added @LoginRequired() decorators for user/user_group views....
r2001 @LoginRequired()
admin-users: moved grid browsing to pyramid....
r1520 @HasPermissionAllDecorator('hg.admin')
def users_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 = {
'first_name': 'name',
'last_name': 'lastname',
}
admin-users: moved grid browsing to pyramid....
r1520 draw, start, limit = self._extract_chunk(self.request)
user-groups: moved the display of user group into a pyramid view
r1980 search_q, order_by, order_dir = self._extract_ordering(
self.request, column_map=column_map)
core: use new style pyramid partial renderer where possible.
r1897 _render = self.request.get_partial_renderer(
partial-renderer: use package resource format for templates....
r2313 'rhodecode:templates/data_table/_dt_elements.mako')
admin-users: moved grid browsing to pyramid....
r1520
def user_actions(user_id, username):
return _render("user_actions", user_id, username)
users_data_total_count = User.query()\
.filter(User.username != User.DEFAULT_USER) \
.count()
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 users_data_total_inactive_count = User.query()\
.filter(User.username != User.DEFAULT_USER) \
.filter(User.active != true())\
.count()
admin-users: moved grid browsing to pyramid....
r1520 # json generate
base_q = User.query().filter(User.username != User.DEFAULT_USER)
Bartłomiej Wołyńczyk
admin users and admin users group: add number of inactive users/users_group, resolves #5454
r2727 base_inactive_q = base_q.filter(User.active != true())
admin-users: moved grid browsing to pyramid....
r1520
if search_q:
core: multiple fixes to unicode vs str usage...
r5065 like_expression = '%{}%'.format(safe_str(search_q))
admin-users: moved grid browsing to pyramid....
r1520 base_q = base_q.filter(or_(
User.username.ilike(like_expression),
User._email.ilike(like_expression),
User.name.ilike(like_expression),
User.lastname.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_inactive_q = base_q.filter(User.active != true())
admin-users: moved grid browsing to pyramid....
r1520
users_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 users_data_total_filtered_inactive_count = base_inactive_q.count()
admin-users: moved grid browsing to pyramid....
r1520
sort_col = getattr(User, order_by, None)
admin-users: replace the previous nullslast() with db independent solution....
r1630 if sort_col:
if order_dir == 'asc':
# handle null values properly to order by NULL last
if order_by in ['last_activity']:
sort_col = coalesce(sort_col, datetime.date.max)
sort_col = sort_col.asc()
else:
# handle null values properly to order by NULL last
if order_by in ['last_activity']:
sort_col = coalesce(sort_col, datetime.date.min)
sort_col = sort_col.desc()
admin-users: moved grid browsing to pyramid....
r1520
admin-users: replace the previous nullslast() with db independent solution....
r1630 base_q = base_q.order_by(sort_col)
admin-users: moved grid browsing to pyramid....
r1520 base_q = base_q.offset(start).limit(limit)
admin-users: replace the previous nullslast() with db independent solution....
r1630
admin-users: moved grid browsing to pyramid....
r1520 users_list = base_q.all()
users_data = []
for user in users_list:
users_data.append({
renderer: remove usage of old non request PartialRenderer
r1947 "username": h.gravatar_with_user(self.request, user.username),
admin-users: moved grid browsing to pyramid....
r1520 "email": user.email,
security: use new safe escaped user attributes across the application....
r1815 "first_name": user.first_name,
"last_name": user.last_name,
admin-users: moved grid browsing to pyramid....
r1520 "last_login": h.format_date(user.last_login),
users: change last activity to re-use new column.
r1546 "last_activity": h.format_date(user.last_activity),
admin-users: moved grid browsing to pyramid....
r1520 "active": h.bool2icon(user.active),
"active_raw": user.active,
"admin": h.bool2icon(user.admin),
"extern_type": user.extern_type,
"extern_name": user.extern_name,
"action": user_actions(user.user_id, user.username),
})
data = ({
'draw': draw,
'data': users_data,
'recordsTotal': users_data_total_count,
'recordsFiltered': users_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 'recordsTotalInactive': users_data_total_inactive_count,
'recordsFilteredInactive': users_data_total_filtered_inactive_count
admin-users: moved grid browsing to pyramid....
r1520 })
return data
users: ported controllers from pylons into pyramid views.
r2114 def _set_personal_repo_group_template_vars(self, c_obj):
DummyUser = AttributeDict({
'username': '${username}',
'user_id': '${user_id}',
})
c_obj.default_create_repo_group = RepoGroupModel() \
.get_default_create_personal_repo_group()
c_obj.personal_repo_group_name = RepoGroupModel() \
.get_personal_group_name(DummyUser)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def users_new(self):
_ = self.request.translate
c = self.load_default_context()
auth/security: enforce that external users cannot reset their password.
r3258 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid
users: ported controllers from pylons into pyramid views.
r2114 self._set_personal_repo_group_template_vars(c)
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def users_create(self):
_ = self.request.translate
c = self.load_default_context()
auth/security: enforce that external users cannot reset their password.
r3258 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid
users: ported controllers from pylons into pyramid views.
r2114 user_model = UserModel()
pylons: remove pylons as dependency...
r2351 user_form = UserForm(self.request.translate)()
users: ported controllers from pylons into pyramid views.
r2114 try:
form_result = user_form.to_python(dict(self.request.POST))
user = user_model.create(form_result)
Session().flush()
creation_data = user.get_api_data()
username = form_result['username']
audit_logger.store_web(
'user.create', action_data={'data': creation_data},
user=c.rhodecode_user)
user_link = h.link_to(
h.escape(username),
h.route_path('user_edit', user_id=user.user_id))
h.flash(h.literal(_('Created user %(user_link)s')
% {'user_link': user_link}), category='success')
Session().commit()
except formencode.Invalid as errors:
self._set_personal_repo_group_template_vars(c)
data = render(
'rhodecode:templates/admin/users/user_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 {},
users: ported controllers from pylons into pyramid views.
r2114 prefix_error=False,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
except UserCreationError as e:
core: multiple fixes to unicode vs str usage...
r5065 h.flash(safe_str(e), 'error')
users: ported controllers from pylons into pyramid views.
r2114 except Exception:
log.exception("Exception creation of user")
h.flash(_('Error occurred during creation of user %s')
% self.request.POST.get('username'), category='error')
raise HTTPFound(h.route_path('users'))
class UsersView(UserAppView):
ALLOW_SCOPED_TOKENS = False
"""
This view has alternative version inside EE, if modified please take a look
in there as well.
"""
dan
authentication: allow super-admins to change bound authentication for users....
r3988 def get_auth_plugins(self):
valid_plugins = []
authn_registry = get_authn_registry(self.request.registry)
for plugin in authn_registry.get_plugins_for_authentication():
if isinstance(plugin, RhodeCodeExternalAuthPlugin):
valid_plugins.append(plugin)
elif plugin.name == 'rhodecode':
valid_plugins.append(plugin)
# extend our choices if user has set a bound plugin which isn't enabled at the
# moment
extern_type = self.db_user.extern_type
if extern_type not in [x.uid for x in valid_plugins]:
try:
plugin = authn_registry.get_plugin_by_uid(extern_type)
if plugin:
valid_plugins.append(plugin)
except Exception:
log.exception(
modernize: updates for python3
r5095 f'Could not extend user plugins with `{extern_type}`')
dan
authentication: allow super-admins to change bound authentication for users....
r3988 return valid_plugins
users: ported controllers from pylons into pyramid views.
r2114 def load_default_context(self):
dan
authentication: allow super-admins to change bound authentication for users....
r3988 req = self.request
users: ported controllers from pylons into pyramid views.
r2114 c = self._get_local_tmpl_context()
c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
c.allowed_languages = [
('en', 'English (en)'),
('de', 'German (de)'),
('fr', 'French (fr)'),
('it', 'Italian (it)'),
('ja', 'Japanese (ja)'),
('pl', 'Polish (pl)'),
('pt', 'Portuguese (pt)'),
('ru', 'Russian (ru)'),
('zh', 'Chinese (zh)'),
]
dan
authentication: allow super-admins to change bound authentication for users....
r3988
c.allowed_extern_types = [
(x.uid, x.get_display_name()) for x in self.get_auth_plugins()
]
app: improve logging, and remove DB calls on app startup.
r4548 perms = req.registry.settings.get('available_permissions')
if not perms:
# inject info about available permissions
auth.set_available_permissions(req.registry.settings)
users: ported controllers from pylons into pyramid views.
r2114
c.available_permissions = req.registry.settings['available_permissions']
PermissionModel().set_global_permission_choices(
c, gettext_translator=req.translate)
return c
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def user_update(self):
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
c.active = 'profile'
c.extern_type = c.user.extern_type
c.extern_name = c.user.extern_name
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
available_languages = [x[0] for x in c.allowed_languages]
pylons: remove pylons as dependency...
r2351 _form = UserForm(self.request.translate, edit=True,
available_languages=available_languages,
users: ported controllers from pylons into pyramid views.
r2114 old_data={'user_id': user_id,
'email': c.user.email})()
users: enable full edit mode for super admins....
r4740
c.edit_mode = self.request.POST.get('edit') == '1'
users: ported controllers from pylons into pyramid views.
r2114 form_result = {}
old_values = c.user.get_api_data()
try:
form_result = _form.to_python(dict(self.request.POST))
dan
authentication: allow super-admins to change bound authentication for users....
r3988 skip_attrs = ['extern_name']
users: ported controllers from pylons into pyramid views.
r2114 # TODO: plugin should define if username can be updated
users: enable full edit mode for super admins....
r4740
if c.extern_type != "rhodecode" and not c.edit_mode:
users: ported controllers from pylons into pyramid views.
r2114 # forbid updating username for external accounts
skip_attrs.append('username')
UserModel().update_user(
user_id, skip_attrs=skip_attrs, **form_result)
audit_logger.store_web(
'user.edit', action_data={'old_data': old_values},
user=c.rhodecode_user)
Session().commit()
h.flash(_('User updated successfully'), category='success')
except formencode.Invalid as errors:
data = render(
'rhodecode:templates/admin/users/user_edit.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 {},
users: ported controllers from pylons into pyramid views.
r2114 prefix_error=False,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
except UserCreationError as e:
core: multiple fixes to unicode vs str usage...
r5065 h.flash(safe_str(e), 'error')
users: ported controllers from pylons into pyramid views.
r2114 except Exception:
log.exception("Exception updating user")
h.flash(_('Error occurred during update of user %s')
% form_result.get('username'), category='error')
raise HTTPFound(h.route_path('user_edit', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def user_delete(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
apps: various fixes and improvements for python3
r5072 _repos = len(c.user.repositories)
_repo_groups = len(c.user.repository_groups)
_user_groups = len(c.user.user_groups)
_pull_requests = len(c.user.user_pull_requests)
_artifacts = len(c.user.artifacts)
users: ported controllers from pylons into pyramid views.
r2114
handle_repos = None
handle_repo_groups = None
handle_user_groups = None
dan
users: added option to detach pull requests for users which we delete....
r4351 handle_pull_requests = None
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 handle_artifacts = None
# calls for flash of handle based on handle case detach or delete
def set_handle_flash_repos():
handle = handle_repos
if handle == 'detach':
apps: various fixes and improvements for python3
r5072 h.flash(_('Detached %s repositories') % _repos,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
elif handle == 'delete':
apps: various fixes and improvements for python3
r5072 h.flash(_('Deleted %s repositories') % _repos,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
def set_handle_flash_repo_groups():
handle = handle_repo_groups
if handle == 'detach':
apps: various fixes and improvements for python3
r5072 h.flash(_('Detached %s repository groups') % _repo_groups,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
elif handle == 'delete':
apps: various fixes and improvements for python3
r5072 h.flash(_('Deleted %s repository groups') % _repo_groups,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
def set_handle_flash_user_groups():
handle = handle_user_groups
if handle == 'detach':
apps: various fixes and improvements for python3
r5072 h.flash(_('Detached %s user groups') % _user_groups,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
elif handle == 'delete':
apps: various fixes and improvements for python3
r5072 h.flash(_('Deleted %s user groups') % _user_groups,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
dan
users: added option to detach pull requests for users which we delete....
r4351 def set_handle_flash_pull_requests():
handle = handle_pull_requests
if handle == 'detach':
apps: various fixes and improvements for python3
r5072 h.flash(_('Detached %s pull requests') % _pull_requests,
dan
users: added option to detach pull requests for users which we delete....
r4351 category='success')
elif handle == 'delete':
apps: various fixes and improvements for python3
r5072 h.flash(_('Deleted %s pull requests') % _pull_requests,
dan
users: added option to detach pull requests for users which we delete....
r4351 category='success')
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 def set_handle_flash_artifacts():
handle = handle_artifacts
if handle == 'detach':
apps: various fixes and improvements for python3
r5072 h.flash(_('Detached %s artifacts') % _artifacts,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
elif handle == 'delete':
apps: various fixes and improvements for python3
r5072 h.flash(_('Deleted %s artifacts') % _artifacts,
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 category='success')
users: ported controllers from pylons into pyramid views.
r2114
dan
users: added option to detach pull requests for users which we delete....
r4351 handle_user = User.get_first_super_admin()
handle_user_id = safe_int(self.request.POST.get('detach_user_id'))
if handle_user_id:
# NOTE(marcink): we get new owner for objects...
handle_user = User.get_or_404(handle_user_id)
users: ported controllers from pylons into pyramid views.
r2114 if _repos and self.request.POST.get('user_repos'):
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 handle_repos = self.request.POST['user_repos']
users: ported controllers from pylons into pyramid views.
r2114
if _repo_groups and self.request.POST.get('user_repo_groups'):
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 handle_repo_groups = self.request.POST['user_repo_groups']
users: ported controllers from pylons into pyramid views.
r2114
if _user_groups and self.request.POST.get('user_user_groups'):
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 handle_user_groups = self.request.POST['user_user_groups']
dan
users: added option to detach pull requests for users which we delete....
r4351 if _pull_requests and self.request.POST.get('user_pull_requests'):
handle_pull_requests = self.request.POST['user_pull_requests']
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 if _artifacts and self.request.POST.get('user_artifacts'):
handle_artifacts = self.request.POST['user_artifacts']
users: ported controllers from pylons into pyramid views.
r2114
old_values = c.user.get_api_data()
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011
users: ported controllers from pylons into pyramid views.
r2114 try:
dan
users: added option to detach pull requests for users which we delete....
r4351
UserModel().delete(
c.user,
handle_repos=handle_repos,
handle_repo_groups=handle_repo_groups,
handle_user_groups=handle_user_groups,
handle_pull_requests=handle_pull_requests,
handle_artifacts=handle_artifacts,
handle_new_owner=handle_user
)
users: ported controllers from pylons into pyramid views.
r2114
audit_logger.store_web(
'user.delete', action_data={'old_data': old_values},
user=c.rhodecode_user)
Session().commit()
set_handle_flash_repos()
set_handle_flash_repo_groups()
set_handle_flash_user_groups()
dan
users: added option to detach pull requests for users which we delete....
r4351 set_handle_flash_pull_requests()
artifacts: handle detach/delete of artifacts for users who own them and are to be deleted....
r4011 set_handle_flash_artifacts()
username = h.escape(old_values['username'])
h.flash(_('Successfully deleted user `{}`').format(username), category='success')
users: ported controllers from pylons into pyramid views.
r2114 except (UserOwnsReposException, UserOwnsRepoGroupsException,
dan
users: added option to detach pull requests for users which we delete....
r4351 UserOwnsUserGroupsException, UserOwnsPullRequestsException,
UserOwnsArtifactsException, DefaultUserException) as e:
core: multiple fixes to unicode vs str usage...
r5065
h.flash(safe_str(e), category='warning')
users: ported controllers from pylons into pyramid views.
r2114 except Exception:
log.exception("Exception during deletion of user")
h.flash(_('An error occurred during deletion of user'),
category='error')
raise HTTPFound(h.route_path('users'))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def user_edit(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
c.active = 'profile'
c.extern_type = c.user.extern_type
c.extern_name = c.user.extern_name
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
users: enable full edit mode for super admins....
r4740 c.edit_mode = self.request.GET.get('edit') == '1'
users: ported controllers from pylons into pyramid views.
r2114
defaults = c.user.get_dict()
defaults.update({'language': c.user.user_data.get('language')})
data = render(
'rhodecode:templates/admin/users/user_edit.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()
@HasPermissionAllDecorator('hg.admin')
def user_edit_advanced(self):
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
dan
users: added option to detach pull requests for users which we delete....
r4351 c.detach_user = User.get_first_super_admin()
detach_user_id = safe_int(self.request.GET.get('detach_user_id'))
if detach_user_id:
c.detach_user = User.get_or_404(detach_user_id)
users: ported controllers from pylons into pyramid views.
r2114 c.active = 'advanced'
c.personal_repo_group = RepoGroup.get_user_personal_repo_group(user_id)
c.personal_repo_group_name = RepoGroupModel()\
.get_personal_group_name(c.user)
c.user_to_review_rules = sorted(
(x.user for x in c.user.user_review_rules),
key=lambda u: u.username.lower())
defaults = c.user.get_dict()
# Interim workaround if the user participated on any pull requests as a
# reviewer.
has_review = len(c.user.reviewer_pull_requests)
c.can_delete_user = not has_review
c.can_delete_user_message = ''
inactive_link = h.link_to(
'inactive', h.route_path('user_edit', user_id=user_id, _anchor='active'))
if has_review == 1:
c.can_delete_user_message = h.literal(_(
'The user participates as reviewer in {} pull request and '
'cannot be deleted. \nYou can set the user to '
'"{}" instead of deleting it.').format(
has_review, inactive_link))
elif has_review:
c.can_delete_user_message = h.literal(_(
'The user participates as reviewer in {} pull requests and '
'cannot be deleted. \nYou can set the user to '
'"{}" instead of deleting it.').format(
has_review, inactive_link))
data = render(
'rhodecode:templates/admin/users/user_edit.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()
@HasPermissionAllDecorator('hg.admin')
def user_edit_global_perms(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
c.active = 'global_perms'
c.default_user = User.get_default_user()
defaults = c.user.get_dict()
defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
defaults.update(c.default_user.get_default_perms())
defaults.update(c.user.get_default_perms())
data = render(
'rhodecode:templates/admin/users/user_edit.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()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def user_edit_global_perms_update(self):
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
c.active = 'global_perms'
try:
# first stage that verifies the checkbox
pylons: remove pylons as dependency...
r2351 _form = UserIndividualPermissionsForm(self.request.translate)
users: ported controllers from pylons into pyramid views.
r2114 form_result = _form.to_python(dict(self.request.POST))
inherit_perms = form_result['inherit_default_permissions']
c.user.inherit_default_permissions = inherit_perms
Session().add(c.user)
if not inherit_perms:
# only update the individual ones if we un check the flag
_form = UserPermissionsForm(
pylons: remove pylons as dependency...
r2351 self.request.translate,
users: ported controllers from pylons into pyramid views.
r2114 [x[0] for x in c.repo_create_choices],
[x[0] for x in c.repo_create_on_write_choices],
[x[0] for x in c.repo_group_create_choices],
[x[0] for x in c.user_group_create_choices],
[x[0] for x in c.fork_choices],
[x[0] for x in c.inherit_default_permission_choices])()
form_result = _form.to_python(dict(self.request.POST))
form_result.update({'perm_user_id': c.user.user_id})
PermissionModel().update_user_permissions(form_result)
# TODO(marcink): implement global permissions
# audit_log.store_web('user.edit.permissions')
Session().commit()
permissions: handle more cases for invalidating permission caches...
r3411
users: ported controllers from pylons into pyramid views.
r2114 h.flash(_('User global permissions updated successfully'),
category='success')
except formencode.Invalid as errors:
data = render(
'rhodecode:templates/admin/users/user_edit.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 {},
users: ported controllers from pylons into pyramid views.
r2114 prefix_error=False,
encoding="UTF-8",
force_defaults=False
)
return Response(html)
except Exception:
log.exception("Exception during permissions saving")
h.flash(_('An error occurred during permissions saving'),
category='error')
permissions: handle more cases for invalidating permission caches...
r3411
affected_user_ids = [user_id]
permissions: properly flush user cache permissions in more cases of permission changes....
r3824 PermissionModel().trigger_permission_flush(affected_user_ids)
users: ported controllers from pylons into pyramid views.
r2114 raise HTTPFound(h.route_path('user_edit_global_perms', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
users: use two distinct actions for user password reset....
r3378 def user_enable_force_password_reset(self):
users: ported controllers from pylons into pyramid views.
r2114 _ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
try:
users: use two distinct actions for user password reset....
r3378 c.user.update_userdata(force_password_change=True)
msg = _('Force password change enabled for user')
audit_logger.store_web('user.edit.password_reset.enabled',
user=c.rhodecode_user)
Session().commit()
h.flash(msg, category='success')
except Exception:
log.exception("Exception during password reset for user")
h.flash(_('An error occurred during password reset for user'),
category='error')
raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
users: ported controllers from pylons into pyramid views.
r2114
users: use two distinct actions for user password reset....
r3378 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def user_disable_force_password_reset(self):
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
try:
c.user.update_userdata(force_password_change=False)
msg = _('Force password change disabled for user')
audit_logger.store_web(
'user.edit.password_reset.disabled',
user=c.rhodecode_user)
users: ported controllers from pylons into pyramid views.
r2114
Session().commit()
h.flash(msg, category='success')
except Exception:
log.exception("Exception during password reset for user")
h.flash(_('An error occurred during password reset for user'),
category='error')
raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
core: added user-notice logic to push notice messages....
r4300 def user_notice_dismiss(self):
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
user_notice_id = safe_int(self.request.POST.get('notice_id'))
notice = UserNotice().query()\
.filter(UserNotice.user_id == user_id)\
.filter(UserNotice.user_notice_id == user_notice_id)\
.scalar()
read = False
if notice:
notice.notice_read = True
Session().add(notice)
Session().commit()
read = True
return {'notice': user_notice_id, 'read': read}
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
users: ported controllers from pylons into pyramid views.
r2114 def user_create_personal_repo_group(self):
"""
Create personal repository group for this user
"""
from rhodecode.model.repo_group import RepoGroupModel
_ = self.request.translate
c = self.load_default_context()
user_id = self.db_user_id
c.user = self.db_user
personal_repo_group = RepoGroup.get_user_personal_repo_group(
c.user.user_id)
if personal_repo_group:
raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
users: personal repo group template also can use first/last names for an user
r3659 personal_repo_group_name = RepoGroupModel().get_personal_group_name(c.user)
users: ported controllers from pylons into pyramid views.
r2114 named_personal_group = RepoGroup.get_by_group_name(
personal_repo_group_name)
try:
if named_personal_group and named_personal_group.user_id == c.user.user_id:
# migrate the same named group, and mark it as personal
named_personal_group.personal = True
Session().add(named_personal_group)
Session().commit()
modernize: updates for python3
r5095 msg = _('Linked repository group `{}` as personal'.format(
personal_repo_group_name))
users: ported controllers from pylons into pyramid views.
r2114 h.flash(msg, category='success')
elif not named_personal_group:
RepoGroupModel().create_personal_repo_group(c.user)
modernize: updates for python3
r5095 msg = _('Created repository group `{}`'.format(
personal_repo_group_name))
users: ported controllers from pylons into pyramid views.
r2114 h.flash(msg, category='success')
else:
modernize: updates for python3
r5095 msg = _('Repository group `{}` is already taken'.format(
personal_repo_group_name))
users: ported controllers from pylons into pyramid views.
r2114 h.flash(msg, category='warning')
except Exception:
log.exception("Exception during repository group creation")
msg = _(
'An error occurred during repository group creation for user')
h.flash(msg, category='error')
Session().rollback()
raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
admin: moved auth tokens into pyramid view....
r1518 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def auth_tokens(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
admin: moved auth tokens into pyramid view....
r1518
c.active = 'auth_tokens'
auth-tokens: allow specifing custom expiration date manually....
r2083 c.lifetime_values = AuthTokenModel.get_lifetime_values(translator=_)
admin: moved auth tokens into pyramid view....
r1518 c.role_values = [
(x, AuthTokenModel.cls._get_role_name(x))
for x in AuthTokenModel.cls.ROLES]
c.role_options = [(c.role_values, _("Role"))]
c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
c.user.user_id, show_expired=True)
repo-auth-tokens: UX, set and disable to VCS scope if selected an repo from select2
r2118 c.role_vcs = AuthTokenModel.cls.ROLE_VCS
admin: moved auth tokens into pyramid view....
r1518 return self._get_template_context(c)
users: added more secure way for fetching authentication tokens....
r4316 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def auth_tokens_view(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
auth_token_id = self.request.POST.get('auth_token_id')
if auth_token_id:
token = UserApiKeys.get_or_404(auth_token_id)
return {
'auth_token': token.api_key
}
admin: moved auth tokens into pyramid view....
r1518 def maybe_attach_token_scope(self, token):
# implemented in EE edition
pass
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def auth_tokens_add(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
admin: moved auth tokens into pyramid view....
r1518
users-admin: moved views into pyramid for editing emails and ips....
r1821 user_data = c.user.get_api_data()
admin: moved auth tokens into pyramid view....
r1518 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
description = self.request.POST.get('description')
role = self.request.POST.get('role')
auth-tokens: abstracted adding token for users into UserModel method for easier usage in scripts, and in future in API.
r2951 token = UserModel().add_auth_token(
user=c.user.user_id,
lifetime_minutes=lifetime, role=role, description=description,
scope_callback=self.maybe_attach_token_scope)
users-admin: moved views into pyramid for editing emails and ips....
r1821 token_data = token.get_api_data()
audit-logs: consistent data between my-account and admin user logs.
r1822 audit_logger.store_web(
audit-logs: implemented full audit logs across application....
r1829 'user.edit.token.add', action_data={
'data': {'token': token_data, 'user': user_data}},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user, )
admin: moved auth tokens into pyramid view....
r1518 Session().commit()
h.flash(_("Auth token successfully created"), category='success')
return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def auth_tokens_delete(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821 user_data = c.user.get_api_data()
admin: moved auth tokens into pyramid view....
r1518
del_auth_token = self.request.POST.get('del_auth_token')
if del_auth_token:
core: no longer rely on webob exception inside get_or_404 function....
r1956 token = UserApiKeys.get_or_404(del_auth_token)
users-admin: moved views into pyramid for editing emails and ips....
r1821 token_data = token.get_api_data()
admin: moved auth tokens into pyramid view....
r1518 AuthTokenModel().delete(del_auth_token, c.user.user_id)
audit-logs: consistent data between my-account and admin user logs.
r1822 audit_logger.store_web(
audit-logs: implemented full audit logs across application....
r1829 'user.edit.token.delete', action_data={
'data': {'token': token_data, 'user': user_data}},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user,)
admin: moved auth tokens into pyramid view....
r1518 Session().commit()
h.flash(_("Auth token successfully deleted"), category='success')
return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556
users-admin: moved views into pyramid for editing emails and ips....
r1821 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
users: added SSH key management for user admin pages
r1993 def ssh_keys(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
users: added SSH key management for user admin pages
r1993
c.active = 'ssh_keys'
c.default_key = self.request.GET.get('default_key')
c.user_ssh_keys = SshKeyModel().get_ssh_keys(c.user.user_id)
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def ssh_keys_generate_keypair(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
users: added SSH key management for user admin pages
r1993
c.active = 'ssh_keys_generate'
comment = 'RhodeCode-SSH {}'.format(c.user.email or '')
ssh-keys: allow generation of legacy keys for older systems and windows.
r4238 private_format = self.request.GET.get('private_format') \
or SshKeyModel.DEFAULT_PRIVATE_KEY_FORMAT
c.private, c.public = SshKeyModel().generate_keypair(
comment=comment, private_format=private_format)
users: added SSH key management for user admin pages
r1993
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def ssh_keys_add(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users: added SSH key management for user admin pages
r1993
user_data = c.user.get_api_data()
key_data = self.request.POST.get('key_data')
description = self.request.POST.get('description')
ssh: show fingerprint when adding already existing key....
r2594 fingerprint = 'unknown'
users: added SSH key management for user admin pages
r1993 try:
if not key_data:
raise ValueError('Please add a valid public key')
key = SshKeyModel().parse_key(key_data.strip())
fingerprint = key.hash_md5()
ssh_key = SshKeyModel().create(
ssh-keys: further sanitize data of inputted SSH keys.
r2751 c.user.user_id, fingerprint, key.keydata, description)
users: added SSH key management for user admin pages
r1993 ssh_key_data = ssh_key.get_api_data()
audit_logger.store_web(
'user.edit.ssh_key.add', action_data={
'data': {'ssh_key': ssh_key_data, 'user': user_data}},
user=self._rhodecode_user, )
Session().commit()
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 # Trigger an event on change of keys.
trigger(SshKeyFileChangeEvent(), self.request.registry)
users: added SSH key management for user admin pages
r1993 h.flash(_("Ssh Key successfully created"), category='success')
except IntegrityError:
log.exception("Exception during ssh key saving")
ssh: show fingerprint when adding already existing key....
r2594 err = 'Such key with fingerprint `{}` already exists, ' \
'please use a different one'.format(fingerprint)
h.flash(_('An error occurred during ssh key saving: {}').format(err),
users: added SSH key management for user admin pages
r1993 category='error')
except Exception as e:
log.exception("Exception during ssh key saving")
h.flash(_('An error occurred during ssh key saving: {}').format(e),
category='error')
return HTTPFound(
h.route_path('edit_user_ssh_keys', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def ssh_keys_delete(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users: added SSH key management for user admin pages
r1993 user_data = c.user.get_api_data()
del_ssh_key = self.request.POST.get('del_ssh_key')
if del_ssh_key:
ssh_key = UserSshKeys.get_or_404(del_ssh_key)
ssh_key_data = ssh_key.get_api_data()
SshKeyModel().delete(del_ssh_key, c.user.user_id)
audit_logger.store_web(
'user.edit.ssh_key.delete', action_data={
'data': {'ssh_key': ssh_key_data, 'user': user_data}},
user=self._rhodecode_user,)
Session().commit()
ssh: added support for auto generating authorized_keys from stored ssh keys.
r1994 # Trigger an event on change of keys.
trigger(SshKeyFileChangeEvent(), self.request.registry)
users: added SSH key management for user admin pages
r1993 h.flash(_("Ssh key successfully deleted"), category='success')
return HTTPFound(h.route_path('edit_user_ssh_keys', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
users-admin: moved views into pyramid for editing emails and ips....
r1821 def emails(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
c.active = 'emails'
c.user_email_map = UserEmailMap.query() \
.filter(UserEmailMap.user == c.user).all()
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def emails_add(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
email = self.request.POST.get('new_email')
user_data = c.user.get_api_data()
try:
pylons: remove pylons as dependency...
r2351
form = UserExtraEmailForm(self.request.translate)()
data = form.to_python({'email': email})
email = data['email']
users-admin: moved views into pyramid for editing emails and ips....
r1821 UserModel().add_extra_email(c.user.user_id, email)
audit_logger.store_web(
users: ported controllers from pylons into pyramid views.
r2114 'user.edit.email.add',
action_data={'email': email, 'user': user_data},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user)
Session().commit()
h.flash(_("Added new email address `%s` for user account") % email,
category='success')
except formencode.Invalid as error:
forms: fixed error handling in forms
r5018 msg = error.unpack_errors()['email']
h.flash(h.escape(msg), category='error')
users: ported controllers from pylons into pyramid views.
r2114 except IntegrityError:
log.warning("Email %s already exists", email)
h.flash(_('Email `{}` is already registered for another user.').format(email),
category='error')
users-admin: moved views into pyramid for editing emails and ips....
r1821 except Exception:
log.exception("Exception during email saving")
h.flash(_('An error occurred during email saving'),
category='error')
raise HTTPFound(h.route_path('edit_user_emails', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def emails_delete(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
email_id = self.request.POST.get('del_email_id')
user_model = UserModel()
email = UserEmailMap.query().get(email_id).email
user_data = c.user.get_api_data()
user_model.delete_extra_email(c.user.user_id, email_id)
audit_logger.store_web(
users: ported controllers from pylons into pyramid views.
r2114 'user.edit.email.delete',
action_data={'email': email, 'user': user_data},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user)
Session().commit()
h.flash(_("Removed email address from user account"),
category='success')
raise HTTPFound(h.route_path('edit_user_emails', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def ips(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
c.active = 'ips'
c.user_ip_map = UserIpMap.query() \
.filter(UserIpMap.user == c.user).all()
c.inherit_default_ips = c.user.inherit_default_permissions
c.default_user_ip_map = UserIpMap.query() \
.filter(UserIpMap.user == User.get_default_user()).all()
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
users: ported controllers from pylons into pyramid views.
r2114 # NOTE(marcink): this view is allowed for default users, as we can
# edit their IP white list
users-admin: moved views into pyramid for editing emails and ips....
r1821 def ips_add(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
user_model = UserModel()
desc = self.request.POST.get('description')
try:
ip_list = user_model.parse_ip_range(
self.request.POST.get('new_ip'))
except Exception as e:
ip_list = []
log.exception("Exception during ip saving")
h.flash(_('An error occurred during ip saving:%s' % (e,)),
category='error')
added = []
user_data = c.user.get_api_data()
for ip in ip_list:
try:
pylons: remove pylons as dependency...
r2351 form = UserExtraIpForm(self.request.translate)()
data = form.to_python({'ip': ip})
ip = data['ip']
users-admin: moved views into pyramid for editing emails and ips....
r1821 user_model.add_extra_ip(c.user.user_id, ip, desc)
audit_logger.store_web(
users: ported controllers from pylons into pyramid views.
r2114 'user.edit.ip.add',
action_data={'ip': ip, 'user': user_data},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user)
Session().commit()
added.append(ip)
except formencode.Invalid as error:
forms: fixed error handling in forms
r5018 msg = error.unpack_errors()['ip']
users-admin: moved views into pyramid for editing emails and ips....
r1821 h.flash(msg, category='error')
except Exception:
log.exception("Exception during ip saving")
h.flash(_('An error occurred during ip saving'),
category='error')
if added:
h.flash(
_("Added ips %s to user whitelist") % (', '.join(ip_list), ),
category='success')
if 'default_user' in self.request.POST:
# case for editing global IP list we do it for 'DEFAULT' user
raise HTTPFound(h.route_path('admin_permissions_ips'))
raise HTTPFound(h.route_path('edit_user_ips', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
users: ported controllers from pylons into pyramid views.
r2114 # NOTE(marcink): this view is allowed for default users, as we can
# edit their IP white list
users-admin: moved views into pyramid for editing emails and ips....
r1821 def ips_delete(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
users-admin: moved views into pyramid for editing emails and ips....
r1821
ip_id = self.request.POST.get('del_ip_id')
user_model = UserModel()
user_data = c.user.get_api_data()
ip = UserIpMap.query().get(ip_id).ip_addr
user_model.delete_extra_ip(c.user.user_id, ip_id)
audit_logger.store_web(
audit-logs: implemented full audit logs across application....
r1829 'user.edit.ip.delete', action_data={'ip': ip, 'user': user_data},
users-admin: moved views into pyramid for editing emails and ips....
r1821 user=self._rhodecode_user)
Session().commit()
h.flash(_("Removed ip address from user whitelist"), category='success')
if 'default_user' in self.request.POST:
# case for editing global IP list we do it for 'DEFAULT' user
raise HTTPFound(h.route_path('admin_permissions_ips'))
raise HTTPFound(h.route_path('edit_user_ips', user_id=user_id))
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def groups_management(self):
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
c.data = c.user.group_member
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556
user-groups: moved get_user_groups from RepoModel to UserGroupModel.
r1676 groups = [UserGroupModel.get_user_groups_as_dict(group.users_group)
for group in c.user.group_member]
json: fixed calls to json after orjson implementation
r4974 c.groups = ext_json.str_json(groups)
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556 c.active = 'groups'
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
security: added missing csrf checks in few missing views.
r1811 @CSRFRequired()
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556 def groups_management_updates(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 user_id = self.db_user_id
c.user = self.db_user
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556
users: changed spelling of users_groups to user_groups. Because English :]
r2067 user_groups = set(self.request.POST.getall('users_group_id'))
user_groups_objects = []
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556
users: changed spelling of users_groups to user_groups. Because English :]
r2067 for ugid in user_groups:
user_groups_objects.append(
UserGroupModel().get_group(safe_int(ugid)))
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556 user_group_model = UserGroupModel()
users: ported controllers from pylons into pyramid views.
r2114 added_to_groups, removed_from_groups = \
user_group_model.change_groups(c.user, user_groups_objects)
user_data = c.user.get_api_data()
for user_group_id in added_to_groups:
user_group = UserGroup.get(user_group_id)
old_values = user_group.get_api_data()
audit_logger.store_web(
'user_group.edit.member.add',
action_data={'user': user_data, 'old_data': old_values},
user=self._rhodecode_user)
for user_group_id in removed_from_groups:
user_group = UserGroup.get(user_group_id)
old_values = user_group.get_api_data()
audit_logger.store_web(
'user_group.edit.member.delete',
action_data={'user': user_data, 'old_data': old_values},
user=self._rhodecode_user)
Bartłomiej Wołyńczyk
admin-users: add view for user groups managment...
r1556
Session().commit()
c.active = 'user_groups_management'
h.flash(_("Groups successfully changed"), category='success')
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559 return HTTPFound(h.route_path(
'edit_user_groups_management', user_id=user_id))
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def user_audit_logs(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559
c.active = 'audit'
p = safe_int(self.request.GET.get('page', 1), 1)
filter_term = self.request.GET.get('filter')
user-audit: share same template for rendering audit logs between user and admin views.
r1696 user_log = UserModel().get_user_log(c.user, filter_term)
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559
dan
webhelpers: replaced paginate library with custom lib
r4091 def url_generator(page_num):
query_params = {
'page': page_num
}
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559 if filter_term:
dan
webhelpers: replaced paginate library with custom lib
r4091 query_params['filter'] = filter_term
return self.request.current_route_path(_query=query_params)
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559
dan
webhelpers: replaced paginate library with custom lib
r4091 c.audit_logs = SqlPage(
user_log, page=p, items_per_page=10, url_maker=url_generator)
admin-users: add audit page to allow showing user actions in RhodeCode....
r1559 c.filter_term = filter_term
return self._get_template_context(c)
users/user_groups: ported permission summary pages into pyramid....
r1998 @LoginRequired()
@HasPermissionAllDecorator('hg.admin')
audit-logs: expose download user audit logs as JSON file....
r3970 def user_audit_logs_download(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
user_log = UserModel().get_user_log(c.user, filter_term=None)
audit_log_data = {}
for entry in user_log:
audit_log_data[entry.user_log_id] = entry.get_dict()
json: fixed calls to json after orjson implementation
r4974 response = Response(ext_json.formatted_str_json(audit_log_data))
response.content_disposition = f'attachment; filename=user_{c.user.user_id}_audit_logs.json'
audit-logs: expose download user audit logs as JSON file....
r3970 response.content_type = 'application/json'
return response
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
users/user_groups: ported permission summary pages into pyramid....
r1998 def user_perms_summary(self):
_ = self.request.translate
c = self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 c.user = self.db_user
users/user_groups: ported permission summary pages into pyramid....
r1998
c.active = 'perms_summary'
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def user_perms_summary_json(self):
self.load_default_context()
users: ported controllers from pylons into pyramid views.
r2114 perm_user = self.db_user.AuthUser(ip_addr=self.request.remote_addr)
users/user_groups: ported permission summary pages into pyramid....
r1998
return perm_user.permissions
caches: rewrite of auth/permission caches to dogpile.
r2845
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def user_caches(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
c.active = 'caches'
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
caches: make sure the global cache namespace prefixes are used....
r5106 cache_namespace_uid = f'cache_user_auth.{rc_cache.PERMISSIONS_CACHE_VER}.{self.db_user.user_id}'
caches: rewrite of auth/permission caches to dogpile.
r2845 c.region = rc_cache.get_or_create_region('cache_perms', cache_namespace_uid)
c.backend = c.region.backend
caches: don't use beaker for file caches anymore
r2846 c.user_keys = sorted(c.region.backend.list_keys(prefix=cache_namespace_uid))
caches: rewrite of auth/permission caches to dogpile.
r2845
return self._get_template_context(c)
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
@CSRFRequired()
def user_caches_update(self):
_ = self.request.translate
c = self.load_default_context()
c.user = self.db_user
c.active = 'caches'
c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
caches: make sure the global cache namespace prefixes are used....
r5106 cache_namespace_uid = f'cache_user_auth.{rc_cache.PERMISSIONS_CACHE_VER}.{self.db_user.user_id}'
fix(permission-flush): use delete method for permission cache invalidation as it's multi-process safe....
r5266 del_keys = rc_cache.clear_cache_namespace('cache_perms', cache_namespace_uid, method=rc_cache.CLEAR_DELETE)
caches: rewrite of auth/permission caches to dogpile.
r2845
caches: don't use beaker for file caches anymore
r2846 h.flash(_("Deleted {} cache keys").format(del_keys), category='success')
caches: rewrite of auth/permission caches to dogpile.
r2845
return HTTPFound(h.route_path(
'edit_user_caches', user_id=c.user.user_id))