Commit 33242fe0 authored by Kirill Fomichev's avatar Kirill Fomichev Committed by Tim Graham
Browse files

Fixed #19019 -- Fixed UserAdmin to log password change.

Thanks Tuttle for the report.
parent 6b4967e8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ class UserAdmin(admin.ModelAdmin):
            form = self.change_password_form(user, request.POST)
            if form.is_valid():
                form.save()
                change_message = self.construct_change_message(request, form, None)
                self.log_change(request, request.user, change_message)
                msg = ugettext('Password changed successfully.')
                messages.success(request, msg)
                return HttpResponseRedirect('..')
+8 −0
Original line number Diff line number Diff line
@@ -350,3 +350,11 @@ class AdminPasswordChangeForm(forms.Form):
        if commit:
            self.user.save()
        return self.user

    def _get_changed_data(self):
        data = super(AdminPasswordChangeForm, self).changed_data
        for name in self.fields.keys():
            if name not in data:
                return []
        return ['password']
    changed_data = property(_get_changed_data)
+62 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ except ImportError: # Python 2

from django.conf import global_settings, settings
from django.contrib.sites.models import Site, RequestSite
from django.contrib.admin.models import LogEntry
from django.contrib.auth.models import User
from django.core import mail
from django.core.urlresolvers import reverse, NoReverseMatch
@@ -54,6 +55,11 @@ class AuthViewsTestCase(TestCase):
        self.assertTrue(SESSION_KEY in self.client.session)
        return response

    def logout(self):
        response = self.client.get('/admin/logout/')
        self.assertEqual(response.status_code, 200)
        self.assertTrue(SESSION_KEY not in self.client.session)

    def assertFormError(self, response, error):
        """Assert that error is found in response.context['form'] errors"""
        form_errors = list(itertools.chain(*response.context['form'].errors.values()))
@@ -670,18 +676,70 @@ class LogoutTest(AuthViewsTestCase):
            self.confirm_logged_out()

@skipIfCustomUser
@override_settings(
    PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
)
class ChangelistTests(AuthViewsTestCase):
    urls = 'django.contrib.auth.tests.urls_admin'

    # #20078 - users shouldn't be allowed to guess password hashes via
    # repeated password__startswith queries.
    def test_changelist_disallows_password_lookups(self):
        # Make me a superuser before loging in.
    def setUp(self):
        # Make me a superuser before logging in.
        User.objects.filter(username='testclient').update(is_staff=True, is_superuser=True)
        self.login()
        self.admin = User.objects.get(pk=1)

    def get_user_data(self, user):
        return {
            'username': user.username,
            'password': user.password,
            'email': user.email,
            'is_active': user.is_active,
            'is_staff': user.is_staff,
            'is_superuser': user.is_superuser,
            'last_login_0': user.last_login.strftime('%Y-%m-%d'),
            'last_login_1': user.last_login.strftime('%H:%M:%S'),
            'initial-last_login_0': user.last_login.strftime('%Y-%m-%d'),
            'initial-last_login_1': user.last_login.strftime('%H:%M:%S'),
            'date_joined_0': user.date_joined.strftime('%Y-%m-%d'),
            'date_joined_1': user.date_joined.strftime('%H:%M:%S'),
            'initial-date_joined_0': user.date_joined.strftime('%Y-%m-%d'),
            'initial-date_joined_1': user.date_joined.strftime('%H:%M:%S'),
            'first_name': user.first_name,
            'last_name': user.last_name,
        }

    # #20078 - users shouldn't be allowed to guess password hashes via
    # repeated password__startswith queries.
    def test_changelist_disallows_password_lookups(self):
        # A lookup that tries to filter on password isn't OK
        with patch_logger('django.security.DisallowedModelAdminLookup', 'error') as logger_calls:
            response = self.client.get('/admin/auth/user/?password__startswith=sha1$')
            self.assertEqual(response.status_code, 400)
            self.assertEqual(len(logger_calls), 1)

    def test_user_change_email(self):
        data = self.get_user_data(self.admin)
        data['email'] = 'new_' + data['email']
        response = self.client.post('/admin/auth/user/%s/' % self.admin.pk, data)
        self.assertRedirects(response, '/admin/auth/user/')
        row = LogEntry.objects.latest('id')
        self.assertEqual(row.change_message, 'Changed email.')

    def test_user_not_change(self):
        response = self.client.post('/admin/auth/user/%s/' % self.admin.pk,
            self.get_user_data(self.admin)
        )
        self.assertRedirects(response, '/admin/auth/user/')
        row = LogEntry.objects.latest('id')
        self.assertEqual(row.change_message, 'No fields changed.')

    def test_user_change_password(self):
        response = self.client.post('/admin/auth/user/%s/password/' % self.admin.pk, {
            'password1': 'password1',
            'password2': 'password1',
        })
        self.assertRedirects(response, '/admin/auth/user/%s/' % self.admin.pk)
        row = LogEntry.objects.latest('id')
        self.assertEqual(row.change_message, 'Changed password.')
        self.logout()
        self.login(password='password1')