manager: show deleted users informations in journal (#51808)

This commit is contained in:
Benjamin Dauvergne 2021-03-09 23:03:00 +01:00
parent 5e29c79224
commit a921332fb2
5 changed files with 64 additions and 41 deletions

View File

@ -15,7 +15,7 @@
{% endif %}
<tr data-event-id="{{ event.id }}" data-event-cursor="{{ event.cursor }}" data-event-type="{{ event.type.name }}">
<td class="journal-list--timestamp-column">{% block event-timestamp %}{{ event.timestamp }}{% endblock %}</td>
<td class="journal-list--user-column" {% if event.user %}data-user-id="{{ event.user.id }}"{% endif %}>{% block event-user %}{{ event.user.get_full_name|default:"-" }}{% endblock %}</td>
<td class="journal-list--user-column" {% if event.user %}data-user-id="{{ event.user.id }}"{% endif %}>{% block event-user %}{% firstof event.user.get_full_name event.user "-" %}{% endblock %}</td>
<td class="journal-list--session-column">{% block event-session %}{{ event.session_id_shortened|default:"-" }}{% endblock %}</td>
<td class="journal-list--message-column">{% block event-message %}{{ event.message|default:"-" }}{% endblock %}</td>
</tr>

View File

@ -414,13 +414,19 @@ class DeletedUser(models.Model):
)
cls.objects.filter(deleted__lt=threshold).delete()
def __str__(self):
def __repr__(self):
return 'DeletedUser(old_id=%s, old_uuid=%s…, old_email=%s)' % (
self.old_user_id or '-',
(self.old_uuid or '')[:6],
self.old_email or '-',
)
def __str__(self):
data = ['#%d' % self.old_user_id]
if self.old_email:
data.append(self.old_email)
return _('deleted user (%s)') % ', '.join(data)
class Meta:
verbose_name = _('deleted user')
verbose_name_plural = _('deleted users')

View File

