I am working on a third party app running django 2.2.12.
I have an admin with 3 kinds of users: "superadmin", "staff" and "other".
When I am logged as "superadmin", when I go to the Users list and click on a user, I am able to edit them and reset their password.
However, when I try to do the same as a "staff" user, I can see the user data, but can't edit anything, and there's no option to reset the password. If I try to access the URL manually (/admin/accounts/user/[USER_ID]/password/
) I get a "403 Forbidden" error message.
I noticed that if I override the has_perm
method in the user model, it allows the "staff" user to edit the user data. However I would like to allow only the password change (if the user is not a superadmin or a staff user), without allowing "staff" users to edit other users.
def has_perm(self, perm, obj=None):
return True
I have the impression this has to do with the Django permission system, but I re-read the docs at https://docs.djangoproject.com/en/2.2/topics/auth/default/ and couldn't figure this out yet.
Thanks
Okay, I was able to make it work with a less than ideal solution, but did the trick.
Basically I overload the has_change_permission
method of the UserAdmin
class and add a custom logic to allow the password change in a special case (url ends with '/password' and user has the correct permissions.
def can_edit_password(self, logged_user, chosen_user=None):
if logged_user and logged_user.is_superuser:
return True
logged_user_has_change_pass_perm = (
logged_user and
logged_user.is_authenticated and
logged_user.has_perm("accounts.change_student_password")
)
return logged_user_has_change_pass_perm
def can_show_change_password_form(self, path, logged_user, chosen_user=None):
is_changing_password = path.endswith('/password/')
return is_changing_password and self.can_edit_password(logged_user, chosen_user)
def has_change_permission(self, request, user=None):
if self.can_show_change_password_form(path=request.path, logged_user=request.user, chosen_user=user):
return True
return super(UserAdmin, self).has_change_permission(request, user)