auth-yes/public/sessions-scripts.js

252 lines
7.9 KiB
JavaScript

let _lastMintedToken = "";
function showNotice(msg, isError) {
const banner = document.getElementById("status-banner");
if (!banner) return;
banner.textContent = msg;
banner.style.display = "block";
banner.style.background = isError ? "var(--danger-bg)" : "var(--success-bg)";
banner.style.color = isError ? "var(--danger-text)" : "var(--success-text)";
banner.style.border = isError
? "1px solid var(--danger-border)"
: "1px solid var(--success-border)";
setTimeout(() => {
banner.style.display = "none";
}, 5000);
}
globalThis.showNotice = showNotice;
function openDelegateDrawer() {
const drawer = document.getElementById("delegateDrawer");
if (drawer) {
drawer.style.display = "block";
drawer.offsetHeight;
drawer.classList.add("open");
const panel = drawer.querySelector(".drawer-panel");
if (panel) panel.classList.add("open");
}
}
globalThis.openDelegateDrawer = openDelegateDrawer;
function closeDelegateDrawer() {
const drawer = document.getElementById("delegateDrawer");
if (drawer) {
drawer.classList.remove("open");
const panel = drawer.querySelector(".drawer-panel");
if (panel) panel.classList.remove("open");
setTimeout(() => {
drawer.style.display = "none";
}, 250);
}
}
globalThis.closeDelegateDrawer = closeDelegateDrawer;
function selectLifespan(btn, hours) {
document.querySelectorAll(".lifespan-pill").forEach((b) =>
b.classList.remove("active")
);
btn.classList.add("active");
const input = document.getElementById("delegateHours");
if (input) input.value = hours;
}
globalThis.selectLifespan = selectLifespan;
function selectMode(btn, mode) {
document.querySelectorAll(".mode-pill").forEach((b) =>
b.classList.remove("active")
);
btn.classList.add("active");
const input = document.getElementById("delegateMode");
if (input) input.value = mode;
const matrix = document.getElementById("customScopeMatrix");
if (matrix) {
matrix.style.display = mode === "custom" ? "block" : "none";
}
}
globalThis.selectMode = selectMode;
function handleTargetAppChange(appName) {
if (appName) {
const scopeVal = "app:" + appName;
document.querySelectorAll(".scope-checkbox").forEach((cb) => {
if (cb.value === scopeVal) cb.checked = true;
});
}
}
globalThis.handleTargetAppChange = handleTargetAppChange;
async function handleDelegateSession(e) {
e.preventDefault();
const labelInput = document.getElementById("delegateLabel");
const label = labelInput ? labelInput.value.trim() : "Delegated Session";
const hoursInput = document.getElementById("delegateHours");
const lifespanHours = parseInt(hoursInput ? hoursInput.value : "1", 10) || 1;
const modeInput = document.getElementById("delegateMode");
let mode = modeInput ? modeInput.value : "read";
const targetAppInput = document.getElementById("delegateTargetApp");
const targetApp = targetAppInput ? targetAppInput.value : "";
const customScopes = [];
if (targetApp) {
customScopes.push("app:" + targetApp);
}
if (mode === "custom" || targetApp) {
document.querySelectorAll(".scope-checkbox:checked").forEach((cb) => {
if (!customScopes.includes(cb.value)) {
customScopes.push(cb.value);
}
});
if (targetApp && mode !== "custom" && mode !== "admin") {
mode = "custom";
}
}
const btn = document.getElementById("submitDelegateBtn");
if (btn) {
btn.disabled = true;
btn.textContent = "Minting...";
}
try {
const res = await fetch("/api/sessions/delegate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ label, lifespanHours, mode, customScopes }),
});
const data = await res.json();
if (res.ok) {
_lastMintedToken = data.token;
const origin = globalThis.location ? globalThis.location.origin : "";
const magicElem = document.getElementById("handoffMagicLinkText");
if (magicElem) {
magicElem.textContent = origin + "/pass?token=" + data.token;
}
const cliElem = document.getElementById("handoffCliText");
if (cliElem) {
cliElem.textContent = 'export AUTH_YES_TOKEN="' + data.token + '"';
}
const curlElem = document.getElementById("handoffCurlText");
if (curlElem) {
curlElem.textContent = '-H "Authorization: Bearer ' + data.token + '"';
}
const handoffModal = document.getElementById("handoffModal");
if (handoffModal) handoffModal.style.display = "block";
showNotice("Delegated session created: " + data.label, false);
} else {
showNotice(data.error || "Failed to delegate session", true);
}
} catch (_err) {
showNotice("Network error delegating session", true);
} finally {
if (btn) {
btn.disabled = false;
btn.textContent = "Mint & Delegate Session";
}
}
}
globalThis.handleDelegateSession = handleDelegateSession;
function copyHandoff(type) {
let text = "";
if (type === "cli") {
const el = document.getElementById("handoffCliText");
if (el) text = el.textContent;
}
if (type === "curl") {
const el = document.getElementById("handoffCurlText");
if (el) text = el.textContent;
}
if (type === "magic") {
const el = document.getElementById("handoffMagicLinkText");
if (el) text = el.textContent;
}
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
showNotice("Copied to clipboard!", false);
}
}
globalThis.copyHandoff = copyHandoff;
function closeHandoffModal() {
const modal = document.getElementById("handoffModal");
if (modal) modal.style.display = "none";
if (globalThis.location) globalThis.location.reload();
}
globalThis.closeHandoffModal = closeHandoffModal;
function openEditScopesModal(sessionId, label, scopesJson) {
let scopes = [];
try {
scopes = typeof scopesJson === "string"
? JSON.parse(scopesJson)
: scopesJson;
if (typeof scopes === "string") scopes = JSON.parse(scopes);
} catch (_e) {
scopes = [];
}
const idInput = document.getElementById("editScopesSessionId");
if (idInput) idInput.value = sessionId;
const labelEl = document.getElementById("editScopesLabel");
if (labelEl) labelEl.textContent = label;
document.querySelectorAll(".edit-scope-chk").forEach((cb) => {
cb.checked = Array.isArray(scopes) && scopes.includes(cb.value);
});
const modal = document.getElementById("editScopesModal");
if (modal) modal.style.display = "flex";
}
globalThis.openEditScopesModal = openEditScopesModal;
function closeEditScopesModal() {
const modal = document.getElementById("editScopesModal");
if (modal) modal.style.display = "none";
}
globalThis.closeEditScopesModal = closeEditScopesModal;
async function saveUpdatedScopes() {
const idInput = document.getElementById("editScopesSessionId");
const sessionId = idInput ? idInput.value : "";
const customScopes = [];
document.querySelectorAll(".edit-scope-chk:checked").forEach((cb) => {
customScopes.push(cb.value);
});
try {
const res = await fetch("/api/sessions/" + sessionId + "/scopes", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ customScopes }),
});
if (res.ok) {
showNotice("Session scopes updated!", false);
setTimeout(() => {
if (globalThis.location) globalThis.location.reload();
}, 500);
} else {
const data = await res.json();
showNotice(data.error || "Failed to update scopes", true);
}
} catch (_err) {
showNotice("Network error updating scopes", true);
}
}
globalThis.saveUpdatedScopes = saveUpdatedScopes;
function copyText(text) {
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
showNotice("Copied to clipboard!", false);
}
}
globalThis.copyText = copyText;
// Global escape listener for modals and drawers
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeDelegateDrawer();
closeEditScopesModal();
}
});