Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2025-06-04 18:34:44 +02:00
parent d2cacdc640
commit 0e0fb37dd7
6 changed files with 52 additions and 69 deletions

View File

@ -4,7 +4,6 @@ from uuid import UUID
from django.http import HttpRequest from django.http import HttpRequest
from django.utils.timezone import now from django.utils.timezone import now
from dramatiq.actor import actor from dramatiq.actor import actor
from dramatiq.composition import group
from requests.exceptions import RequestException from requests.exceptions import RequestException
from structlog.stdlib import get_logger from structlog.stdlib import get_logger

View File

@ -1,6 +1,7 @@
"""Event notification tasks""" """Event notification tasks"""
from uuid import UUID from uuid import UUID
from django.db.models.query_utils import Q from django.db.models.query_utils import Q
from dramatiq.actor import actor from dramatiq.actor import actor
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user

View File

@ -159,7 +159,7 @@ class AuthenticatorDuoStageViewSet(UsedByMixin, ModelViewSet):
}, },
status=400, status=400,
) )
result = duo_import_devices.send(str(stage.pk)).get_result() result = duo_import_devices.send(stage.pk).get_result()
return Response(data=result, status=200 if result["error"] == "" else 400) return Response(data=result, status=200 if result["error"] == "" else 400)

View File

@ -1,5 +1,7 @@
"""duo tasks""" """duo tasks"""
from uuid import UUID
from dramatiq.actor import actor from dramatiq.actor import actor
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
@ -10,7 +12,7 @@ LOGGER = get_logger()
@actor(store_results=True) @actor(store_results=True)
def duo_import_devices(stage_pk: str): def duo_import_devices(stage_pk: UUID):
"""Import duo devices""" """Import duo devices"""
created = 0 created = 0
stage: AuthenticatorDuoStage = AuthenticatorDuoStage.objects.filter(pk=stage_pk).first() stage: AuthenticatorDuoStage = AuthenticatorDuoStage.objects.filter(pk=stage_pk).first()

View File

@ -14,7 +14,6 @@ from authentik.stages.authenticator_webauthn.models import (
WebAuthnDeviceType, WebAuthnDeviceType,
) )
from authentik.tasks.middleware import CurrentTask from authentik.tasks.middleware import CurrentTask
from authentik.tasks.models import Task, TaskStatus
CACHE_KEY_MDS_NO = "goauthentik.io/stages/authenticator_webauthn/mds_no" CACHE_KEY_MDS_NO = "goauthentik.io/stages/authenticator_webauthn/mds_no"
AAGUID_BLOB_PATH = Path(__file__).parent / "mds" / "aaguid.json" AAGUID_BLOB_PATH = Path(__file__).parent / "mds" / "aaguid.json"
@ -32,7 +31,7 @@ def mds_ca() -> bytes:
@actor @actor
def webauthn_mds_import(force=False): def webauthn_mds_import(force=False):
"""Background task to import FIDO Alliance MDS blob and AAGUIDs into database""" """Background task to import FIDO Alliance MDS blob and AAGUIDs into database"""
self: Task = CurrentTask.get_task() self = CurrentTask.get_task()
with open(MDS_BLOB_PATH, mode="rb") as _raw_blob: with open(MDS_BLOB_PATH, mode="rb") as _raw_blob:
blob = parse_blob(_raw_blob.read(), mds_ca()) blob = parse_blob(_raw_blob.read(), mds_ca())
to_create_update = [ to_create_update = [
@ -87,7 +86,4 @@ def webauthn_mds_import(force=False):
unique_fields=["aaguid"], unique_fields=["aaguid"],
) )
self.set_status( self.info("Successfully imported FIDO Alliance MDS blobs and AAGUIDs.")
TaskStatus.SUCCESSFUL,
"Successfully imported FIDO Alliance MDS blobs and AAGUIDs.",
)

View File

