UI improvements
parent
a265519ffb
commit
c91e94d0a2
|
@ -58,6 +58,10 @@ file-manager
|
|||
|
||||
The following environmental variables can be used to configure `file-manager`.
|
||||
|
||||
### SESSION_KEY=
|
||||
|
||||
Express session key, generate something random.
|
||||
|
||||
### SHELL=
|
||||
|
||||
Enable the shell feature, which allows users to start a login shell (when set to `login`) or the binary specified by this option (example: `/bin/bash`). Be careful when enabling this feature as anyone with access to this portal can execute any command on your machine.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* jshint esversion: 6 */
|
||||
|
||||
document.querySelectorAll("[title]").forEach(element => {
|
||||
new bootstrap.Tooltip(element);
|
||||
new bootstrap.Tooltip(element, {
|
||||
delay: 500,
|
||||
});
|
||||
});
|
||||
|
|
45
index.js
45
index.js
|
@ -77,7 +77,7 @@ app.use("/@assets/xterm-addon-attach", express.static(path.join(__dirname, "node
|
|||
app.use("/@assets/xterm-addon-fit", express.static(path.join(__dirname, "node_modules/xterm-addon-fit")));
|
||||
|
||||
app.use(session({
|
||||
secret: "meowmeow"
|
||||
secret: process.env.SESSION_KEY || "meowmeow"
|
||||
}));
|
||||
app.use(flash());
|
||||
app.use(busboy());
|
||||
|
@ -103,7 +103,6 @@ app.get("/@login", (req, res) => {
|
|||
});
|
||||
app.post("/@login", (req, res) => {
|
||||
let pass = notp.totp.verify(req.body.token.replace(" ", ""), KEY);
|
||||
console.log(pass, req.body.token.replace(" ", ""));
|
||||
if (pass) {
|
||||
req.session.login = true;
|
||||
res.redirect("/");
|
||||
|
@ -168,34 +167,6 @@ app.all("/*", (req, res, next) => {
|
|||
});
|
||||
});
|
||||
|
||||
// currently unused
|
||||
app.put("/*", (req, res) => {
|
||||
if (res.stats.error) {
|
||||
req.busboy.on("file", (key, file, filename) => {
|
||||
if (key == "file") {
|
||||
let save = fs.createWriteStream(relative(res.filename));
|
||||
file.pipe(save);
|
||||
save.on("close", () => {
|
||||
res.flash("success", "File saved. ");
|
||||
res.redirect("back");
|
||||
});
|
||||
save.on("error", (err) => {
|
||||
res.flash("error", err.toString());
|
||||
res.redirect("back");
|
||||
});
|
||||
}
|
||||
});
|
||||
req.busboy.on("field", (key, value) => {
|
||||
|
||||
});
|
||||
req.pipe(req.busboy);
|
||||
}
|
||||
else {
|
||||
req.flash("error", "File exists, cannot overwrite. ");
|
||||
res.redirect("back");
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/*@upload", (req, res) => {
|
||||
res.filename = req.params[0];
|
||||
|
||||
|
@ -233,6 +204,7 @@ app.post("/*@upload", (req, res) => {
|
|||
});
|
||||
|
||||
fileExists.then((stats) => {
|
||||
console.warn("file exists, cannot overwrite");
|
||||
req.flash("error", "File exists, cannot overwrite. ");
|
||||
res.redirect("back");
|
||||
}).catch((err) => {
|
||||
|
@ -253,6 +225,7 @@ app.post("/*@upload", (req, res) => {
|
|||
res.redirect("back");
|
||||
});
|
||||
save.on("error", (err) => {
|
||||
console.warn(err);
|
||||
req.flash("error", err.toString());
|
||||
res.redirect("back");
|
||||
});
|
||||
|
@ -287,6 +260,7 @@ app.post("/*@mkdir", (req, res) => {
|
|||
}).catch((err) => {
|
||||
fs.mkdir(relative(res.filename, folder), (err) => {
|
||||
if (err) {
|
||||
console.warn(err);
|
||||
req.flash("error", err.toString());
|
||||
res.redirect("back");
|
||||
return;
|
||||
|
@ -347,10 +321,12 @@ app.post("/*@delete", (req, res) => {
|
|||
req.flash("success", "Files deleted. ");
|
||||
res.redirect("back");
|
||||
}).catch((err) => {
|
||||
console.warn(err);
|
||||
req.flash("error", "Unable to delete some files: " + err);
|
||||
res.redirect("back");
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn(err);
|
||||
req.flash("error", err.toString());
|
||||
res.redirect("back");
|
||||
});
|
||||
|
@ -386,6 +362,7 @@ app.get("/*@download", (req, res) => {
|
|||
Promise.all(promises).then((files) => {
|
||||
let zip = archiver("zip", {});
|
||||
zip.on("error", function(err) {
|
||||
console.warn(err);
|
||||
res.status(500).send({
|
||||
error: err.message
|
||||
});
|
||||
|
@ -403,7 +380,7 @@ app.get("/*@download", (req, res) => {
|
|||
|
||||
zip.finalize();
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
console.warn(err);
|
||||
req.flash("error", err.toString());
|
||||
res.redirect("back");
|
||||
});
|
||||
|
@ -425,12 +402,14 @@ if (shellable || cmdable) {
|
|||
if (!cmd || cmd.length < 1) {
|
||||
return res.status(400).end();
|
||||
}
|
||||
console.log("running command " + cmd);
|
||||
|
||||
child_process.exec(cmd, {
|
||||
cwd: relative(res.filename),
|
||||
timeout: 60 * 1000,
|
||||
}, (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.log("command run failed: " + JSON.stringify(err));
|
||||
req.flash("error", "Command failed due to non-zero exit code");
|
||||
}
|
||||
res.render("cmd", flashify(req, {
|
||||
|
@ -455,7 +434,6 @@ if (shellable || cmdable) {
|
|||
|
||||
const ws = new WebSocket.Server({ server: http });
|
||||
ws.on("connection", (socket, request) => {
|
||||
console.log(request.url);
|
||||
const { path } = querystring.parse(request.url.split("?")[1]);
|
||||
let cwd = relative(path);
|
||||
let term = pty.spawn(exec, args, {
|
||||
|
@ -529,6 +507,7 @@ app.get("/*", (req, res) => {
|
|||
const promises = filenames.map(f => new Promise((resolve, reject) => {
|
||||
fs.stat(relative(res.filename, f), (err, stats) => {
|
||||
if (err) {
|
||||
console.warn(err);
|
||||
return resolve({
|
||||
name: f,
|
||||
error: err
|
||||
|
@ -551,6 +530,7 @@ app.get("/*", (req, res) => {
|
|||
files: files,
|
||||
}));
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
res.render("list", flashify(req, {
|
||||
shellable: shellable,
|
||||
cmdable: cmdable,
|
||||
|
@ -561,6 +541,7 @@ app.get("/*", (req, res) => {
|
|||
}));
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn(err);
|
||||
res.render("list", flashify(req, {
|
||||
shellable: shellable,
|
||||
cmdable: cmdable,
|
||||
|
|
|
@ -21,16 +21,20 @@
|
|||
</main>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-light bg-light fixed-bottom p-1 px-2">
|
||||
<div class="btn-group m-1" role="group">
|
||||
<a class="btn btn-primary" href="/{{path}}" data-placement="top" title="Return to folder">
|
||||
{{octicon "chevron-left"}}
|
||||
<span class="d-none d-sm-inline">Back</span>
|
||||
</a>
|
||||
<a class="btn btn-warning" href="@cmd" data-toggle="modal" data-target="#cmd" data-placement="top" title="Run another command">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-sm-inline">Run command</span>
|
||||
</a>
|
||||
<nav class="navbar navbar-light bg-light fixed-bottom">
|
||||
<div class="container-fluid px-2">
|
||||
<div class="d-flex">
|
||||
<div class="btn-group me-2" role="group">
|
||||
<a class="btn btn-secondary" href="/{{path}}">
|
||||
{{octicon "chevron-left"}}
|
||||
<span class="d-none d-sm-inline">Back</span>
|
||||
</a>
|
||||
<a class="btn btn-info" href="@cmd" data-bs-toggle="modal" data-bs-target="#cmd" title="Run another command" data-bs-placement="top">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-sm-inline">Run command</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
{{else}}
|
||||
{{#if error}}
|
||||
<a href="./{{name}}/" class="name" title="{{error}}">{{name}}/</a>
|
||||
<span class="badge rounded-pill bg-danger badge-alignment">err</span>
|
||||
{{else}}
|
||||
<a href="./{{name}}" class="name">{{name}}</a>
|
||||
<span class="badge rounded-pill bg-secondary badge-alignment">{{filesize size}}</span>
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="cmd-cmd">Command: </label>
|
||||
<input name="cmd" class="form-control" type="text" id="cmd-cmd" placeholder="g++ sort.c" required />
|
||||
</div>
|
||||
<input class="form-control" name="cmd" type="text" id="cmd-cmd" placeholder="g++ sort.c" required />
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="reset" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<label class="form-label" for="mkdir-folder">Folder name</label>
|
||||
<input class="form-control" name="folder" type="text" id="mkdir-folder" placeholder="folder" required />
|
||||
</div>
|
||||
<input class="form-control" name="folder" type="text" id="mkdir-folder" placeholder="folder-name" required />
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="reset" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbar">
|
||||
<div class="navbar-nav mr-auto">
|
||||
<div class="navbar-nav me-auto">
|
||||
{{#eachpath path}}
|
||||
<a class="nav-item nav-link{{#if current}} active{{/if}}" href="{{path}}">{{name}}</a>
|
||||
{{/eachpath}}
|
||||
|
@ -13,12 +13,12 @@
|
|||
<div class="navbar-nav">
|
||||
{{#if isloginenabled}}
|
||||
{{#if isloggingin}}
|
||||
<a class="nav-item nav-link" href="/@login" title="Sign in">
|
||||
<span class="octicon octicon-sign-in"></span>
|
||||
<a class="nav-item nav-link" href="/@login" title="Sign in" data-bs-placement="left">
|
||||
{{octicon "sign-in"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a class="nav-item nav-link" href="/@logout" title="Sign out">
|
||||
<span class="octicon octicon-sign-out"></span>
|
||||
<a class="nav-item nav-link" href="/@logout" title="Sign out" data-bs-placement="left">
|
||||
{{octicon "sign-out"}}
|
||||
</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
<div class="container-fluid px-2">
|
||||
<div class="d-flex">
|
||||
<div class="btn-group me-2" role="group">
|
||||
<a class="btn btn-primary" href="@upload" data-bs-toggle="modal" data-bs-target="#upload" data-placement="top" title="Upload">
|
||||
<a class="btn btn-primary" href="@upload" data-bs-toggle="modal" data-bs-target="#upload" title="Upload a file" data-bs-placement="top">
|
||||
{{octicon "cloud-upload"}}
|
||||
<span class="d-none d-sm-inline">Upload</span>
|
||||
</a>
|
||||
<a class="btn btn-secondary" href="@mkdir" data-bs-toggle="modal" data-bs-target="#mkdir" data-placement="top" title="New folder">
|
||||
<a class="btn btn-secondary" href="@mkdir" data-bs-toggle="modal" data-bs-target="#mkdir" title="Create a new folder" data-bs-placement="top">
|
||||
{{octicon "file-directory"}}
|
||||
<span class="d-none d-md-inline">New folder</span>
|
||||
</a>
|
||||
|
@ -14,13 +14,13 @@
|
|||
{{#either cmdable shellable}}
|
||||
<div class="btn-group me-2" role="group">
|
||||
{{#if cmdable}}
|
||||
<a class="btn btn-info" href="@cmd" data-bs-toggle="modal" data-bs-target="#cmd" data-placement="top" title="Run command">
|
||||
<a class="btn btn-info" href="@cmd" data-bs-toggle="modal" data-bs-target="#cmd" title="Run a command" data-bs-placement="top">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-lg-inline">Run command</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if shellable}}
|
||||
<a class="btn btn-warning" href="@shell" data-placement="top" title="Open shell">
|
||||
<a class="btn btn-warning" href="@shell" title="Open a new shell" data-bs-placement="top">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-md-inline">Open shell</span>
|
||||
</a>
|
||||
|
@ -28,13 +28,13 @@
|
|||
</div>
|
||||
{{/either}}
|
||||
<div class="btn-group me-2" role="group">
|
||||
<a class="btn btn-success" href="@download" data-bs-toggle="modal" data-bs-target="#download" data-placement="top" title="Download file archive">
|
||||
<a class="btn btn-success" href="@download" data-bs-toggle="modal" data-bs-target="#download" title="Download file archive" data-bs-placement="top">
|
||||
{{octicon "file-zip"}}
|
||||
<span class="d-none d-md-inline">Download</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group me-2" role="group">
|
||||
<a class="btn btn-danger" href="@delete" data-bs-toggle="modal" data-bs-target="#delete" data-placement="top" title="Delete files">
|
||||
<a class="btn btn-danger" href="@delete" data-bs-toggle="modal" data-bs-target="#delete" title="Delete selected files" data-bs-placement="top">
|
||||
{{octicon "trashcan"}}
|
||||
<span class="d-none d-md-inline">Delete</span>
|
||||
</a>
|
||||
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="btn-group ms-2" role="group">
|
||||
<a class="btn btn-warning" href="./" data-placement="top" title="Refresh list">
|
||||
<a class="btn btn-warning" href="./" title="Refresh list" data-bs-placement="top">
|
||||
{{octicon "sync"}}
|
||||
<span class="d-none d-lg-inline">Refresh</span>
|
||||
</a>
|
||||
|
|
|
@ -4,15 +4,19 @@
|
|||
<main id="shell" style="height: 100%; background: #000" data-path="/{{path}}"></main>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-light bg-light fixed-bottom p-1 px-2">
|
||||
<div class="btn-group m-1" role="group">
|
||||
<a class="btn btn-danger" href="/{{path}}" id="shell-close" data-placement="top" title="Close and return to folder">
|
||||
{{octicon "chevron-left"}}
|
||||
<span class="d-none d-sm-inline">Close shell</span>
|
||||
</a>
|
||||
<a class="btn btn-warning" href="@shell" target="_blank" data-placement="top" title="Open shell in new tab">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-sm-inline">New shell</span>
|
||||
</a>
|
||||
<nav class="navbar navbar-light bg-light fixed-bottom">
|
||||
<div class="container-fluid px-2">
|
||||
<div class="d-flex">
|
||||
<div class="btn-group me-2" role="group">
|
||||
<a class="btn btn-danger" href="/{{path}}" id="shell-close">
|
||||
{{octicon "chevron-left"}}
|
||||
<span class="d-none d-sm-inline">Exit shell</span>
|
||||
</a>
|
||||
<a class="btn btn-warning" href="@shell" target="_blank" title="Open a new shell tab" data-bs-placement="top">
|
||||
{{octicon "terminal"}}
|
||||
<span class="d-none d-sm-inline">New shell</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
Loading…
Reference in New Issue