authentik.enterprise.audit.tests

  1from unittest.mock import PropertyMock, patch
  2
  3from django.apps import apps
  4from django.conf import settings
  5from django.urls import reverse
  6from rest_framework.test import APITestCase
  7
  8from authentik.core.models import Group, User
  9from authentik.core.tests.utils import create_test_admin_user
 10from authentik.enterprise.audit.apps import AuditIncludeExpandedDiff
 11from authentik.enterprise.audit.middleware import EnterpriseAuditMiddleware
 12from authentik.events.models import Event, EventAction
 13from authentik.events.utils import sanitize_item
 14from authentik.lib.generators import generate_id
 15from authentik.tenants.flags import patch_flag
 16
 17
 18class TestEnterpriseAudit(APITestCase):
 19    """Test audit middleware"""
 20
 21    def setUp(self) -> None:
 22        self.user = create_test_admin_user()
 23
 24    def test_import(self):
 25        """Ensure middleware is imported when app.ready is called"""
 26        # Revert import swap
 27        orig_import = "authentik.events.middleware.AuditMiddleware"
 28        new_import = "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware"
 29        settings.MIDDLEWARE = [orig_import if x == new_import else x for x in settings.MIDDLEWARE]
 30        # Re-call ready()
 31        apps.get_app_config("authentik_enterprise_audit").ready()
 32        self.assertIn(
 33            "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware", settings.MIDDLEWARE
 34        )
 35
 36    @patch(
 37        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
 38        PropertyMock(return_value=True),
 39    )
 40    def test_create(self):
 41        """Test create audit log"""
 42        self.client.force_login(self.user)
 43        username = generate_id()
 44        response = self.client.post(
 45            reverse("authentik_api:user-list"),
 46            data={"name": generate_id(), "username": username, "groups": [], "path": "foo"},
 47        )
 48        user = User.objects.get(username=username)
 49        self.assertEqual(response.status_code, 201)
 50        events = Event.objects.filter(
 51            action=EventAction.MODEL_CREATED,
 52            context__model__model_name="user",
 53            context__model__app="authentik_core",
 54            context__model__pk=user.pk,
 55        )
 56        event = events.first()
 57        self.assertIsNotNone(event)
 58        self.assertIsNotNone(event.context["diff"])
 59        diff = event.context["diff"]
 60        diff.pop("last_updated")
 61        self.assertEqual(
 62            diff,
 63            {
 64                "name": {
 65                    "new_value": user.name,
 66                    "previous_value": None,
 67                },
 68                "path": {"new_value": "foo", "previous_value": None},
 69                "type": {"new_value": "internal", "previous_value": None},
 70                "uuid": {
 71                    "new_value": user.uuid.hex,
 72                    "previous_value": None,
 73                },
 74                "email": {"new_value": "", "previous_value": None},
 75                "username": {
 76                    "new_value": user.username,
 77                    "previous_value": None,
 78                },
 79                "is_active": {"new_value": True, "previous_value": None},
 80                "attributes": {"new_value": {}, "previous_value": None},
 81                "date_joined": {
 82                    "new_value": sanitize_item(user.date_joined),
 83                    "previous_value": None,
 84                },
 85                "first_name": {"new_value": "", "previous_value": None},
 86                "id": {"new_value": user.pk, "previous_value": None},
 87                "last_name": {"new_value": "", "previous_value": None},
 88                "password": {"new_value": "********************", "previous_value": None},
 89                "password_change_date": {
 90                    "new_value": sanitize_item(user.password_change_date),
 91                    "previous_value": None,
 92                },
 93            },
 94        )
 95
 96    @patch(
 97        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
 98        PropertyMock(return_value=True),
 99    )
