fix(platform): isolate authentik admin styling

This commit is contained in:
Codex
2026-05-25 01:08:50 +03:00
parent e9def6672c
commit c1ac8b1a10
16 changed files with 670 additions and 61 deletions
@@ -21,8 +21,38 @@
})();
</script>
{% with request_host=request.get_host %}
{% if request_host|slice:":11" != "auth-admin." and request_host|slice:":9" != "id-admin." and request_host|slice:":12" != "172.22.0.222" %}
{% if request.path|slice:":9" == "/if/flow/" or request.path|slice:":7" == "/flows/" or request.path|slice:":7" == "/login/" %}
<script data-id="nodedc-auth-flow-scope">
"use strict";
(function () {
const isAuthentikAdminHost =
window.location.hostname.startsWith("auth-admin.") ||
window.location.hostname.startsWith("id-admin.") ||
window.location.hostname === "172.22.0.222";
const isAuthExperiencePage =
!isAuthentikAdminHost &&
(
window.location.pathname.includes("/if/flow/") ||
window.location.pathname.includes("/flows/") ||
window.location.pathname.includes("/login/")
);
document.documentElement.classList.toggle("nodedc-auth-flow-page", isAuthExperiencePage);
window.addEventListener("DOMContentLoaded", function () {
document.body?.classList.toggle("nodedc-auth-flow-page", isAuthExperiencePage);
}, { once: true });
})();
</script>
<style data-id="nodedc-auth-login-css">
{% include "branding/nodedc-login.css" %}
</style>
<style data-id="nodedc-auth-critical-loader">
:root {
html.nodedc-auth-flow-page {
--ak-global--primary: rgb(195, 255, 102) !important;
--ak-global--background: #0e0f10 !important;
--ak-global--background-image: none !important;
@@ -37,22 +67,22 @@
--nodedc-auth-bg: #0e0f10 !important;
}
html,
body,
html body .pf-c-login {
html.nodedc-auth-flow-page,
html.nodedc-auth-flow-page body,
html.nodedc-auth-flow-page body .pf-c-login {
background: #0e0f10 !important;
color-scheme: dark !important;
}
html body ak-flow-executor::part(main),
html body .pf-c-login__main,
html body .pf-c-empty-state,
html body .pf-v5-c-empty-state,
html body .pf-v6-c-empty-state,
html body .pf-c-card,
html body .pf-v5-c-card,
html body .pf-v6-c-card,
html body [class*="empty-state"] {
html.nodedc-auth-flow-page body ak-flow-executor::part(main),
html.nodedc-auth-flow-page body .pf-c-login__main,
html.nodedc-auth-flow-page body .pf-c-empty-state,
html.nodedc-auth-flow-page body .pf-v5-c-empty-state,
html.nodedc-auth-flow-page body .pf-v6-c-empty-state,
html.nodedc-auth-flow-page body .pf-c-card,
html.nodedc-auth-flow-page body .pf-v5-c-card,
html.nodedc-auth-flow-page body .pf-v6-c-card,
html.nodedc-auth-flow-page body [class*="empty-state"] {
background: transparent !important;
box-shadow: none !important;
border: 0 !important;
@@ -60,11 +90,11 @@
backdrop-filter: none !important;
}
html body .pf-c-spinner,
html body .pf-v5-c-spinner,
html body .pf-v6-c-spinner,
html body [role="progressbar"],
html body ak-spinner {
html.nodedc-auth-flow-page body .pf-c-spinner,
html.nodedc-auth-flow-page body .pf-v5-c-spinner,
html.nodedc-auth-flow-page body .pf-v6-c-spinner,
html.nodedc-auth-flow-page body [role="progressbar"],
html.nodedc-auth-flow-page body ak-spinner {
--pf-c-spinner--Color: rgb(195, 255, 102) !important;
--pf-v5-c-spinner--Color: rgb(195, 255, 102) !important;
--pf-v6-c-spinner--Color: rgb(195, 255, 102) !important;
@@ -74,8 +104,8 @@
color: rgb(195, 255, 102) !important;
}
html body #ak-placeholder.ak-c-placeholder,
html body .ak-c-placeholder[slot="placeholder"] {
html.nodedc-auth-flow-page body #ak-placeholder.ak-c-placeholder,
html.nodedc-auth-flow-page body .ak-c-placeholder[slot="placeholder"] {
position: fixed !important;
top: 50% !important;
left: 50% !important;
@@ -98,16 +128,16 @@
overflow: visible !important;
}
html body #ak-placeholder.ak-c-placeholder .pf-c-spinner,
html body .ak-c-placeholder[slot="placeholder"] .pf-c-spinner,
html body #ak-placeholder.ak-c-placeholder [role="progressbar"],
html body .ak-c-placeholder[slot="placeholder"] [role="progressbar"] {
html.nodedc-auth-flow-page body #ak-placeholder.ak-c-placeholder .pf-c-spinner,
html.nodedc-auth-flow-page body .ak-c-placeholder[slot="placeholder"] .pf-c-spinner,
html.nodedc-auth-flow-page body #ak-placeholder.ak-c-placeholder [role="progressbar"],
html.nodedc-auth-flow-page body .ak-c-placeholder[slot="placeholder"] [role="progressbar"] {
opacity: 0 !important;
visibility: hidden !important;
}
html body #ak-placeholder.ak-c-placeholder::before,
html body .ak-c-placeholder[slot="placeholder"]::before {
html.nodedc-auth-flow-page body #ak-placeholder.ak-c-placeholder::before,
html.nodedc-auth-flow-page body .ak-c-placeholder[slot="placeholder"]::before {
content: "";
position: absolute;
inset: 0;
@@ -118,14 +148,14 @@
pointer-events: none;
}
html body.nodedc-auth-loading ak-flow-executor::part(main),
html body.nodedc-auth-loading .pf-c-login__main {
html.nodedc-auth-flow-page body.nodedc-auth-loading ak-flow-executor::part(main),
html.nodedc-auth-flow-page body.nodedc-auth-loading .pf-c-login__main {
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
}
html body.nodedc-auth-loading::before {
html.nodedc-auth-flow-page body.nodedc-auth-loading::before {
content: "";
position: fixed;
top: 50%;
@@ -141,7 +171,7 @@
pointer-events: none;
}
html body.nodedc-auth-card-ready::before {
html.nodedc-auth-flow-page body.nodedc-auth-card-ready::before {
display: none !important;
}
@@ -165,14 +195,38 @@
}
}
</style>
{% endif %}
{% endif %}
{% endwith %}
<script data-id="authentik-config">
"use strict";
const isAuthentikAdminHost =
window.location.hostname.startsWith("auth-admin.") ||
window.location.hostname.startsWith("id-admin.") ||
window.location.hostname === "172.22.0.222";
const isAuthExperiencePage =
!isAuthentikAdminHost &&
(
window.location.pathname.includes("/if/flow/") ||
window.location.pathname.includes("/flows/") ||
window.location.pathname.includes("/login/")
);
const authentikBrand = JSON.parse('{{ brand_json|escapejs }}' || "{}");
if (isAuthExperiencePage) {
const nodedcAuthLoginCss = document.querySelector('style[data-id="nodedc-auth-login-css"]')?.textContent || "";
authentikBrand.branding_custom_css = nodedcAuthLoginCss;
authentikBrand.brandingCustomCss = nodedcAuthLoginCss;
} else {
authentikBrand.branding_custom_css = "";
authentikBrand.brandingCustomCss = "";
}
window.authentik = {
locale: "ru",
config: JSON.parse('{{ config_json|escapejs }}' || "{}"),
brand: JSON.parse('{{ brand_json|escapejs }}' || "{}"),
brand: authentikBrand,
versionFamily: "{{ version_family }}",
versionSubdomain: "{{ version_subdomain }}",
build: "{{ build }}",
@@ -197,10 +251,31 @@
});
</script>
{% with request_host=request.get_host %}
{% if request_host|slice:":11" != "auth-admin." and request_host|slice:":9" != "id-admin." and request_host|slice:":12" != "172.22.0.222" %}
{% if request.path|slice:":9" == "/if/flow/" or request.path|slice:":7" == "/flows/" or request.path|slice:":7" == "/login/" %}
<script data-id="nodedc-auth-field-enhancements">
"use strict";
(function () {
const isAuthentikAdminHost =
window.location.hostname.startsWith("auth-admin.") ||
window.location.hostname.startsWith("id-admin.") ||
window.location.hostname === "172.22.0.222";
const isAuthExperiencePage =
!isAuthentikAdminHost &&
(
window.location.pathname.includes("/if/flow/") ||
window.location.pathname.includes("/flows/") ||
window.location.pathname.includes("/login/")
);
if (!isAuthExperiencePage) return;
document.documentElement.classList.add("nodedc-auth-flow-page");
window.addEventListener("DOMContentLoaded", function () {
document.body?.classList.add("nodedc-auth-flow-page");
}, { once: true });
const logoSvg = `
<svg id="nodedc-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220.82 54.55" aria-hidden="true">
<defs>
@@ -254,9 +329,11 @@
["Continue", "Продолжить"],
["Show password", "Показать пароль"],
["Hide password", "Скрыть пароль"],
["Permission denied", "Доступ ограничен"],
["Permission denied", "Доступ запрещён"],
["Not you?", "Сменить пользователя"],
["Request has been denied.", "Доступ к модулю ограничен."],
["Request has been denied.", "Доступ запрещён."],
["The request has been denied.", "Доступ запрещён."],
["В произведении запроса было отказано.", "Доступ запрещён."],
["Go home", "Вернуться назад"],
["Response returned an error code", "Не удалось завершить операцию."],
]);
@@ -366,7 +443,11 @@
denied = [
"Permission denied",
"Доступ ограничен",
"Доступ запрещен",
"Доступ запрещён",
"Request has been denied.",
"The request has been denied.",
"В произведении запроса было отказано.",
"Доступ к модулю ограничен.",
].some((message) => text.includes(message));
});
@@ -387,8 +468,8 @@
}
function applyPermissionDeniedLayout(root) {
const deniedTitleMessages = ["Permission denied", "Доступ ограничен"];
const deniedSubtitle = "Доступ к модулю NODE.DC ограничен.";
const deniedTitleMessages = ["Permission denied", "Доступ ограничен", "Доступ запрещен", "Доступ запрещён"];
const deniedSubtitle = "Доступ запрещён.";
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode(node) {
const text = node.nodeValue?.trim() || "";
@@ -426,7 +507,19 @@
}
function hidePermissionDeniedReason(root) {
const deniedMessages = ["Request has been denied.", "Доступ к модулю ограничен."];
const deniedMessages = [
"Request has been denied.",
"The request has been denied.",
"В произведении запроса было отказано.",
"Доступ к модулю ограничен.",
"Объяснение:",
"Reason:",
"Привязка политики",
"Policy binding",
"returned result",
"returned a result",
"'None' вернула результат",
];
root.querySelectorAll(".pf-c-alert, .pf-v5-c-alert, .pf-c-empty-state__body, [class*='alert']").forEach((element) => {
const text = element.textContent || "";
@@ -547,12 +640,35 @@
enhancePasswordFields(root);
}
function dispatchSyntheticInput(input) {
if (!input) return;
try {
input.dispatchEvent(new InputEvent("input", {
bubbles: true,
composed: true,
inputType: "insertReplacementText",
data: input.value || "",
}));
} catch {
input.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
}
input.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
}
function syncFormFieldsBeforeSubmit(form) {
form.querySelectorAll("#ak-identifier-input, #ak-stage-identification-password, #ak-stage-password-input").forEach((input) => {
dispatchSyntheticInput(input);
});
}
function enhanceSubmitHandoff(root) {
root.querySelectorAll("form").forEach((form) => {
if (form.dataset.nodedcSubmitBound === "true") return;
form.dataset.nodedcSubmitBound = "true";
form.addEventListener("submit", () => {
syncFormFieldsBeforeSubmit(form);
document.body?.classList.add("nodedc-auth-submitting");
}, true);
});
@@ -823,3 +939,6 @@
});
})();
</script>
{% endif %}
{% endif %}
{% endwith %}