lib: fix event creation when deprecated config is detected (#7969)
* lib: fix event creation when deprecated config is detected Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix black parsing errors Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
e4d3365a1c
commit
48e5823ad6
|
@ -2,6 +2,7 @@
|
||||||
from prometheus_client import Gauge
|
from prometheus_client import Gauge
|
||||||
|
|
||||||
from authentik.blueprints.apps import ManagedAppConfig
|
from authentik.blueprints.apps import ManagedAppConfig
|
||||||
|
from authentik.lib.config import CONFIG, ENV_PREFIX
|
||||||
|
|
||||||
GAUGE_TASKS = Gauge(
|
GAUGE_TASKS = Gauge(
|
||||||
"authentik_system_tasks",
|
"authentik_system_tasks",
|
||||||
|
@ -21,3 +22,24 @@ class AuthentikEventsConfig(ManagedAppConfig):
|
||||||
def reconcile_load_events_signals(self):
|
def reconcile_load_events_signals(self):
|
||||||
"""Load events signals"""
|
"""Load events signals"""
|
||||||
self.import_module("authentik.events.signals")
|
self.import_module("authentik.events.signals")
|
||||||
|
|
||||||
|
def reconcile_check_deprecations(self):
|
||||||
|
"""Check for config deprecations"""
|
||||||
|
from authentik.events.models import Event, EventAction
|
||||||
|
|
||||||
|
for key_replace, msg in CONFIG.deprecations.items():
|
||||||
|
key, replace = key_replace
|
||||||
|
key_env = f"{ENV_PREFIX}_{key.replace('.', '__')}".upper()
|
||||||
|
replace_env = f"{ENV_PREFIX}_{replace.replace('.', '__')}".upper()
|
||||||
|
if Event.objects.filter(
|
||||||
|
action=EventAction.CONFIGURATION_ERROR, context__deprecated_option=key
|
||||||
|
).exists():
|
||||||
|
continue
|
||||||
|
Event.new(
|
||||||
|
EventAction.CONFIGURATION_ERROR,
|
||||||
|
deprecated_option=key,
|
||||||
|
deprecated_env=key_env,
|
||||||
|
replacement_option=replace,
|
||||||
|
replacement_env=replace_env,
|
||||||
|
message=msg,
|
||||||
|
).save()
|
||||||
|
|
|
@ -113,6 +113,8 @@ class ConfigLoader:
|
||||||
|
|
||||||
A variable like AUTHENTIK_POSTGRESQL__HOST would translate to postgresql.host"""
|
A variable like AUTHENTIK_POSTGRESQL__HOST would translate to postgresql.host"""
|
||||||
|
|
||||||
|
deprecations: dict[tuple[str, str], str] = {}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.__config = {}
|
self.__config = {}
|
||||||
|
@ -139,9 +141,9 @@ class ConfigLoader:
|
||||||
self.update_from_file(env_file)
|
self.update_from_file(env_file)
|
||||||
self.update_from_env()
|
self.update_from_env()
|
||||||
self.update(self.__config, kwargs)
|
self.update(self.__config, kwargs)
|
||||||
self.check_deprecations()
|
self.deprecations = self.check_deprecations()
|
||||||
|
|
||||||
def check_deprecations(self):
|
def check_deprecations(self) -> dict[str, str]:
|
||||||
"""Warn if any deprecated configuration options are used"""
|
"""Warn if any deprecated configuration options are used"""
|
||||||
|
|
||||||
def _pop_deprecated_key(current_obj, dot_parts, index):
|
def _pop_deprecated_key(current_obj, dot_parts, index):
|
||||||
|
@ -154,25 +156,23 @@ class ConfigLoader:
|
||||||
current_obj.pop(dot_part)
|
current_obj.pop(dot_part)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
deprecation_replacements = {}
|
||||||
for deprecation, replacement in DEPRECATIONS.items():
|
for deprecation, replacement in DEPRECATIONS.items():
|
||||||
if self.get(deprecation, default=UNSET) is not UNSET:
|
if self.get(deprecation, default=UNSET) is UNSET:
|
||||||
message = (
|
continue
|
||||||
f"'{deprecation}' has been deprecated in favor of '{replacement}'! "
|
message = (
|
||||||
+ "Please update your configuration."
|
f"'{deprecation}' has been deprecated in favor of '{replacement}'! "
|
||||||
)
|
+ "Please update your configuration."
|
||||||
self.log(
|
)
|
||||||
"warning",
|
self.log(
|
||||||
message,
|
"warning",
|
||||||
)
|
message,
|
||||||
try:
|
)
|
||||||
from authentik.events.models import Event, EventAction
|
deprecation_replacements[(deprecation, replacement)] = message
|
||||||
|
|
||||||
Event.new(EventAction.CONFIGURATION_ERROR, message=message).save()
|
deprecated_attr = _pop_deprecated_key(self.__config, deprecation.split("."), 0)
|
||||||
except ImportError:
|
self.set(replacement, deprecated_attr)
|
||||||
continue
|
return deprecation_replacements
|
||||||
|
|
||||||
deprecated_attr = _pop_deprecated_key(self.__config, deprecation.split("."), 0)
|
|
||||||
self.set(replacement, deprecated_attr.value)
|
|
||||||
|
|
||||||
def log(self, level: str, message: str, **kwargs):
|
def log(self, level: str, message: str, **kwargs):
|
||||||
"""Custom Log method, we want to ensure ConfigLoader always logs JSON even when
|
"""Custom Log method, we want to ensure ConfigLoader always logs JSON even when
|
||||||
|
@ -318,7 +318,9 @@ class ConfigLoader:
|
||||||
|
|
||||||
def set(self, path: str, value: Any, sep="."):
|
def set(self, path: str, value: Any, sep="."):
|
||||||
"""Set value using same syntax as get()"""
|
"""Set value using same syntax as get()"""
|
||||||
set_path_in_dict(self.raw, path, Attr(value), sep=sep)
|
if not isinstance(value, Attr):
|
||||||
|
value = Attr(value)
|
||||||
|
set_path_in_dict(self.raw, path, value, sep=sep)
|
||||||
|
|
||||||
|
|
||||||
CONFIG = ConfigLoader()
|
CONFIG = ConfigLoader()
|
||||||
|
|
|
@ -17,12 +17,12 @@ pythonPlatform = "All"
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 100
|
line-length = 100
|
||||||
target-version = ['py311']
|
target-version = ['py312']
|
||||||
exclude = 'node_modules'
|
exclude = 'node_modules'
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 100
|
line-length = 100
|
||||||
target-version = "py311"
|
target-version = "py312"
|
||||||
exclude = ["**/migrations/**", "**/node_modules/**"]
|
exclude = ["**/migrations/**", "**/node_modules/**"]
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
|
|
Reference in a new issue