100    def test_update(self):
101        """Test update audit log"""
102        self.client.force_login(self.user)
103        user = create_test_admin_user()
104        current_name = user.name
105        new_name = generate_id()
106        response = self.client.patch(
107            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
108            data={"name": new_name},
109        )
110        user.refresh_from_db()
111        self.assertEqual(response.status_code, 200)
112        events = Event.objects.filter(
113            action=EventAction.MODEL_UPDATED,
114            context__model__model_name="user",
115            context__model__app="authentik_core",
116            context__model__pk=user.pk,
117        )
118        event = events.first()
119        self.assertIsNotNone(event)
120        self.assertIsNotNone(event.context["diff"])
121        diff = event.context["diff"]
122        diff.pop("last_updated")
123        self.assertEqual(
124            diff,
125            {
126                "name": {
127                    "new_value": new_name,
128                    "previous_value": current_name,
129                },
130            },
131        )
132
133    @patch(
134        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
135        PropertyMock(return_value=True),
136    )
137    def test_delete(self):
138        """Test delete audit log"""
139        self.client.force_login(self.user)
140        user = create_test_admin_user()
141        response = self.client.delete(
142            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
143        )
144        self.assertEqual(response.status_code, 204)
145        events = Event.objects.filter(
146            action=EventAction.MODEL_DELETED,
147            context__model__model_name="user",
148            context__model__app="authentik_core",
149            context__model__pk=user.pk,
150        )
151        event = events.first()
152        self.assertIsNotNone(event)
153        self.assertNotIn("diff", event.context)
154
155    @patch(
156        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
157        PropertyMock(return_value=True),
158    )
159    def test_m2m_add(self):
160        """Test m2m add audit log"""
161        self.client.force_login(self.user)
162        user = create_test_admin_user()
163        group = Group.objects.create(name=generate_id())
164        response = self.client.post(
165            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
166            data={
167                "pk": user.pk,
168            },
169        )
170        self.assertEqual(response.status_code, 204)
171        events = Event.objects.filter(
172            action=EventAction.MODEL_UPDATED,
173            context__model__model_name="group",
174            context__model__app="authentik_core",
175            context__model__pk=group.pk.hex,
176        )
177        event = events.first()
178        self.assertIsNotNone(event)
179        self.assertIsNotNone(event.context["diff"])
180        diff = event.context["diff"]
181        self.assertEqual(
182            diff,
183            {"users": {"add": [user.pk]}},
184        )
185
186    @patch(
187        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
188        PropertyMock(return_value=True),
189    )
190    @patch_flag(AuditIncludeExpandedDiff, True)
191    def test_m2m_add_expanded(self):
192        """Test m2m add audit log"""
193        user = create_test_admin_user()
194        group = Group.objects.create(name=generate_id())
195        self.client.force_login(self.user)
196        response = self.client.post(
197            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
198            data={
199                "pk": user.pk,
200            },
201        )
202        self.assertEqual(response.status_code, 204)
203        events = Event.objects.filter(
204            action=EventAction.MODEL_UPDATED,
205            context__model__model_name="group",
206            context__model__app="authentik_core",
207            context__model__pk=group.pk.hex,
208        )
209        event = events.first()
210        self.assertIsNotNone(event)
211        self.assertIsNotNone(event.context["diff"])
212        diff = event.context["diff"]
213        self.assertEqual(
214            diff,
215            {
216                "users": {
217                    "add": [
218                        {
219                            "attributes": {},
220                            "date_joined": sanitize_item(user.date_joined),
221                            "email": user.email,
222                            "first_name": "",
223                            "id": user.pk,
224                            "is_active": True,
225                            "last_login": None,
226                            "last_name": "",
227                            "last_updated": sanitize_item(user.last_updated),
228                            "name": user.name,
229                            "password": "********************",
230                            "password_change_date": sanitize_item(user.password_change_date),
231                            "path": "users",
232                            "type": "internal",
233                            "username": user.username,
234                            "uuid": user.uuid.hex,
235                        }
236                    ]
237                }
238            },
239        )
240
241    @patch(
242        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
243        PropertyMock(return_value=True),
244    )
245    def test_m2m_remove(self):
246        """Test m2m remove audit log"""
247        self.client.force_login(self.user)
248        user = create_test_admin_user()
249        group = Group.objects.create(name=generate_id())
250        response = self.client.post(
251            reverse("authentik_api:group-remove-user", kwargs={"pk": group.group_uuid}),
252            data={
253                "pk": user.pk,
254            },
255        )
256        self.assertEqual(response.status_code, 204)
257        events = Event.objects.filter(
258            action=EventAction.MODEL_UPDATED,
259            context__model__model_name="group",
260            context__model__app="authentik_core",
261            context__model__pk=group.pk.hex,
262        )
263        event = events.first()
264        self.assertIsNotNone(event)
265        self.assertIsNotNone(event.context["diff"])
266        diff = event.context["diff"]
267        self.assertEqual(
268            diff,
269            {"users": {"remove": [user.pk]}},
270        )
271
272    @patch(
273        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
274        PropertyMock(return_value=True),
275    )
276    def test_diff_update_fields(self):
277        """Test update audit log"""
278        self.client.force_login(self.user)
279        diff = EnterpriseAuditMiddleware(None).diff(
280            {
281                "foo": "bar",
282                "is_active": False,
283            },
284            {
285                "foo": "baz",
286                "is_active": True,
287            },
288            update_fields=["is_active"],
289        )
290        self.assertEqual(diff, {"is_active": {"new_value": True, "previous_value": False}})
class TestEnterpriseAudit(rest_framework.test.APITestCase):
 19class TestEnterpriseAudit(APITestCase):
 20    """Test audit middleware"""
 21
 22    def setUp(self) -> None:
 23        self.user = create_test_admin_user()
 24
 25    def test_import(self):
 26        """Ensure middleware is imported when app.ready is called"""
 27        # Revert import swap
 28        orig_import = "authentik.events.middleware.AuditMiddleware"
 29        new_import = "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware"
 30        settings.MIDDLEWARE = [orig_import if x == new_import else x for x in settings.MIDDLEWARE]
 31        # Re-call ready()
 32        apps.get_app_config("authentik_enterprise_audit").ready()
 33        self.assertIn(
 34            "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware", settings.MIDDLEWARE
 35        )
 36
 37    @patch(
 38        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
 39        PropertyMock(return_value=True),
 40    )
 41    def test_create(self):
 42        """Test create audit log"""
 43        self.client.force_login(self.user)
 44        username = generate_id()
 45        response = self.client.post(
 46            reverse("authentik_api:user-list"),
 47            data={"name": generate_id(), "username": username, "groups": [], "path": "foo"},
 48        )
 49        user = User.objects.get(username=username)
 50        self.assertEqual(response.status_code, 201)
 51        events = Event.objects.filter(
 52            action=EventAction.MODEL_CREATED,
 53            context__model__model_name="user",
 54            context__model__app="authentik_core",
 55            context__model__pk=user.pk,
 56        )
 57        event = events.first()
 58        self.assertIsNotNone(event)
 59        self.assertIsNotNone(event.context["diff"])
 60        diff = event.context["diff"]
 61        diff.pop("last_updated")
 62        self.assertEqual(
 63            diff,
 64            {
 65                "name": {
 66                    "new_value": user.name,
 67                    "previous_value": None,
 68                },
 69                "path": {"new_value": "foo", "previous_value": None},
 70                "type": {"new_value": "internal", "previous_value": None},
 71                "uuid": {
 72                    "new_value": user.uuid.hex,
 73                    "previous_value": None,
 74                },
 75                "email": {"new_value": "", "previous_value": None},
 76                "username": {
 77                    "new_value": user.username,
 78                    "previous_value": None,
 79                },
 80                "is_active": {"new_value": True, "previous_value": None},
 81                "attributes": {"new_value": {}, "previous_value": None},
 82                "date_joined": {
 83                    "new_value": sanitize_item(user.date_joined),
 84                    "previous_value": None,
 85                },
 86                "first_name": {"new_value": "", "previous_value": None},
 87                "id": {"new_value": user.pk, "previous_value": None},
 88                "last_name": {"new_value": "", "previous_value": None},
 89                "password": {"new_value": "********************", "previous_value": None},
 90                "password_change_date": {
 91                    "new_value": sanitize_item(user.password_change_date),
 92                    "previous_value": None,
 93                },
 94            },
 95        )
 96
 97    @patch(
 98        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
 99        PropertyMock(return_value=True),
100    )
101    def test_update(self):
102        """Test update audit log"""
103        self.client.force_login(self.user)
104        user = create_test_admin_user()
105        current_name = user.name
106        new_name = generate_id()
107        response = self.client.patch(
108            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
109            data={"name": new_name},
110        )
111        user.refresh_from_db()
112        self.assertEqual(response.status_code, 200)
113        events = Event.objects.filter(
114            action=EventAction.MODEL_UPDATED,
115            context__model__model_name="user",
116            context__model__app="authentik_core",
117            context__model__pk=user.pk,
118        )
119        event = events.first()
120        self.assertIsNotNone(event)
121        self.assertIsNotNone(event.context["diff"])
122        diff = event.context["diff"]
123        diff.pop("last_updated")
124        self.assertEqual(
125            diff,
126            {
127                "name": {
128                    "new_value": new_name,
129                    "previous_value": current_name,
130                },
131            },
132        )
133
134    @patch(
135        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
136        PropertyMock(return_value=True),
137    )
138    def test_delete(self):
139        """Test delete audit log"""
140        self.client.force_login(self.user)
141        user = create_test_admin_user()
142        response = self.client.delete(
143            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
144        )
145        self.assertEqual(response.status_code, 204)
146        events = Event.objects.filter(
147            action=EventAction.MODEL_DELETED,
148            context__model__model_name="user",
149            context__model__app="authentik_core",
150            context__model__pk=user.pk,
151        )
152        event = events.first()
153        self.assertIsNotNone(event)
154        self.assertNotIn("diff", event.context)
155
156    @patch(
157        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
158        PropertyMock(return_value=True),
159    )
160    def test_m2m_add(self):
161        """Test m2m add audit log"""
162        self.client.force_login(self.user)
163        user = create_test_admin_user()
164        group = Group.objects.create(name=generate_id())
165        response = self.client.post(
166            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
167            data={
168                "pk": user.pk,
169            },
170        )
171        self.assertEqual(response.status_code, 204)
172        events = Event.objects.filter(
173            action=EventAction.MODEL_UPDATED,
174            context__model__model_name="group",
175            context__model__app="authentik_core",
176            context__model__pk=group.pk.hex,
177        )
178        event = events.first()
179        self.assertIsNotNone(event)
180        self.assertIsNotNone(event.context["diff"])
181        diff = event.context["diff"]
182        self.assertEqual(
183            diff,
184            {"users": {"add": [user.pk]}},
185        )
186
187    @patch(
188        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
189        PropertyMock(return_value=True),
190    )
191    @patch_flag(AuditIncludeExpandedDiff, True)
192    def test_m2m_add_expanded(self):
193        """Test m2m add audit log"""
194        user = create_test_admin_user()
195        group = Group.objects.create(name=generate_id())
196        self.client.force_login(self.user)
197        response = self.client.post(
198            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
199            data={
200                "pk": user.pk,
201            },
202        )
203        self.assertEqual(response.status_code, 204)
204        events = Event.objects.filter(
205            action=EventAction.MODEL_UPDATED,
206            context__model__model_name="group",
207            context__model__app="authentik_core",
208            context__model__pk=group.pk.hex,
209        )
210        event = events.first()
211        self.assertIsNotNone(event)
212        self.assertIsNotNone(event.context["diff"])
213        diff = event.context["diff"]
214        self.assertEqual(
215            diff,
216            {
217                "users": {
218                    "add": [
219                        {
220                            "attributes": {},
221                            "date_joined": sanitize_item(user.date_joined),
222                            "email": user.email,
223                            "first_name": "",
224                            "id": user.pk,
225                            "is_active": True,
226                            "last_login": None,
227                            "last_name": "",
228                            "last_updated": sanitize_item(user.last_updated),
229                            "name": user.name,
230                            "password": "********************",
231                            "password_change_date": sanitize_item(user.password_change_date),
232                            "path": "users",
233                            "type": "internal",
234                            "username": user.username,
235                            "uuid": user.uuid.hex,
236                        }
237                    ]
238                }
239            },
240        )
241
242    @patch(
243        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
244        PropertyMock(return_value=True),
245    )
246    def test_m2m_remove(self):
247        """Test m2m remove audit log"""
248        self.client.force_login(self.user)
249        user = create_test_admin_user()
250        group = Group.objects.create(name=generate_id())
251        response = self.client.post(
252            reverse("authentik_api:group-remove-user", kwargs={"pk": group.group_uuid}),
253            data={
254                "pk": user.pk,
255            },
256        )
257        self.assertEqual(response.status_code, 204)
258        events = Event.objects.filter(
259            action=EventAction.MODEL_UPDATED,
260            context__model__model_name="group",
261            context__model__app="authentik_core",
262            context__model__pk=group.pk.hex,
263        )
264        event = events.first()
265        self.assertIsNotNone(event)
266        self.assertIsNotNone(event.context["diff"])
267        diff = event.context["diff"]
268        self.assertEqual(
269            diff,
270            {"users": {"remove": [user.pk]}},
271        )
272
273    @patch(
274        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
275        PropertyMock(return_value=True),
276    )
277    def test_diff_update_fields(self):
278        """Test update audit log"""
279        self.client.force_login(self.user)
280        diff = EnterpriseAuditMiddleware(None).diff(
281            {
282                "foo": "bar",
283                "is_active": False,
284            },
285            {
286                "foo": "baz",
287                "is_active": True,
288            },
289            update_fields=["is_active"],
290        )
291        self.assertEqual(diff, {"is_active": {"new_value": True, "previous_value": False}})

