mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
The previous commit wrote the same proxy-aware logout expression into
four javascript.js.j2 templates. The rule it encodes - sign out of
oauth2-proxy first when the app is proxy-gated, else go straight to the
provider - belongs where proxy-gating is already decided.
utils/roles/applications/services/sso.py gains logout_url(url,
is_proxy_gated) next to get_sso_config, with OAUTH2_SIGN_OUT_PATH as the
path constant; the rd value is quoted exactly as Jinja's urlencode
filter does it. The sso lookup exposes it as the logout_url term: it
renders OIDC through the templar, takes is_proxy_gated from the same
resolution, and refuses a context without OIDC. Prometheus, Checkmk,
Baserow and Jitsi now render lookup('sso', application_id, 'logout_url').
Behaviour is unchanged: the resolver tests pin the rd encoding against
jinja2's do_urlencode, and the lookup tests cover a proxy-gated app, an
OIDC-native app, a disabled SSO and a missing OIDC.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
66 lines
2.0 KiB
Django/Jinja
66 lines
2.0 KiB
Django/Jinja
(function () {
|
|
const LOGOUT_URL = {{ lookup('sso', application_id, 'logout_url') | to_json }};
|
|
const INJECTED_ATTR = "data-injected-logout";
|
|
const LOGOUT_SVG =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">' +
|
|
'<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/>' +
|
|
'<polyline points="10 17 15 12 10 7"/>' +
|
|
'<line x1="15" y1="12" x2="3" y2="12"/>' +
|
|
"</svg>";
|
|
|
|
function ensureLogoutIcon() {
|
|
if (document.querySelector("[" + INJECTED_ATTR + "]")) return;
|
|
if (!document.body) return;
|
|
|
|
const btn = document.createElement("button");
|
|
btn.setAttribute(INJECTED_ATTR, "true");
|
|
btn.setAttribute("type", "button");
|
|
btn.setAttribute("title", "Logout");
|
|
btn.setAttribute("aria-label", "Logout");
|
|
btn.style.cssText = [
|
|
"position:fixed",
|
|
"top:12px",
|
|
"right:12px",
|
|
"z-index:2147483647",
|
|
"display:inline-flex",
|
|
"align-items:center",
|
|
"justify-content:center",
|
|
"width:36px",
|
|
"height:36px",
|
|
"padding:6px",
|
|
"background:rgba(0,0,0,0.55)",
|
|
"color:#ffffff",
|
|
"border:1px solid rgba(255,255,255,0.25)",
|
|
"border-radius:6px",
|
|
"cursor:pointer",
|
|
].join(";");
|
|
btn.innerHTML = LOGOUT_SVG;
|
|
btn.addEventListener(
|
|
"click",
|
|
(e) => {
|
|
e.preventDefault();
|
|
window.location.href = LOGOUT_URL;
|
|
},
|
|
{ capture: true },
|
|
);
|
|
document.body.appendChild(btn);
|
|
}
|
|
|
|
function start() {
|
|
ensureLogoutIcon();
|
|
if (!("MutationObserver" in window)) return;
|
|
new MutationObserver(() => ensureLogoutIcon()).observe(document.body, {
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
setTimeout(ensureLogoutIcon, 750);
|
|
setTimeout(ensureLogoutIcon, 2500);
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", start, { once: true });
|
|
} else {
|
|
start();
|
|
}
|
|
})();
|