diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index dde2e758d..092b584ad 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -1468,6 +1468,8 @@ class LDAPBackend(object): return self._return_django_user(dn, username, password, conn, block, attributes) def _return_django_user(self, dn, username, password, conn, block, attributes): + from authentic2.manager.journal_event_types import ManagerUserActivation + user = self.lookup_existing_user(username, block, attributes) if user: log.debug('found existing user %r', user) @@ -1485,6 +1487,8 @@ class LDAPBackend(object): if not user.is_active and user.deactivation_reason and user.deactivation_reason.startswith('ldap-'): user.mark_as_active() + ldap_uri = conn.get_option(ldap.OPT_URI) + ManagerUserActivation.record(target_user=user, reason='ldap-reactivation', origin=ldap_uri) user_login_success(user.get_username()) return user diff --git a/src/authentic2/manager/journal_event_types.py b/src/authentic2/manager/journal_event_types.py index 094c28432..2445e7ef8 100644 --- a/src/authentic2/manager/journal_event_types.py +++ b/src/authentic2/manager/journal_event_types.py @@ -194,16 +194,26 @@ class ManagerUserActivation(EventTypeDefinition): label = _('user activation') @classmethod - def record(cls, user, session, target_user): - super().record(user=user, session=session, references=[target_user]) + def record(cls, target_user, user=None, session=None, origin=None, reason=None): + data = {'origin': origin, 'reason': reason} + super().record(user=user, session=session, references=[target_user], data=data) @classmethod def get_message(cls, event, context): (user,) = event.get_typed_references((DeletedUser, User)) + reason = event.get_data('reason') if context and context == user: - return _('activation by administrator') + if reason == 'ldap-reactivation': + return _('automatic activation because the associated LDAP account reappeared') + else: + return _('activation by administrator') elif user: - return _('activation of user "%s"') % user_to_str(user) + if reason == 'ldap-reactivation': + return _( + 'automatic activation of user "%s" because the associated LDAP account reappeared' + ) % user_to_str(user) + else: + return _('activation of user "%s"') % user_to_str(user) return super().get_message(event, context) diff --git a/tests/test_ldap.py b/tests/test_ldap.py index bf79fb1e5..e425b8570 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -312,15 +312,21 @@ def test_deactivate_orphaned_users(slapd, settings, client, db): ).count() == 1 ) - assert ( - User.objects.filter( - is_active=True, deactivation_reason__isnull=True, deactivation__isnull=True - ).count() - == 4 + reactivated_users = User.objects.filter( + is_active=True, deactivation_reason__isnull=True, deactivation__isnull=True ) + assert reactivated_users.count() == 4 assert User.objects.filter(is_active=False).count() == 2 assert User.objects.count() == 6 + for user in reactivated_users: + utils.assert_event( + 'manager.user.activation', + target_user=user, + reason='ldap-reactivation', + origin=slapd.ldap_url, + ) + @pytest.mark.django_db def test_simple_with_binddn(slapd, settings, client): diff --git a/tests/test_manager_journal.py b/tests/test_manager_journal.py index 36ff5a074..d42261108 100644 --- a/tests/test_manager_journal.py +++ b/tests/test_manager_journal.py @@ -261,6 +261,11 @@ def events(db, freezer): target_user=user, reason='ldap-old-source', ) + make( + 'manager.user.activation', + target_user=user, + reason='ldap-reactivation', + ) # verify we created at least one event for each type assert set(Event.objects.values_list("type__name", flat=True)) == set(_registry) @@ -564,6 +569,12 @@ def test_global_journal(app, superuser, events): 'user': '-', 'message': 'automatic deactivation of user "Johnny doe" because the associated LDAP source has been deleted', }, + { + 'message': 'automatic activation of user "Johnny doe" because the associated LDAP account reappeared', + 'timestamp': 'Jan. 2, 2020, 7 p.m.', + 'type': 'manager.user.activation', + 'user': '-', + }, ] @@ -761,6 +772,12 @@ def test_user_journal(app, superuser, events): 'user': '-', 'message': 'automatic deactivation because the associated LDAP source has been deleted', }, + { + 'message': 'automatic activation because the associated LDAP account reappeared', + 'timestamp': 'Jan. 2, 2020, 7 p.m.', + 'type': 'manager.user.activation', + 'user': '-', + }, ] @@ -1019,6 +1036,7 @@ def test_search(app, superuser, events): table_content = [text_content(p) for p in response.pyquery('tbody td.journal-list--message-column')] assert table_content == [ + 'automatic activation of user "Johnny doe" because the associated LDAP account reappeared', 'automatic deactivation of user "Johnny doe" because the associated LDAP source has been deleted', 'automatic deactivation of user "Johnny doe" because the associated LDAP account does not exist anymore', 'deactivation of user "Johnny doe"',