From b365840ff675b456990b4f4ce6d9b57d95fbc7f3 Mon Sep 17 00:00:00 2001
From: Paul Marillonnet <pmarillonnet@entrouvert.com>
Date: Wed, 5 Jan 2022 15:59:44 +0100
Subject: [PATCH 2/3] journal: add user profile management events (#58554)

---
 src/authentic2/journal_event_types.py | 51 +++++++++++++++++++++++
 tests/test_manager_journal.py         | 59 ++++++++++++++++++++++++++-
 2 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/src/authentic2/journal_event_types.py b/src/authentic2/journal_event_types.py
index 8634aa91..0f6acb52 100644
--- a/src/authentic2/journal_event_types.py
+++ b/src/authentic2/journal_event_types.py
@@ -364,3 +364,54 @@ class UserEmailChange(EventTypeDefinition):
         new_email = event.get_data('email')
         old_email = event.get_data('old_email')
         return _('email address changed from "{0}" to "{1}"').format(old_email, new_email)
+
+
+class UserProfileAdd(EventTypeDefinition):
+    name = 'user.profile.add'
+    label = _('user profile creation')
+
+    @classmethod
+    def record(cls, user, profile_type):
+        data = {
+            'profile_type': profile_type.name or profile_type.slug,
+        }
+        super().record(user=user, data=data)
+
+    @classmethod
+    def get_message(cls, event, context):
+        profile_type = event.get_data('profile_type')
+        return _('profile of type {0} created for user').format(profile_type)
+
+
+class UserProfileUpdate(EventTypeDefinition):
+    name = 'user.profile.update'
+    label = _('user profile update')
+
+    @classmethod
+    def record(cls, user, profile_type):
+        data = {
+            'profile_type': profile_type.name or profile_type.slug,
+        }
+        super().record(user=user, data=data)
+
+    @classmethod
+    def get_message(cls, event, context):
+        profile_type = event.get_data('profile_type')
+        return _('profile of type {0} updated for user').format(profile_type)
+
+
+class UserProfileDelete(EventTypeDefinition):
+    name = 'user.profile.delete'
+    label = _('user profile deletion')
+
+    @classmethod
+    def record(cls, user, profile_type):
+        data = {
+            'profile_type': profile_type.name or profile_type.slug,
+        }
+        super().record(user=user, data=data)
+
+    @classmethod
+    def get_message(cls, event, context):
+        profile_type = event.get_data('profile_type')
+        return _('profile of type {0} deleted for user').format(profile_type)
diff --git a/tests/test_manager_journal.py b/tests/test_manager_journal.py
index c0a9600b..ca429b7f 100644
--- a/tests/test_manager_journal.py
+++ b/tests/test_manager_journal.py
@@ -24,7 +24,7 @@ from django.utils.timezone import make_aware
 from authentic2.a2_rbac.models import Role
 from authentic2.a2_rbac.utils import get_default_ou
 from authentic2.apps.journal.models import Event, _registry
-from authentic2.custom_user.models import User
+from authentic2.custom_user.models import ProfileType, User
 from authentic2.journal import journal
 from authentic2.models import Service
 
@@ -50,6 +50,7 @@ def events(db, freezer):
     user = User.objects.create(
         username="user", email="user@example.com", ou=ou, uuid="1" * 32, first_name='Johnny', last_name='doe'
     )
+    profile_type = ProfileType.objects.create(name='One Type', slug='one-type')
     agent = User.objects.create(username="agent", email="agent@example.com", ou=ou, uuid="2" * 32)
     role_user = Role.objects.create(name="role1", ou=ou)
     role_agent = Role.objects.create(name="role2", ou=ou)
@@ -269,6 +270,22 @@ def events(db, freezer):
 
     make("user.service.sso.refusal", user=user, session=session1, service=service)
 
+    make(
+        'user.profile.add',
+        user=user,
+        profile_type=profile_type,
+    )
+    make(
+        'user.profile.update',
+        user=user,
+        profile_type=profile_type,
+    )
+    make(
+        'user.profile.delete',
+        user=user,
+        profile_type=profile_type,
+    )
+
     # verify we created at least one event for each type
     assert set(Event.objects.values_list("type__name", flat=True)) == set(_registry)
 
@@ -591,6 +608,24 @@ def test_global_journal(app, superuser, events):
             'type': 'user.service.sso.refusal',
             'user': 'Johnny doe',
         },
+        {
+            'timestamp': 'Jan. 2, 2020, 9 p.m.',
+            'type': 'user.profile.add',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type created for user',
+        },
+        {
+            'timestamp': 'Jan. 2, 2020, 10 p.m.',
+            'type': 'user.profile.update',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type updated for user',
+        },
+        {
+            'timestamp': 'Jan. 2, 2020, 11 p.m.',
+            'type': 'user.profile.delete',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type deleted for user',
+        },
     ]
 
     agent_page = response.click('agent', index=1)
@@ -805,6 +840,24 @@ def test_user_journal(app, superuser, events):
             'type': 'user.service.sso.refusal',
             'user': 'Johnny doe',
         },
+        {
+            'timestamp': 'Jan. 2, 2020, 9 p.m.',
+            'type': 'user.profile.add',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type created for user',
+        },
+        {
+            'timestamp': 'Jan. 2, 2020, 10 p.m.',
+            'type': 'user.profile.update',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type updated for user',
+        },
+        {
+            'timestamp': 'Jan. 2, 2020, 11 p.m.',
+            'type': 'user.profile.delete',
+            'user': 'Johnny doe',
+            'message': 'profile of type One Type deleted for user',
+        },
     ]
 
 
@@ -1084,6 +1137,9 @@ 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 == [
+        'profile of type One Type deleted for user',
+        'profile of type One Type updated for user',
+        'profile of type One Type created for user',
         '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'
@@ -1102,7 +1158,6 @@ def test_search(app, superuser, events):
         'password reset request with email "user@example.com"',
         'user deletion',
         'profile edit (first name)',
-        'password change',
     ]
 
     response.form['event_type'].select(text='Role management')
-- 
2.34.1