Test audit middleware

def setUp(self) -> None:
22    def setUp(self) -> None:
23        self.user = create_test_admin_user()

Hook method for setting up the test fixture before exercising it.

def test_import(self):
25    def test_import(self):
26        """Ensure middleware is imported when app.ready is called"""
27        # Revert import swap
28        orig_import = "authentik.events.middleware.AuditMiddleware"
29        new_import = "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware"
30        settings.MIDDLEWARE = [orig_import if x == new_import else x for x in settings.MIDDLEWARE]
31        # Re-call ready()
32        apps.get_app_config("authentik_enterprise_audit").ready()
33        self.assertIn(
34            "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware", settings.MIDDLEWARE
35        )

Ensure middleware is imported when app.ready is called

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_create(self):
37    @patch(
38        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
39        PropertyMock(return_value=True),
40    )
41    def test_create(self):
42        """Test create audit log"""
43        self.client.force_login(self.user)
44        username = generate_id()
45        response = self.client.post(
46            reverse("authentik_api:user-list"),
47            data={"name": generate_id(), "username": username, "groups": [], "path": "foo"},
48        )
49        user = User.objects.get(username=username)
50        self.assertEqual(response.status_code, 201)
51        events = Event.objects.filter(
52            action=EventAction.MODEL_CREATED,
53            context__model__model_name="user",
54            context__model__app="authentik_core",
55            context__model__pk=user.pk,
56        )
57        event = events.first()
58        self.assertIsNotNone(event)
59        self.assertIsNotNone(event.context["diff"])
60        diff = event.context["diff"]
61        diff.pop("last_updated")
62        self.assertEqual(
63            diff,
64            {
65                "name": {
66                    "new_value": user.name,
67                    "previous_value": None,
68                },
69                "path": {"new_value": "foo", "previous_value": None},
70                "type": {"new_value": "internal", "previous_value": None},
71                "uuid": {
72                    "new_value": user.uuid.hex,
73                    "previous_value": None,
74                },
75                "email": {"new_value": "", "previous_value": None},
76                "username": {
77                    "new_value": user.username,
78                    "previous_value": None,
79                },
80                "is_active": {"new_value": True, "previous_value": None},
81                "attributes": {"new_value": {}, "previous_value": None},
82                "date_joined": {
83                    "new_value": sanitize_item(user.date_joined),
84                    "previous_value": None,
85                },
86                "first_name": {"new_value": "", "previous_value": None},
87                "id": {"new_value": user.pk, "previous_value": None},
88                "last_name": {"new_value": "", "previous_value": None},
89                "password": {"new_value": "********************", "previous_value": None},
90                "password_change_date": {
91                    "new_value": sanitize_item(user.password_change_date),
92                    "previous_value": None,
93                },
94            },
95        )

