From 0852a3ac841a4babf11b1e51d08afdd2270b988b Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 3 Jul 2018 15:11:00 +0200 Subject: [PATCH] disable password change for LDAP backend without user_can_change_password (fixes #20731) --- src/authentic2/backends/ldap_backend.py | 5 ++++- src/authentic2/custom_user/models.py | 3 +++ src/authentic2/profile_urls.py | 3 +++ .../authentic2/login_password_profile.html | 4 ++-- src/authentic2/views.py | 3 ++- tests/test_ldap.py | 22 +++++++++++++++++++ 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index 534a39d6..ede46afb 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -182,7 +182,7 @@ class LDAPUser(get_user_model()): self.set_unusable_password() def has_usable_password(self): - return self.block['user_can_change_password'] + return True def get_connection(self): ldap_password = self.get_password_in_session() @@ -210,6 +210,9 @@ class LDAPUser(get_user_model()): def can_reset_password(self): return self.block['can_reset_password'] + def can_change_password(self): + return app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD and self.block['user_can_change_password'] + class LDAPBackend(object): _DEFAULTS = { diff --git a/src/authentic2/custom_user/models.py b/src/authentic2/custom_user/models.py index 4000cdd0..068712a4 100644 --- a/src/authentic2/custom_user/models.py +++ b/src/authentic2/custom_user/models.py @@ -252,3 +252,6 @@ class User(AbstractBaseUser, PermissionMixin): def can_reset_password(self): return self.has_usable_password() + + def can_change_password(self): + return app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD diff --git a/src/authentic2/profile_urls.py b/src/authentic2/profile_urls.py index 7929fd1d..476564c0 100644 --- a/src/authentic2/profile_urls.py +++ b/src/authentic2/profile_urls.py @@ -26,6 +26,9 @@ def password_change_view(request, *args, **kwargs): post_change_redirect = request.GET[REDIRECT_FIELD_NAME] elif post_change_redirect is None: post_change_redirect = reverse('account_management') + if not request.user.can_change_password(): + messages.warning(request, _('Password change is forbidden')) + return redirect(request, post_change_redirect) if 'cancel' in request.POST: return redirect(request, post_change_redirect) kwargs['post_change_redirect'] = post_change_redirect diff --git a/src/authentic2/templates/authentic2/login_password_profile.html b/src/authentic2/templates/authentic2/login_password_profile.html index 8b359bae..90febe6d 100644 --- a/src/authentic2/templates/authentic2/login_password_profile.html +++ b/src/authentic2/templates/authentic2/login_password_profile.html @@ -1,12 +1,12 @@ {% load i18n %} -{% if can_change_password %} +{% if user.can_change_password %}

{% trans "Password" %}

- {% if has_usable_password %} + {% if user.has_usable_password %} {% trans "Change your password" %} {% else %} {% trans "Set your password" %} diff --git a/src/authentic2/views.py b/src/authentic2/views.py index 50faac8c..200c6c7b 100644 --- a/src/authentic2/views.py +++ b/src/authentic2/views.py @@ -501,7 +501,8 @@ class ProfileView(cbv.TemplateNamesMixin, TemplateView): 'allow_account_deletion': app_settings.A2_REGISTRATION_CAN_DELETE_ACCOUNT, 'allow_profile_edit': EditProfile.can_edit_profile(), 'allow_email_change': app_settings.A2_PROFILE_CAN_CHANGE_EMAIL, - 'allow_password_change': app_settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD, + # TODO: deprecated should be removed when publik-base-theme is updated + 'allow_password_change': request.user.can_change_password(), 'federation_management': federation_management, }) hooks.call_hooks('modify_context_data', self, context_instance) diff --git a/tests/test_ldap.py b/tests/test_ldap.py index 5a22dba5..58ba4b12 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -528,3 +528,25 @@ def test_reset_password_ldap_user(slapd, settings, app, db): with pytest.raises(ldap.INVALID_CREDENTIALS): slapd.get_connection().bind_s(DN, PASS) assert not User.objects.get().has_usable_password() + + +def test_user_cannot_change_password(slapd, settings, app, db): + settings.LDAP_AUTH_SETTINGS = [{ + 'url': [slapd.ldap_url], + 'binddn': slapd.root_bind_dn, + 'bindpw': slapd.root_bind_password, + 'basedn': 'o=orga', + 'use_tls': False, + 'user_can_change_password': False, + }] + User = get_user_model() + assert User.objects.count() == 0 + # first login + response = app.get('/login/') + response.form['username'] = USERNAME + response.form['password'] = PASS + response = response.form.submit('login-password-submit').follow() + response = response.click('Your account') + assert 'Password' not in response + response = app.get('/accounts/password/change/') + assert response['Location'].endswith('/accounts/') -- 2.18.0