manager: show deleted users informations in journal (#51808)
This commit is contained in:
parent
5e29c79224
commit
a921332fb2
|
@ -15,7 +15,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<tr data-event-id="{{ event.id }}" data-event-cursor="{{ event.cursor }}" data-event-type="{{ event.type.name }}">
|
<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--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--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>
|
<td class="journal-list--message-column">{% block event-message %}{{ event.message|default:"-" }}{% endblock %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -414,13 +414,19 @@ class DeletedUser(models.Model):
|
||||||
)
|
)
|
||||||
cls.objects.filter(deleted__lt=threshold).delete()
|
cls.objects.filter(deleted__lt=threshold).delete()
|
||||||
|
|
||||||
def __str__(self):
|
def __repr__(self):
|
||||||
return 'DeletedUser(old_id=%s, old_uuid=%s…, old_email=%s)' % (
|
return 'DeletedUser(old_id=%s, old_uuid=%s…, old_email=%s)' % (
|
||||||
self.old_user_id or '-',
|
self.old_user_id or '-',
|
||||||
(self.old_uuid or '')[:6],
|
(self.old_uuid or '')[:6],
|
||||||
self.old_email or '-',
|
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:
|
class Meta:
|
||||||
verbose_name = _('deleted user')
|
verbose_name = _('deleted user')
|
||||||
verbose_name_plural = _('deleted users')
|
verbose_name_plural = _('deleted users')
|
||||||
|
|
|
@ -23,6 +23,7 @@ from authentic2.backends.ldap_backend import (
|
||||||
LDAP_DEACTIVATION_REASON_NOT_PRESENT,
|
LDAP_DEACTIVATION_REASON_NOT_PRESENT,
|
||||||
LDAP_DEACTIVATION_REASON_OLD_SOURCE,
|
LDAP_DEACTIVATION_REASON_OLD_SOURCE,
|
||||||
)
|
)
|
||||||
|
from authentic2.custom_user.models import DeletedUser
|
||||||
from authentic2.journal_event_types import EventTypeWithService, get_attributes_label
|
from authentic2.journal_event_types import EventTypeWithService, get_attributes_label
|
||||||
from django_rbac.utils import get_role_model
|
from django_rbac.utils import get_role_model
|
||||||
|
|
||||||
|
@ -30,6 +31,12 @@ User = get_user_model()
|
||||||
Role = get_role_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):
|
class ManagerUserCreation(EventTypeDefinition):
|
||||||
name = 'manager.user.creation'
|
name = 'manager.user.creation'
|
||||||
label = _('user creation')
|
label = _('user creation')
|
||||||
|
@ -40,13 +47,13 @@ class ManagerUserCreation(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
# user journal page
|
# user journal page
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('creation by administrator')
|
return _('creation by administrator')
|
||||||
elif user:
|
elif user:
|
||||||
# manager gloabal journal page
|
# 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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,13 +67,13 @@ class ManagerUserProfileEdit(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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 {}
|
new = event.get_data('new') or {}
|
||||||
edited_attributes = ', '.join(get_attributes_label(new)) or ''
|
edited_attributes = ', '.join(get_attributes_label(new)) or ''
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('edit by administrator (%s)') % edited_attributes
|
return _('edit by administrator (%s)') % edited_attributes
|
||||||
elif user:
|
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 _('edit of user "{0}" ({1})').format(user_full_name, edited_attributes)
|
||||||
return super().get_message(event, context)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
@ -85,12 +92,12 @@ class ManagerUserEmailChangeRequest(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
new_email = event.get_data('email')
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('email change for email address "%s" requested by administrator') % new_email
|
return _('email change for email address "%s" requested by administrator') % new_email
|
||||||
elif user:
|
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 _('email change of user "{0}" for email address "{1}"').format(user_full_name, new_email)
|
||||||
return super().get_message(event, context)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
@ -109,7 +116,7 @@ class ManagerUserPasswordChange(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
send_mail = event.get_data('send_mail')
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
if send_mail:
|
if send_mail:
|
||||||
|
@ -117,7 +124,7 @@ class ManagerUserPasswordChange(EventTypeDefinition):
|
||||||
else:
|
else:
|
||||||
return _('password change by administrator')
|
return _('password change by administrator')
|
||||||
elif user:
|
elif user:
|
||||||
user_full_name = user.get_full_name()
|
user_full_name = user_to_str(user)
|
||||||
if send_mail:
|
if send_mail:
|
||||||
return _('password change of user "%s" and notification by mail') % user_full_name
|
return _('password change of user "%s" and notification by mail') % user_full_name
|
||||||
else:
|
else:
|
||||||
|
@ -137,12 +144,12 @@ class ManagerUserPasswordResetRequest(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
email = event.get_data('email')
|
email = event.get_data('email')
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('password reset request by administrator sent to "%s"') % email
|
return _('password reset request by administrator sent to "%s"') % email
|
||||||
elif user:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,11 +163,11 @@ class ManagerUserPasswordChangeForce(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('mandatory password change at next login set by administrator')
|
return _('mandatory password change at next login set by administrator')
|
||||||
elif user:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,11 +181,11 @@ class ManagerUserPasswordChangeUnforce(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('mandatory password change at next login unset by administrator')
|
return _('mandatory password change at next login unset by administrator')
|
||||||
elif user:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,11 +199,11 @@ class ManagerUserActivation(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('activation by administrator')
|
return _('activation by administrator')
|
||||||
elif user:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,7 +218,7 @@ class ManagerUserDeactivation(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
reason = event.get_data('reason')
|
reason = event.get_data('reason')
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
|
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
|
||||||
|
@ -222,21 +229,15 @@ class ManagerUserDeactivation(EventTypeDefinition):
|
||||||
return _('deactivation by administrator')
|
return _('deactivation by administrator')
|
||||||
elif user:
|
elif user:
|
||||||
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
|
if reason == LDAP_DEACTIVATION_REASON_NOT_PRESENT:
|
||||||
return (
|
return _(
|
||||||
_(
|
'automatic deactivation of user "%s" because the associated LDAP account does not exist anymore'
|
||||||
'automatic deactivation of user "%s" because the associated LDAP account does not exist anymore'
|
) % user_to_str(user)
|
||||||
)
|
|
||||||
% user.get_full_name()
|
|
||||||
)
|
|
||||||
elif reason == LDAP_DEACTIVATION_REASON_OLD_SOURCE:
|
elif reason == LDAP_DEACTIVATION_REASON_OLD_SOURCE:
|
||||||
return (
|
return _(
|
||||||
_(
|
'automatic deactivation of user "%s" because the associated LDAP source has been deleted'
|
||||||
'automatic deactivation of user "%s" because the associated LDAP source has been deleted'
|
) % user_to_str(user)
|
||||||
)
|
|
||||||
% user.get_full_name()
|
|
||||||
)
|
|
||||||
else:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,11 +251,11 @@ class ManagerUserDeletion(EventTypeDefinition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
(user,) = event.get_typed_references(User)
|
(user,) = event.get_typed_references((DeletedUser, User))
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('deletion by administrator')
|
return _('deletion by administrator')
|
||||||
elif user:
|
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)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ class ManagerUserSSOAuthorizationDeletion(EventTypeWithService):
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
def get_message(cls, event, context):
|
||||||
# first reference is to the service
|
# 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)
|
service_name = cls.get_service_name(event)
|
||||||
if context and context == user:
|
if context and context == user:
|
||||||
return _('deletion of authorization of single sign on with "{service}" by administrator').format(
|
return _('deletion of authorization of single sign on with "{service}" by administrator').format(
|
||||||
|
@ -278,7 +279,7 @@ class ManagerUserSSOAuthorizationDeletion(EventTypeWithService):
|
||||||
elif user:
|
elif user:
|
||||||
return _('deletion of authorization of single sign on with "{service}" of user "{user}"').format(
|
return _('deletion of authorization of single sign on with "{service}" of user "{user}"').format(
|
||||||
service=service_name,
|
service=service_name,
|
||||||
user=user.get_full_name(),
|
user=user_to_str(user),
|
||||||
)
|
)
|
||||||
return super().get_message(event, context)
|
return super().get_message(event, context)
|
||||||
|
|
||||||
|
@ -357,7 +358,7 @@ class ManagerRoleMembershipGrant(RoleEventsMixin):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
role = role or event.get_data('role_name')
|
||||||
member = member or event.get_data('member_name')
|
member = member or event.get_data('member_name')
|
||||||
if context == member:
|
if context == member:
|
||||||
|
@ -379,7 +380,7 @@ class ManagerRoleMembershipRemoval(RoleEventsMixin):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
role = role or event.get_data('role_name')
|
||||||
member = member or event.get_data('member_name')
|
member = member or event.get_data('member_name')
|
||||||
if context == member:
|
if context == member:
|
||||||
|
@ -491,14 +492,14 @@ class ManagerRoleAdministratorUserAddition(RoleEventsMixin):
|
||||||
@classmethod
|
@classmethod
|
||||||
def record(cls, user, session, role, admin_user):
|
def record(cls, user, session, role, admin_user):
|
||||||
data = {
|
data = {
|
||||||
'admin_user_name': admin_user.get_full_name(),
|
'admin_user_name': user_to_str(admin_user),
|
||||||
'admin_user_uuid': admin_user.uuid,
|
'admin_user_uuid': admin_user.uuid,
|
||||||
}
|
}
|
||||||
super().record(user=user, session=session, role=role, references=[admin_user], data=data)
|
super().record(user=user, session=session, role=role, references=[admin_user], data=data)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
role = role or event.get_data('role_name')
|
||||||
admin_user = admin_user or event.get_data('admin_user_name')
|
admin_user = admin_user or event.get_data('admin_user_name')
|
||||||
if context == role:
|
if context == role:
|
||||||
|
@ -517,7 +518,7 @@ class ManagerRoleAdministratorUserRemoval(ManagerRoleAdministratorUserAddition):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_message(cls, event, context):
|
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')
|
role = role or event.get_data('role_name')
|
||||||
admin_user = admin_user or event.get_data('admin_user_name')
|
admin_user = admin_user or event.get_data('admin_user_name')
|
||||||
if context == role:
|
if context == role:
|
||||||
|
|
|
@ -125,6 +125,12 @@ class JournalForm(JournalForm):
|
||||||
|
|
||||||
return qs
|
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):
|
class BaseJournalView(views.TitleMixin, views.MediaMixin, views.MultipleOUMixin, JournalView):
|
||||||
template_name = 'authentic2/manager/journal.html'
|
template_name = 'authentic2/manager/journal.html'
|
||||||
|
|
|
@ -1047,3 +1047,13 @@ def test_search(app, superuser, events):
|
||||||
'addition of user "user (111111)" as administrator of role "role1"',
|
'addition of user "user (111111)" as administrator of role "role1"',
|
||||||
'removal of role "role2" 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 "deleted user (#%s, user@example.com)"' % old_user_id in str(response)
|
||||||
|
|
Loading…
Reference in New Issue