Skip to content

Commit

Permalink
Merge pull request ckan#8122 from qld-gov-au/github-4193-username-edi…
Browse files Browse the repository at this point in the history
…ting

allow sysadmins to edit usernames, ckan#4193
  • Loading branch information
amercader authored Apr 19, 2024
2 parents 2dfd6b5 + 4f04000 commit a638395
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 5 deletions.
1 change: 1 addition & 0 deletions changes/4193.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow sysadmins to change usernames of other accounts
2 changes: 1 addition & 1 deletion ckan/logic/action/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ def user_update(context: Context, data_dict: DataDict) -> ActionResult.UserUpdat
'''Update a user account.
Normal users can only update their own user accounts. Sysadmins can update
any user account. Can not modify exisiting user's name.
any user account and modify existing usernames.
.. note:: Update methods may delete parameters not explicitly provided in the
data_dict. If you want to edit only a specific attribute use `user_patch`
Expand Down
8 changes: 5 additions & 3 deletions ckan/logic/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
from sqlalchemy.orm.exc import NoResultFound

import ckan.lib.navl.dictization_functions as df
import ckan.logic as logic
from ckan import authz, logic
import ckan.logic.converters as converters
import ckan.lib.helpers as h
from ckan.model import (MAX_TAG_LENGTH, MIN_TAG_LENGTH,
PACKAGE_NAME_MIN_LENGTH, PACKAGE_NAME_MAX_LENGTH,
PACKAGE_VERSION_MAX_LENGTH,
VOCABULARY_NAME_MAX_LENGTH,
VOCABULARY_NAME_MIN_LENGTH)
import ckan.authz as authz
from ckan.model.core import State

from ckan.common import _
Expand Down Expand Up @@ -615,10 +614,13 @@ def user_name_validator(key: FlattenKey, data: FlattenDataDict,
return
else:
# Otherwise return an error: there's already another user with that
# name, so you can create a new user with that name or update an
# name, so you can't create a new user with that name or update an
# existing user's name to that name.
errors[key].append(_('That login name is not available.'))
elif user_obj_from_context:
requester = context.get('auth_user_obj', None)
if requester and authz.is_sysadmin(requester.name):
return
old_user = model.User.get(user_obj_from_context.id)
if old_user is not None and old_user.state != model.State.PENDING:
errors[key].append(_('That login name can not be modified.'))
Expand Down
6 changes: 5 additions & 1 deletion ckan/templates/user/edit_user_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
{% block core_fields %}
<fieldset>
<legend>{{ _('Change details') }}</legend>
{{ form.input('name', label=_('Username'), id='field-username', value=data.name, error=errors.name, classes=['control-medium'], attrs={'readonly': '', 'class': 'form-control'}) }}
{% if g.userobj.sysadmin %}
{{ form.input('name', label=_('Username'), id='field-username', value=data.name, error=errors.name, classes=['control-medium'], is_required=true) }}
{% else %}
{{ form.input('name', label=_('Username'), id='field-username', value=data.name, error=errors.name, classes=['control-medium'], attrs={'readonly': '', 'class': 'form-control'}) }}
{% endif %}

{{ form.input('fullname', label=_('Full name'), id='field-fullname', value=data.fullname, error=errors.fullname, placeholder=_('eg. Joe Bloggs'), classes=['control-medium']) }}

Expand Down
18 changes: 18 additions & 0 deletions ckan/tests/controllers/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,24 @@ def test_edit_user_logged_in_username_change_by_id(self, app, user):

assert "That login name can not be modified" in response

def test_edit_user_logged_in_username_change_by_sysadmin(
self, app, user, sysadmin):

headers = {"Authorization": sysadmin["token"]}
response = app.post(
url=url_for("user.edit", id=user["id"]),
data={
"email": user["email"],
"save": "",
"old_password": "correct123",
"password1": "",
"password2": "",
"name": factories.User.stub().name,
},
headers=headers
)
assert 'Profile updated' in response

def test_perform_reset_for_key_change(self, app):
password = "TestPassword1"
params = {"password1": password, "password2": password}
Expand Down

0 comments on commit a638395

Please sign in to comment.