Test create audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_update(self):
 97    @patch(
 98        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
 99        PropertyMock(return_value=True),
100    )
101    def test_update(self):
102        """Test update audit log"""
103        self.client.force_login(self.user)
104        user = create_test_admin_user()
105        current_name = user.name
106        new_name = generate_id()
107        response = self.client.patch(
108            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
109            data={"name": new_name},
110        )
111        user.refresh_from_db()
112        self.assertEqual(response.status_code, 200)
113        events = Event.objects.filter(
114            action=EventAction.MODEL_UPDATED,
115            context__model__model_name="user",
116            context__model__app="authentik_core",
117            context__model__pk=user.pk,
118        )
119        event = events.first()
120        self.assertIsNotNone(event)
121        self.assertIsNotNone(event.context["diff"])
122        diff = event.context["diff"]
123        diff.pop("last_updated")
124        self.assertEqual(
125            diff,
126            {
127                "name": {
128                    "new_value": new_name,
129                    "previous_value": current_name,
130                },
131            },
132        )

Test update audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_delete(self):
134    @patch(
135        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
136        PropertyMock(return_value=True),
137    )
138    def test_delete(self):
139        """Test delete audit log"""
140        self.client.force_login(self.user)
141        user = create_test_admin_user()
142        response = self.client.delete(
143            reverse("authentik_api:user-detail", kwargs={"pk": user.id}),
144        )
145        self.assertEqual(response.status_code, 204)
146        events = Event.objects.filter(
147            action=EventAction.MODEL_DELETED,
148            context__model__model_name="user",
149            context__model__app="authentik_core",
150            context__model__pk=user.pk,
151        )
152        event = events.first()
153        self.assertIsNotNone(event)
154        self.assertNotIn("diff", event.context)

