migrate outpost to soft-delete
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -3,11 +3,14 @@
|
||||
from typing import Any
|
||||
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_delete, pre_delete
|
||||
from django.dispatch import Signal
|
||||
from django.utils import timezone
|
||||
from model_utils.managers import InheritanceManager
|
||||
from rest_framework.serializers import BaseSerializer
|
||||
|
||||
pre_soft_delete = Signal()
|
||||
post_soft_delete = Signal()
|
||||
|
||||
|
||||
class SerializerModel(models.Model):
|
||||
"""Base Abstract Model which has a serializer"""
|
||||
@ -83,7 +86,7 @@ class SoftDeleteModel(models.Model):
|
||||
return self.deleted_at is not None
|
||||
|
||||
def delete(self, using: Any = ..., keep_parents: bool = ...) -> tuple[int, dict[str, int]]:
|
||||
pre_delete.send(sender=self.__class__, instance=self)
|
||||
pre_soft_delete.send(sender=self.__class__, instance=self)
|
||||
now = timezone.now()
|
||||
self.deleted_at = now
|
||||
self.save(
|
||||
@ -91,7 +94,7 @@ class SoftDeleteModel(models.Model):
|
||||
"deleted_at",
|
||||
]
|
||||
)
|
||||
post_delete.send(sender=self.__class__, instance=self)
|
||||
post_soft_delete.send(sender=self.__class__, instance=self)
|
||||
return tuple()
|
||||
|
||||
def force_delete(self, using: Any = ...):
|
||||
|
||||
18
authentik/outposts/migrations/0022_outpost_deleted_at.py
Normal file
18
authentik/outposts/migrations/0022_outpost_deleted_at.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.4 on 2024-04-23 21:00
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_outposts", "0021_alter_outpost_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="outpost",
|
||||
name="deleted_at",
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@ -33,7 +33,7 @@ from authentik.core.models import (
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.models import InheritanceForeignKey, SerializerModel
|
||||
from authentik.lib.models import InheritanceForeignKey, SerializerModel, SoftDeleteModel
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.outposts.controllers.k8s.utils import get_namespace
|
||||
@ -131,7 +131,7 @@ class OutpostServiceConnection(models.Model):
|
||||
verbose_name = _("Outpost Service-Connection")
|
||||
verbose_name_plural = _("Outpost Service-Connections")
|
||||
|
||||
def __str__(self) -> __version__:
|
||||
def __str__(self):
|
||||
return f"Outpost service connection {self.name}"
|
||||
|
||||
@property
|
||||
@ -241,7 +241,7 @@ class KubernetesServiceConnection(SerializerModel, OutpostServiceConnection):
|
||||
return "ak-service-connection-kubernetes-form"
|
||||
|
||||
|
||||
class Outpost(SerializerModel, ManagedModel):
|
||||
class Outpost(SoftDeleteModel, SerializerModel, ManagedModel):
|
||||
"""Outpost instance which manages a service user and token"""
|
||||
|
||||
uuid = models.UUIDField(default=uuid4, editable=False, primary_key=True)
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Model
|
||||
from django.db.models.signals import m2m_changed, post_save, pre_delete, pre_save
|
||||
from django.db.models.signals import m2m_changed, post_save, pre_save
|
||||
from django.dispatch import receiver
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.models import Provider
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.lib.models import post_soft_delete
|
||||
from authentik.lib.utils.reflection import class_to_path
|
||||
from authentik.outposts.models import Outpost, OutpostServiceConnection
|
||||
from authentik.outposts.tasks import CACHE_KEY_OUTPOST_DOWN, outpost_controller, outpost_post_save
|
||||
@ -67,9 +68,7 @@ def post_save_update(sender, instance: Model, created: bool, **_):
|
||||
outpost_post_save.delay(class_to_path(instance.__class__), instance.pk)
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=Outpost)
|
||||
def pre_delete_cleanup(sender, instance: Outpost, **_):
|
||||
@receiver(post_soft_delete, sender=Outpost)
|
||||
def outpost_cleanup(sender, instance: Outpost, **_):
|
||||
"""Ensure that Outpost's user is deleted (which will delete the token through cascade)"""
|
||||
instance.user.delete()
|
||||
cache.set(CACHE_KEY_OUTPOST_DOWN % instance.pk.hex, instance)
|
||||
outpost_controller.delay(instance.pk.hex, action="down", from_cache=True)
|
||||
outpost_controller.delay(instance.pk.hex, action="down")
|
||||
|
||||
@ -129,17 +129,10 @@ def outpost_controller_all():
|
||||
|
||||
|
||||
@CELERY_APP.task(bind=True, base=SystemTask)
|
||||
def outpost_controller(
|
||||
self: SystemTask, outpost_pk: str, action: str = "up", from_cache: bool = False
|
||||
):
|
||||
def outpost_controller(self: SystemTask, outpost_pk: str, action: str = "up"):
|
||||
"""Create/update/monitor/delete the deployment of an Outpost"""
|
||||
logs = []
|
||||
if from_cache:
|
||||
outpost: Outpost = cache.get(CACHE_KEY_OUTPOST_DOWN % outpost_pk)
|
||||
LOGGER.debug("Getting outpost from cache to delete")
|
||||
else:
|
||||
outpost: Outpost = Outpost.objects.filter(pk=outpost_pk).first()
|
||||
LOGGER.debug("Getting outpost from DB")
|
||||
outpost: Outpost = Outpost.objects.filter(pk=outpost_pk).first()
|
||||
if not outpost:
|
||||
LOGGER.warning("No outpost")
|
||||
return
|
||||
@ -155,9 +148,10 @@ def outpost_controller(
|
||||
except (ControllerException, ServiceConnectionInvalid) as exc:
|
||||
self.set_error(exc)
|
||||
else:
|
||||
if from_cache:
|
||||
cache.delete(CACHE_KEY_OUTPOST_DOWN % outpost_pk)
|
||||
self.set_status(TaskStatus.SUCCESSFUL, *logs)
|
||||
finally:
|
||||
if action == "down":
|
||||
outpost.force_delete()
|
||||
|
||||
|
||||
@CELERY_APP.task(bind=True, base=SystemTask)
|
||||
|
||||
Reference in New Issue
Block a user