From 12d43d5a65ed34922a1539c930b1ef5d66b77def Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 10 Aug 2021 17:59:44 +0200 Subject: [PATCH] manager: expose user deactivation reason (#19718) --- src/authentic2/custom_user/models.py | 14 ++++++++++++ .../authentic2/manager/user_detail.html | 4 +++- src/authentic2/manager/user_views.py | 2 +- tests/test_ldap.py | 22 +++++++++++++++---- tests/test_manager.py | 1 + 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/authentic2/custom_user/models.py b/src/authentic2/custom_user/models.py index 711de9b5..0d1ff80f 100644 --- a/src/authentic2/custom_user/models.py +++ b/src/authentic2/custom_user/models.py @@ -374,6 +374,20 @@ class User(AbstractBaseUser, PermissionMixin): self.deactivation_reason = reason self.save(update_fields=['is_active', 'deactivation', 'deactivation_reason']) + @property + def verbose_deactivation_reason(self): + from authentic2.backends.ldap_backend import ( + LDAP_DEACTIVATION_REASON_NOT_PRESENT, + LDAP_DEACTIVATION_REASON_OLD_SOURCE, + ) + + if self.deactivation_reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT: + return _('associated LDAP account does not exist anymore') + elif self.deactivation_reason == LDAP_DEACTIVATION_REASON_OLD_SOURCE: + return _('associated LDAP source has been deleted') + else: + return self.deactivation_reason + def set_random_password(self): self.set_password(base64.b64encode(os.urandom(32)).decode('ascii')) diff --git a/src/authentic2/manager/templates/authentic2/manager/user_detail.html b/src/authentic2/manager/templates/authentic2/manager/user_detail.html index 08e9a4e6..692acd99 100644 --- a/src/authentic2/manager/templates/authentic2/manager/user_detail.html +++ b/src/authentic2/manager/templates/authentic2/manager/user_detail.html @@ -69,7 +69,9 @@ {% if not object.is_active and object.deactivation %}

- {% blocktrans with date=object.deactivation %}Deactivated on {{ date }}{% endblocktrans %} + {% blocktrans trimmed with date=object.deactivation reason=object.verbose_deactivation_reason %} + Deactivated on {{ date }} ({{ reason }}). + {% endblocktrans %}

{% endif %} diff --git a/src/authentic2/manager/user_views.py b/src/authentic2/manager/user_views.py index 4a6d0972..69bf032c 100644 --- a/src/authentic2/manager/user_views.py +++ b/src/authentic2/manager/user_views.py @@ -355,7 +355,7 @@ class UserDetailView(OtherActionsMixin, BaseDetailView): if request.user == self.object: messages.warning(request, _('You cannot desactivate your own ' 'user')) else: - self.object.mark_as_inactive() + self.object.mark_as_inactive(reason=_('by %s') % request.user.get_full_name()) request.journal.record('manager.user.deactivation', target_user=self.object) def action_password_reset(self, request, *args, **kwargs): diff --git a/tests/test_ldap.py b/tests/test_ldap.py index 6bd2d5d4..646e332f 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -233,7 +233,7 @@ def test_simple(slapd, settings, client, db): assert 'password' not in client.session['ldap-data'] -def test_deactivate_orphaned_users(slapd, settings, client, db): +def test_deactivate_orphaned_users(slapd, settings, client, db, app, superuser): settings.LDAP_AUTH_SETTINGS = [ { 'url': [slapd.ldap_url], @@ -241,13 +241,16 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): 'use_tls': False, } ] + utils.login(app, superuser) # create users as a side effect - list(ldap_backend.LDAPBackend.get_users()) + users = list(ldap_backend.LDAPBackend.get_users()) block = settings.LDAP_AUTH_SETTINGS[0] assert ( ldap_backend.UserExternalId.objects.filter(user__is_active=False, source=block['realm']).count() == 0 ) + resp = app.get('/manage/users/%s/' % users[0].pk) + assert 'Deactivated' not in resp.text conn = slapd.get_connection_admin() conn.delete_s(DN) @@ -267,6 +270,9 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): reason='ldap-not-present', origin=slapd.ldap_url, ) + resp = app.get('/manage/users/%s/' % deactivated_user.user.pk) + assert 'Deactivated' in resp.text + assert 'associated LDAP account does not exist anymore' in resp.text # deactivate an active user manually User.objects.filter(is_active=True).first().mark_as_inactive(reason='bad user') @@ -298,6 +304,9 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): target_user=ldap_user.user, reason='ldap-old-source', ) + resp = app.get('/manage/users/%s/' % ldap_user.user.pk) + assert 'Deactivated' in resp.text + assert 'associated LDAP source has been deleted' in resp.text # reactivate users settings.LDAP_AUTH_SETTINGS = [block] @@ -313,11 +322,14 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): == 1 ) reactivated_users = User.objects.filter( - is_active=True, deactivation_reason__isnull=True, deactivation__isnull=True + is_active=True, + deactivation_reason__isnull=True, + deactivation__isnull=True, + userexternalid__isnull=False, ) assert reactivated_users.count() == 4 assert User.objects.filter(is_active=False).count() == 2 - assert User.objects.count() == 6 + assert User.objects.count() == 7 for user in reactivated_users: utils.assert_event( @@ -326,6 +338,8 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): reason='ldap-reactivation', origin=slapd.ldap_url, ) + resp = app.get('/manage/users/%s/' % user.pk) + assert 'Deactivated' not in resp.text @pytest.mark.django_db diff --git a/tests/test_manager.py b/tests/test_manager.py index d282d6fd..6eeedf9d 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -644,6 +644,7 @@ def test_manager_deactivate_user(app, admin, settings): form = response.forms['object-actions'] response = form.submit('deactivate') assert 'Deactivated on' in response.text + assert 'by global admin' in response.text assert 'Activate' in response.text -- 2.20.1