events: add additional validation for event transport

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-09-23 16:29:58 +02:00
parent 40a62ac1e5
commit 64b4e851ce
3 changed files with 40 additions and 2 deletions

View File

@ -1,7 +1,10 @@
"""NotificationTransport API Views""" """NotificationTransport API Views"""
from typing import Any
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, ListField, SerializerMethodField from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
@ -29,6 +32,14 @@ class NotificationTransportSerializer(ModelSerializer):
"""Return selected mode with a UI Label""" """Return selected mode with a UI Label"""
return TransportMode(instance.mode).label return TransportMode(instance.mode).label
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
"""Ensure the required fields are set."""
mode = attrs.get("mode")
if mode in [TransportMode.WEBHOOK, TransportMode.WEBHOOK_SLACK]:
if "webhook_url" not in attrs or attrs.get("webhook_url", "") == "":
raise ValidationError("Webhook URL may not be empty.")
return attrs
class Meta: class Meta:
model = NotificationTransport model = NotificationTransport

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Optional, Type, Union
from uuid import uuid4 from uuid import uuid4
from django.conf import settings from django.conf import settings
from django.core.validators import URLValidator
from django.db import models from django.db import models
from django.http import HttpRequest from django.http import HttpRequest
from django.http.request import QueryDict from django.http.request import QueryDict
@ -223,7 +224,7 @@ class NotificationTransport(models.Model):
name = models.TextField(unique=True) name = models.TextField(unique=True)
mode = models.TextField(choices=TransportMode.choices) mode = models.TextField(choices=TransportMode.choices)
webhook_url = models.TextField(blank=True) webhook_url = models.TextField(blank=True, validators=[URLValidator()])
webhook_mapping = models.ForeignKey( webhook_mapping = models.ForeignKey(
"NotificationWebhookMapping", on_delete=models.SET_DEFAULT, null=True, default=None "NotificationWebhookMapping", on_delete=models.SET_DEFAULT, null=True, default=None
) )

View File

@ -4,7 +4,13 @@ from django.urls import reverse
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from authentik.core.models import User from authentik.core.models import User
from authentik.events.models import Event, EventAction, Notification, NotificationSeverity from authentik.events.models import (
Event,
EventAction,
Notification,
NotificationSeverity,
TransportMode,
)
class TestEventsAPI(APITestCase): class TestEventsAPI(APITestCase):
@ -41,3 +47,23 @@ class TestEventsAPI(APITestCase):
) )
notification.refresh_from_db() notification.refresh_from_db()
self.assertTrue(notification.seen) self.assertTrue(notification.seen)
def test_transport(self):
"""Test transport API"""
response = self.client.post(
reverse("authentik_api:notificationtransport-list"),
data={
"name": "foo-with",
"mode": TransportMode.WEBHOOK,
"webhook_url": "http://foo.com",
},
)
self.assertEqual(response.status_code, 201)
response = self.client.post(
reverse("authentik_api:notificationtransport-list"),
data={
"name": "foo-without",
"mode": TransportMode.WEBHOOK,
},
)
self.assertEqual(response.status_code, 400)