const token = localStorage.getItem("indiko_session"); const appsList = document.getElementById("appsList") as HTMLElement; if (!token) { window.location.href = "/login"; } interface App { clientId: string; name: string; scopes: string[]; grantedAt: number; lastUsed: number; } async function loadApps() { try { const response = await fetch("/api/apps", { headers: { Authorization: `Bearer ${token}`, }, }); if (response.status === 401 || response.status === 403) { localStorage.removeItem("indiko_session"); window.location.href = "/login"; return; } if (!response.ok) { throw new Error("Failed to load apps"); } const data = await response.json(); displayApps(data.apps); } catch (error) { console.error("Failed to load apps:", error); appsList.innerHTML = '
Failed to load authorized apps
'; } } function displayApps(apps: App[]) { if (apps.length === 0) { appsList.innerHTML = '
No authorized apps yet. Apps will appear here after you grant them access.
'; return; } appsList.innerHTML = apps .map((app) => { const lastUsedDate = new Date(app.lastUsed * 1000).toLocaleDateString(); const grantedDate = new Date(app.grantedAt * 1000).toLocaleDateString(); return `
${app.name}
Granted ${grantedDate} • Last used ${lastUsedDate}
permissions
${app.scopes.map((scope) => `${scope}`).join("")}
`; }) .join(""); } (window as any).revokeApp = async (clientId: string, event?: Event) => { const btn = event?.target as HTMLButtonElement | undefined; // Double-click confirmation pattern if (btn?.dataset.confirmState === "pending") { // Second click - execute revoke delete btn.dataset.confirmState; btn.disabled = true; btn.textContent = "revoking..."; const card = document.querySelector(`[data-client-id="${clientId}"]`); try { const response = await fetch( `/api/apps/${encodeURIComponent(clientId)}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}`, }, }, ); if (!response.ok) { throw new Error("Failed to revoke app"); } // Remove from UI card?.remove(); // Check if list is now empty const remaining = document.querySelectorAll(".app-card"); if (remaining.length === 0) { appsList.innerHTML = '
No authorized apps yet. Apps will appear here after you grant them access.
'; } } catch (error) { console.error("Failed to revoke app:", error); alert("Failed to revoke app access. Please try again."); if (btn) { btn.disabled = false; btn.textContent = "revoke"; } } } else { // First click - set pending state if (btn) { const originalText = btn.textContent; btn.dataset.confirmState = "pending"; btn.textContent = "you sure?"; // Reset after 3 seconds if not confirmed setTimeout(() => { if (btn.dataset.confirmState === "pending") { delete btn.dataset.confirmState; btn.textContent = originalText; } }, 3000); } } }; loadApps();