@ -23,6 +23,7 @@ from authentic2.backends.ldap_backend import (
LDAP_DEACTIVATION_REASON_NOT_PRESENT,
LDAP_DEACTIVATION_REASON_OLD_SOURCE,
)
from authentic2.custom_user.models import DeletedUser
from authentic2.journal_event_types import EventTypeWithService, get_attributes_label
from django_rbac.utils import get_role_model
@ -30,6 +31,12 @@ User = get_user_model()
Role = get_role_model()
def user_to_str(user):
if hasattr(user, 'get_full_name'):
return user.get_full_name()
return str(user)
class ManagerUserCreation(EventTypeDefinition):
name = 'manager.user.creation'
label = _('user creation')
@ -40,13 +47,13 @@ class ManagerUserCreation(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
# user journal page
if context and context == user:
return _('creation by administrator')
elif user:
# manager gloabal journal page
return _('creation of user "%s"') % user.get_full_name()
return _('creation of user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -60,13 +67,13 @@ class ManagerUserProfileEdit(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
new = event.get_data('new') or {}
edited_attributes = ', '.join(get_attributes_label(new)) or ''
if context and context == user:
return _('edit by administrator (%s)') % edited_attributes
elif user:
user_full_name = user.get_full_name()
user_full_name = user_to_str(user)
return _('edit of user "{0}" ({1})').format(user_full_name, edited_attributes)
return super().get_message(event, context)
@ -85,12 +92,12 @@ class ManagerUserEmailChangeRequest(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
new_email = event.get_data('email')
if context and context == user:
return _('email change for email address "%s" requested by administrator') % new_email
elif user:
user_full_name = user.get_full_name()
user_full_name = user_to_str(user)
return _('email change of user "{0}" for email address "{1}"').format(user_full_name, new_email)
return super().get_message(event, context)
@ -109,7 +116,7 @@ class ManagerUserPasswordChange(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
send_mail = event.get_data('send_mail')
if context and context == user:
if send_mail:
@ -117,7 +124,7 @@ class ManagerUserPasswordChange(EventTypeDefinition):
else:
return _('password change by administrator')
elif user:
user_full_name = user.get_full_name()
user_full_name = user_to_str(user)
if send_mail:
return _('password change of user "%s" and notification by mail') % user_full_name
else:
@ -137,12 +144,12 @@ class ManagerUserPasswordResetRequest(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
email = event.get_data('email')
if context and context == user:
return _('password reset request by administrator sent to "%s"') % email
elif user:
return _('password reset request of "{0}" sent to "{1}"').format(user.get_full_name(), email)
return _('password reset request of "{0}" sent to "{1}"').format(user_to_str(user), email)
return super().get_message(event, context)
@ -156,11 +163,11 @@ class ManagerUserPasswordChangeForce(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
if context and context == user:
return _('mandatory password change at next login set by administrator')
elif user:
return _('mandatory password change at next login set for user "%s"') % user.get_full_name()
return _('mandatory password change at next login set for user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -174,11 +181,11 @@ class ManagerUserPasswordChangeUnforce(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
if context and context == user:
return _('mandatory password change at next login unset by administrator')
elif user:
return _('mandatory password change at next login unset for user "%s"') % user.get_full_name()
return _('mandatory password change at next login unset for user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -192,11 +199,11 @@ class ManagerUserActivation(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
if context and context == user:
return _('activation by administrator')
elif user:
return _('activation of user "%s"') % user.get_full_name()
return _('activation of user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -211,7 +218,7 @@ class ManagerUserDeactivation(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
reason = event.get_data('reason')
if context and context == user:
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
@ -222,21 +229,15 @@ class ManagerUserDeactivation(EventTypeDefinition):
return _('deactivation by administrator')
elif user:
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
return (
_(
'automatic deactivation of user "%s" because the associated LDAP account does not exist anymore'
)
% user.get_full_name()
)
return _(
'automatic deactivation of user "%s" because the associated LDAP account does not exist anymore'
) % user_to_str(user)
elif reason == LDAP_DEACTIVATION_REASON_OLD_SOURCE:
return (
_(
'automatic deactivation of user "%s" because the associated LDAP source has been deleted'
)
% user.get_full_name()
)
return _(
'automatic deactivation of user "%s" because the associated LDAP source has been deleted'
) % user_to_str(user)
else:
return _('deactivation of user "%s"') % user.get_full_name()
return _('deactivation of user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -250,11 +251,11 @@ class ManagerUserDeletion(EventTypeDefinition):
@classmethod
def get_message(cls, event, context):
(user,) = event.get_typed_references(User)
(user,) = event.get_typed_references((DeletedUser, User))
if context and context == user:
return _('deletion by administrator')
elif user:
return _('deletion of user "%s"') % user.get_full_name()
return _('deletion of user "%s"') % user_to_str(user)
return super().get_message(event, context)
@ -269,7 +270,7 @@ class ManagerUserSSOAuthorizationDeletion(EventTypeWithService):
@classmethod
def get_message(cls, event, context):
# first reference is to the service
__, user = event.get_typed_references(None, User)
__, user = event.get_typed_references(None, (DeletedUser, User))
service_name = cls.get_service_name(event)
if context and context == user:
return _('deletion of authorization of single sign on with "{service}" by administrator').format(
@ -278,7 +279,7 @@ class ManagerUserSSOAuthorizationDeletion(EventTypeWithService):
elif user:
return _('deletion of authorization of single sign on with "{service}" of user "{user}"').format(
service=service_name,
user=user.get_full_name(),
user=user_to_str(user),
)
return super().get_message(event, context)
@ -357,7 +358,7 @@ class ManagerRoleMembershipGrant(RoleEventsMixin):
@classmethod
def get_message(cls, event, context):
role, member = event.get_typed_references(Role, User)
role, member = event.get_typed_references(Role, (DeletedUser, User))
role = role or event.get_data('role_name')
member = member or event.get_data('member_name')
if context == member:
@ -379,7 +380,7 @@ class ManagerRoleMembershipRemoval(RoleEventsMixin):
@classmethod
def get_message(cls, event, context):
role, member = event.get_typed_references(Role, User)
role, member = event.get_typed_references(Role, (DeletedUser, User))
role = role or event.get_data('role_name')
member = member or event.get_data('member_name')
if context == member:
@ -491,14 +492,14 @@ class ManagerRoleAdministratorUserAddition(RoleEventsMixin):
@classmethod
def record(cls, user, session, role, admin_user):
data = {
'admin_user_name': admin_user.get_full_name(),
'admin_user_name': user_to_str(admin_user),
'admin_user_uuid': admin_user.uuid,
}
super().record(user=user, session=session, role=role, references=[admin_user], data=data)
@classmethod
def get_message(cls, event, context):
role, admin_user = event.get_typed_references(Role, User)
role, admin_user = event.get_typed_references(Role, (DeletedUser, User))
role = role or event.get_data('role_name')
admin_user = admin_user or event.get_data('admin_user_name')
if context == role:
@ -517,7 +518,7 @@ class ManagerRoleAdministratorUserRemoval(ManagerRoleAdministratorUserAddition):
@classmethod
def get_message(cls, event, context):
role, admin_user = event.get_typed_references(Role, User)
role, admin_user = event.get_typed_references(Role, (DeletedUser, User))
role = role or event.get_data('role_name')
admin_user = admin_user or event.get_data('admin_user_name')
if context == role:

View File

@ -125,6 +125,12 @@ class JournalForm(JournalForm):
return qs
def prefetcher(self, model, pks):
if not issubclass(model, User):
return
for deleted_user in DeletedUser.objects.filter(old_user_id__in=pks):
yield deleted_user.old_user_id, deleted_user
class BaseJournalView(views.TitleMixin, views.MediaMixin, views.MultipleOUMixin, JournalView):
template_name = 'authentic2/manager/journal.html'

View File

@ -1047,3 +1047,13 @@ def test_search(app, superuser, events):
'addition of user "user (111111)" as administrator of role "role1"',
'removal of role "role2" as administrator of role "role1"',
]
def test_delete_user(app, superuser, events):
old_user_id = events['user'].id
events['user'].delete()
response = login(app, user=superuser, path="/manage/journal/")
response.form.set('search', events['user'].email)
response = response.form.submit()
assert len(response.pyquery('tbody tr')) == 20
assert 'deletion of user &quot;deleted user (#%s, user@example.com)&quot;' % old_user_id in str(response)