authentik.events.tests.test_transports
transport tests
1"""transport tests""" 2 3from unittest.mock import PropertyMock, patch 4 5from django.core import mail 6from django.core.mail.backends.locmem import EmailBackend 7from django.test import TestCase 8from django.urls import reverse 9from requests_mock import Mocker 10 11from authentik import authentik_full_version 12from authentik.core.tests.utils import create_test_admin_user 13from authentik.crypto.models import CertificateKeyPair 14from authentik.events.api.notification_transports import NotificationTransportSerializer 15from authentik.events.models import ( 16 Event, 17 Notification, 18 NotificationSeverity, 19 NotificationTransport, 20 NotificationWebhookMapping, 21 TransportMode, 22) 23from authentik.lib.generators import generate_id 24from authentik.stages.email.models import get_template_choices 25 26 27class TestEventTransports(TestCase): 28 """Test Event Transports""" 29 30 def setUp(self) -> None: 31 self.user = create_test_admin_user() 32 self.event = Event.new("foo", "testing", foo="bar,").set_user(self.user) 33 self.event.save() 34 self.notification = Notification.objects.create( 35 severity=NotificationSeverity.ALERT, 36 body="foo", 37 event=self.event, 38 user=self.user, 39 ) 40 41 def test_transport_webhook(self): 42 """Test webhook transport""" 43 transport: NotificationTransport = NotificationTransport.objects.create( 44 name=generate_id(), 45 mode=TransportMode.WEBHOOK, 46 webhook_url="http://localhost:1234/test", 47 ) 48 with Mocker() as mocker: 49 mocker.post("http://localhost:1234/test") 50 transport.send(self.notification) 51 self.assertEqual(mocker.call_count, 1) 52 self.assertEqual(mocker.request_history[0].method, "POST") 53 self.assertJSONEqual( 54 mocker.request_history[0].body.decode(), 55 { 56 "body": "foo", 57 "severity": "alert", 58 "user_email": self.user.email, 59 "user_username": self.user.username, 60 "event_user_email": self.user.email, 61 "event_user_username": self.user.username, 62 }, 63 ) 64 65 def test_transport_webhook_ca_invalid_unset(self): 66 """Test webhook transport""" 67 transport: NotificationTransport = NotificationTransport.objects.create( 68 name=generate_id(), 69 mode=TransportMode.WEBHOOK, 70 webhook_url="https://localhost:1234/test", 71 ) 72 with Mocker() as mocker: 73 mocker.post("https://localhost:1234/test") 74 transport.send(self.notification) 75 self.assertEqual(mocker.call_count, 1) 76 self.assertTrue(mocker.request_history[0].verify) 77 78 def test_transport_webhook_ca(self): 79 """Test webhook transport""" 80 kp = CertificateKeyPair.objects.create( 81 name=generate_id(), 82 certificate_data="foo", 83 ) 84 transport: NotificationTransport = NotificationTransport.objects.create( 85 name=generate_id(), 86 mode=TransportMode.WEBHOOK, 87 webhook_url="https://localhost:1234/test", 88 webhook_ca=kp, 89 ) 90 with Mocker() as mocker: 91 mocker.post("https://localhost:1234/test") 92 transport.send(self.notification) 93 self.assertEqual(mocker.call_count, 1) 94 self.assertIsNotNone(mocker.request_history[0].verify) 95 96 def test_transport_webhook_mapping(self): 97 """Test webhook transport with custom mapping""" 98 mapping_body = NotificationWebhookMapping.objects.create( 99 name=generate_id(), expression="return request.user" 100 ) 101 mapping_headers = NotificationWebhookMapping.objects.create( 102 name=generate_id(), expression="""return {"foo": "bar"}""" 103 ) 104 transport: NotificationTransport = NotificationTransport.objects.create( 105 name=generate_id(), 106 mode=TransportMode.WEBHOOK, 107 webhook_url="http://localhost:1234/test", 108 webhook_mapping_body=mapping_body, 109 webhook_mapping_headers=mapping_headers, 110 ) 111 with Mocker() as mocker: 112 mocker.post("http://localhost:1234/test") 113 transport.send(self.notification) 114 self.assertEqual(mocker.call_count, 1) 115 self.assertEqual(mocker.request_history[0].method, "POST") 116 self.assertEqual(mocker.request_history[0].headers["foo"], "bar") 117 self.assertJSONEqual( 118 mocker.request_history[0].body.decode(), 119 {"email": self.user.email, "pk": self.user.pk, "username": self.user.username}, 120 ) 121 122 def test_transport_webhook_slack(self): 123 """Test webhook transport (slack)""" 124 transport: NotificationTransport = NotificationTransport.objects.create( 125 name=generate_id(), 126 mode=TransportMode.WEBHOOK_SLACK, 127 webhook_url="http://localhost:1234/test", 128 ) 129 with Mocker() as mocker: 130 mocker.post("http://localhost:1234/test") 131 transport.send(self.notification) 132 self.assertEqual(mocker.call_count, 1) 133 self.assertEqual(mocker.request_history[0].method, "POST") 134 self.assertJSONEqual( 135 mocker.request_history[0].body.decode(), 136 { 137 "username": "authentik", 138 "icon_url": "https://goauthentik.io/img/icon.png", 139 "attachments": [ 140 { 141 "author_name": "authentik", 142 "author_link": "https://goauthentik.io", 143 "author_icon": "https://goauthentik.io/img/icon.png", 144 "title": "custom_foo", 145 "color": "#fd4b2d", 146 "fields": [ 147 {"title": "Severity", "value": "alert", "short": True}, 148 { 149 "title": "Dispatched for user", 150 "value": self.user.username, 151 "short": True, 152 }, 153 {"short": True, "title": "Event user", "value": self.user.username}, 154 {"title": "foo", "value": "bar,"}, 155 ], 156 "footer": f"authentik {authentik_full_version()}", 157 } 158 ], 159 }, 160 ) 161 162 def test_transport_email(self): 163 """Test email transport""" 164 transport: NotificationTransport = NotificationTransport.objects.create( 165 name=generate_id(), 166 mode=TransportMode.EMAIL, 167 ) 168 with patch( 169 "authentik.stages.email.models.EmailStage.backend_class", 170 PropertyMock(return_value=EmailBackend), 171 ): 172 transport.send(self.notification) 173 self.assertEqual(len(mail.outbox), 1) 174 self.assertEqual(mail.outbox[0].subject, "authentik Notification: custom_foo") 175 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0]) 176 177 def test_transport_email_custom_template(self): 178 """Test email transport with custom template""" 179 transport: NotificationTransport = NotificationTransport.objects.create( 180 name=generate_id(), 181 mode=TransportMode.EMAIL, 182 email_template="email/event_notification.html", 183 ) 184 with patch( 185 "authentik.stages.email.models.EmailStage.backend_class", 186 PropertyMock(return_value=EmailBackend), 187 ): 188 transport.send(self.notification) 189 self.assertEqual(len(mail.outbox), 1) 190 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0]) 191 192 def test_transport_email_custom_subject_prefix(self): 193 """Test email transport with custom subject prefix""" 194 transport: NotificationTransport = NotificationTransport.objects.create( 195 name=generate_id(), 196 mode=TransportMode.EMAIL, 197 email_subject_prefix="[CUSTOM] ", 198 ) 199 with patch( 200 "authentik.stages.email.models.EmailStage.backend_class", 201 PropertyMock(return_value=EmailBackend), 202 ): 203 transport.send(self.notification) 204 self.assertEqual(len(mail.outbox), 1) 205 self.assertEqual(mail.outbox[0].subject, "[CUSTOM] custom_foo") 206 207 def test_transport_email_validation(self): 208 """Test email transport template validation""" 209 210 # Test valid template 211 serializer = NotificationTransportSerializer( 212 data={ 213 "name": generate_id(), 214 "mode": TransportMode.EMAIL, 215 "email_template": "email/event_notification.html", 216 } 217 ) 218 self.assertTrue(serializer.is_valid()) 219 220 # Test invalid template - should fail due to choices validation 221 serializer = NotificationTransportSerializer( 222 data={ 223 "name": generate_id(), 224 "mode": TransportMode.EMAIL, 225 "email_template": "invalid/template.html", 226 } 227 ) 228 self.assertFalse(serializer.is_valid()) 229 self.assertIn("email_template", serializer.errors) 230 231 def test_templates_api_endpoint(self): 232 """Test templates API endpoint returns valid templates""" 233 self.client.force_login(self.user) 234 response = self.client.get(reverse("authentik_api:emailstage-templates")) 235 self.assertEqual(response.status_code, 200) 236 237 data = response.json() 238 self.assertIsInstance(data, list) 239 240 # Check that we have at least the default templates 241 template_names = [item["name"] for item in data] 242 self.assertIn("email/event_notification.html", template_names) 243 244 # Verify all templates are valid choices 245 valid_choices = dict(get_template_choices()) 246 for template in data: 247 self.assertIn(template["name"], valid_choices) 248 self.assertEqual(template["description"], valid_choices[template["name"]])
class
TestEventTransports(django.test.testcases.TestCase):
28class TestEventTransports(TestCase): 29 """Test Event Transports""" 30 31 def setUp(self) -> None: 32 self.user = create_test_admin_user() 33 self.event = Event.new("foo", "testing", foo="bar,").set_user(self.user) 34 self.event.save() 35 self.notification = Notification.objects.create( 36 severity=NotificationSeverity.ALERT, 37 body="foo", 38 event=self.event, 39 user=self.user, 40 ) 41 42 def test_transport_webhook(self): 43 """Test webhook transport""" 44 transport: NotificationTransport = NotificationTransport.objects.create( 45 name=generate_id(), 46 mode=TransportMode.WEBHOOK, 47 webhook_url="http://localhost:1234/test", 48 ) 49 with Mocker() as mocker: 50 mocker.post("http://localhost:1234/test") 51 transport.send(self.notification) 52 self.assertEqual(mocker.call_count, 1) 53 self.assertEqual(mocker.request_history[0].method, "POST") 54 self.assertJSONEqual( 55 mocker.request_history[0].body.decode(), 56 { 57 "body": "foo", 58 "severity": "alert", 59 "user_email": self.user.email, 60 "user_username": self.user.username, 61 "event_user_email": self.user.email, 62 "event_user_username": self.user.username, 63 }, 64 ) 65 66 def test_transport_webhook_ca_invalid_unset(self): 67 """Test webhook transport""" 68 transport: NotificationTransport = NotificationTransport.objects.create( 69 name=generate_id(), 70 mode=TransportMode.WEBHOOK, 71 webhook_url="https://localhost:1234/test", 72 ) 73 with Mocker() as mocker: 74 mocker.post("https://localhost:1234/test") 75 transport.send(self.notification) 76 self.assertEqual(mocker.call_count, 1) 77 self.assertTrue(mocker.request_history[0].verify) 78 79 def test_transport_webhook_ca(self): 80 """Test webhook transport""" 81 kp = CertificateKeyPair.objects.create( 82 name=generate_id(), 83 certificate_data="foo", 84 ) 85 transport: NotificationTransport = NotificationTransport.objects.create( 86 name=generate_id(), 87 mode=TransportMode.WEBHOOK, 88 webhook_url="https://localhost:1234/test", 89 webhook_ca=kp, 90 ) 91 with Mocker() as mocker: 92 mocker.post("https://localhost:1234/test") 93 transport.send(self.notification) 94 self.assertEqual(mocker.call_count, 1) 95 self.assertIsNotNone(mocker.request_history[0].verify) 96 97 def test_transport_webhook_mapping(self): 98 """Test webhook transport with custom mapping""" 99 mapping_body = NotificationWebhookMapping.objects.create( 100 name=generate_id(), expression="return request.user" 101 ) 102 mapping_headers = NotificationWebhookMapping.objects.create( 103 name=generate_id(), expression="""return {"foo": "bar"}""" 104 ) 105 transport: NotificationTransport = NotificationTransport.objects.create( 106 name=generate_id(), 107 mode=TransportMode.WEBHOOK, 108 webhook_url="http://localhost:1234/test", 109 webhook_mapping_body=mapping_body, 110 webhook_mapping_headers=mapping_headers, 111 ) 112 with Mocker() as mocker: 113 mocker.post("http://localhost:1234/test") 114 transport.send(self.notification) 115 self.assertEqual(mocker.call_count, 1) 116 self.assertEqual(mocker.request_history[0].method, "POST") 117 self.assertEqual(mocker.request_history[0].headers["foo"], "bar") 118 self.assertJSONEqual( 119 mocker.request_history[0].body.decode(), 120 {"email": self.user.email, "pk": self.user.pk, "username": self.user.username}, 121 ) 122 123 def test_transport_webhook_slack(self): 124 """Test webhook transport (slack)""" 125 transport: NotificationTransport = NotificationTransport.objects.create( 126 name=generate_id(), 127 mode=TransportMode.WEBHOOK_SLACK, 128 webhook_url="http://localhost:1234/test", 129 ) 130 with Mocker() as mocker: 131 mocker.post("http://localhost:1234/test") 132 transport.send(self.notification) 133 self.assertEqual(mocker.call_count, 1) 134 self.assertEqual(mocker.request_history[0].method, "POST") 135 self.assertJSONEqual( 136 mocker.request_history[0].body.decode(), 137 { 138 "username": "authentik", 139 "icon_url": "https://goauthentik.io/img/icon.png", 140 "attachments": [ 141 { 142 "author_name": "authentik", 143 "author_link": "https://goauthentik.io", 144 "author_icon": "https://goauthentik.io/img/icon.png", 145 "title": "custom_foo", 146 "color": "#fd4b2d", 147 "fields": [ 148 {"title": "Severity", "value": "alert", "short": True}, 149 { 150 "title": "Dispatched for user", 151 "value": self.user.username, 152 "short": True, 153 }, 154 {"short": True, "title": "Event user", "value": self.user.username}, 155 {"title": "foo", "value": "bar,"}, 156 ], 157 "footer": f"authentik {authentik_full_version()}", 158 } 159 ], 160 }, 161 ) 162 163 def test_transport_email(self): 164 """Test email transport""" 165 transport: NotificationTransport = NotificationTransport.objects.create( 166 name=generate_id(), 167 mode=TransportMode.EMAIL, 168 ) 169 with patch( 170 "authentik.stages.email.models.EmailStage.backend_class", 171 PropertyMock(return_value=EmailBackend), 172 ): 173 transport.send(self.notification) 174 self.assertEqual(len(mail.outbox), 1) 175 self.assertEqual(mail.outbox[0].subject, "authentik Notification: custom_foo") 176 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0]) 177 178 def test_transport_email_custom_template(self): 179 """Test email transport with custom template""" 180 transport: NotificationTransport = NotificationTransport.objects.create( 181 name=generate_id(), 182 mode=TransportMode.EMAIL, 183 email_template="email/event_notification.html", 184 ) 185 with patch( 186 "authentik.stages.email.models.EmailStage.backend_class", 187 PropertyMock(return_value=EmailBackend), 188 ): 189 transport.send(self.notification) 190 self.assertEqual(len(mail.outbox), 1) 191 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0]) 192 193 def test_transport_email_custom_subject_prefix(self): 194 """Test email transport with custom subject prefix""" 195 transport: NotificationTransport = NotificationTransport.objects.create( 196 name=generate_id(), 197 mode=TransportMode.EMAIL, 198 email_subject_prefix="[CUSTOM] ", 199 ) 200 with patch( 201 "authentik.stages.email.models.EmailStage.backend_class", 202 PropertyMock(return_value=EmailBackend), 203 ): 204 transport.send(self.notification) 205 self.assertEqual(len(mail.outbox), 1) 206 self.assertEqual(mail.outbox[0].subject, "[CUSTOM] custom_foo") 207 208 def test_transport_email_validation(self): 209 """Test email transport template validation""" 210 211 # Test valid template 212 serializer = NotificationTransportSerializer( 213 data={ 214 "name": generate_id(), 215 "mode": TransportMode.EMAIL, 216 "email_template": "email/event_notification.html", 217 } 218 ) 219 self.assertTrue(serializer.is_valid()) 220 221 # Test invalid template - should fail due to choices validation 222 serializer = NotificationTransportSerializer( 223 data={ 224 "name": generate_id(), 225 "mode": TransportMode.EMAIL, 226 "email_template": "invalid/template.html", 227 } 228 ) 229 self.assertFalse(serializer.is_valid()) 230 self.assertIn("email_template", serializer.errors) 231 232 def test_templates_api_endpoint(self): 233 """Test templates API endpoint returns valid templates""" 234 self.client.force_login(self.user) 235 response = self.client.get(reverse("authentik_api:emailstage-templates")) 236 self.assertEqual(response.status_code, 200) 237 238 data = response.json() 239 self.assertIsInstance(data, list) 240 241 # Check that we have at least the default templates 242 template_names = [item["name"] for item in data] 243 self.assertIn("email/event_notification.html", template_names) 244 245 # Verify all templates are valid choices 246 valid_choices = dict(get_template_choices()) 247 for template in data: 248 self.assertIn(template["name"], valid_choices) 249 self.assertEqual(template["description"], valid_choices[template["name"]])
Test Event Transports
def
setUp(self) -> None:
31 def setUp(self) -> None: 32 self.user = create_test_admin_user() 33 self.event = Event.new("foo", "testing", foo="bar,").set_user(self.user) 34 self.event.save() 35 self.notification = Notification.objects.create( 36 severity=NotificationSeverity.ALERT, 37 body="foo", 38 event=self.event, 39 user=self.user, 40 )
Hook method for setting up the test fixture before exercising it.
def
test_transport_webhook(self):
42 def test_transport_webhook(self): 43 """Test webhook transport""" 44 transport: NotificationTransport = NotificationTransport.objects.create( 45 name=generate_id(), 46 mode=TransportMode.WEBHOOK, 47 webhook_url="http://localhost:1234/test", 48 ) 49 with Mocker() as mocker: 50 mocker.post("http://localhost:1234/test") 51 transport.send(self.notification) 52 self.assertEqual(mocker.call_count, 1) 53 self.assertEqual(mocker.request_history[0].method, "POST") 54 self.assertJSONEqual( 55 mocker.request_history[0].body.decode(), 56 { 57 "body": "foo", 58 "severity": "alert", 59 "user_email": self.user.email, 60 "user_username": self.user.username, 61 "event_user_email": self.user.email, 62 "event_user_username": self.user.username, 63 }, 64 )
Test webhook transport
def
test_transport_webhook_ca_invalid_unset(self):
66 def test_transport_webhook_ca_invalid_unset(self): 67 """Test webhook transport""" 68 transport: NotificationTransport = NotificationTransport.objects.create( 69 name=generate_id(), 70 mode=TransportMode.WEBHOOK, 71 webhook_url="https://localhost:1234/test", 72 ) 73 with Mocker() as mocker: 74 mocker.post("https://localhost:1234/test") 75 transport.send(self.notification) 76 self.assertEqual(mocker.call_count, 1) 77 self.assertTrue(mocker.request_history[0].verify)
Test webhook transport
def
test_transport_webhook_ca(self):
79 def test_transport_webhook_ca(self): 80 """Test webhook transport""" 81 kp = CertificateKeyPair.objects.create( 82 name=generate_id(), 83 certificate_data="foo", 84 ) 85 transport: NotificationTransport = NotificationTransport.objects.create( 86 name=generate_id(), 87 mode=TransportMode.WEBHOOK, 88 webhook_url="https://localhost:1234/test", 89 webhook_ca=kp, 90 ) 91 with Mocker() as mocker: 92 mocker.post("https://localhost:1234/test") 93 transport.send(self.notification) 94 self.assertEqual(mocker.call_count, 1) 95 self.assertIsNotNone(mocker.request_history[0].verify)
Test webhook transport
def
test_transport_webhook_mapping(self):
97 def test_transport_webhook_mapping(self): 98 """Test webhook transport with custom mapping""" 99 mapping_body = NotificationWebhookMapping.objects.create( 100 name=generate_id(), expression="return request.user" 101 ) 102 mapping_headers = NotificationWebhookMapping.objects.create( 103 name=generate_id(), expression="""return {"foo": "bar"}""" 104 ) 105 transport: NotificationTransport = NotificationTransport.objects.create( 106 name=generate_id(), 107 mode=TransportMode.WEBHOOK, 108 webhook_url="http://localhost:1234/test", 109 webhook_mapping_body=mapping_body, 110 webhook_mapping_headers=mapping_headers, 111 ) 112 with Mocker() as mocker: 113 mocker.post("http://localhost:1234/test") 114 transport.send(self.notification) 115 self.assertEqual(mocker.call_count, 1) 116 self.assertEqual(mocker.request_history[0].method, "POST") 117 self.assertEqual(mocker.request_history[0].headers["foo"], "bar") 118 self.assertJSONEqual( 119 mocker.request_history[0].body.decode(), 120 {"email": self.user.email, "pk": self.user.pk, "username": self.user.username}, 121 )
Test webhook transport with custom mapping
def
test_transport_webhook_slack(self):
123 def test_transport_webhook_slack(self): 124 """Test webhook transport (slack)""" 125 transport: NotificationTransport = NotificationTransport.objects.create( 126 name=generate_id(), 127 mode=TransportMode.WEBHOOK_SLACK, 128 webhook_url="http://localhost:1234/test", 129 ) 130 with Mocker() as mocker: 131 mocker.post("http://localhost:1234/test") 132 transport.send(self.notification) 133 self.assertEqual(mocker.call_count, 1) 134 self.assertEqual(mocker.request_history[0].method, "POST") 135 self.assertJSONEqual( 136 mocker.request_history[0].body.decode(), 137 { 138 "username": "authentik", 139 "icon_url": "https://goauthentik.io/img/icon.png", 140 "attachments": [ 141 { 142 "author_name": "authentik", 143 "author_link": "https://goauthentik.io", 144 "author_icon": "https://goauthentik.io/img/icon.png", 145 "title": "custom_foo", 146 "color": "#fd4b2d", 147 "fields": [ 148 {"title": "Severity", "value": "alert", "short": True}, 149 { 150 "title": "Dispatched for user", 151 "value": self.user.username, 152 "short": True, 153 }, 154 {"short": True, "title": "Event user", "value": self.user.username}, 155 {"title": "foo", "value": "bar,"}, 156 ], 157 "footer": f"authentik {authentik_full_version()}", 158 } 159 ], 160 }, 161 )
Test webhook transport (slack)
def
test_transport_email(self):
163 def test_transport_email(self): 164 """Test email transport""" 165 transport: NotificationTransport = NotificationTransport.objects.create( 166 name=generate_id(), 167 mode=TransportMode.EMAIL, 168 ) 169 with patch( 170 "authentik.stages.email.models.EmailStage.backend_class", 171 PropertyMock(return_value=EmailBackend), 172 ): 173 transport.send(self.notification) 174 self.assertEqual(len(mail.outbox), 1) 175 self.assertEqual(mail.outbox[0].subject, "authentik Notification: custom_foo") 176 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0])
Test email transport
def
test_transport_email_custom_template(self):
178 def test_transport_email_custom_template(self): 179 """Test email transport with custom template""" 180 transport: NotificationTransport = NotificationTransport.objects.create( 181 name=generate_id(), 182 mode=TransportMode.EMAIL, 183 email_template="email/event_notification.html", 184 ) 185 with patch( 186 "authentik.stages.email.models.EmailStage.backend_class", 187 PropertyMock(return_value=EmailBackend), 188 ): 189 transport.send(self.notification) 190 self.assertEqual(len(mail.outbox), 1) 191 self.assertIn(self.notification.body, mail.outbox[0].alternatives[0][0])
Test email transport with custom template
def
test_transport_email_custom_subject_prefix(self):
193 def test_transport_email_custom_subject_prefix(self): 194 """Test email transport with custom subject prefix""" 195 transport: NotificationTransport = NotificationTransport.objects.create( 196 name=generate_id(), 197 mode=TransportMode.EMAIL, 198 email_subject_prefix="[CUSTOM] ", 199 ) 200 with patch( 201 "authentik.stages.email.models.EmailStage.backend_class", 202 PropertyMock(return_value=EmailBackend), 203 ): 204 transport.send(self.notification) 205 self.assertEqual(len(mail.outbox), 1) 206 self.assertEqual(mail.outbox[0].subject, "[CUSTOM] custom_foo")
Test email transport with custom subject prefix
def
test_transport_email_validation(self):
208 def test_transport_email_validation(self): 209 """Test email transport template validation""" 210 211 # Test valid template 212 serializer = NotificationTransportSerializer( 213 data={ 214 "name": generate_id(), 215 "mode": TransportMode.EMAIL, 216 "email_template": "email/event_notification.html", 217 } 218 ) 219 self.assertTrue(serializer.is_valid()) 220 221 # Test invalid template - should fail due to choices validation 222 serializer = NotificationTransportSerializer( 223 data={ 224 "name": generate_id(), 225 "mode": TransportMode.EMAIL, 226 "email_template": "invalid/template.html", 227 } 228 ) 229 self.assertFalse(serializer.is_valid()) 230 self.assertIn("email_template", serializer.errors)
Test email transport template validation
def
test_templates_api_endpoint(self):
232 def test_templates_api_endpoint(self): 233 """Test templates API endpoint returns valid templates""" 234 self.client.force_login(self.user) 235 response = self.client.get(reverse("authentik_api:emailstage-templates")) 236 self.assertEqual(response.status_code, 200) 237 238 data = response.json() 239 self.assertIsInstance(data, list) 240 241 # Check that we have at least the default templates 242 template_names = [item["name"] for item in data] 243 self.assertIn("email/event_notification.html", template_names) 244 245 # Verify all templates are valid choices 246 valid_choices = dict(get_template_choices()) 247 for template in data: 248 self.assertIn(template["name"], valid_choices) 249 self.assertEqual(template["description"], valid_choices[template["name"]])
Test templates API endpoint returns valid templates