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
	 Jens Langhammer
					Jens Langhammer