mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #35959 -- Checked for change permission to show "password" field.
Removed "password" from UserAdmin fieldset for users without change permission, omitting ReadOnlyPasswordHashField in UserChangeForm. Thanks to Sarah Boyce for help with implementation! Co-authored-by: Sarah Boyce <sarahvboyce95@gmail.com>
This commit is contained in:
parent
c075d4c2c8
commit
e1971467d7
@ -1,3 +1,5 @@
|
|||||||
|
import copy
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.contrib.admin.options import IS_POPUP_VAR
|
from django.contrib.admin.options import IS_POPUP_VAR
|
||||||
@ -82,10 +84,23 @@ class UserAdmin(admin.ModelAdmin):
|
|||||||
"user_permissions",
|
"user_permissions",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _remove_fields_from_fieldsets(fieldsets, fields):
|
||||||
|
fieldset_without_fields = []
|
||||||
|
for fieldset_name, fieldset in copy.deepcopy(fieldsets):
|
||||||
|
fieldset["fields"] = [f for f in fieldset["fields"] if f not in fields]
|
||||||
|
fieldset_without_fields.append((fieldset_name, fieldset))
|
||||||
|
return fieldset_without_fields
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fieldsets(self, request, obj=None):
|
||||||
if not obj:
|
if not obj:
|
||||||
return self.add_fieldsets
|
return self.add_fieldsets
|
||||||
return super().get_fieldsets(request, obj)
|
fieldsets = super().get_fieldsets(request, obj)
|
||||||
|
if not self.has_change_permission(request, obj):
|
||||||
|
return self._remove_fields_from_fieldsets(
|
||||||
|
fieldsets=fieldsets, fields=["password"]
|
||||||
|
)
|
||||||
|
return fieldsets
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1680,7 +1680,7 @@ class ChangelistTests(MessagesTestMixin, AuthViewsTestCase):
|
|||||||
(_request, user), _kwargs = has_change_permission.call_args
|
(_request, user), _kwargs = has_change_permission.call_args
|
||||||
self.assertEqual(user.pk, self.admin.pk)
|
self.assertEqual(user.pk, self.admin.pk)
|
||||||
|
|
||||||
def test_view_user_password_is_readonly(self):
|
def test_password_not_viewable_for_user_without_change_permission(self):
|
||||||
u = User.objects.get(username="testclient")
|
u = User.objects.get(username="testclient")
|
||||||
u.is_superuser = False
|
u.is_superuser = False
|
||||||
u.save()
|
u.save()
|
||||||
@ -1692,7 +1692,7 @@ class ChangelistTests(MessagesTestMixin, AuthViewsTestCase):
|
|||||||
algo, salt, hash_string = u.password.split("$")
|
algo, salt, hash_string = u.password.split("$")
|
||||||
self.assertContains(response, '<div class="readonly">testclient</div>')
|
self.assertContains(response, '<div class="readonly">testclient</div>')
|
||||||
# ReadOnlyPasswordHashWidget is used to render the field.
|
# ReadOnlyPasswordHashWidget is used to render the field.
|
||||||
self.assertContains(
|
self.assertNotContains(
|
||||||
response,
|
response,
|
||||||
"<strong>algorithm</strong>: <bdi>%s</bdi>\n\n"
|
"<strong>algorithm</strong>: <bdi>%s</bdi>\n\n"
|
||||||
"<strong>salt</strong>: <bdi>%s********************</bdi>\n\n"
|
"<strong>salt</strong>: <bdi>%s********************</bdi>\n\n"
|
||||||
@ -1704,6 +1704,9 @@ class ChangelistTests(MessagesTestMixin, AuthViewsTestCase):
|
|||||||
),
|
),
|
||||||
html=True,
|
html=True,
|
||||||
)
|
)
|
||||||
|
self.assertNotContains(
|
||||||
|
response, '<a class="button" href="../password/">Reset password</a>'
|
||||||
|
)
|
||||||
# Value in POST data is ignored.
|
# Value in POST data is ignored.
|
||||||
data = self.get_user_data(u)
|
data = self.get_user_data(u)
|
||||||
data["password"] = "shouldnotchange"
|
data["password"] = "shouldnotchange"
|
||||||
|
Loading…
Reference in New Issue
Block a user