chore: comment config.example.toml and format code with prettier/cargo
This commit is contained in:
@@ -16,5 +16,6 @@
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "none",
|
||||
"useTabs": true,
|
||||
"vueIndentScriptAndStyle": false
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"plugins": ["prettier-plugin-toml"]
|
||||
}
|
||||
|
||||
@@ -21,15 +21,21 @@ accountID = ""
|
||||
licenseKey = ""
|
||||
|
||||
[tcp]
|
||||
# Enabled the raw TCP socket server
|
||||
# You usually want to leave this disabled
|
||||
enabled = false
|
||||
host = "0.0.0.0"
|
||||
port = 6014
|
||||
|
||||
[auth]
|
||||
# Enables the CollabVM account authentication system
|
||||
# Requires an authentication server (https://git.computernewb.com/collabvm/CollabVMAuthServer)
|
||||
enabled = false
|
||||
apiEndpoint = ""
|
||||
secretKey = "hunter2"
|
||||
|
||||
# When account authentication is enabled, this section defines what guests can and can't do
|
||||
# Has no effect if auth is disabled
|
||||
[auth.guestPermissions]
|
||||
chat = true
|
||||
turn = false
|
||||
@@ -37,13 +43,21 @@ callForReset = false
|
||||
vote = true
|
||||
|
||||
[vm]
|
||||
# Configures the type of VM this server will use
|
||||
# Supported values:
|
||||
# "qemu" - Runs a QEMU VM
|
||||
# "vncvm" - Connects to an existing VNC server
|
||||
type = "qemu"
|
||||
|
||||
# QEMU options
|
||||
# Only used if vm.type is set to "qemu"
|
||||
[qemu]
|
||||
qemuArgs = "qemu-system-x86_64"
|
||||
vncPort = 5900
|
||||
snapshots = true
|
||||
|
||||
# VNC options
|
||||
# Only used if vm.type is set to "vncvm"
|
||||
[vncvm]
|
||||
vncHost = "127.0.0.1"
|
||||
vncPort = 5900
|
||||
@@ -69,12 +83,16 @@ database = "cvmts"
|
||||
cvmban = false
|
||||
|
||||
[collabvm]
|
||||
# Node ID for this server
|
||||
# Make sure this is unique among all the other nodes in a webapp
|
||||
node = "acoolvm"
|
||||
# HTML display name shown on the VM list
|
||||
displayname = "A <b>Really</b> Cool CollabVM Instance"
|
||||
# HTML message shown in the chat when a user joins
|
||||
motd = "welcome!"
|
||||
# Maximum amount of active connections allowed from the same IP.
|
||||
maxConnections = 3
|
||||
# Moderator rank enabled
|
||||
# Moderator rank enabled (permissions are defined below)
|
||||
moderatorEnabled = true
|
||||
# List of disallowed usernames
|
||||
usernameblacklist = []
|
||||
@@ -103,8 +121,9 @@ modpass = "fb8c2e2b85ca81eb4350199faddd983cb26af3064614e737ea9f479621cfa57a"
|
||||
turnwhitelist = false
|
||||
# SHA256 sum for the password to take a turn. Only takes effect if turnwhitelist == true. If set to an empty string or not provided, only admins and mods can take turns
|
||||
turnpass = ""
|
||||
[collabvm.moderatorPermissions]
|
||||
|
||||
# What a moderator can and can't do
|
||||
[collabvm.moderatorPermissions]
|
||||
restore = true
|
||||
reboot = true
|
||||
ban = true
|
||||
|
||||
9
cvm-rs/index.d.ts
vendored
9
cvm-rs/index.d.ts
vendored
@@ -5,10 +5,10 @@ export function guacDecode(input: string): string[];
|
||||
export function guacEncode(...items: string[]): string;
|
||||
|
||||
interface JpegInputArgs {
|
||||
width: number,
|
||||
height: number,
|
||||
stride: number, // The width of your input framebuffer OR your image width (if encoding a full image)
|
||||
buffer: Buffer
|
||||
width: number;
|
||||
height: number;
|
||||
stride: number; // The width of your input framebuffer OR your image width (if encoding a full image)
|
||||
buffer: Buffer;
|
||||
|
||||
// TODO: Allow different formats, or export a boxed ffi object which can store a format
|
||||
// (i.e: new JpegEncoder(FORMAT_xxx)).
|
||||
@@ -19,7 +19,6 @@ export function jpegEncode(input: JpegInputArgs) : Promise<Buffer>;
|
||||
|
||||
// TODO: Version that can downscale?
|
||||
|
||||
|
||||
/* remoting API?
|
||||
|
||||
js side api:
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"scripts": {
|
||||
"build": "cargo-cp-artifact -nc index.node -- cargo build --release --message-format=json-render-diagnostics",
|
||||
"install": "yarn build",
|
||||
"test": "cargo test"
|
||||
"test": "cargo test",
|
||||
"format": "cargo fmt"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cargo-cp-artifact": "^0.1"
|
||||
|
||||
@@ -29,7 +29,7 @@ impl fmt::Display for DecodeError {
|
||||
Self::InvalidFormat => write!(f, "Invalid Guacamole instruction while decoding"),
|
||||
Self::InstructionTooLong => write!(f, "Instruction too long for current decode policy"),
|
||||
Self::ElementTooLong => write!(f, "Element too long for current decode policy"),
|
||||
Self::ElementSizeInvalid => write!(f, "Element size is invalid")
|
||||
Self::ElementSizeInvalid => write!(f, "Element size is invalid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ impl<const INST_SIZE: usize, const ELEM_SIZE: usize> StaticDecodePolicy<INST_SIZ
|
||||
/// The default decode policy.
|
||||
pub type DefaultDecodePolicy = StaticDecodePolicy<12288, 4096>;
|
||||
|
||||
|
||||
/// Encodes elements into a Guacamole instruction
|
||||
pub fn encode_instruction(elements: &Elements) -> String {
|
||||
let mut str = String::new();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use neon::prelude::*;
|
||||
use crate::guac;
|
||||
use neon::prelude::*;
|
||||
|
||||
fn guac_decode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsArray> {
|
||||
let input = cx.argument::<JsString>(0)?.value(cx);
|
||||
|
||||
@@ -4,10 +4,8 @@ mod guac_js;
|
||||
mod jpeg_compressor;
|
||||
mod jpeg_js;
|
||||
|
||||
|
||||
use neon::prelude::*;
|
||||
|
||||
|
||||
#[neon::main]
|
||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
// Mostly transitionary, later on API should change
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc -outDir dist -rootDir src/",
|
||||
"serve": "node dist/index.js"
|
||||
"serve": "node dist/index.js",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"author": "Elijah R, modeco80",
|
||||
"license": "GPL-3.0",
|
||||
@@ -29,7 +30,6 @@
|
||||
"@types/node": "^20.12.5",
|
||||
"@types/ws": "^8.5.5",
|
||||
"pino-pretty": "^11.2.1",
|
||||
"prettier": "^3.2.5",
|
||||
"typescript": "^5.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ExecaSyncError, execa, execaCommand } from "execa";
|
||||
import { BanConfig } from "./IConfig";
|
||||
import pino from "pino";
|
||||
import { Database } from "./Database";
|
||||
import { Address6 } from "ip-address";
|
||||
import { isIP } from "net";
|
||||
import { ExecaSyncError, execa, execaCommand } from 'execa';
|
||||
import { BanConfig } from './IConfig';
|
||||
import pino from 'pino';
|
||||
import { Database } from './Database';
|
||||
import { Address6 } from 'ip-address';
|
||||
import { isIP } from 'net';
|
||||
|
||||
export class BanManager {
|
||||
private cfg: BanConfig;
|
||||
@@ -13,7 +13,7 @@ export class BanManager {
|
||||
constructor(config: BanConfig, db: Database | undefined) {
|
||||
this.cfg = config;
|
||||
this.logger = pino({
|
||||
name: "CVMTS.BanManager"
|
||||
name: 'CVMTS.BanManager'
|
||||
});
|
||||
this.db = db;
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export class BanManager {
|
||||
case 0:
|
||||
default:
|
||||
// Invalid IP
|
||||
throw new Error("Invalid IP address (what the hell did you even do???)");
|
||||
throw new Error('Invalid IP address (what the hell did you even do???)');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export class BanManager {
|
||||
ip = this.formatIP(ip);
|
||||
// If cvmban enabled, write to DB
|
||||
if (this.cfg.cvmban) {
|
||||
if (!this.db) throw new Error("CVMBAN enabled but Database is undefined");
|
||||
if (!this.db) throw new Error('CVMBAN enabled but Database is undefined');
|
||||
await this.db.banIP(ip, username);
|
||||
}
|
||||
// If ban command enabled, run it
|
||||
@@ -77,5 +77,4 @@ export class BanManager {
|
||||
private banCmdArgs(arg: string, ip: string, username: string): string {
|
||||
return arg.replace(/\$IP/g, ip).replace(/\$NAME/g, username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,7 +39,6 @@ type VoteTally = {
|
||||
no: number;
|
||||
};
|
||||
|
||||
|
||||
export default class CollabVMServer {
|
||||
private Config: IConfig;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import pino, { Logger } from "pino";
|
||||
import { MySQLConfig } from "./IConfig";
|
||||
import pino, { Logger } from 'pino';
|
||||
import { MySQLConfig } from './IConfig';
|
||||
import mariadb from 'mariadb';
|
||||
|
||||
export class Database {
|
||||
@@ -9,7 +9,7 @@ export class Database {
|
||||
constructor(config: MySQLConfig) {
|
||||
this.cfg = config;
|
||||
this.logger = pino({
|
||||
name: "CVMTS.Database"
|
||||
name: 'CVMTS.Database'
|
||||
});
|
||||
this.db = mariadb.createPool({
|
||||
host: this.cfg.host,
|
||||
@@ -17,27 +17,29 @@ export class Database {
|
||||
password: this.cfg.password,
|
||||
database: this.cfg.database,
|
||||
connectionLimit: 5,
|
||||
multipleStatements: false,
|
||||
multipleStatements: false
|
||||
});
|
||||
}
|
||||
|
||||
async init() {
|
||||
// Make sure tables exist
|
||||
let conn = await this.db.getConnection();
|
||||
await conn.execute("CREATE TABLE IF NOT EXISTS bans (ip VARCHAR(43) PRIMARY KEY NOT NULL, username VARCHAR(20) NOT NULL, reason TEXT DEFAULT NULL, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
||||
await conn.execute(
|
||||
'CREATE TABLE IF NOT EXISTS bans (ip VARCHAR(43) PRIMARY KEY NOT NULL, username VARCHAR(20) NOT NULL, reason TEXT DEFAULT NULL, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);'
|
||||
);
|
||||
conn.release();
|
||||
this.logger.info("MySQL successfully initialized");
|
||||
this.logger.info('MySQL successfully initialized');
|
||||
}
|
||||
|
||||
async banIP(ip: string, username: string, reason: string | null = null) {
|
||||
let conn = await this.db.getConnection();
|
||||
await conn.execute("INSERT INTO bans (ip, username, reason) VALUES (?, ?, ?);", [ip, username, reason]);
|
||||
await conn.execute('INSERT INTO bans (ip, username, reason) VALUES (?, ?, ?);', [ip, username, reason]);
|
||||
conn.release();
|
||||
}
|
||||
|
||||
async isIPBanned(ip: string): Promise<boolean> {
|
||||
let conn = await this.db.getConnection();
|
||||
let res = (await conn.query('SELECT COUNT(ip) AS cnt FROM bans WHERE ip = ?', [ip]));
|
||||
let res = await conn.query('SELECT COUNT(ip) AS cnt FROM bans WHERE ip = ?', [ip]);
|
||||
conn.release();
|
||||
return res[0]['cnt'] !== 0n;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export default interface IConfig {
|
||||
directory: string;
|
||||
accountID: string;
|
||||
licenseKey: string;
|
||||
}
|
||||
};
|
||||
tcp: {
|
||||
enabled: boolean;
|
||||
host: string;
|
||||
|
||||
@@ -37,7 +37,7 @@ export default class TCPClient extends EventEmitter implements NetworkClient {
|
||||
|
||||
send(msg: string): Promise<void> {
|
||||
return new Promise((res, rej) => {
|
||||
let _msg = new Uint32Array([TextHeader, ...Buffer.from(msg, "utf-8")]);
|
||||
let _msg = new Uint32Array([TextHeader, ...Buffer.from(msg, 'utf-8')]);
|
||||
this.socket.write(Buffer.from(_msg), (err) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class TCPServer extends EventEmitter implements NetworkServer {
|
||||
private async onConnection(socket: Socket) {
|
||||
this.logger.info(`New TCP connection from ${socket.remoteAddress}`);
|
||||
if (await this.banmgr.isIPBanned(socket.remoteAddress!)) {
|
||||
socket.write("6.banned;");
|
||||
socket.write('6.banned;');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export default class WSServer extends EventEmitter implements NetworkServer {
|
||||
}
|
||||
|
||||
if (await this.banmgr.isIPBanned(ip)) {
|
||||
socket.write("HTTP/1.1 403 Forbidden\n\nYou have been banned.");
|
||||
socket.write('HTTP/1.1 403 Forbidden\n\nYou have been banned.');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,11 +56,11 @@ async function start() {
|
||||
let auth = Config.auth.enabled ? new AuthManager(Config.auth.apiEndpoint, Config.auth.secretKey) : null;
|
||||
// Database and ban manager
|
||||
if (Config.bans.cvmban && !Config.mysql.enabled) {
|
||||
logger.error("MySQL must be configured to use cvmban.");
|
||||
logger.error('MySQL must be configured to use cvmban.');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!Config.bans.cvmban && !Config.bans.bancmd) {
|
||||
logger.warn("Neither cvmban nor ban command are configured. Bans will not function.");
|
||||
logger.warn('Neither cvmban nor ban command are configured. Bans will not function.');
|
||||
}
|
||||
let db = undefined;
|
||||
if (Config.mysql.enabled) {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"extends": "../tsconfig.json",
|
||||
"include": ["src/**/*"],
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"name": "cvmts-repo",
|
||||
"workspaces": [
|
||||
"shared",
|
||||
"cvm-rs",
|
||||
"cvmts",
|
||||
"collab-vm-1.2-binary-protocol"
|
||||
@@ -13,7 +12,8 @@
|
||||
"@types/jsbn": "^1.2.33",
|
||||
"@types/node": "^20.14.10",
|
||||
"parcel": "^2.12.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-toml": "^2.0.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.4.4"
|
||||
},
|
||||
@@ -21,6 +21,7 @@
|
||||
"scripts": {
|
||||
"build": "yarn workspaces foreach -Apt run build",
|
||||
"serve": "node cvmts/dist/index.js",
|
||||
"clean": "npx rimraf .parcel-cache .yarn **/node_modules **/dist cvm-rs/target cvm-rs/index.node"
|
||||
"clean": "npx rimraf .parcel-cache .yarn **/node_modules **/dist cvm-rs/target cvm-rs/index.node",
|
||||
"format": "prettier -w config.example.toml && yarn workspaces foreach -Apt run format"
|
||||
}
|
||||
}
|
||||
|
||||
33
yarn.lock
33
yarn.lock
@@ -88,7 +88,6 @@ __metadata:
|
||||
msgpackr: "npm:^1.10.2"
|
||||
pino: "npm:^9.3.1"
|
||||
pino-pretty: "npm:^11.2.1"
|
||||
prettier: "npm:^3.2.5"
|
||||
sharp: "npm:^0.33.3"
|
||||
toml: "npm:^3.0.0"
|
||||
typescript: "npm:^5.4.4"
|
||||
@@ -1466,6 +1465,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@taplo/core@npm:^0.1.0":
|
||||
version: 0.1.1
|
||||
resolution: "@taplo/core@npm:0.1.1"
|
||||
checksum: 10c0/c36f761431b2e959742d8e186e74306fb8991d84589e2f03b6481244cc407275fa448a217ef87b8aa1e226615fd7ba85c60e6f0221f01d891b90dd30b45cb13b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@taplo/lib@npm:^0.4.0-alpha.2":
|
||||
version: 0.4.0-alpha.2
|
||||
resolution: "@taplo/lib@npm:0.4.0-alpha.2"
|
||||
dependencies:
|
||||
"@taplo/core": "npm:^0.1.0"
|
||||
checksum: 10c0/650ed35ba949054eb8dcfbaf77d6154d9639f5d8fa96d89546c399a95e699d7e01f65e308f89478d41e0120baa3572f25595fe088d19e62cc56ad3eb2b5acbb5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@trysound/sax@npm:0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "@trysound/sax@npm:0.2.0"
|
||||
@@ -1966,7 +1981,8 @@ __metadata:
|
||||
"@types/jsbn": "npm:^1.2.33"
|
||||
"@types/node": "npm:^20.14.10"
|
||||
parcel: "npm:^2.12.0"
|
||||
prettier: "npm:^3.2.5"
|
||||
prettier: "npm:^3.3.3"
|
||||
prettier-plugin-toml: "npm:^2.0.1"
|
||||
rimraf: "npm:^6.0.1"
|
||||
typescript: "npm:^5.4.4"
|
||||
languageName: unknown
|
||||
@@ -3504,7 +3520,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^3.2.5":
|
||||
"prettier-plugin-toml@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "prettier-plugin-toml@npm:2.0.1"
|
||||
dependencies:
|
||||
"@taplo/lib": "npm:^0.4.0-alpha.2"
|
||||
peerDependencies:
|
||||
prettier: ^3.0.3
|
||||
checksum: 10c0/8a67133b1a71d82f6fe20fe92e18251ae2930d0fe96d18af8c2333cc8fffce408642b6d6f21441932a97a248815cc82b3f372971eae84aab80cad2f0d78bdc68
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^3.3.3":
|
||||
version: 3.3.3
|
||||
resolution: "prettier@npm:3.3.3"
|
||||
bin:
|
||||
|
||||
Reference in New Issue
Block a user