diff --git a/authentik/api/apps.py b/authentik/api/apps.py index 86e817eea..664fcf9fa 100644 --- a/authentik/api/apps.py +++ b/authentik/api/apps.py @@ -18,7 +18,6 @@ class AuthentikAPIConfig(AppConfig): # Class is defined here as it needs to be created early enough that drf-spectacular will # find it, but also won't cause any import issues - # pylint: disable=unused-variable class TokenSchema(OpenApiAuthenticationExtension): """Auth schema""" diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index 47486bc2f..0e2d54b12 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -8,7 +8,7 @@ from uuid import uuid4 from dacite import from_dict from django.contrib.auth.models import Permission from django.core.cache import cache -from django.db import models, transaction +from django.db import IntegrityError, models, transaction from django.db.models.base import Model from django.utils.translation import gettext_lazy as _ from docker.client import DockerClient @@ -380,21 +380,24 @@ class Outpost(models.Model): tokens = Token.filter_not_expired( identifier=self.token_identifier, intent=TokenIntents.INTENT_API, - ) - if tokens.exists(): - token = tokens.first() - if not token.managed: - token.managed = managed - token.save() - return token - return Token.objects.create( - user=self.user, - identifier=self.token_identifier, - intent=TokenIntents.INTENT_API, - description=f"Autogenerated by authentik for Outpost {self.name}", - expiring=False, managed=managed, ) + if tokens.exists(): + return tokens.first() + try: + return Token.objects.create( + user=self.user, + identifier=self.token_identifier, + intent=TokenIntents.INTENT_API, + description=f"Autogenerated by authentik for Outpost {self.name}", + expiring=False, + managed=managed, + ) + except IntegrityError: + # Integrity error happens mostly when managed is re-used + Token.objects.filter(managed=managed).delete() + Token.objects.filter(identifier=self.token_identifier).delete() + return self.token def get_required_objects(self) -> Iterable[Union[models.Model, str]]: """Get an iterator of all objects the user needs read access to"""