events: catch errors during send and re-raise as custom type

This commit is contained in:
Jens Langhammer 2021-01-12 21:48:16 +01:00
parent c727c845df
commit f30bdbecd6
2 changed files with 36 additions and 14 deletions

View file

@ -1,6 +1,6 @@
"""authentik events models"""
from inspect import getmodule, stack
from smtplib import SMTPException
from typing import Optional, Union
from uuid import uuid4
@ -9,7 +9,7 @@ from django.core.exceptions import ValidationError
from django.db import models
from django.http import HttpRequest
from django.utils.translation import gettext as _
from requests import post
from requests import RequestException, post
from structlog.stdlib import get_logger
from authentik import __version__
@ -19,6 +19,7 @@ from authentik.core.middleware import (
)
from authentik.core.models import Group, User
from authentik.events.utils import cleanse_dict, get_user, sanitize_dict
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.http import get_client_ip
from authentik.policies.models import PolicyBindingModel
from authentik.stages.email.tasks import send_mail
@ -27,6 +28,10 @@ from authentik.stages.email.utils import TemplateEmailMessage
LOGGER = get_logger("authentik.events")
class NotificationTransportError(SentryIgnoredException):
"""Error raised when a notification fails to be delivered"""
class EventAction(models.TextChoices):
"""All possible actions to save into the events log"""
@ -192,13 +197,17 @@ class NotificationTransport(models.Model):
def send_webhook(self, notification: "Notification") -> list[str]:
"""Send notification to generic webhook"""
response = post(
self.webhook_url,
json={
"body": notification.body,
"severity": notification.severity,
},
)
try:
response = post(
self.webhook_url,
json={
"body": notification.body,
"severity": notification.severity,
},
)
response.raise_for_status()
except RequestException as exc:
raise NotificationTransportError from exc
return [
response.status_code,
response.text,
@ -235,7 +244,11 @@ class NotificationTransport(models.Model):
if notification.event:
body["attachments"][0]["title"] = notification.event.action
body["attachments"][0]["text"] = notification.event.action
response = post(self.webhook_url, json=body)
try:
response = post(self.webhook_url, json=body)
response.raise_for_status()
except RequestException as exc:
raise NotificationTransportError from exc
return [
response.status_code,
response.text,
@ -257,8 +270,11 @@ class NotificationTransport(models.Model):
},
)
# Email is sent directly here, as the call to send() should have been from a task.
# pyright: reportGeneralTypeIssues=false
return send_mail(mail.__dict__) # pylint: disable=no-value-for-parameter
try:
# pyright: reportGeneralTypeIssues=false
return send_mail(mail.__dict__) # pylint: disable=no-value-for-parameter
except (SMTPException, ConnectionError) as exc:
raise NotificationTransportError from exc
class Meta:

View file

@ -6,6 +6,7 @@ from authentik.events.models import (
Event,
Notification,
NotificationTransport,
NotificationTransportError,
NotificationTrigger,
)
from authentik.lib.tasks import MonitoredTask, TaskResult, TaskResultStatus
@ -64,7 +65,12 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
)
@CELERY_APP.task(bind=True, base=MonitoredTask)
@CELERY_APP.task(
bind=True,
autoretry_for=(NotificationTransportError),
retry_backoff=True,
base=MonitoredTask,
)
def notification_transport(
self: MonitoredTask, notification_pk: int, transport_pk: int
):
@ -77,6 +83,6 @@ def notification_transport(
)
transport.send(notification)
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL))
except Exception as exc:
except NotificationTransportError as exc:
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
raise exc