fix: improve terminal robustness with exponential backoff and better keepalive #34

Merged
jimmy merged 9 commits from dev into main 2026-03-11 23:34:37 +08:00
3 changed files with 43 additions and 11 deletions
Showing only changes of commit 2f8a5d84dc - Show all commits
+1 -1
View File
@@ -42,7 +42,7 @@ TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
TELEGRAM_PROXY = os.environ.get("TELEGRAM_PROXY", "")
WEBAUTHN_RP_ID = os.environ.get("WEBAUTHN_RP_ID", "nas.jimmygan.com")
WEBAUTHN_ORIGINS = os.environ.get("WEBAUTHN_ORIGIN", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
WEBAUTHN_ORIGINS = os.environ.get("WEBAUTHN_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
# CORS
CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
+31 -4
View File
@@ -23,19 +23,46 @@ export function setRefreshToken() {}
let refreshPromise = null;
export async function tryRefreshSession() {
if (refreshPromise) return refreshPromise;
refreshPromise = (async () => {
try {
function getLegacyRefreshToken() {
return localStorage.getItem("refresh_token") || "";
}
function clearLegacyRefreshToken() {
localStorage.removeItem("refresh_token");
}
async function requestRefresh(body) {
const r = await fetch(BASE + "/auth/refresh", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "same-origin",
body: body ? JSON.stringify(body) : undefined,
});
if (!r.ok) return false;
const data = await r.json();
setToken(data.access_token || "");
return !!data.access_token;
}
export async function tryRefreshSession() {
if (refreshPromise) return refreshPromise;
refreshPromise = (async () => {
try {
const cookieRefreshed = await requestRefresh();
if (cookieRefreshed) {
clearLegacyRefreshToken();
return true;
}
const legacyRefreshToken = getLegacyRefreshToken();
if (!legacyRefreshToken) return false;
const legacyRefreshed = await requestRefresh({ refresh_token: legacyRefreshToken });
if (legacyRefreshed) {
clearLegacyRefreshToken();
return true;
}
clearLegacyRefreshToken();
return false;
} catch {
return false;
} finally {
@@ -49,6 +49,9 @@
opts.excludeCredentials = opts.excludeCredentials.map(c => ({ ...c, id: base64urlToBuffer(c.id) }));
}
const cred = await navigator.credentials.create({ publicKey: opts });
if (!cred) {
throw new Error("Passkey creation was cancelled");
}
const name = prompt("Name this passkey (e.g. MacBook, iPhone):", "Passkey") || "Passkey";
const body = {
id: cred.id,
@@ -64,10 +67,12 @@
passkeyMsg = "Passkey registered successfully";
await loadPasskeys();
} catch (e) {
console.error("Passkey registration error:", e);
passkeyErr = e.body?.detail || e.message || "Failed to register passkey";
}
} finally {
passkeyLoading = false;
}
}
async function clearPasskeys() {
if (!confirm("Remove all passkeys?")) return;