This commit is contained in:
Louis Lam
2023-10-26 13:23:45 +08:00
parent 5f70fa6baf
commit 7d1da2ad99
34 changed files with 1650 additions and 510 deletions

View File

@ -1,61 +1,84 @@
import { SocketHandler } from "../socket-handler.js";
import { DockgeServer } from "../dockge-server";
import { checkLogin, DockgeSocket } from "../util-server";
import { callbackError, checkLogin, DockgeSocket, ValidationError } from "../util-server";
import { log } from "../log";
const allowedCommandList : string[] = [
"docker",
];
import yaml from "yaml";
import path from "path";
import fs from "fs";
import {
allowedCommandList,
allowedRawKeys,
getComposeTerminalName,
isDev,
PROGRESS_TERMINAL_ROWS
} from "../util-common";
import { Terminal } from "../terminal";
import { Stack } from "../stack";
export class DockerSocketHandler extends SocketHandler {
create(socket : DockgeSocket, server : DockgeServer) {
socket.on("composeUp", async (compose, callback) => {
});
socket.on("terminalInput", async (cmd : unknown, errorCallback) => {
try {
checkLogin(socket);
if (typeof(cmd) !== "string") {
throw new Error("Command must be a string.");
}
// Check if the command is allowed
const cmdParts = cmd.split(" ");
const executable = cmdParts[0].trim();
log.debug("console", "Executable: " + executable);
log.debug("console", "Executable length: " + executable.length);
if (!allowedCommandList.includes(executable)) {
throw new Error("Command not allowed.");
}
server.terminal.write(cmd);
} catch (e) {
errorCallback({
ok: false,
msg: e.message,
});
}
});
// Setup
socket.on("getTerminalBuffer", async (callback) => {
socket.on("deployStack", async (name : unknown, composeYAML : unknown, isAdd : unknown, callback) => {
try {
checkLogin(socket);
const stack = this.saveStack(socket, server, name, composeYAML, isAdd);
await stack.deploy(socket);
callback({
ok: true,
buffer: server.terminal.getBuffer(),
});
} catch (e) {
callback({
ok: false,
msg: e.message,
});
callbackError(e, callback);
}
});
socket.on("saveStack", async (name : unknown, composeYAML : unknown, isAdd : unknown, callback) => {
try {
checkLogin(socket);
this.saveStack(socket, server, name, composeYAML, isAdd);
callback({
ok: true,
"msg": "Saved"
});
server.sendStackList(socket);
} catch (e) {
callbackError(e, callback);
}
});
socket.on("getStack", (stackName : unknown, callback) => {
try {
checkLogin(socket);
if (typeof(stackName) !== "string") {
throw new ValidationError("Stack name must be a string");
}
const stack = Stack.getStack(server, stackName);
callback({
ok: true,
stack: stack.toJSON(),
});
} catch (e) {
callbackError(e, callback);
}
});
}
saveStack(socket : DockgeSocket, server : DockgeServer, name : unknown, composeYAML : unknown, isAdd : unknown) : Stack {
// Check types
if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string");
}
if (typeof(composeYAML) !== "string") {
throw new ValidationError("Compose YAML must be a string");
}
if (typeof(isAdd) !== "boolean") {
throw new ValidationError("isAdd must be a boolean");
}
const stack = new Stack(server, name, composeYAML);
stack.save(isAdd);
return stack;
}
}

View File

@ -71,7 +71,7 @@ export class MainSocketHandler extends SocketHandler {
}
log.debug("auth", "afterLogin");
await this.afterLogin(socket, user);
await this.afterLogin(server, socket, user);
log.debug("auth", "afterLogin ok");
log.info("auth", `Successfully logged in user ${decoded.username}. IP=${clientIP}`);
@ -128,7 +128,7 @@ export class MainSocketHandler extends SocketHandler {
if (user) {
if (user.twofa_status === 0) {
this.afterLogin(socket, user);
this.afterLogin(server, socket, user);
log.info("auth", `Successfully logged in user ${data.username}. IP=${clientIP}`);
@ -151,7 +151,7 @@ export class MainSocketHandler extends SocketHandler {
const verify = notp.totp.verify(data.token, user.twofa_secret, twoFAVerifyOptions);
if (user.twofa_last_token !== data.token && verify) {
this.afterLogin(socket, user);
this.afterLogin(server, socket, user);
await R.exec("UPDATE `user` SET twofa_last_token = ? WHERE id = ? ", [
data.token,
@ -189,10 +189,15 @@ export class MainSocketHandler extends SocketHandler {
});
}
async afterLogin(socket : DockgeSocket, user : User) {
async afterLogin(server: DockgeServer, socket : DockgeSocket, user : User) {
socket.userID = user.id;
socket.join(user.id + "");
socket.join("terminal");
socket.join(user.id.toString());
try {
server.sendStackList(socket);
} catch (e) {
log.error("server", e);
}
}
async login(username : string, password : string) {

View File

@ -0,0 +1,111 @@
import { SocketHandler } from "../socket-handler.js";
import { DockgeServer } from "../dockge-server";
import { callbackError, checkLogin, DockgeSocket, ValidationError } from "../util-server";
import { log } from "../log";
import yaml from "yaml";
import path from "path";
import fs from "fs";
import { allowedCommandList, allowedRawKeys, isDev } from "../util-common";
import { Terminal } from "../terminal";
export class TerminalSocketHandler extends SocketHandler {
create(socket : DockgeSocket, server : DockgeServer) {
socket.on("terminalInputRaw", async (key : unknown) => {
try {
checkLogin(socket);
if (typeof(key) !== "string") {
throw new Error("Key must be a string.");
}
if (allowedRawKeys.includes(key)) {
server.terminal.write(key);
}
} catch (e) {
}
});
socket.on("terminalInput", async (terminalName : unknown, cmd : unknown, errorCallback : unknown) => {
try {
checkLogin(socket);
if (typeof(cmd) !== "string") {
throw new Error("Command must be a string.");
}
// Check if the command is allowed
const cmdParts = cmd.split(" ");
const executable = cmdParts[0].trim();
log.debug("console", "Executable: " + executable);
log.debug("console", "Executable length: " + executable.length);
if (!allowedCommandList.includes(executable)) {
throw new Error("Command not allowed.");
}
server.terminal.write(cmd);
} catch (e) {
if (typeof(errorCallback) === "function") {
errorCallback({
ok: false,
msg: e.message,
});
}
}
});
// Create Terminal
socket.on("terminalCreate", async (terminalName : unknown, callback : unknown) => {
});
// Join Terminal
socket.on("terminalJoin", async (terminalName : unknown, callback : unknown) => {
if (typeof(callback) !== "function") {
log.debug("console", "Callback is not a function.");
return;
}
try {
checkLogin(socket);
if (typeof(terminalName) !== "string") {
throw new ValidationError("Terminal name must be a string.");
}
let buffer : string = Terminal.getTerminal(terminalName)?.getBuffer() ?? "";
if (!buffer) {
log.debug("console", "No buffer found.");
}
callback({
ok: true,
buffer,
});
} catch (e) {
callbackError(e, callback);
}
});
// Close Terminal
socket.on("terminalClose", async (terminalName : unknown, callback : unknown) => {
});
// Resize Terminal
socket.on("terminalResize", async (rows : unknown) => {
try {
checkLogin(socket);
if (typeof(rows) !== "number") {
throw new Error("Rows must be a number.");
}
log.debug("console", "Resize terminal to " + rows + " rows.");
server.terminal.resize(rows);
} catch (e) {
}
});
}
}