From 621131699d79efe393818f67f99fda5ca60b4b54 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Fri, 12 Jul 2024 18:11:55 -0400 Subject: [PATCH] Sanitize channel settings on channel creation --- src/channel/Channel.ts | 48 +++++++++++++++++++++++++++------------- src/channel/forceLoad.ts | 3 ++- src/channel/settings.ts | 30 ++++++++++++++++--------- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/channel/Channel.ts b/src/channel/Channel.ts index 9787827..73c3a62 100644 --- a/src/channel/Channel.ts +++ b/src/channel/Channel.ts @@ -60,20 +60,20 @@ export class Channel extends EventEmitter { ) { super(); - this.settings = {}; - mixin(this.settings, config.defaultSettings); this.logger = new Logger("Channel - " + _id); + this.settings = {}; - // Validate settings in set - // Set the verified settings + // Copy default settings + mixin(this.settings, config.defaultSettings); if (!this.isLobby()) { if (set) { - //this.logger.debug("Passed settings:", set); + // Validate settings in set const validatedSet = validateChannelSettings(set); - //this.logger.debug("Validated settings:", validatedSet); - for (const key of Object.keys(set)) { + // Set the verified settings + for (const key of Object.keys(validatedSet)) { + this.logger.debug(`${key}: ${(validatedSet as any)[key]}`); if ((validatedSet as any)[key] === false) continue; (this.settings as any)[key] = (set as any)[key]; } @@ -95,6 +95,7 @@ export class Channel extends EventEmitter { ChannelList.add(this); // TODO implement owner_id + this.settings.owner_id = owner_id; this.logger.info("Created"); } @@ -382,10 +383,6 @@ export class Channel extends EventEmitter { * @returns undefined */ public join(socket: Socket, force: boolean = false): void { - //! /!\ Players are forced to join the same channel on two different tabs! - //? TODO Should this be a bug or a feature? - //this.logger.debug("join triggered"); - if (this.isDestroyed()) return; const part = socket.getParticipant() as Participant; @@ -400,6 +397,18 @@ export class Channel extends EventEmitter { for (const ch of chs) { const chid = ch.getID(); if (chid == config.fullChannel) { + const banTime = this.getBanTime(socket.getUserID()); + this.logger.debug("Ban time:", banTime); + if (banTime) { + const minutes = Math.floor((banTime.endTime - banTime.startTime) / 1000 / 60); + + socket.sendNotification({ + class: "short", + duration: 7000, + target: "#room", + text: `Currently banned from "${this.getID()}" for ${minutes} minutes.` + }); + } return socket.setChannel(chid) } } @@ -859,10 +868,7 @@ export class Channel extends EventEmitter { uuidsToKick = [...uuidsToKick, ...bannedUUIDs]; - this.logger.debug("Banned UUIDs:", uuidsToKick); - for (const socket of socketsBySocketID.values()) { - this.logger.debug("Checking UUID:", socket.getUUID(), "| Result:", uuidsToKick.indexOf(socket.getUUID()) !== -1); if (uuidsToKick.indexOf(socket.getUUID()) !== -1) { socket.sendNotification({ title: "Notice", @@ -875,7 +881,6 @@ export class Channel extends EventEmitter { // If they are here, move them to the ban channel const ch = socket.getCurrentChannel(); if (ch) { - this.logger.debug("Current channel:", ch.getID(), "| We are:", this.getID()); if (ch.getID() == this.getID()) socket.setChannel(banChannel.getID()); } @@ -1028,6 +1033,19 @@ export class Channel extends EventEmitter { return config.fullChannel; } } + + /** + * Get the amount of time someone is banned in this channel for. + * @param userId User ID + * @returns Object containing endTime and startTime of the ban + **/ + public getBanTime(userId: string) { + for (const ban of this.bans) { + if (userId == ban.userId) { + return { endTime: ban.endTime, startTime: ban.startTime }; + } + } + } } export default Channel; diff --git a/src/channel/forceLoad.ts b/src/channel/forceLoad.ts index 6dcf667..eb35a3a 100644 --- a/src/channel/forceLoad.ts +++ b/src/channel/forceLoad.ts @@ -36,6 +36,7 @@ export function loadDefaultForcedChannels() { } if (!hasFullChannel) { - new Channel(config.fullChannel, undefined, undefined, undefined, true); + //new Channel(config.fullChannel, undefined, undefined, undefined, true); + forceloadChannel(config.fullChannel); } } diff --git a/src/channel/settings.ts b/src/channel/settings.ts index 0dc9f1c..58b2ab8 100644 --- a/src/channel/settings.ts +++ b/src/channel/settings.ts @@ -1,12 +1,11 @@ -import { Logger } from "../util/Logger"; import { IChannelSettings } from "../util/types"; type Validator = "boolean" | "string" | "number" | ((val: unknown) => boolean); -// This record contains the exact data Brandon used to check channel settings, down to the regex. -// It also contains things that might be useful to other people in the future (things that make me vomit) +// This record contains almost the exact code Brandon used to check channel settings, down to the regex. +// It also contains things that might be useful in the future, like MPPNet settings const validationRecord: Record = { - // Brandon + // Brandon's stuff lobby: "boolean", visible: "boolean", chat: "boolean", @@ -21,17 +20,25 @@ const validationRecord: Record = { }, owner_id: "string", - // MPPClone (why?) - limit: "number", + // MPPNet's stuff + limit: val => { + return typeof val === "number" && val <= 99 && val >= 0 + }, noindex: "boolean" }; +// i made this +const adminOnlyKeys = [ + "lobby", + "owner_id" +]; + /** * Check the validity of channel settings * @param set Dirty settings - * @returns Record of which settings are correct + * @returns Record of which settings are correct (true) and which ones aren't (false) */ -export function validateChannelSettings(set: Partial) { +export function validateChannelSettings(set: Partial, admin = false) { // Create record let record: Partial> = {}; @@ -47,6 +54,9 @@ export function validateChannelSettings(set: Partial) { continue; } + // Are we allowed? + if (adminOnlyKeys.indexOf(key) !== -1 && !admin) continue; + // Set valid status record[key as keyof IChannelSettings] = validate(val, validator); } @@ -58,8 +68,8 @@ export default validateChannelSettings; export function validate(value: any, validator: Validator) { // What type of validator? - if (typeof validator == "function") { - // We are copying Zod's functionality + if (typeof validator === "function") { + // Run the function return validator(value) === true; } else if (typeof value === validator) { return true;