Files
computer-playbook/roles/web-app-jitsi/templates/javascript.js.j2
kevinveenbirkenbachandClaude Opus 5 9d0f618e23 refactor(sso): compute the app logout target once in the sso lookup
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>
2026-09-11 13:06:19 +02:00

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();
}
})();