diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py index 72ddfa9eee..48ec8bd0f5 100644 --- a/authentik/admin/api/version.py +++ b/authentik/admin/api/version.py @@ -1,6 +1,7 @@ """authentik administration overview""" from django.core.cache import cache +from django_tenants.utils import get_public_schema_name from drf_spectacular.utils import extend_schema from packaging.version import parse from rest_framework.fields import SerializerMethodField @@ -13,6 +14,7 @@ from authentik import __version__, get_build_hash from authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version from authentik.core.api.utils import PassiveSerializer from authentik.outposts.models import Outpost +from authentik.tenants.utils import get_current_tenant class VersionSerializer(PassiveSerializer): @@ -35,6 +37,8 @@ class VersionSerializer(PassiveSerializer): def get_version_latest(self, _) -> str: """Get latest version from cache""" + if get_current_tenant().schema_name == get_public_schema_name(): + return __version__ version_in_cache = cache.get(VERSION_CACHE_KEY) if not version_in_cache: # pragma: no cover update_latest_version.delay() diff --git a/authentik/admin/apps.py b/authentik/admin/apps.py index def7d51ede..31e55797d9 100644 --- a/authentik/admin/apps.py +++ b/authentik/admin/apps.py @@ -14,3 +14,19 @@ class AuthentikAdminConfig(ManagedAppConfig): label = "authentik_admin" verbose_name = "authentik Admin" default = True + + @ManagedAppConfig.reconcile_global + def clear_update_notifications(self): + """Clear update notifications on startup if the notification was for the version + we're running now.""" + from packaging.version import parse + + from authentik.admin.tasks import LOCAL_VERSION + from authentik.events.models import EventAction, Notification + + for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE): + if "new_version" not in notification.event.context: + continue + notification_version = notification.event.context["new_version"] + if LOCAL_VERSION >= parse(notification_version): + notification.delete() diff --git a/authentik/admin/settings.py b/authentik/admin/settings.py index 7c5b561ff0..4db9a57a97 100644 --- a/authentik/admin/settings.py +++ b/authentik/admin/settings.py @@ -1,6 +1,7 @@ """authentik admin settings""" from celery.schedules import crontab +from django_tenants.utils import get_public_schema_name from authentik.lib.utils.time import fqdn_rand @@ -8,6 +9,7 @@ CELERY_BEAT_SCHEDULE = { "admin_latest_version": { "task": "authentik.admin.tasks.update_latest_version", "schedule": crontab(minute=fqdn_rand("admin_latest_version"), hour="*"), + "tenant_schemas": [get_public_schema_name()], "options": {"queue": "authentik_scheduled"}, } } diff --git a/authentik/admin/tasks.py b/authentik/admin/tasks.py index 8d38adb2cc..30b266ba65 100644 --- a/authentik/admin/tasks.py +++ b/authentik/admin/tasks.py @@ -1,7 +1,6 @@ """authentik admin tasks""" from django.core.cache import cache -from django.db import DatabaseError, InternalError, ProgrammingError from django.utils.translation import gettext_lazy as _ from packaging.version import parse from requests import RequestException @@ -9,7 +8,7 @@ from structlog.stdlib import get_logger from authentik import __version__, get_build_hash from authentik.admin.apps import PROM_INFO -from authentik.events.models import Event, EventAction, Notification +from authentik.events.models import Event, EventAction from authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task from authentik.lib.config import CONFIG from authentik.lib.utils.http import get_http_session @@ -33,20 +32,6 @@ def _set_prom_info(): ) -@CELERY_APP.task( - throws=(DatabaseError, ProgrammingError, InternalError), -) -def clear_update_notifications(): - """Clear update notifications on startup if the notification was for the version - we're running now.""" - for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE): - if "new_version" not in notification.event.context: - continue - notification_version = notification.event.context["new_version"] - if LOCAL_VERSION >= parse(notification_version): - notification.delete() - - @CELERY_APP.task(bind=True, base=SystemTask) @prefill_task def update_latest_version(self: SystemTask): diff --git a/authentik/admin/tests/test_tasks.py b/authentik/admin/tests/test_tasks.py index b88d16aec9..22926b5948 100644 --- a/authentik/admin/tests/test_tasks.py +++ b/authentik/admin/tests/test_tasks.py @@ -1,12 +1,12 @@ """test admin tasks""" +from django.apps import apps from django.core.cache import cache from django.test import TestCase from requests_mock import Mocker from authentik.admin.tasks import ( VERSION_CACHE_KEY, - clear_update_notifications, update_latest_version, ) from authentik.events.models import Event, EventAction @@ -72,12 +72,13 @@ class TestAdminTasks(TestCase): def test_clear_update_notifications(self): """Test clear of previous notification""" + admin_config = apps.get_app_config("authentik_admin") Event.objects.create( action=EventAction.UPDATE_AVAILABLE, context={"new_version": "99999999.9999999.9999999"} ) Event.objects.create(action=EventAction.UPDATE_AVAILABLE, context={"new_version": "1.1.1"}) Event.objects.create(action=EventAction.UPDATE_AVAILABLE, context={}) - clear_update_notifications() + admin_config.clear_update_notifications() self.assertFalse( Event.objects.filter( action=EventAction.UPDATE_AVAILABLE, context__new_version="1.1" diff --git a/authentik/root/celery.py b/authentik/root/celery.py index e71f241e0d..c7d6b077e5 100644 --- a/authentik/root/celery.py +++ b/authentik/root/celery.py @@ -98,11 +98,7 @@ def _get_startup_tasks_default_tenant() -> list[Callable]: def _get_startup_tasks_all_tenants() -> list[Callable]: """Get all tasks to be run on startup for all tenants""" - from authentik.admin.tasks import clear_update_notifications - - return [ - clear_update_notifications, - ] + return [] @worker_ready.connect