@ -1,7 +1,6 @@
"""email stage tasks""" """email stage tasks"""
from email.utils import make_msgid from email.utils import make_msgid
from smtplib import SMTPException
from typing import Any from typing import Any
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
@ -17,7 +16,6 @@ from authentik.stages.authenticator_email.models import AuthenticatorEmailStage
from authentik.stages.email.models import EmailStage from authentik.stages.email.models import EmailStage
from authentik.stages.email.utils import logo_data from authentik.stages.email.utils import logo_data
from authentik.tasks.middleware import CurrentTask from authentik.tasks.middleware import CurrentTask
from authentik.tasks.models import Task, TaskStatus
LOGGER = get_logger() LOGGER = get_logger()
@ -56,67 +54,54 @@ def send_mail(
email_stage_pk: str | None = None, email_stage_pk: str | None = None,
): ):
"""Send Email for Email Stage. Retries are scheduled automatically.""" """Send Email for Email Stage. Retries are scheduled automatically."""
self: Task = CurrentTask.get_task() self = CurrentTask.get_task()
# TODO: fix me
# self.save_on_success = False
message_id = make_msgid(domain=DNS_NAME) message_id = make_msgid(domain=DNS_NAME)
self.set_uid(slugify(message_id.replace(".", "_").replace("@", "_"))) self.set_uid(slugify(message_id.replace(".", "_").replace("@", "_")))
try: if not stage_class_path or not email_stage_pk:
if not stage_class_path or not email_stage_pk: stage = EmailStage(use_global_settings=True)
stage = EmailStage(use_global_settings=True) else:
else: stage_class = path_to_class(stage_class_path)
stage_class = path_to_class(stage_class_path) stages = stage_class.objects.filter(pk=email_stage_pk)
stages = stage_class.objects.filter(pk=email_stage_pk) if not stages.exists():
if not stages.exists(): self.warning("Email stage does not exist anymore. Discarding message.")
self.set_status(
TaskStatus.WARNING,
"Email stage does not exist anymore. Discarding message.",
)
return
stage: EmailStage | AuthenticatorEmailStage = stages.first()
try:
backend = stage.backend
except ValueError as exc:
LOGGER.warning("failed to get email backend", exc=exc)
self.set_error(exc)
return return
backend.open() stage: EmailStage | AuthenticatorEmailStage = stages.first()
# Since django's EmailMessage objects are not JSON serialisable, try:
# we need to rebuild them from a dict backend = stage.backend
message_object = EmailMultiAlternatives() except ValueError as exc:
for key, value in message.items(): LOGGER.warning("failed to get email backend", exc=exc)
setattr(message_object, key, value) self.error(exc)
if not stage.use_global_settings: return
message_object.from_email = stage.from_address backend.open()
# Because we use the Message-ID as UID for the task, manually assign it # Since django's EmailMessage objects are not JSON serialisable,
message_object.extra_headers["Message-ID"] = message_id # we need to rebuild them from a dict
message_object = EmailMultiAlternatives()
for key, value in message.items():
setattr(message_object, key, value)
if not stage.use_global_settings:
message_object.from_email = stage.from_address
# Because we use the Message-ID as UID for the task, manually assign it
message_object.extra_headers["Message-ID"] = message_id
# Add the logo (we can't add it in the previous message since MIMEImage # Add the logo (we can't add it in the previous message since MIMEImage
# can't be converted to json) # can't be converted to json)
message_object.attach(logo_data()) message_object.attach(logo_data())
if ( if (
message_object.to message_object.to
and isinstance(message_object.to[0], str) and isinstance(message_object.to[0], str)
and "=?utf-8?" in message_object.to[0] and "=?utf-8?" in message_object.to[0]
): ):
message_object.to = [message_object.to[0].split("<")[-1].replace(">", "")] message_object.to = [message_object.to[0].split("<")[-1].replace(">", "")]
LOGGER.debug("Sending mail", to=message_object.to) LOGGER.debug("Sending mail", to=message_object.to)
backend.send_messages([message_object]) backend.send_messages([message_object])
Event.new( Event.new(
EventAction.EMAIL_SENT, EventAction.EMAIL_SENT,
message=f"Email to {', '.join(message_object.to)} sent", message=f"Email to {', '.join(message_object.to)} sent",
subject=message_object.subject, subject=message_object.subject,
body=get_email_body(message_object), body=get_email_body(message_object),
from_email=message_object.from_email, from_email=message_object.from_email,
to_email=message_object.to, to_email=message_object.to,
).save() ).save()
self.set_status( self.info("Successfully sent mail.")
TaskStatus.SUCCESSFUL,
"Successfully sent Mail.",
)
except (SMTPException, ConnectionError, OSError) as exc:
LOGGER.debug("Error sending email, retrying...", exc=exc)
self.set_error(exc)
raise exc