core: pre-hydrate config into templates to directly load correct assets
closes #3228 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
d4af47f576
commit
cada292e00
|
@ -68,10 +68,9 @@ class ConfigView(APIView):
|
|||
caps.append(Capabilities.CAN_IMPERSONATE)
|
||||
return caps
|
||||
|
||||
@extend_schema(responses={200: ConfigSerializer(many=False)})
|
||||
def get(self, request: Request) -> Response:
|
||||
"""Retrieve public configuration options"""
|
||||
config = ConfigSerializer(
|
||||
def get_config(self) -> ConfigSerializer:
|
||||
"""Get Config"""
|
||||
return ConfigSerializer(
|
||||
{
|
||||
"error_reporting": {
|
||||
"enabled": CONFIG.y("error_reporting.enabled"),
|
||||
|
@ -86,4 +85,8 @@ class ConfigView(APIView):
|
|||
"cache_timeout_reputation": int(CONFIG.y("redis.cache_timeout_reputation")),
|
||||
}
|
||||
)
|
||||
return Response(config.data)
|
||||
|
||||
@extend_schema(responses={200: ConfigSerializer(many=False)})
|
||||
def get(self, request: Request) -> Response:
|
||||
"""Retrieve public configuration options"""
|
||||
return Response(self.get_config().data)
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
<script src="{% static 'dist/admin/AdminInterface.js' %}" type="module"></script>
|
||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||
<script>
|
||||
window.authentik = {};
|
||||
window.authentik.locale = "{{ tenant.default_locale }}";
|
||||
window.authentik.config = JSON.parse('{{ config_json|safe }}');
|
||||
window.authentik.tenant = JSON.parse('{{ tenant_json|safe }}');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
<script>ShadyDOM = { force: !navigator.webdriver };</script>
|
||||
{% endif %}
|
||||
<script>
|
||||
window.authentik = {
|
||||
"locale": "{{ tenant.default_locale }}",
|
||||
};
|
||||
window.authentik = {};
|
||||
window.authentik.locale = "{{ tenant.default_locale }}";
|
||||
window.authentik.config = JSON.parse( '{{ config_json|safe }}');
|
||||
window.authentik.tenant = JSON.parse('{{ tenant_json|safe }}');
|
||||
window.authentik.flow = {
|
||||
"layout": "{{ flow.layout }}",
|
||||
};
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
<script src="{% static 'dist/user/UserInterface.js' %}" type="module"></script>
|
||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
|
||||
<script>
|
||||
window.authentik = {};
|
||||
window.authentik.locale = "{{ tenant.default_locale }}";
|
||||
window.authentik.config = JSON.parse('{{ config_json|safe }}');
|
||||
window.authentik.tenant = JSON.parse('{{ tenant_json|safe }}');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
|
|
@ -4,11 +4,10 @@ from django.contrib.auth.decorators import login_required
|
|||
from django.urls import path
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.generic import RedirectView
|
||||
from django.views.generic.base import TemplateView
|
||||
|
||||
from authentik.core.views import apps, impersonate
|
||||
from authentik.core.views.debug import AccessDeniedView
|
||||
from authentik.core.views.interface import FlowInterfaceView
|
||||
from authentik.core.views.interface import FlowInterfaceView, InterfaceView
|
||||
from authentik.core.views.session import EndSessionView
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -39,12 +38,12 @@ urlpatterns = [
|
|||
# Interfaces
|
||||
path(
|
||||
"if/admin/",
|
||||
ensure_csrf_cookie(TemplateView.as_view(template_name="if/admin.html")),
|
||||
ensure_csrf_cookie(InterfaceView.as_view(template_name="if/admin.html")),
|
||||
name="if-admin",
|
||||
),
|
||||
path(
|
||||
"if/user/",
|
||||
ensure_csrf_cookie(TemplateView.as_view(template_name="if/user.html")),
|
||||
ensure_csrf_cookie(InterfaceView.as_view(template_name="if/user.html")),
|
||||
name="if-user",
|
||||
),
|
||||
path(
|
||||
|
@ -58,10 +57,10 @@ urlpatterns = [
|
|||
name="if-session-end",
|
||||
),
|
||||
# Fallback for WS
|
||||
path("ws/outpost/<uuid:pk>/", TemplateView.as_view(template_name="if/admin.html")),
|
||||
path("ws/outpost/<uuid:pk>/", InterfaceView.as_view(template_name="if/admin.html")),
|
||||
path(
|
||||
"ws/client/",
|
||||
TemplateView.as_view(template_name="if/admin.html"),
|
||||
InterfaceView.as_view(template_name="if/admin.html"),
|
||||
),
|
||||
]
|
||||
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
"""Interface views"""
|
||||
from typing import Any
|
||||
from json import dumps
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views.generic.base import TemplateView
|
||||
from rest_framework.request import Request
|
||||
|
||||
from authentik.api.v3.config import ConfigView
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.tenants.api import CurrentTenantSerializer
|
||||
|
||||
|
||||
class FlowInterfaceView(TemplateView):
|
||||
class InterfaceView(TemplateView):
|
||||
"""Base interface view"""
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
kwargs["config_json"] = dumps(ConfigView(request=Request(self.request)).get_config().data)
|
||||
kwargs["tenant_json"] = dumps(CurrentTenantSerializer(self.request.tenant).data)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class FlowInterfaceView(InterfaceView):
|
||||
"""Flow interface"""
|
||||
|
||||
template_name = "if/flow.html"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { VERSION } from "@goauthentik/web/constants";
|
||||
import { globalAK } from "@goauthentik/web/api/Global";
|
||||
import { EVENT_REFRESH, VERSION } from "@goauthentik/web/constants";
|
||||
import { MessageMiddleware } from "@goauthentik/web/elements/messages/Middleware";
|
||||
import { APIMiddleware } from "@goauthentik/web/elements/notifications/APIDrawer";
|
||||
import { activateLocale } from "@goauthentik/web/interfaces/locale";
|
||||
|
@ -6,9 +7,11 @@ import { getCookie } from "@goauthentik/web/utils";
|
|||
|
||||
import {
|
||||
Config,
|
||||
ConfigFromJSON,
|
||||
Configuration,
|
||||
CoreApi,
|
||||
CurrentTenant,
|
||||
CurrentTenantFromJSON,
|
||||
FetchParams,
|
||||
Middleware,
|
||||
RequestContext,
|
||||
|
@ -27,7 +30,9 @@ export class LoggingMiddleware implements Middleware {
|
|||
}
|
||||
}
|
||||
|
||||
let globalConfigPromise: Promise<Config>;
|
||||
let globalConfigPromise: Promise<Config> | undefined = Promise.resolve(
|
||||
ConfigFromJSON(globalAK()?.config),
|
||||
);
|
||||
export function config(): Promise<Config> {
|
||||
if (!globalConfigPromise) {
|
||||
globalConfigPromise = new RootApi(DEFAULT_CONFIG).rootConfigRetrieve();
|
||||
|
@ -60,7 +65,9 @@ export function tenantSetLocale(tenant: CurrentTenant) {
|
|||
activateLocale(tenant.defaultLocale);
|
||||
}
|
||||
|
||||
let globalTenantPromise: Promise<CurrentTenant>;
|
||||
let globalTenantPromise: Promise<CurrentTenant> | undefined = Promise.resolve(
|
||||
CurrentTenantFromJSON(globalAK()?.tenant),
|
||||
);
|
||||
export function tenant(): Promise<CurrentTenant> {
|
||||
if (!globalTenantPromise) {
|
||||
globalTenantPromise = new CoreApi(DEFAULT_CONFIG)
|
||||
|
@ -108,4 +115,13 @@ export function AndNext(url: string): string {
|
|||
return `?next=${encodeURIComponent(url)}`;
|
||||
}
|
||||
|
||||
window.addEventListener(EVENT_REFRESH, () => {
|
||||
// Upon global refresh, disregard whatever was pre-hydrated and
|
||||
// actually load info from API
|
||||
globalConfigPromise = undefined;
|
||||
globalTenantPromise = undefined;
|
||||
config();
|
||||
tenant();
|
||||
});
|
||||
|
||||
console.debug(`authentik(early): version ${VERSION}, apiBase ${DEFAULT_CONFIG.basePath}`);
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { Config, CurrentTenant } from "@goauthentik/api";
|
||||
|
||||
export interface GlobalAuthentik {
|
||||
locale?: string;
|
||||
flow?: {
|
||||
layout: string;
|
||||
};
|
||||
config: Config;
|
||||
tenant: CurrentTenant;
|
||||
}
|
||||
|
||||
export interface AuthentikWindow {
|
||||
|
|
Reference in New Issue