authentik.events.tests.test_api

Event API tests

  1"""Event API tests"""
  2
  3from datetime import timedelta
  4from json import loads
  5
  6from django.urls import reverse
  7from django.utils.datastructures import MultiValueDict
  8from django.utils.http import urlencode
  9from django.utils.timezone import now
 10from rest_framework.test import APITestCase
 11
 12from authentik.core.tests.utils import create_test_admin_user
 13from authentik.events.models import (
 14    Event,
 15    EventAction,
 16    Notification,
 17    NotificationSeverity,
 18    TransportMode,
 19)
 20from authentik.events.utils import model_to_dict
 21from authentik.lib.generators import generate_id
 22from authentik.providers.oauth2.models import OAuth2Provider
 23
 24
 25class TestEventsAPI(APITestCase):
 26    """Test Event API"""
 27
 28    def setUp(self) -> None:
 29        self.user = create_test_admin_user()
 30        self.client.force_login(self.user)
 31
 32    def test_filter_model_pk_int(self):
 33        """Test event list with context_model_pk and integer PKs"""
 34        provider = OAuth2Provider.objects.create(
 35            name=generate_id(),
 36        )
 37        event = Event.new(EventAction.MODEL_CREATED, model=model_to_dict(provider))
 38        event.save()
 39        response = self.client.get(
 40            reverse("authentik_api:event-list"),
 41            data={
 42                "context_model_pk": provider.pk,
 43                "context_model_app": "authentik_providers_oauth2",
 44                "context_model_name": "oauth2provider",
 45            },
 46        )
 47        self.assertEqual(response.status_code, 200)
 48        body = loads(response.content)
 49        self.assertEqual(body["pagination"]["count"], 1)
 50
 51    def test_top_n(self):
 52        """Test top_per_user"""
 53        event = Event.new(EventAction.AUTHORIZE_APPLICATION)
 54        event.save()  # We save to ensure nothing is un-saveable
 55        response = self.client.get(
 56            reverse("authentik_api:event-top-per-user"),
 57            data={"filter_action": EventAction.AUTHORIZE_APPLICATION},
 58        )
 59        self.assertEqual(response.status_code, 200)
 60
 61    def test_actions(self):
 62        """Test actions"""
 63        response = self.client.get(
 64            reverse("authentik_api:event-actions"),
 65        )
 66        self.assertEqual(response.status_code, 200)
 67
 68    def test_notifications(self):
 69        """Test notifications"""
 70        notification = Notification.objects.create(
 71            user=self.user, severity=NotificationSeverity.ALERT, body="", seen=False
 72        )
 73        self.client.post(
 74            reverse("authentik_api:notification-mark-all-seen"),
 75        )
 76        notification.refresh_from_db()
 77        self.assertTrue(notification.seen)
 78
 79    def test_transport(self):
 80        """Test transport API"""
 81        response = self.client.post(
 82            reverse("authentik_api:notificationtransport-list"),
 83            data={
 84                "name": "foo-with",
 85                "mode": TransportMode.WEBHOOK,
 86                "webhook_url": "http://foo.com",
 87            },
 88        )
 89        self.assertEqual(response.status_code, 201)
 90        response = self.client.post(
 91            reverse("authentik_api:notificationtransport-list"),
 92            data={
 93                "name": "foo-without",
 94                "mode": TransportMode.WEBHOOK,
 95            },
 96        )
 97        self.assertEqual(response.status_code, 400)
 98
 99    def test_volume(self):
