CH-J Server Managerserverio valdymas per SSH
Meniu
Paskelbtas šaltinis

CH-J Server Manager

Naršyti aplankus ir failus konkrečiai programai išleisti.

Atsisiųsti šaltinį ZIP
CH-J / Server Manager 339 failai
core-20261014T184258Z-3fbed0b93fdf Pridėta: Data neregistruota · Pastatytas:
Failai
index.js Pridėta: Data neregistruota 5,9 KB · 87 eilutės
Atsiųsti failą
1"use strict";
3const api = window.chjPlugin;
4const elements = Object.fromEntries(["pluginVersion", "closeButton", "sessionSelect", "refreshSessionsButton", "refreshUsersButton", "sudoPassword", "status", "createForm", "newUsername", "newAdmin", "createButton", "usersBody"].map((id) => [id, document.querySelector(`#${id}`)]));
5let sessions = [];
6let busy = false;
8function setStatus(message, error = false) { elements.status.textContent = message; elements.status.classList.toggle("error", error); }
9function selectedSession() { return sessions.find((session) => session.sessionId === elements.sessionSelect.value) || null; }
10function setBusy(value) {
11 busy = value; const disabled = value || !elements.sessionSelect.value;
12 elements.refreshUsersButton.disabled = disabled; elements.createButton.disabled = disabled;
13 elements.sessionSelect.disabled = value; elements.refreshSessionsButton.disabled = value;
16function button(label, action, username, danger = false) {
17 const result = document.createElement("button"); result.type = "button"; result.className = `mini${danger ? " danger" : ""}`;
18 result.textContent = label; result.dataset.action = action; result.dataset.username = username; return result;
21function render(users) {
22 const session = selectedSession(); const fragment = document.createDocumentFragment();
23 for (const user of users) {
24 const row = document.createElement("tr");
25 for (const value of [user.username, String(user.uid), user.home || "—", user.shell || "—"]) { const cell = document.createElement("td"); cell.textContent = value; row.append(cell); }
26 const state = document.createElement("td"); state.innerHTML = `<span class="badge ${user.locked ? "locked" : "active"}">${user.locked ? "zamčený" : "aktivní"}</span>`; row.append(state);
27 const role = document.createElement("td"); role.textContent = user.admin ? "admin" : "uživatel"; row.append(role);
28 const actions = document.createElement("td"); actions.className = "actions";
29 const protectedUser = user.username === "root" || user.username === session?.username;
30 if (!protectedUser) {
31 actions.append(button(user.locked ? "Odemknout" : "Zamknout", user.locked ? "unlock" : "lock", user.username));
32 actions.append(button(user.admin ? "Odebrat admin" : "Přidat admin", user.admin ? "revokeAdmin" : "grantAdmin", user.username));
33 actions.append(button("Smazat", "delete", user.username, true));
34 } else { const note = document.createElement("small"); note.textContent = "chráněný účet"; actions.append(note); }
35 row.append(actions); fragment.append(row);
36 }
37 elements.usersBody.replaceChildren(fragment);
38 if (!users.length) elements.usersBody.innerHTML = '<tr><td colspan="7" class="empty">Server nevrátil žádné spravovatelné účty.</td></tr>';
41async function loadSessions() {
42 const current = elements.sessionSelect.value;
43 sessions = (await api.sessions.list()).filter((session) => session.state === "connected");
44 elements.sessionSelect.replaceChildren(new Option(sessions.length ? "Vyberte relaci…" : "Žádná připojená relace", ""));
45 for (const session of sessions) elements.sessionSelect.add(new Option(`${session.label} — ${session.username}@${session.host}`, session.sessionId));
46 elements.sessionSelect.value = sessions.some((session) => session.sessionId === current) ? current : (sessions[0]?.sessionId || "");
47 setBusy(false);
48 if (!sessions.length) setStatus("Nejprve se v Core připojte k serveru přes SSH.");
51async function loadUsers() {
52 if (!elements.sessionSelect.value || busy) return;
53 setBusy(true); setStatus("Načítám uživatelské účty…");
54 try { const users = await api.users.list(elements.sessionSelect.value); render(users); setStatus(`Načteno ${users.length} účtů.`); }
55 catch (error) { setStatus(error?.message || String(error), true); }
56 finally { setBusy(false); }
59async function mutate(payload) {
60 if (!elements.sessionSelect.value || busy) return;
61 setBusy(true); setStatus("Provádím potvrzenou změnu…");
62 try {
63 const result = await api.users.manage(elements.sessionSelect.value, { ...payload, sudoPassword: elements.sudoPassword.value });
64 elements.sudoPassword.value = ""; render(result.users); setStatus(`Operace ${result.action} pro ${result.username} byla dokončena.`);
65 } catch (error) { setStatus(error?.message || String(error), true); }
66 finally { setBusy(false); }
69elements.closeButton.addEventListener("click", () => api.close());
70elements.refreshSessionsButton.addEventListener("click", async () => { await loadSessions(); await loadUsers(); });
71elements.refreshUsersButton.addEventListener("click", loadUsers);
72elements.sessionSelect.addEventListener("change", () => { setBusy(false); void loadUsers(); });
73elements.createForm.addEventListener("submit", (event) => {
74 event.preventDefault(); const username = elements.newUsername.value.trim();
75 if (!window.confirm(`Vytvořit na serveru účet ${username}?`)) return;
76 void mutate({ action: "create", username, admin: elements.newAdmin.checked }).then(() => { elements.newUsername.value = ""; elements.newAdmin.checked = false; });
77});
78elements.usersBody.addEventListener("click", (event) => {
79 const target = event.target.closest("button[data-action]"); if (!target) return;
80 const action = target.dataset.action; const username = target.dataset.username;
81 const destructive = action === "delete"; const message = destructive ? `Opravdu smazat účet ${username}? Další potvrzení rozhodne, zda odstranit i jeho domovský adresář.` : `Provést operaci ${action} pro účet ${username}?`;
82 if (!window.confirm(message)) return;
83 const removeHome = destructive && window.confirm(`Odstranit také domovský adresář účtu ${username}?`);
84 void mutate({ action, username, removeHome });
85});
87(async () => { const info = await api.getInfo(); elements.pluginVersion.textContent = `${info.name} v${info.version} · ${info.publisher}`; await loadSessions(); await loadUsers(); })().catch((error) => setStatus(error?.message || String(error), true));
SHA-25662a7b23188a9b1d8187727c03fd6aec61ac53bc30d763a03b0e35b15051966c1

CH-J Proprietary Software License 1.14 · Šaltinis pateiktas pagal CH-J Proprietary Software License 1.14. Jo prieinamumas nekeičia licencijos sąlygų ir nesuteikia papildomų teisių.

Archyvas SHA-2563df08cf5e899262a6ce92d7ec2caf5c42b683f1f2b57055662b845ff7dde67a8