feat: file manager on SSH hosts through a machine - open from the plus menu

This commit is contained in:
redtea committed 2026-10-15 21:32:18 +03:00
1 parent 2859e69abe
commit 7e4daeda4c
8 files changed
+202 -11

No files matched your search

+24
View File
@@ -55,6 +55,21 @@
close() {}
}
// An SSH host's files, through the machine that holds the connection.
class SSHSource {
constructor(agent, conn, home) { this.agent = agent; this.conn = conn; this.homeDir = home || '/'; this.caps = {zip: false, sqlite: false}; }
base() { return '/api/panel/agents/' + encodeURIComponent(this.agent.id) + '/sshfs/' + encodeURIComponent(this.conn) + '/'; }
url(what, path) { return this.base() + what + '?path=' + encodeURIComponent(path); }
op(name, body) {
return fetch(this.base() + name, {
method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(body || {}), credentials: 'same-origin'
}).then(r => r.status === 404 ? {ok: false, error: 'нет доступа к машине'} : r.json()).catch(() => ({ok: false, error: 'ошибка сети'}));
}
home() { return this.homeDir; }
// The pane closing lets the machine drop the connection at once.
close() { fetch(this.base() + 'close', {method: 'POST', keepalive: true, credentials: 'same-origin'}).catch(() => {}); }
}
const UP_CAP = 512 * 1024 * 1024;
const SORT_DEF = {by: 'name', dir: 1};
const byName = (a, b) => a.name.localeCompare(b.name, undefined, {numeric: true, sensitivity: 'base'}) || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
@@ -366,4 +381,13 @@
window.FilePane = FilePane;
window.MachineSource = MachineSource;
Workspace.paneTypes.files = agent => new FilePane({kind: 'agent', agent});
Workspace.paneTypes.sshfiles = (agent, o) => new FilePane({kind: 'ssh', agent, ssh: o.ssh, src: new SSHSource(agent, o.conn, o.home)});
// sshFiles connects agent to the SSH host t, then opens its files in a
// pane; the password or key goes to the machine once and is not kept here.
Workspace.sshFiles = (agent, t) => fetch('/api/panel/agents/' + encodeURIComponent(agent.id) + '/sshfs/open', {
method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ssh: t}), credentials: 'same-origin'
}).then(r => r.status === 404 ? {ok: false, error: 'нет доступа к машине'} : r.json()).then(r => {
if (r.ok) Workspace.open('sshfiles', agent, {conn: r.data.id, home: r.data.home, ssh: {host: t.host, port: t.port, user: t.user}});
return r;
}).catch(() => ({ok: false, error: 'ошибка сети'}));
})();