events: catch errors during send and re-raise as custom type
This commit is contained in:
		| @ -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: | ||||
|  | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer