const token = localStorage.getItem("indiko_session");
const footer = document.getElementById("footer") as HTMLElement;
const usersList = document.getElementById("usersList") as HTMLElement;
let currentUserId: number;
// Check auth and display user
async function checkAuth() {
if (!token) {
window.location.href = "/login";
return;
}
try {
const response = await fetch("/api/hello", {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.status === 401 || response.status === 403) {
localStorage.removeItem("indiko_session");
window.location.href = "/login";
return;
}
const data = await response.json();
currentUserId = data.id;
footer.innerHTML = `admin • signed in as ${data.username} • sign out
`;
// Handle logout
document
.getElementById("logoutLink")
?.addEventListener("click", async (e) => {
e.preventDefault();
try {
await fetch("/auth/logout", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
});
} catch {
// Ignore logout errors
}
localStorage.removeItem("indiko_session");
window.location.href = "/login";
});
// Check if admin
if (!data.isAdmin) {
window.location.href = "/";
return;
}
// Load users if admin
loadUsers();
} catch (error) {
console.error("Auth check failed:", error);
footer.textContent = "error loading user info";
usersList.innerHTML = 'Failed to load users
';
}
}
async function loadUsers() {
try {
const response = await fetch("/api/users", {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error("Failed to load users");
}
const data = await response.json();
if (data.users.length === 0) {
usersList.innerHTML = 'No users found
';
return;
}
usersList.innerHTML = data.users
.map(
(user: {
id: number;
username: string;
name: string;
email: string | null;
photo: string | null;
status: string;
role: string;
isAdmin: boolean;
createdAt: number;
credentialCount: number;
}) => {
const createdDate = new Date(
user.createdAt * 1000,
).toLocaleDateString();
const initials = user.username.substring(0, 2).toUpperCase();
const avatarContent = user.photo
? `
`
: initials;
const isSelf = user.id === currentUserId;
return `
${avatarContent}
${user.username}${isSelf ? " (you)" : ""}
${user.credentialCount} passkey${user.credentialCount !== 1 ? "s" : ""}
joined ${createdDate}
${user.email ? `${user.email}` : ""}
${user.status}
${user.role}
${
!isSelf
? user.status === "suspended"
? ``
: ``
: ""
}
${!isSelf ? `` : ""}
`;
},
)
.join("");
// Add event listeners for action buttons
document.querySelectorAll("button[data-action]").forEach((btn) => {
btn.addEventListener("click", handleUserAction);
});
} catch (error) {
console.error("Failed to load users:", error);
usersList.innerHTML = 'Failed to load users
';
}
}
async function handleUserAction(e: Event) {
const btn = e.target as HTMLButtonElement;
const action = btn.dataset.action;
const userId = btn.dataset.userId;
if (!userId || !action) return;
// Check if already in confirmation state
if (btn.dataset.confirmState === "pending") {
// Second click - perform action
btn.dataset.confirmState = "";
btn.disabled = true;
try {
let endpoint = "";
let method = "POST";
if (action === "delete") {
endpoint = `/api/admin/users/${userId}/delete`;
method = "DELETE";
} else if (action === "disable") {
endpoint = `/api/admin/users/${userId}/disable`;
} else if (action === "enable") {
endpoint = `/api/admin/users/${userId}/enable`;
}
const response = await fetch(endpoint, {
method,
headers: {
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || "Failed to perform action");
}
// Reload users list
loadUsers();
} catch (error) {
console.error(`Failed to ${action} user:`, error);
alert(
`Failed to ${action} user: ${error instanceof Error ? error.message : "Unknown error"}`,
);
btn.disabled = false;
}
} else {
// First click - set confirmation state
const originalText = btn.textContent;
btn.dataset.confirmState = "pending";
btn.dataset.originalText = originalText || "";
btn.textContent = "you sure?";
// Reset after 3 seconds if not clicked again
setTimeout(() => {
if (btn.dataset.confirmState === "pending") {
btn.dataset.confirmState = "";
btn.textContent = btn.dataset.originalText || originalText;
}
}, 3000);
}
}
checkAuth();