tons of server side fixes

This commit is contained in:
KingKDot
2026-04-14 10:23:59 -05:00
parent 59da653142
commit 303b7a43ba
9 changed files with 227 additions and 11 deletions
+20 -3
View File
@@ -19,6 +19,7 @@ const solMemoCheckbox = document.getElementById("sol-memo");
const solSettings = document.getElementById("sol-settings");
let currentServerVersion = null;
let currentUserRole = null;
async function loadServerVersion() {
try {
@@ -96,7 +97,6 @@ function saveFormSettings() {
solMemo: document.getElementById("sol-memo")?.checked ?? false,
solAddress: document.getElementById("sol-address")?.value ?? "",
solRpcEndpoints: document.getElementById("sol-rpc-endpoints")?.value ?? "",
outputName: document.getElementById("output-name")?.value ?? "",
mutex: document.getElementById("mutex")?.value ?? "",
disableMutex: document.querySelector('input[name="disable-mutex"]')?.checked ?? false,
stripDebug: document.querySelector('input[name="strip-debug"]')?.checked ?? true,
@@ -148,7 +148,6 @@ function restoreFormSettings() {
if (s.solMemo !== undefined) setCb("#sol-memo", s.solMemo);
if (s.solAddress !== undefined) setVal("sol-address", s.solAddress);
if (s.solRpcEndpoints !== undefined) setVal("sol-rpc-endpoints", s.solRpcEndpoints);
if (s.outputName !== undefined) setVal("output-name", s.outputName);
if (s.mutex !== undefined) setVal("mutex", s.mutex);
if (s.disableMutex !== undefined) setCb('input[name="disable-mutex"]', s.disableMutex);
if (s.stripDebug !== undefined) setCb('input[name="strip-debug"]', s.stripDebug);
@@ -829,6 +828,7 @@ async function init() {
}
const data = await res.json();
currentUserRole = data.role;
usernameDisplay.textContent = data.username;
const roleBadges = {
@@ -886,6 +886,20 @@ async function init() {
await loadServerVersion();
await loadSavedBuilds();
const toggleAllBuildsBtn = document.getElementById("toggle-all-builds-btn");
const toggleAllBuildsLabel = document.getElementById("toggle-all-builds-label");
if (toggleAllBuildsBtn && currentUserRole === "admin") {
toggleAllBuildsBtn.classList.remove("hidden");
toggleAllBuildsBtn.addEventListener("click", async () => {
showAllBuilds = !showAllBuilds;
if (toggleAllBuildsLabel) {
toggleAllBuildsLabel.textContent = showAllBuilds ? "My Builds" : "Show All";
}
buildFilesDiv.innerHTML = "";
await loadSavedBuilds();
});
}
} catch (err) {
console.error("Failed to fetch user info:", err);
window.location.href = "/";
@@ -1431,9 +1445,12 @@ function removeBuildFromStorage(buildId) {
}
}
let showAllBuilds = false;
async function loadSavedBuilds() {
try {
const res = await fetch("/api/build/list", {
const queryParam = showAllBuilds && currentUserRole === "admin" ? "?all=true" : "";
const res = await fetch(`/api/build/list${queryParam}`, {
credentials: "include",
});
+29 -1
View File
@@ -830,6 +830,7 @@ async function wipeOfflineClients() {
const sessionsTableBody = document.getElementById("sessions-table-body");
const sessionsMessage = document.getElementById("sessions-message");
const refreshSessionsBtn = document.getElementById("refresh-sessions-btn");
const removeInactiveSessionsBtn = document.getElementById("remove-inactive-sessions-btn");
function parseUserAgent(ua) {
if (!ua) return "Unknown";
@@ -905,7 +906,7 @@ async function loadSessions() {
<tr>
<td class="px-3 py-2 font-mono text-xs text-slate-100">${escapeHtml(s.ip || "—")}</td>
<td class="px-3 py-2 text-slate-300 text-xs max-w-[200px] truncate" title="${escapeHtml(s.userAgent || "")}">${escapeHtml(parseUserAgent(s.userAgent))}</td>
<td class="px-3 py-2 text-slate-400 text-xs">${formatDate(s.createdAt)}</td>
<td class="px-3 py-2 text-slate-400 text-xs">${formatDate(s.createdAt * 1000)}</td>
<td class="px-3 py-2 text-slate-400 text-xs">${formatRelativeTime(s.lastActivity)}</td>
<td class="px-3 py-2 text-xs">${statusLabel}${currentBadge}</td>
<td class="px-3 py-2 text-right">
@@ -972,6 +973,32 @@ async function handleRevokeSessionClick(event) {
}
}
async function handleRemoveInactiveSessions() {
if (!confirm("Remove all expired and revoked sessions?")) return;
if (removeInactiveSessionsBtn) removeInactiveSessionsBtn.disabled = true;
try {
const res = await fetch("/api/sessions/inactive", {
method: "DELETE",
credentials: "include",
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
showSessionsMessage(data.error || "Failed to remove inactive sessions", "error");
return;
}
showSessionsMessage(`Removed ${data.removed || 0} inactive session(s)`);
await loadSessions();
} catch {
showSessionsMessage("Request failed", "error");
} finally {
if (removeInactiveSessionsBtn) removeInactiveSessionsBtn.disabled = false;
}
}
async function init() {
try {
await loadCurrentUser();
@@ -1020,6 +1047,7 @@ async function init() {
await loadSessions();
if (refreshSessionsBtn) refreshSessionsBtn.addEventListener("click", loadSessions);
if (removeInactiveSessionsBtn) removeInactiveSessionsBtn.addEventListener("click", handleRemoveInactiveSessions);
if (sessionsTableBody) sessionsTableBody.addEventListener("click", handleRevokeSessionClick);
} catch (error) {
console.error("settings init failed", error);
+13 -3
View File
@@ -596,9 +596,19 @@
</div>
<div id="build-results" class="mt-4 hidden">
<h3 class="font-medium mb-2 flex items-center gap-2">
<i class="fa-solid fa-download"></i> Built Clients
</h3>
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium flex items-center gap-2">
<i class="fa-solid fa-download"></i> Built Clients
</h3>
<button
id="toggle-all-builds-btn"
class="hidden inline-flex items-center gap-2 px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-300 text-xs transition-colors"
type="button"
>
<i class="fa-solid fa-eye"></i>
<span id="toggle-all-builds-label">Show All</span>
</button>
</div>
<div id="build-files" class="flex flex-col gap-2"></div>
</div>
</div>
+7
View File
@@ -261,6 +261,13 @@
>
<i class="fa-solid fa-rotate"></i>Refresh
</button>
<button
id="remove-inactive-sessions-btn"
class="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-red-900/40 hover:bg-red-800/60 text-red-100 border border-red-700/60 text-sm transition-colors"
type="button"
>
<i class="fa-solid fa-broom"></i>Remove Inactive
</button>
</div>
<div class="overflow-x-auto border border-slate-800 rounded-lg">