We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
False version status in admin dashboard for AirGapped environments
**Describe the bug**
In an AirGapped environment with `AUTHENTIK_DISABLE_UPDATE_CHECK=true`, or when the version check has not yet been performed, the version tile on the admin dashboard will always state its `Up-to-date!` which may not actually be the case.

**To Reproduce**
Steps to reproduce the behavior:

1. Deploy a fresh Authentik installation on an older version (e.g. `2023.10.7`) and ensure  `AUTHENTIK_DISABLE_UPDATE_CHECK=true` is set.
2. Go to the admin dashboard
3. Observe the version tile stating proudly that its up-to-date.

**Expected behavior**
Not incorrectly stating its up-to-date as that would give a false sense of security.

**Screenshots**
![image](https://github.com/goauthentik/authentik/assets/68224306/0a470c2b-73f7-4ba1-ad83-7e35a7f9a053)

**Logs**
N/a

**Version and Deployment (please complete the following information):**

-   authentik version: 2024.2.0
-   Deployment: docker-compose

**Additional context**
N/a


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `authentik/admin/api/version.py`
Content:
```
1 """authentik administration overview"""
2 
3 from django.core.cache import cache
4 from drf_spectacular.utils import extend_schema
5 from packaging.version import parse
6 from rest_framework.fields import SerializerMethodField
7 from rest_framework.permissions import IsAuthenticated
8 from rest_framework.request import Request
9 from rest_framework.response import Response
10 from rest_framework.views import APIView
11 
12 from authentik import __version__, get_build_hash
13 from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
14 from authentik.core.api.utils import PassiveSerializer
15 
16 
17 class VersionSerializer(PassiveSerializer):
18     """Get running and latest version."""
19 
20     version_current = SerializerMethodField()
21     version_latest = SerializerMethodField()
22     build_hash = SerializerMethodField()
23     outdated = SerializerMethodField()
24 
25     def get_build_hash(self, _) -> str:
26         """Get build hash, if version is not latest or released"""
27         return get_build_hash()
28 
29     def get_version_current(self, _) -> str:
30         """Get current version"""
31         return __version__
32 
33     def get_version_latest(self, _) -> str:
34         """Get latest version from cache"""
35         version_in_cache = cache.get(VERSION_CACHE_KEY)
36         if not version_in_cache:  # pragma: no cover
37             update_latest_version.delay()
38             return __version__
39         return version_in_cache
40 
41     def get_outdated(self, instance) -> bool:
42         """Check if we're running the latest version"""
43         return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance))
44 
45 
46 class VersionView(APIView):
47     """Get running and latest version."""
48 
49     permission_classes = [IsAuthenticated]
50     pagination_class = None
51     filter_backends = []
52 
53     @extend_schema(responses={200: VersionSerializer(many=False)})
54     def get(self, request: Request) -> Response:
55         """Get running and latest version."""
56         return Response(VersionSerializer(True).data)
57
```

Path: `authentik/admin/tasks.py`
Content:
```
1 """authentik admin tasks"""
2 
3 import re
4 
5 from django.core.cache import cache
6 from django.core.validators import URLValidator
7 from django.db import DatabaseError, InternalError, ProgrammingError
8 from packaging.version import parse
9 from requests import RequestException
10 from structlog.stdlib import get_logger
11 
12 from authentik import __version__, get_build_hash
13 from authentik.admin.apps import PROM_INFO
14 from authentik.events.models import Event, EventAction, Notification
15 from authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task
16 from authentik.lib.config import CONFIG
17 from authentik.lib.utils.http import get_http_session
18 from authentik.root.celery import CELERY_APP
19 
20 LOGGER = get_logger()
21 VERSION_CACHE_KEY = "authentik_latest_version"
22 VERSION_CACHE_TIMEOUT = 8 * 60 * 60  # 8 hours
23 # Chop of the first ^ because we want to search the entire string
24 URL_FINDER = URLValidator.regex.pattern[1:]
25 LOCAL_VERSION = parse(__version__)
26 
27 
28 def _set_prom_info():
29     """Set prometheus info for version"""
30     PROM_INFO.info(
31         {
32             "version": __version__,
33             "latest": cache.get(VERSION_CACHE_KEY, ""),
34             "build_hash": get_build_hash(),
35         }
36     )
37 
38 
39 @CELERY_APP.task(
40     throws=(DatabaseError, ProgrammingError, InternalError),
41 )
42 def clear_update_notifications():
43     """Clear update notifications on startup if the notification was for the version
44     we're running now."""
45     for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE):
46         if "new_version" not in notification.event.context:
47             continue
48         notification_version = notification.event.context["new_version"]
49         if LOCAL_VERSION >= parse(notification_version):
50             notification.delete()
51 
52 
53 @CELERY_APP.task(bind=True, base=SystemTask)
54 @prefill_task
55 def update_latest_version(self: SystemTask):
56     """Update latest version info"""
57     if CONFIG.get_bool("disable_update_check"):
58         cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT)
59         self.set_status(TaskStatus.WARNING, "Version check disabled.")
60         return
61     try:
62         response = get_http_session().get(
63             "https://version.goauthentik.io/version.json",
64         )
65         response.raise_for_status()
66         data = response.json()
67         upstream_version = data.get("stable", {}).get("version")
68         cache.set(VERSION_CACHE_KEY, upstream_version, VERSION_CACHE_TIMEOUT)
69         self.set_status(TaskStatus.SUCCESSFUL, "Successfully updated latest Version")
70         _set_prom_info()
71         # Check if upstream version is newer than what we're running,
72         # and if no event exists yet, create one.
73         if LOCAL_VERSION < parse(upstream_version):
74             # Event has already been created, don't create duplicate
75             if Event.objects.filter(
76                 action=EventAction.UPDATE_AVAILABLE,
77                 context__new_version=upstream_version,
78             ).exists():
79                 return
80             event_dict = {"new_version": upstream_version}
81             if match := re.search(URL_FINDER, data.get("stable", {}).get("changelog", "")):
82                 event_dict["message"] = f"Changelog: {match.group()}"
83             Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()
84     except (RequestException, IndexError) as exc:
85         cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT)
86         self.set_error(exc)
87 
88 
89 _set_prom_info()
90
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py
--- a/authentik/admin/api/version.py
+++ b/authentik/admin/api/version.py
@@ -10,7 +10,7 @@
 from rest_framework.views import APIView
 
 from authentik import __version__, get_build_hash
-from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
+from authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version
 from authentik.core.api.utils import PassiveSerializer
 
 
@@ -19,6 +19,7 @@
 
     version_current = SerializerMethodField()
     version_latest = SerializerMethodField()
+    version_latest_valid = SerializerMethodField()
     build_hash = SerializerMethodField()
     outdated = SerializerMethodField()
 
@@ -38,6 +39,10 @@
             return __version__
         return version_in_cache
 
+    def get_version_latest_valid(self, _) -> str:
+        """Check if latest version is valid"""
+        return cache.get(VERSION_CACHE_KEY) != VERSION_NULL
+
     def get_outdated(self, instance) -> bool:
         """Check if we're running the latest version"""
         return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance))
diff --git a/authentik/admin/tasks.py b/authentik/admin/tasks.py
--- a/authentik/admin/tasks.py
+++ b/authentik/admin/tasks.py
@@ -18,6 +18,7 @@
 from authentik.root.celery import CELERY_APP
 
 LOGGER = get_logger()
+VERSION_NULL = "0.0.0"
 VERSION_CACHE_KEY = "authentik_latest_version"
 VERSION_CACHE_TIMEOUT = 8 * 60 * 60  # 8 hours
 # Chop of the first ^ because we want to search the entire string
@@ -55,7 +56,7 @@
 def update_latest_version(self: SystemTask):
     """Update latest version info"""
     if CONFIG.get_bool("disable_update_check"):
-        cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT)
+        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)
         self.set_status(TaskStatus.WARNING, "Version check disabled.")
         return
     try:
@@ -82,7 +83,7 @@
                 event_dict["message"] = f"Changelog: {match.group()}"
             Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()
     except (RequestException, IndexError) as exc:
-        cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT)
+        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)
         self.set_error(exc)

{"golden_diff": "diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py\n--- a/authentik/admin/api/version.py\n+++ b/authentik/admin/api/version.py\n@@ -10,7 +10,7 @@\n from rest_framework.views import APIView\n \n from authentik import __version__, get_build_hash\n-from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version\n+from authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version\n from authentik.core.api.utils import PassiveSerializer\n \n \n@@ -19,6 +19,7 @@\n \n     version_current = SerializerMethodField()\n     version_latest = SerializerMethodField()\n+    version_latest_valid = SerializerMethodField()\n     build_hash = SerializerMethodField()\n     outdated = SerializerMethodField()\n \n@@ -38,6 +39,10 @@\n             return __version__\n         return version_in_cache\n \n+    def get_version_latest_valid(self, _) -> str:\n+        \"\"\"Check if latest version is valid\"\"\"\n+        return cache.get(VERSION_CACHE_KEY) != VERSION_NULL\n+\n     def get_outdated(self, instance) -> bool:\n         \"\"\"Check if we're running the latest version\"\"\"\n         return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance))\ndiff --git a/authentik/admin/tasks.py b/authentik/admin/tasks.py\n--- a/authentik/admin/tasks.py\n+++ b/authentik/admin/tasks.py\n@@ -18,6 +18,7 @@\n from authentik.root.celery import CELERY_APP\n \n LOGGER = get_logger()\n+VERSION_NULL = \"0.0.0\"\n VERSION_CACHE_KEY = \"authentik_latest_version\"\n VERSION_CACHE_TIMEOUT = 8 * 60 * 60  # 8 hours\n # Chop of the first ^ because we want to search the entire string\n@@ -55,7 +56,7 @@\n def update_latest_version(self: SystemTask):\n     \"\"\"Update latest version info\"\"\"\n     if CONFIG.get_bool(\"disable_update_check\"):\n-        cache.set(VERSION_CACHE_KEY, \"0.0.0\", VERSION_CACHE_TIMEOUT)\n+        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)\n         self.set_status(TaskStatus.WARNING, \"Version check disabled.\")\n         return\n     try:\n@@ -82,7 +83,7 @@\n                 event_dict[\"message\"] = f\"Changelog: {match.group()}\"\n             Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()\n     except (RequestException, IndexError) as exc:\n-        cache.set(VERSION_CACHE_KEY, \"0.0.0\", VERSION_CACHE_TIMEOUT)\n+        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)\n         self.set_error(exc)\n", "issue": "False version status in admin dashboard for AirGapped environments\n**Describe the bug**\r\nIn an AirGapped environment with `AUTHENTIK_DISABLE_UPDATE_CHECK=true`, or when the version check has not yet been performed, the version tile on the admin dashboard will always state its `Up-to-date!` which may not actually be the case.\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n\r\n1. Deploy a fresh Authentik installation on an older version (e.g. `2023.10.7`) and ensure  `AUTHENTIK_DISABLE_UPDATE_CHECK=true` is set.\r\n2. Go to the admin dashboard\r\n3. Observe the version tile stating proudly that its up-to-date.\r\n\r\n**Expected behavior**\r\nNot incorrectly stating its up-to-date as that would give a false sense of security.\r\n\r\n**Screenshots**\r\n![image](https://github.com/goauthentik/authentik/assets/68224306/0a470c2b-73f7-4ba1-ad83-7e35a7f9a053)\r\n\r\n**Logs**\r\nN/a\r\n\r\n**Version and Deployment (please complete the following information):**\r\n\r\n-   authentik version: 2024.2.0\r\n-   Deployment: docker-compose\r\n\r\n**Additional context**\r\nN/a\r\n\n", "before_files": [{"content": "\"\"\"authentik administration overview\"\"\"\n\nfrom django.core.cache import cache\nfrom drf_spectacular.utils import extend_schema\nfrom packaging.version import parse\nfrom rest_framework.fields import SerializerMethodField\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nfrom authentik import __version__, get_build_hash\nfrom authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version\nfrom authentik.core.api.utils import PassiveSerializer\n\n\nclass VersionSerializer(PassiveSerializer):\n    \"\"\"Get running and latest version.\"\"\"\n\n    version_current = SerializerMethodField()\n    version_latest = SerializerMethodField()\n    build_hash = SerializerMethodField()\n    outdated = SerializerMethodField()\n\n    def get_build_hash(self, _) -> str:\n        \"\"\"Get build hash, if version is not latest or released\"\"\"\n        return get_build_hash()\n\n    def get_version_current(self, _) -> str:\n        \"\"\"Get current version\"\"\"\n        return __version__\n\n    def get_version_latest(self, _) -> str:\n        \"\"\"Get latest version from cache\"\"\"\n        version_in_cache = cache.get(VERSION_CACHE_KEY)\n        if not version_in_cache:  # pragma: no cover\n            update_latest_version.delay()\n            return __version__\n        return version_in_cache\n\n    def get_outdated(self, instance) -> bool:\n        \"\"\"Check if we're running the latest version\"\"\"\n        return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance))\n\n\nclass VersionView(APIView):\n    \"\"\"Get running and latest version.\"\"\"\n\n    permission_classes = [IsAuthenticated]\n    pagination_class = None\n    filter_backends = []\n\n    @extend_schema(responses={200: VersionSerializer(many=False)})\n    def get(self, request: Request) -> Response:\n        \"\"\"Get running and latest version.\"\"\"\n        return Response(VersionSerializer(True).data)\n", "path": "authentik/admin/api/version.py"}, {"content": "\"\"\"authentik admin tasks\"\"\"\n\nimport re\n\nfrom django.core.cache import cache\nfrom django.core.validators import URLValidator\nfrom django.db import DatabaseError, InternalError, ProgrammingError\nfrom packaging.version import parse\nfrom requests import RequestException\nfrom structlog.stdlib import get_logger\n\nfrom authentik import __version__, get_build_hash\nfrom authentik.admin.apps import PROM_INFO\nfrom authentik.events.models import Event, EventAction, Notification\nfrom authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task\nfrom authentik.lib.config import CONFIG\nfrom authentik.lib.utils.http import get_http_session\nfrom authentik.root.celery import CELERY_APP\n\nLOGGER = get_logger()\nVERSION_CACHE_KEY = \"authentik_latest_version\"\nVERSION_CACHE_TIMEOUT = 8 * 60 * 60  # 8 hours\n# Chop of the first ^ because we want to search the entire string\nURL_FINDER = URLValidator.regex.pattern[1:]\nLOCAL_VERSION = parse(__version__)\n\n\ndef _set_prom_info():\n    \"\"\"Set prometheus info for version\"\"\"\n    PROM_INFO.info(\n        {\n            \"version\": __version__,\n            \"latest\": cache.get(VERSION_CACHE_KEY, \"\"),\n            \"build_hash\": get_build_hash(),\n        }\n    )\n\n\n@CELERY_APP.task(\n    throws=(DatabaseError, ProgrammingError, InternalError),\n)\ndef clear_update_notifications():\n    \"\"\"Clear update notifications on startup if the notification was for the version\n    we're running now.\"\"\"\n    for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE):\n        if \"new_version\" not in notification.event.context:\n            continue\n        notification_version = notification.event.context[\"new_version\"]\n        if LOCAL_VERSION >= parse(notification_version):\n            notification.delete()\n\n\n@CELERY_APP.task(bind=True, base=SystemTask)\n@prefill_task\ndef update_latest_version(self: SystemTask):\n    \"\"\"Update latest version info\"\"\"\n    if CONFIG.get_bool(\"disable_update_check\"):\n        cache.set(VERSION_CACHE_KEY, \"0.0.0\", VERSION_CACHE_TIMEOUT)\n        self.set_status(TaskStatus.WARNING, \"Version check disabled.\")\n        return\n    try:\n        response = get_http_session().get(\n            \"https://version.goauthentik.io/version.json\",\n        )\n        response.raise_for_status()\n        data = response.json()\n        upstream_version = data.get(\"stable\", {}).get(\"version\")\n        cache.set(VERSION_CACHE_KEY, upstream_version, VERSION_CACHE_TIMEOUT)\n        self.set_status(TaskStatus.SUCCESSFUL, \"Successfully updated latest Version\")\n        _set_prom_info()\n        # Check if upstream version is newer than what we're running,\n        # and if no event exists yet, create one.\n        if LOCAL_VERSION < parse(upstream_version):\n            # Event has already been created, don't create duplicate\n            if Event.objects.filter(\n                action=EventAction.UPDATE_AVAILABLE,\n                context__new_version=upstream_version,\n            ).exists():\n                return\n            event_dict = {\"new_version\": upstream_version}\n            if match := re.search(URL_FINDER, data.get(\"stable\", {}).get(\"changelog\", \"\")):\n                event_dict[\"message\"] = f\"Changelog: {match.group()}\"\n            Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()\n    except (RequestException, IndexError) as exc:\n        cache.set(VERSION_CACHE_KEY, \"0.0.0\", VERSION_CACHE_TIMEOUT)\n        self.set_error(exc)\n\n\n_set_prom_info()\n", "path": "authentik/admin/tasks.py"}], "after_files": [{"content": "\"\"\"authentik administration overview\"\"\"\n\nfrom django.core.cache import cache\nfrom drf_spectacular.utils import extend_schema\nfrom packaging.version import parse\nfrom rest_framework.fields import SerializerMethodField\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nfrom authentik import __version__, get_build_hash\nfrom authentik.admin.tasks import VERSION_CACHE_KEY, VERSION_NULL, update_latest_version\nfrom authentik.core.api.utils import PassiveSerializer\n\n\nclass VersionSerializer(PassiveSerializer):\n    \"\"\"Get running and latest version.\"\"\"\n\n    version_current = SerializerMethodField()\n    version_latest = SerializerMethodField()\n    version_latest_valid = SerializerMethodField()\n    build_hash = SerializerMethodField()\n    outdated = SerializerMethodField()\n\n    def get_build_hash(self, _) -> str:\n        \"\"\"Get build hash, if version is not latest or released\"\"\"\n        return get_build_hash()\n\n    def get_version_current(self, _) -> str:\n        \"\"\"Get current version\"\"\"\n        return __version__\n\n    def get_version_latest(self, _) -> str:\n        \"\"\"Get latest version from cache\"\"\"\n        version_in_cache = cache.get(VERSION_CACHE_KEY)\n        if not version_in_cache:  # pragma: no cover\n            update_latest_version.delay()\n            return __version__\n        return version_in_cache\n\n    def get_version_latest_valid(self, _) -> str:\n        \"\"\"Check if latest version is valid\"\"\"\n        return cache.get(VERSION_CACHE_KEY) != VERSION_NULL\n\n    def get_outdated(self, instance) -> bool:\n        \"\"\"Check if we're running the latest version\"\"\"\n        return parse(self.get_version_current(instance)) < parse(self.get_version_latest(instance))\n\n\nclass VersionView(APIView):\n    \"\"\"Get running and latest version.\"\"\"\n\n    permission_classes = [IsAuthenticated]\n    pagination_class = None\n    filter_backends = []\n\n    @extend_schema(responses={200: VersionSerializer(many=False)})\n    def get(self, request: Request) -> Response:\n        \"\"\"Get running and latest version.\"\"\"\n        return Response(VersionSerializer(True).data)\n", "path": "authentik/admin/api/version.py"}, {"content": "\"\"\"authentik admin tasks\"\"\"\n\nimport re\n\nfrom django.core.cache import cache\nfrom django.core.validators import URLValidator\nfrom django.db import DatabaseError, InternalError, ProgrammingError\nfrom packaging.version import parse\nfrom requests import RequestException\nfrom structlog.stdlib import get_logger\n\nfrom authentik import __version__, get_build_hash\nfrom authentik.admin.apps import PROM_INFO\nfrom authentik.events.models import Event, EventAction, Notification\nfrom authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task\nfrom authentik.lib.config import CONFIG\nfrom authentik.lib.utils.http import get_http_session\nfrom authentik.root.celery import CELERY_APP\n\nLOGGER = get_logger()\nVERSION_NULL = \"0.0.0\"\nVERSION_CACHE_KEY = \"authentik_latest_version\"\nVERSION_CACHE_TIMEOUT = 8 * 60 * 60  # 8 hours\n# Chop of the first ^ because we want to search the entire string\nURL_FINDER = URLValidator.regex.pattern[1:]\nLOCAL_VERSION = parse(__version__)\n\n\ndef _set_prom_info():\n    \"\"\"Set prometheus info for version\"\"\"\n    PROM_INFO.info(\n        {\n            \"version\": __version__,\n            \"latest\": cache.get(VERSION_CACHE_KEY, \"\"),\n            \"build_hash\": get_build_hash(),\n        }\n    )\n\n\n@CELERY_APP.task(\n    throws=(DatabaseError, ProgrammingError, InternalError),\n)\ndef clear_update_notifications():\n    \"\"\"Clear update notifications on startup if the notification was for the version\n    we're running now.\"\"\"\n    for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE):\n        if \"new_version\" not in notification.event.context:\n            continue\n        notification_version = notification.event.context[\"new_version\"]\n        if LOCAL_VERSION >= parse(notification_version):\n            notification.delete()\n\n\n@CELERY_APP.task(bind=True, base=SystemTask)\n@prefill_task\ndef update_latest_version(self: SystemTask):\n    \"\"\"Update latest version info\"\"\"\n    if CONFIG.get_bool(\"disable_update_check\"):\n        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)\n        self.set_status(TaskStatus.WARNING, \"Version check disabled.\")\n        return\n    try:\n        response = get_http_session().get(\n            \"https://version.goauthentik.io/version.json\",\n        )\n        response.raise_for_status()\n        data = response.json()\n        upstream_version = data.get(\"stable\", {}).get(\"version\")\n        cache.set(VERSION_CACHE_KEY, upstream_version, VERSION_CACHE_TIMEOUT)\n        self.set_status(TaskStatus.SUCCESSFUL, \"Successfully updated latest Version\")\n        _set_prom_info()\n        # Check if upstream version is newer than what we're running,\n        # and if no event exists yet, create one.\n        if LOCAL_VERSION < parse(upstream_version):\n            # Event has already been created, don't create duplicate\n            if Event.objects.filter(\n                action=EventAction.UPDATE_AVAILABLE,\n                context__new_version=upstream_version,\n            ).exists():\n                return\n            event_dict = {\"new_version\": upstream_version}\n            if match := re.search(URL_FINDER, data.get(\"stable\", {}).get(\"changelog\", \"\")):\n                event_dict[\"message\"] = f\"Changelog: {match.group()}\"\n            Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()\n    except (RequestException, IndexError) as exc:\n        cache.set(VERSION_CACHE_KEY, VERSION_NULL, VERSION_CACHE_TIMEOUT)\n        self.set_error(exc)\n\n\n_set_prom_info()\n", "path": "authentik/admin/tasks.py"}]}