Files
ssh-jumphost/static/js/dashboard.js
2026-08-20 17:10:19 +02:00

113 lines
3.7 KiB
JavaScript

(() => {
"use strict";
async function getJson(url) {
const res = await fetch(url, { credentials: "same-origin" });
if (res.status === 401) {
window.location.href = "/";
throw new Error("nicht angemeldet");
}
return res.json();
}
async function showCredentials(host) {
const box = document.getElementById("credentials-box");
box.className = "reveal-box";
box.textContent = `Lade Zugangsdaten fuer ${host.hostname} ...`;
try {
const info = await getJson(`/admin/hosts/${host.id}/credentials`);
const lines = [`Zugangsdaten fuer ${host.hostname}:`];
lines.push(
info.ssh_keys.length
? `SSH-Keys: ${info.ssh_keys.map((k) => k.label).join(", ")}`
: "SSH-Keys: keine zugeordnet"
);
lines.push(
info.rdp_credentials_set
? `RDP-Passwort gesetzt (zuletzt aktualisiert: ${info.rdp_credentials_updated_at}).`
: "RDP-Passwort: nicht gesetzt."
);
box.textContent = lines.join("\n");
} catch (err) {
box.className = "banner error";
box.textContent = `Zugangsdaten konnten nicht geladen werden: ${err.message}`;
}
}
function hostCard(host) {
const div = document.createElement("div");
div.className = "host-card";
const name = document.createElement("div");
name.className = "hostname";
name.textContent = host.hostname;
div.appendChild(name);
const meta = document.createElement("div");
meta.className = "meta";
meta.textContent = `${host.protocol.toUpperCase()} · ${host.os_type} · ${host.address}`;
div.appendChild(meta);
const actions = document.createElement("div");
actions.className = "actions";
const connect = document.createElement("a");
connect.href = host.protocol === "ssh" ? `/terminal/${host.id}` : `/rdp/${host.id}`;
connect.textContent = "Verbinden";
actions.appendChild(connect);
if (host.can_view_credentials) {
const credBtn = document.createElement("button");
credBtn.type = "button";
credBtn.textContent = "Zugangsdaten";
credBtn.addEventListener("click", () => {
document.getElementById("credentials-box").classList.remove("hidden");
showCredentials(host);
});
actions.appendChild(credBtn);
}
div.appendChild(actions);
return div;
}
async function main() {
const me = await getJson("/auth/me");
document.getElementById("whoami").textContent = `${me.username}${me.is_admin ? " (Admin)" : ""}`;
if (me.is_admin) {
document.getElementById("admin-link").classList.remove("hidden");
}
const hosts = await getJson("/catalog/hosts");
const byGroup = {};
for (const h of hosts) {
(byGroup[h.host_group_name] = byGroup[h.host_group_name] || []).push(h);
}
const container = document.getElementById("groups");
if (hosts.length === 0) {
container.innerHTML = '<p class="hint">Keine Hosts zugewiesen. Bitte an einen Administrator wenden.</p>';
return;
}
for (const [groupName, groupHosts] of Object.entries(byGroup)) {
const section = document.createElement("div");
section.className = "group";
const h2 = document.createElement("h2");
h2.textContent = groupName;
section.appendChild(h2);
const list = document.createElement("div");
list.className = "host-list";
for (const host of groupHosts) list.appendChild(hostCard(host));
section.appendChild(list);
container.appendChild(section);
}
}
document.getElementById("logout-btn").addEventListener("click", async () => {
await fetch("/auth/logout", { method: "POST", credentials: "same-origin" });
window.location.href = "/";
});
main().catch((err) => console.error(err));
})();