Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions promgen/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.core import validators
from django.urls import path
from django.utils.html import format_html
from knox.admin import AuthTokenAdmin

from promgen import actions, models, plugins, views
from promgen.forms import PromgenAuthTokenCreateForm
from promgen.notification.email import NotificationEmail


class PrometheusInline(admin.TabularInline):
Expand Down Expand Up @@ -65,11 +63,6 @@ class Meta:
model = models.Sender
exclude = ["content_object"]

def clean(self):
if self.cleaned_data["sender"] == NotificationEmail.__module__:
validator = validators.EmailValidator()
validator(self.cleaned_data["value"])


@admin.register(models.Sender)
class SenderAdmin(admin.ModelAdmin):
Expand Down
15 changes: 15 additions & 0 deletions promgen/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldDoesNotExist
from django.core.validators import EmailValidator
from django.db import models, transaction
from django.forms.models import model_to_dict
from django.urls import reverse
Expand Down Expand Up @@ -178,6 +179,20 @@ def filtered(self, alert):
def get_absolute_url(self):
return reverse("notifier-edit", kwargs={"pk": self.pk})

def clean(self):
super().clean()
if self.sender == "promgen.notification.email":
validator = EmailValidator()
validator(self.value)

def save(self, *args, **kwargs):
# Django model validation is not automatically invoked when calling the original method
# save(). It runs automatically when data is handled through standard Django Forms or
# ModelForms. Therefore, we need to explicitly call full_clean() before saving the model
# instance to ensure that all field validations are always performed.
self.full_clean()
super().save(*args, **kwargs)


class Filter(models.Model):
sender = models.ForeignKey("Sender", on_delete=models.CASCADE)
Expand Down
5 changes: 5 additions & 0 deletions promgen/rest_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from rest_framework.exceptions import MethodNotAllowed, NotFound, PermissionDenied, ValidationError
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework.serializers import as_serializer_error
from rest_framework.views import APIView, exception_handler

import promgen.templatetags.promgen as promgen_templatetags
Expand Down Expand Up @@ -78,6 +79,10 @@ def get_urls(self):


def custom_exception_handler(exc, context):
if isinstance(exc, DjangoValidationError):
# Convert DjangoValidationError to a DRFValidationError
exc = ValidationError(detail=as_serializer_error(exc))

# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
Expand Down
11 changes: 0 additions & 11 deletions promgen/tests/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,14 +662,3 @@ def test_exception_handler(self):
)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json(), {"name": ["This field may not be blank."]})

# Unexpected exception (django.ValidationError) returns 500 HTTP code with
# the default response.
response = self.client.patch(
reverse("api-v2:rule-detail", kwargs={"id": 1}),
data={"clause": "This clause is not valid."},
content_type="application/json",
HTTP_AUTHORIZATION=f"Token {admin_token}",
)
self.assertEqual(response.status_code, 500)
self.assertEqual(response.json(), {"error": "Server Error (500)"})