From 58e5d3ef2b45a1a3fa68262e682e308d762f6666 Mon Sep 17 00:00:00 2001 From: Leo Vasanko Date: Wed, 19 Aug 2026 00:57:35 +0000 Subject: [PATCH] Replace Paskia iframe auth flow with plain /auth/ links Paskia does not support being iframed; the login/profile buttons are now plain anchors, and a pageshow handler re-probes auth when history navigation restores a cached page. Drops the paskia JS dependency. --- frontend/package.json | 1 - frontend/src/assets/pagerite.css | 14 ++++--- frontend/src/pagerite.js | 71 +++++++++----------------------- 3 files changed, 28 insertions(+), 58 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 925cbc6..ee5d68a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,7 +19,6 @@ "@lezer/highlight": "^1.2.3", "codemirror": "^6.0.2", "overlayscrollbars": "^2.16.0", - "paskia": "file:../../paskia/paskia-js", "transliteration": "^2.6.1", "vue": "^3.5.26", "vuedraggable": "^4.1.0" diff --git a/frontend/src/assets/pagerite.css b/frontend/src/assets/pagerite.css index 1375a63..97ff90d 100644 --- a/frontend/src/assets/pagerite.css +++ b/frontend/src/assets/pagerite.css @@ -316,13 +316,15 @@ body.editing #main { gap: 0.6rem; } -.editor-pens button { +.editor-pens button, +.editor-pens a { position: static; font: inherit; border: none; cursor: pointer; background: none; padding: 0; + text-decoration: none; } #sidebar { @@ -488,17 +490,17 @@ article h1 .edit-link { opacity: 1; } -/* Login/profile buttons injected by pagerite.js when Paskia SSO is in use. +/* Login/profile links injected by pagerite.js when Paskia SSO is in use. They live inside the .editor-pens flex container in the banner's top-right corner and inherit its reset; keep only their opacity/text-shadow tweaks. */ -button.login-link, -button.profile-link { +.editor-pens a.login-link, +.editor-pens a.profile-link { opacity: 0.7; text-shadow: 0 0 0.1em black; } -button.login-link:hover, -button.profile-link:hover { +.editor-pens a.login-link:hover, +.editor-pens a.profile-link:hover { opacity: 1; } diff --git a/frontend/src/pagerite.js b/frontend/src/pagerite.js index 18b91f7..0991f91 100644 --- a/frontend/src/pagerite.js +++ b/frontend/src/pagerite.js @@ -4,7 +4,6 @@ // // Also: scroll-reveal effects and code copy buttons. These need no // support from the article itself and are re-applied after each swap. -import { showAuthIframe } from 'paskia' import { OverlayScrollbars } from "overlayscrollbars"; import "overlayscrollbars/overlayscrollbars.css"; @@ -47,14 +46,13 @@ import "overlayscrollbars/overlayscrollbars.css"; // /_api/settings endpoint: the same reverse proxy that gates /_api returns // 401/403 here, and a 200 means the permission is present. // - // When Paskia SSO is in use, 401/403 responses carry `auth.iframe`, which - // we use to open the login/profile dialogs inline instead of navigating - // away. A separate probe to /auth/api/settings tells us whether Paskia is - // available at all; if it isn't, we treat the site as dev/no-proxy and - // leave editing open. + // When Paskia SSO is in use (probed via /auth/api/settings), the banner + // corner gets a plain link to /auth/ — 🔑 log in for anonymous visitors, + // 🔐 profile when logged in. Normal navigation: Paskia does not support + // being iframed, and history.back() returns to the page as-is (the + // pageshow handler below re-probes auth to refresh the pens). let ssoAvailable = false; let isAdmin = false; - let loginIframeUrl = null; let editorMeta = null; function makePen(mode) { @@ -86,34 +84,13 @@ import "overlayscrollbars/overlayscrollbars.css"; } } - function makeLoginButton(url) { - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "login-link"; - btn.title = "log in"; - btn.textContent = "🔑"; - btn.addEventListener("click", async () => { - try { - await showAuthIframe(url); - // Successful login: refresh the auth UI (may now show edit pens). - setupAuth(); - } catch { - // Cancelled or error: leave the button in place. - } - }); - return btn; - } - - function makeProfileButton() { - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "profile-link"; - btn.title = "profile"; - btn.textContent = "🔐"; - btn.addEventListener("click", () => { - showAuthIframe("/auth/").catch(() => {}); - }); - return btn; + function makeAuthLink(admin) { + const a = document.createElement("a"); + a.className = admin ? "profile-link" : "login-link"; + a.href = "/auth/"; + a.title = admin ? "profile" : "log in"; + a.textContent = admin ? "\u{1F510}" : "\u{1F511}"; + return a; } function renderAuthUi() { @@ -130,13 +107,7 @@ import "overlayscrollbars/overlayscrollbars.css"; pens.append(makePen("banner")); pens.append(makePen("site")); } - if (isAdmin && ssoAvailable) { - pens.append(makeProfileButton()); - } else if (!isAdmin && ssoAvailable && loginIframeUrl) { - pens.append(makeLoginButton(loginIframeUrl)); - } else if (!isAdmin && ssoAvailable) { - pens.append(makeProfileButton()); - } + if (ssoAvailable) pens.append(makeAuthLink(isAdmin)); banner.after(pens); } if (canEdit) injectPagePen(); @@ -160,23 +131,21 @@ import "overlayscrollbars/overlayscrollbars.css"; // Check whether the current session has pagerite:admin. isAdmin = false; - loginIframeUrl = null; - let status = 0; try { - const res = await fetch("/_api/settings"); - status = res.status; - if (status === 401) { - const data = await res.json().catch(() => ({})); - loginIframeUrl = data.auth?.iframe || null; - } + isAdmin = (await fetch("/_api/settings")).status === 200; } catch { // No auth proxy / dev. } - if (status === 200) isAdmin = true; renderAuthUi(); } + // Returning to the page via history back/forward may restore a cached + // copy whose auth UI predates a login/logout — re-probe and re-render. + addEventListener("pageshow", (ev) => { + if (ev.persisted) setupAuth(); + }); + function runScripts(root) { // Scripts inserted via DOM swapping do not execute; re-create them. for (const old of root.querySelectorAll("script")) {