Test delete audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_m2m_add(self):
156    @patch(
157        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
158        PropertyMock(return_value=True),
159    )
160    def test_m2m_add(self):
161        """Test m2m add audit log"""
162        self.client.force_login(self.user)
163        user = create_test_admin_user()
164        group = Group.objects.create(name=generate_id())
165        response = self.client.post(
166            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
167            data={
168                "pk": user.pk,
169            },
170        )
171        self.assertEqual(response.status_code, 204)
172        events = Event.objects.filter(
173            action=EventAction.MODEL_UPDATED,
174            context__model__model_name="group",
175            context__model__app="authentik_core",
176            context__model__pk=group.pk.hex,
177        )
178        event = events.first()
179        self.assertIsNotNone(event)
180        self.assertIsNotNone(event.context["diff"])
181        diff = event.context["diff"]
182        self.assertEqual(
183            diff,
184            {"users": {"add": [user.pk]}},
185        )

Test m2m add audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
@patch_flag(AuditIncludeExpandedDiff, True)
def test_m2m_add_expanded(self):
187    @patch(
188        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
189        PropertyMock(return_value=True),
190    )
191    @patch_flag(AuditIncludeExpandedDiff, True)
192    def test_m2m_add_expanded(self):
193        """Test m2m add audit log"""
194        user = create_test_admin_user()
195        group = Group.objects.create(name=generate_id())
196        self.client.force_login(self.user)
197        response = self.client.post(
198            reverse("authentik_api:group-add-user", kwargs={"pk": group.group_uuid}),
199            data={
200                "pk": user.pk,
201            },
202        )
203        self.assertEqual(response.status_code, 204)
204        events = Event.objects.filter(
205            action=EventAction.MODEL_UPDATED,
206            context__model__model_name="group",
207            context__model__app="authentik_core",
208            context__model__pk=group.pk.hex,
209        )
210        event = events.first()
211        self.assertIsNotNone(event)
212        self.assertIsNotNone(event.context["diff"])
213        diff = event.context["diff"]
214        self.assertEqual(
215            diff,
216            {
217                "users": {
218                    "add": [
219                        {
220                            "attributes": {},
221                            "date_joined": sanitize_item(user.date_joined),
222                            "email": user.email,
223                            "first_name": "",
224                            "id": user.pk,
225                            "is_active": True,
226                            "last_login": None,
227                            "last_name": "",
228                            "last_updated": sanitize_item(user.last_updated),
229                            "name": user.name,
230                            "password": "********************",
231                            "password_change_date": sanitize_item(user.password_change_date),
232                            "path": "users",
233                            "type": "internal",
234                            "username": user.username,
235                            "uuid": user.uuid.hex,
236                        }
237                    ]
238                }
239            },
240        )

