diff options
Diffstat (limited to 'src/api/dashboard')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 17 | ||||
| -rw-r--r-- | src/api/dashboard/login.html | 18 |
2 files changed, 32 insertions, 3 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index fa4d436..17ff44b 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -2058,7 +2058,7 @@ if (handOver) { // The fragment that opens another node's dashboard (`id`'s) as this page is now // (`handOver`). What is in focus stays, but `id` itself: its page is its own. Also this // node's own page, reloaded for a new version (`id` null). -function handOff(id) { +function handOff(id, handed) { const settings = {}; try { for (let i = 0; i < localStorage.length; i++) { @@ -2076,6 +2076,9 @@ function handOff(id) { legend: !document.getElementById("legends").hidden, figures: [...open], document: [...documentOpen], + // A token reading only, for five minutes: the other node's login page begins a + // session with it (`login.html`), where the browser has none there. + token: handed || undefined, })); } // `[x, y]` turned by `angle`. @@ -2446,11 +2449,19 @@ addEventListener("keydown", event => { // opened in this page; else its halo flashes red, larger than usual, and "no dashboard" // rises from it in the same red, both fading out. This node's own: here already. const FLASH_MS = 1200; -function openDashboard(id) { +const READ_ALL = [{ path: [], rights: ["read"] }, { path: ["_continuum"], rights: ["read"] }]; +async function openDashboard(id) { const member = state.graph.members[id]; if (!member || member.self) return; if (member.dashboard) { - location.assign(member.dashboard.split("#")[0] + handOff(id)); + let handed = null; + if (token) { + try { + handed = (await tokenCall("../auth/refresh", token.token, + { limit: READ_ALL, lifetime: 300 })).token; + } catch (_) { /* the other dashboard asks for a login then */ } + } + location.assign(member.dashboard.split("#")[0] + handOff(id, handed)); return; } const layer = document.getElementById("flashes"); diff --git a/src/api/dashboard/login.html b/src/api/dashboard/login.html index 77668ee..e09d31c 100644 --- a/src/api/dashboard/login.html +++ b/src/api/dashboard/login.html @@ -73,6 +73,24 @@ document.getElementById("token").addEventListener("submit", async event => { why.textContent = ""; try { await begin(event.target.token.value.trim()); } catch (error) { failed(error); } }); +// Opened from another member's dashboard (`handOff`), sent here for want of a session: +// its token, reading only, begins one; the rest goes on to the dashboard. +(async () => { + const HAND_OFF = "#continuum="; + if (!location.hash.startsWith(HAND_OFF)) return; + const fragment = location.hash; + try { history.replaceState(null, "", location.pathname + location.search); } catch (_) {} + let handed; + try { handed = JSON.parse(decodeURIComponent(fragment.slice(HAND_OFF.length))); } catch (_) { return; } + if (!handed || typeof handed.token !== "string") return; + try { + await call("auth/session", "POST", "Bearer " + handed.token); + delete handed.token; + location.replace("admin/dashboard" + HAND_OFF + encodeURIComponent(JSON.stringify(handed))); + } catch (error) { + why.textContent = "The token handed over isn't taken (" + error.message + "): log in."; + } +})(); document.getElementById("out").addEventListener("click", async () => { await fetch("auth/session", { method: "DELETE", credentials: "same-origin" }).catch(() => {}); why.textContent = "Logged out of this browser."; |
