87 lines
3.6 KiB
JavaScript
87 lines
3.6 KiB
JavaScript
/*
|
|
* Copyright (C) 2026 Mateusz Gruszczyński @linuxiarz.pl
|
|
* Source-Available Code / Dual-Licensed.
|
|
*
|
|
* Free for non-commercial and evaluation use under terms of BSL/GPLv3.
|
|
* Commercial or production use requires a valid paid license.
|
|
* See LICENSE file in repository root for details.
|
|
*/
|
|
|
|
export function accessTokenKey(resourceKind, resourceSlug) { return `rustpad:access:${resourceKind}:${resourceSlug}`; }
|
|
export function getAccessToken(resourceKind, resourceSlug) {
|
|
return localStorage.getItem(accessTokenKey(resourceKind, resourceSlug)) || "";
|
|
}
|
|
export function setAccessToken(resourceKind, resourceSlug, token) {
|
|
const key = accessTokenKey(resourceKind, resourceSlug);
|
|
if (token) localStorage.setItem(key, token);
|
|
else localStorage.removeItem(key);
|
|
}
|
|
// Remove plaintext passwords saved by the previous frontend version.
|
|
for (let i = localStorage.length - 1; i >= 0; i--) {
|
|
const key = localStorage.key(i);
|
|
if (key?.startsWith("rustpad:workspace:") && key.endsWith(":password")) localStorage.removeItem(key);
|
|
}
|
|
|
|
const NICKNAME_KEY = "rustpad:nickname";
|
|
const NICKNAME_COOKIE = "rustpad_nickname";
|
|
// A session cookie is shared by tabs, but disappears when the browser session
|
|
// ends. The nickname is not an authentication secret.
|
|
function getCookie(name) {
|
|
const prefix = `${name}=`;
|
|
const item = document.cookie.split("; ").find(value => value.startsWith(prefix));
|
|
if (!item) return "";
|
|
try { return decodeURIComponent(item.slice(prefix.length)); } catch { return ""; }
|
|
}
|
|
function setNicknameCookie(value) {
|
|
if (value) document.cookie = `${NICKNAME_COOKIE}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`;
|
|
else document.cookie = `${NICKNAME_COOKIE}=; Path=/; SameSite=Lax; Max-Age=0`;
|
|
}
|
|
localStorage.removeItem(NICKNAME_KEY);
|
|
export function getNickname() {
|
|
const nickname = sessionStorage.getItem(NICKNAME_KEY) || getCookie(NICKNAME_COOKIE);
|
|
if (nickname) sessionStorage.setItem(NICKNAME_KEY, nickname);
|
|
return nickname;
|
|
}
|
|
export function setNickname(value) {
|
|
const nickname = value.trim();
|
|
if (nickname) sessionStorage.setItem(NICKNAME_KEY, nickname);
|
|
else sessionStorage.removeItem(NICKNAME_KEY);
|
|
setNicknameCookie(nickname);
|
|
}
|
|
|
|
const GUEST_ID_COOKIE = "rustpad_guest_id";
|
|
export function getGuestId() {
|
|
let guestId = getCookie(GUEST_ID_COOKIE);
|
|
if (!/^[a-zA-Z0-9_-]{16,64}$/.test(guestId)) {
|
|
guestId = crypto.randomUUID().replaceAll("-", "");
|
|
document.cookie = `${GUEST_ID_COOKIE}=${guestId}; Path=/; SameSite=Lax`;
|
|
}
|
|
return guestId;
|
|
}
|
|
|
|
const AUTH_TOKEN_KEY = "rustpad:auth-token";
|
|
// Account sessions must be shared by every tab on this origin. Keep a
|
|
// compatibility fallback for sessions created by older frontend versions.
|
|
const legacySessionToken = sessionStorage.getItem(AUTH_TOKEN_KEY);
|
|
if (legacySessionToken && !localStorage.getItem(AUTH_TOKEN_KEY)) {
|
|
localStorage.setItem(AUTH_TOKEN_KEY, legacySessionToken);
|
|
}
|
|
sessionStorage.removeItem(AUTH_TOKEN_KEY);
|
|
export function getAuthToken() { return localStorage.getItem(AUTH_TOKEN_KEY) || ""; }
|
|
export function setAuthSession(session) {
|
|
localStorage.setItem(AUTH_TOKEN_KEY, session.token);
|
|
sessionStorage.removeItem(AUTH_TOKEN_KEY);
|
|
setNickname(session.nickname);
|
|
}
|
|
export function clearAuthSession() {
|
|
localStorage.removeItem(AUTH_TOKEN_KEY);
|
|
sessionStorage.removeItem(AUTH_TOKEN_KEY);
|
|
localStorage.removeItem(NICKNAME_KEY);
|
|
sessionStorage.removeItem(NICKNAME_KEY);
|
|
setNicknameCookie("");
|
|
}
|
|
export async function resolveIdentity(api, nickname) {
|
|
const result = await api("/api/auth/identity", { method: "POST", body: JSON.stringify({ nickname, session_token: getAuthToken() || null }) });
|
|
setNickname(result.nickname); return result;
|
|
}
|