100        Event.objects.all().delete()
101        Event.new(EventAction.LOGIN).set_user(self.user).save()
102        evt = Event.new(EventAction.LOGIN).set_user(self.user)
103        evt.created = now() - timedelta(days=6)
104        evt.save()
105        res = self.client.get(
106            reverse("authentik_api:event-volume")
107            + "?"
108            + urlencode(
109                {
110                    "action": EventAction.LOGIN,
111                }
112            )
113        )
114        self.assertEqual(res.status_code, 200)
115        data = loads(res.content)
116        self.assertEqual(len(data), 1)
117
118    def test_stats(self):
119        Event.objects.all().delete()
120        Event.new(EventAction.LOGIN).set_user(self.user).save()
121        evt = Event.new(EventAction.LOGIN).set_user(self.user)
122        evt.created = now() - timedelta(days=6)
123        evt.save()
124        res = self.client.get(
125            reverse("authentik_api:event-stats")
126            + "?"
127            + urlencode(
128                MultiValueDict({"count_steps": ["hours=24", "days=7", "days=240"]}), doseq=True
129            )
130        )
131        self.assertEqual(res.status_code, 200, res.content)
132        self.assertJSONEqual(
133            res.content, {"unique_users": 1, "count_step": {"hours24": 2, "days7": 2, "days240": 2}}
134        )
135
136    def test_stats_invalid(self):
137        res = self.client.get(
138            reverse("authentik_api:event-stats")
139            + "?"
140            + urlencode({"count_steps": "24d"}, doseq=True)
141        )
142        self.assertEqual(res.status_code, 400)
143        self.assertJSONEqual(
144            res.content,
145            {"count_steps": {"0": ["24d is not in the correct format of 'hours=3;minutes=1'."]}},
146        )
class TestEventsAPI(rest_framework.test.APITestCase):
 26class TestEventsAPI(APITestCase):
 27    """Test Event API"""
 28
 29    def setUp(self) -> None:
 30        self.user = create_test_admin_user()
 31        self.client.force_login(self.user)
 32
 33    def test_filter_model_pk_int(self):
 34        """Test event list with context_model_pk and integer PKs"""
 35        provider = OAuth2Provider.objects.create(
 36            name=generate_id(),
 37        )
 38        event = Event.new(EventAction.MODEL_CREATED, model=model_to_dict(provider))
 39        event.save()
 40        response = self.client.get(
 41            reverse("authentik_api:event-list"),
 42            data={
 43                "context_model_pk": provider.pk,
 44                "context_model_app": "authentik_providers_oauth2",
 45                "context_model_name": "oauth2provider",
 46            },
 47        )
 48        self.assertEqual(response.status_code, 200)
 49        body = loads(response.content)
 50        self.assertEqual(body["pagination"]["count"], 1)
 51
 52    def test_top_n(self):
 53        """Test top_per_user"""
 54        event = Event.new(EventAction.AUTHORIZE_APPLICATION)
 55        event.save()  # We save to ensure nothing is un-saveable
 56        response = self.client.get(
 57            reverse("authentik_api:event-top-per-user"),
 58            data={"filter_action": EventAction.AUTHORIZE_APPLICATION},
 59        )
 60        self.assertEqual(response.status_code, 200)
 61
 62    def test_actions(self):
 63        """Test actions"""
 64        response = self.client.get(
 65            reverse("authentik_api:event-actions"),
 66        )
 67        self.assertEqual(response.status_code, 200)
 68
 69    def test_notifications(self):
 70        """Test notifications"""
 71        notification = Notification.objects.create(
 72            user=self.user, severity=NotificationSeverity.ALERT, body="", seen=False
 73        )
 74        self.client.post(
 75            reverse("authentik_api:notification-mark-all-seen"),
 76        )
 77        notification.refresh_from_db()
 78        self.assertTrue(notification.seen)
 79
 80    def test_transport(self):
 81        """Test transport API"""
 82        response = self.client.post(
 83            reverse("authentik_api:notificationtransport-list"),
 84            data={
 85                "name": "foo-with",
 86                "mode": TransportMode.WEBHOOK,
 87                "webhook_url": "http://foo.com",
 88            },
 89        )
 90        self.assertEqual(response.status_code, 201)
 91        response = self.client.post(
 92            reverse("authentik_api:notificationtransport-list"),
 93            data={
 94                "name": "foo-without",
 95                "mode": TransportMode.WEBHOOK,
 96            },
 97        )
 98        self.assertEqual(response.status_code, 400)
 99
100    def test_volume(self):
101        Event.objects.all().delete()
102        Event.new(EventAction.LOGIN).set_user(self.user).save()
103        evt = Event.new(EventAction.LOGIN).set_user(self.user)
104        evt.created = now() - timedelta(days=6)
105        evt.save()
106        res = self.client.get(
107            reverse("authentik_api:event-volume")
108            + "?"
109            + urlencode(
110                {
111                    "action": EventAction.LOGIN,
112                }
113            )
114        )
115        self.assertEqual(res.status_code, 200)
116        data = loads(res.content)
117        self.assertEqual(len(data), 1)
118
119    def test_stats(self):
120        Event.objects.all().delete()
121        Event.new(EventAction.LOGIN).set_user(self.user).save()
122        evt = Event.new(EventAction.LOGIN).set_user(self.user)
123        evt.created = now() - timedelta(days=6)
124        evt.save()
125        res = self.client.get(
126            reverse("authentik_api:event-stats")
127            + "?"
128            + urlencode(
129                MultiValueDict({"count_steps": ["hours=24", "days=7", "days=240"]}), doseq=True
130            )
131        )
132        self.assertEqual(res.status_code, 200, res.content)
133        self.assertJSONEqual(
134            res.content, {"unique_users": 1, "count_step": {"hours24": 2, "days7": 2, "days240": 2}}
135        )
136
137    def test_stats_invalid(self):
138        res = self.client.get(
139            reverse("authentik_api:event-stats")
140            + "?"
141            + urlencode({"count_steps": "24d"}, doseq=True)
142        )
143        self.assertEqual(res.status_code, 400)
144        self.assertJSONEqual(
145            res.content,
146            {"count_steps": {"0": ["24d is not in the correct format of 'hours=3;minutes=1'."]}},
147        )

