feat: v2.7.7 — File Explorer on workspaces and the user's home, clone with per-user git identity
- File Explorer (Files in the sidebar, /files; also from a workspace's Files tab, portalled so no panel clips it), laid out like GNOME Files: places (Home, workspaces, Trash), Back/Forward/Up, path bar, search, icon grid with image thumbnails or list, labelled New/Upload, selection action bar, hidden files behind Ctrl+H, right-click menus and the usual keys. Make, rename, move, copy (within a workspace, between workspaces, home ↔ workspace), delete into a per-account trash restorable for 7 days, streamed upload of files and whole folders (≤ 500 MB a batch, Replace / Keep both / Skip on a taken name), download a file or a zip of anything. server/lib/file-explorer.js, /api/lanes/:id/fs/*, /api/homes/:who/fs/*. - The user's home: every dot entry at its top stays hidden and refused (also via a symlink, download, zip or as a copy source); an admin may view other users' homes read-only, audited. - write-as learns move/copy (re-run `sudo agenthub server install-system`). - Hardening: a write to a workspace re-checks its owner by the live role; S3 keeps its server.conf if the file stops reading and a tmux call never falls back to the host's server; the AI Proxy gateway marks what it relays and the dashboard refuses it; a NUL in a pane's argv/env is refused. - OpenAPI for the new routes (server/openapi-extra/files.js); docs (API, SERVER-MODE, CLAUDE.md) updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,12 +29,20 @@ const confPath = () => process.env.AGENTHUB_SERVER_CONF || "/etc/agenthub/server
|
||||
|
||||
// server.conf is read on every tmux call's account lookup — keep it 5 s.
|
||||
let confCache = { at: 0, path: null, value: null };
|
||||
// The last server.conf that read well, per path. A server that started with
|
||||
// S3 keeps it if the file later fails to read (a transient error, an edit in
|
||||
// progress): falling back to "no S3" would run a member's pane as the HOST
|
||||
// account in their folder. Removing S3 for good is followed by a restart.
|
||||
let lastGood = { path: null, value: null };
|
||||
|
||||
/** `{hostUser, hostUid, usersRoot, port, bins}` from server.conf, or null. */
|
||||
function serverConf() {
|
||||
const file = confPath();
|
||||
if (confCache.path === file && Date.now() - confCache.at < 5000) return confCache.value;
|
||||
confCache = { at: Date.now(), path: file, value: readConf(file) };
|
||||
let value = readConf(file);
|
||||
if (value) lastGood = { path: file, value };
|
||||
else if (lastGood.path === file && require("./auth").isServerMode()) value = lastGood.value;
|
||||
confCache = { at: Date.now(), path: file, value };
|
||||
return confCache.value;
|
||||
}
|
||||
|
||||
@@ -135,6 +143,7 @@ function provision(action, username) {
|
||||
|
||||
function __resetConfCache() {
|
||||
confCache = { at: 0, path: null, value: null };
|
||||
lastGood = { path: null, value: null };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user