Publicētais avots
Lejupielādēt avota ZIP
CH-J Server Manager
Pārlūkot mapes un failus konkrētai lietojumprogrammas izdošanai.
CH-J / Server Manager
339 faili
core-20261014T184258Z-3fbed0b93fdf
Pievienots: Datums nav reģistrēts · Būvēts:
1
"use strict";3
const api = window.chjPlugin;4
const elements = Object.fromEntries(["pluginVersion", "closeButton", "sessionSelect", "refreshSessionsButton", "refreshUsersButton", "sudoPassword", "status", "createForm", "newUsername", "newAdmin", "createButton", "usersBody"].map((id) => [id, document.querySelector(`#${id}`)]));5
let sessions = [];6
let busy = false;8
function setStatus(message, error = false) { elements.status.textContent = message; elements.status.classList.toggle("error", error); }9
function selectedSession() { return sessions.find((session) => session.sessionId === elements.sessionSelect.value) || null; }10
function 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;14
}16
function 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;19
}21
function 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>';39
}41
async 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.");49
}51
async 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); }57
}59
async 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); }67
}69
elements.closeButton.addEventListener("click", () => api.close());70
elements.refreshSessionsButton.addEventListener("click", async () => { await loadSessions(); await loadUsers(); });71
elements.refreshUsersButton.addEventListener("click", loadUsers);72
elements.sessionSelect.addEventListener("change", () => { setBusy(false); void loadUsers(); });73
elements.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
});78
elements.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-256
62a7b23188a9b1d8187727c03fd6aec61ac53bc30d763a03b0e35b15051966c1CH-J Proprietary Software License 1.14 · Avots ir sniegts saskaņā ar CH-J Proprietary Software License 1.14. Tā pieejamība nemaina licences noteikumus un nepiešķir papildu tiesības.
Arhīvs SHA-256
3df08cf5e899262a6ce92d7ec2caf5c42b683f1f2b57055662b845ff7dde67a8