Test Event API

def setUp(self) -> None:
29    def setUp(self) -> None:
30        self.user = create_test_admin_user()
31        self.client.force_login(self.user)

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

def test_filter_model_pk_int(self):
33    def test_filter_model_pk_int(self):
34        """Test event list with context_model_pk and integer PKs"""
35        provider = OAuth2Provider.objects.create(
36            name=generate_id(),
37        )
38        event = Event.new(EventAction.MODEL_CREATED, model=model_to_dict(provider))
39        event.save()
40        response = self.client.get(
41            reverse("authentik_api:event-list"),
42            data={
43                "context_model_pk": provider.pk,
44                "context_model_app": "authentik_providers_oauth2",
45                "context_model_name": "oauth2provider",
46            },
47        )
48        self.assertEqual(response.status_code, 200)
49        body = loads(response.content)
50        self.assertEqual(body["pagination"]["count"], 1)

Test event list with context_model_pk and integer PKs

def test_top_n(self):
52    def test_top_n(self):
53        """Test top_per_user"""
54        event = Event.new(EventAction.AUTHORIZE_APPLICATION)
55        event.save()  # We save to ensure nothing is un-saveable
56        response = self.client.get(
57            reverse("authentik_api:event-top-per-user"),
58            data={"filter_action": EventAction.AUTHORIZE_APPLICATION},
59        )
60        self.assertEqual(response.status_code, 200)

Test top_per_user

def test_actions(self):
62    def test_actions(self):
63        """Test actions"""
64        response = self.client.get(
65            reverse("authentik_api:event-actions"),
66        )
67        self.assertEqual(response.status_code, 200)

Test actions

def test_notifications(self):
69    def test_notifications(self):
70        """Test notifications"""
71        notification = Notification.objects.create(
72            user=self.user, severity=NotificationSeverity.ALERT, body="", seen=False
73        )
74        self.client.post(
75            reverse("authentik_api:notification-mark-all-seen"),
76        )
77        notification.refresh_from_db()
78        self.assertTrue(notification.seen)

Test notifications

def test_transport(self):
80    def test_transport(self):
81        """Test transport API"""
82        response = self.client.post(
83            reverse("authentik_api:notificationtransport-list"),
84            data={
85                "name": "foo-with",
86                "mode": TransportMode.WEBHOOK,
87                "webhook_url": "http://foo.com",
88            },
89        )
90        self.assertEqual(response.status_code, 201)
91        response = self.client.post(
92            reverse("authentik_api:notificationtransport-list"),
93            data={
94                "name": "foo-without",
95                "mode": TransportMode.WEBHOOK,
96            },
97        )
98        self.assertEqual(response.status_code, 400)

Test transport API

def test_volume(self):
100    def test_volume(self):
101        Event.objects.all().delete()
102        Event.new(EventAction.LOGIN).set_user(self.user).save()
103        evt = Event.new(EventAction.LOGIN).set_user(self.user)
104        evt.created = now() - timedelta(days=6)
105        evt.save()
106        res = self.client.get(
107            reverse("authentik_api:event-volume")
108            + "?"
109            + urlencode(
110                {
111                    "action": EventAction.LOGIN,
112                }
113            )
114        )
115        self.assertEqual(res.status_code, 200)
116        data = loads(res.content)
117        self.assertEqual(len(data), 1)
def test_stats(self):
119    def test_stats(self):
120        Event.objects.all().delete()
121        Event.new(EventAction.LOGIN).set_user(self.user).save()
122        evt = Event.new(EventAction.LOGIN).set_user(self.user)
123        evt.created = now() - timedelta(days=6)
124        evt.save()
125        res = self.client.get(
126            reverse("authentik_api:event-stats")
127            + "?"
128            + urlencode(
129                MultiValueDict({"count_steps": ["hours=24", "days=7", "days=240"]}), doseq=True
130            )
131        )
132        self.assertEqual(res.status_code, 200, res.content)
133        self.assertJSONEqual(
134            res.content, {"unique_users": 1, "count_step": {"hours24": 2, "days7": 2, "days240": 2}}
135        )
def test_stats_invalid(self):
137    def test_stats_invalid(self):
138        res = self.client.get(
139            reverse("authentik_api:event-stats")
140            + "?"
141            + urlencode({"count_steps": "24d"}, doseq=True)
142        )
143        self.assertEqual(res.status_code, 400)
144        self.assertJSONEqual(
145            res.content,
146            {"count_steps": {"0": ["24d is not in the correct format of 'hours=3;minutes=1'."]}},
147        )