Test m2m add audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_m2m_remove(self):
242    @patch(
243        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
244        PropertyMock(return_value=True),
245    )
246    def test_m2m_remove(self):
247        """Test m2m remove audit log"""
248        self.client.force_login(self.user)
249        user = create_test_admin_user()
250        group = Group.objects.create(name=generate_id())
251        response = self.client.post(
252            reverse("authentik_api:group-remove-user", kwargs={"pk": group.group_uuid}),
253            data={
254                "pk": user.pk,
255            },
256        )
257        self.assertEqual(response.status_code, 204)
258        events = Event.objects.filter(
259            action=EventAction.MODEL_UPDATED,
260            context__model__model_name="group",
261            context__model__app="authentik_core",
262            context__model__pk=group.pk.hex,
263        )
264        event = events.first()
265        self.assertIsNotNone(event)
266        self.assertIsNotNone(event.context["diff"])
267        diff = event.context["diff"]
268        self.assertEqual(
269            diff,
270            {"users": {"remove": [user.pk]}},
271        )

Test m2m remove audit log

@patch('authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled', PropertyMock(return_value=True))
def test_diff_update_fields(self):
273    @patch(
274        "authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
275        PropertyMock(return_value=True),
276    )
277    def test_diff_update_fields(self):
278        """Test update audit log"""
279        self.client.force_login(self.user)
280        diff = EnterpriseAuditMiddleware(None).diff(
281            {
282                "foo": "bar",
283                "is_active": False,
284            },
285            {
286                "foo": "baz",
287                "is_active": True,
288            },
289            update_fields=["is_active"],
290        )
291        self.assertEqual(diff, {"is_active": {"new_value": True, "previous_value": False}})

Test update audit log