summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-12-17 09:27:18 +0100
committerRory& <root@rory.gay>2025-12-17 09:27:18 +0100
commitc323e5529031a6b7014dd9525a933a1109edb3a6 (patch)
tree79a55e5e4bab2a923176c7379d41d40df462db7f
parentPrettier u9 (diff)
downloadserver-ts-c323e5529031a6b7014dd9525a933a1109edb3a6.tar.xz
Prettier u10
-rw-r--r--src/gateway/events/Connection.ts40
-rw-r--r--src/gateway/events/Message.ts15
-rw-r--r--src/gateway/util/Send.ts19
-rw-r--r--src/gateway/util/Utils.ts13
-rw-r--r--src/util/Signing.ts114
5 files changed, 52 insertions, 149 deletions
diff --git a/src/gateway/events/Connection.ts b/src/gateway/events/Connection.ts

index 7ad37176..37e2ebac 100644 --- a/src/gateway/events/Connection.ts +++ b/src/gateway/events/Connection.ts
@@ -42,37 +42,22 @@ try { // TODO: specify rate limit in config // TODO: check msg max size -export async function Connection( - this: WS.Server, - socket: WebSocket, - request: IncomingMessage, -) { +export async function Connection(this: WS.Server, socket: WebSocket, request: IncomingMessage) { const forwardedFor = Config.get().security.forwardedFor; - const ipAddress = forwardedFor - ? (request.headers[forwardedFor.toLowerCase()] as string) - : request.socket.remoteAddress; + const ipAddress = forwardedFor ? (request.headers[forwardedFor.toLowerCase()] as string) : request.socket.remoteAddress; socket.ipAddress = ipAddress; socket.userAgent = request.headers["user-agent"] as string; if (!ipAddress && Config.get().security.cdnSignatureIncludeIp) { - return socket.close( - CLOSECODES.Decode_error, - "Gateway connection rejected: IP address is required.", - ); + return socket.close(CLOSECODES.Decode_error, "Gateway connection rejected: IP address is required."); } - if ( - !socket.userAgent && - Config.get().security.cdnSignatureIncludeUserAgent - ) { - return socket.close( - CLOSECODES.Decode_error, - "Gateway connection rejected: User-Agent header is required.", - ); + if (!socket.userAgent && Config.get().security.cdnSignatureIncludeUserAgent) { + return socket.close(CLOSECODES.Decode_error, "Gateway connection rejected: User-Agent header is required."); } - if (request.headers.cookie?.split("; ").find(x => x.startsWith("__sb_sessid="))) { + if (request.headers.cookie?.split("; ").find((x) => x.startsWith("__sb_sessid="))) { socket.fingerprint = request.headers.cookie .split("; ") .find((x) => x.startsWith("__sb_sessid=")) @@ -91,9 +76,7 @@ export async function Connection( socket.on("error", (err) => console.error("[Gateway]", err)); - console.log( - `[Gateway] New connection from ${ipAddress}, total ${this.clients.size}`, - ); + console.log(`[Gateway] New connection from ${ipAddress}, total ${this.clients.size}`); if (process.env.WS_LOGEVENTS) [ @@ -112,15 +95,12 @@ export async function Connection( const { searchParams } = new URL(`http://localhost${request.url}`); // @ts-ignore socket.encoding = searchParams.get("encoding") || "json"; - if (!["json", "etf"].includes(socket.encoding)) - return socket.close(CLOSECODES.Decode_error); + if (!["json", "etf"].includes(socket.encoding)) return socket.close(CLOSECODES.Decode_error); - if (socket.encoding === "etf" && !erlpack) - throw new Error("Erlpack is not installed: 'npm i @yukikaze-bot/erlpack'"); + if (socket.encoding === "etf" && !erlpack) throw new Error("Erlpack is not installed: 'npm i @yukikaze-bot/erlpack'"); socket.version = Number(searchParams.get("version")) || 8; - if (socket.version != 8) - return socket.close(CLOSECODES.Invalid_API_version); + if (socket.version != 8) return socket.close(CLOSECODES.Invalid_API_version); // @ts-ignore socket.compress = searchParams.get("compress") || ""; diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts
index 2987f464..dbdad935 100644 --- a/src/gateway/events/Message.ts +++ b/src/gateway/events/Message.ts
@@ -24,7 +24,7 @@ import path from "path"; import WS from "ws"; import OPCodeHandlers from "../opcodes"; import { check } from "../opcodes/instanceOf"; -import { PayloadSchema } from "@spacebar/schemas" +import { PayloadSchema } from "@spacebar/schemas"; const bigIntJson = BigIntJson({ storeAsString: true }); @@ -67,22 +67,15 @@ export async function Message(this: WebSocket, buffer: WS.Data) { } } else return this.close(CLOSECODES.Decode_error); - if (process.env.WS_VERBOSE) - console.log(`[Websocket] Incomming message: ${JSON.stringify(data)}`); + if (process.env.WS_VERBOSE) console.log(`[Websocket] Incomming message: ${JSON.stringify(data)}`); if (process.env.WS_DUMP) { const id = this.session_id || "unknown"; await fs.mkdir(path.join("dump", id), { recursive: true }); - await fs.writeFile( - path.join("dump", id, `${Date.now()}.in.json`), - JSON.stringify(data, null, 2), - ); + await fs.writeFile(path.join("dump", id, `${Date.now()}.in.json`), JSON.stringify(data, null, 2)); - if (!this.session_id) - console.log( - "[Gateway] Unknown session id, dumping to unknown folder", - ); + if (!this.session_id) console.log("[Gateway] Unknown session id, dumping to unknown folder"); } check.call(this, PayloadSchema, data); diff --git a/src/gateway/util/Send.ts b/src/gateway/util/Send.ts
index cee3aa8c..90c1f942 100644 --- a/src/gateway/util/Send.ts +++ b/src/gateway/util/Send.ts
@@ -37,15 +37,13 @@ const recurseJsonReplace = (json: any) => { json[key] = JSONReplacer.call(json, key, json[key]); - if (typeof json[key] == "object" && json[key] !== null) - json[key] = recurseJsonReplace(json[key]); + if (typeof json[key] == "object" && json[key] !== null) json[key] = recurseJsonReplace(json[key]); } return json; }; export async function Send(socket: WebSocket, data: Payload) { - if (process.env.WS_VERBOSE) - console.log(`[Websocket] Outgoing message: ${JSON.stringify(data)}`); + if (process.env.WS_VERBOSE) console.log(`[Websocket] Outgoing message: ${JSON.stringify(data)}`); if (process.env.WS_DUMP) { const id = socket.session_id || "unknown"; @@ -53,10 +51,7 @@ export async function Send(socket: WebSocket, data: Payload) { await fs.mkdir(path.join("dump", id), { recursive: true, }); - await fs.writeFile( - path.join("dump", id, `${Date.now()}.out.json`), - JSON.stringify(data, null, 2), - ); + await fs.writeFile(path.join("dump", id, `${Date.now()}.out.json`), JSON.stringify(data, null, 2)); } let buffer: Buffer | string; @@ -66,18 +61,16 @@ export async function Send(socket: WebSocket, data: Payload) { buffer = erlpack.pack(data); } // TODO: encode circular object - else if (socket.encoding === "json") - buffer = JSON.stringify(data, JSONReplacer); + else if (socket.encoding === "json") buffer = JSON.stringify(data, JSONReplacer); else return; // TODO: compression if (socket.compress === "zlib-stream") { buffer = socket.deflate!.process(buffer) as Buffer; } else if (socket.compress === "zstd-stream") { - if (typeof(buffer) === "string") - buffer = Buffer.from(buffer as string); + if (typeof buffer === "string") buffer = Buffer.from(buffer as string); - buffer = await socket.zstdEncoder!.encode(buffer as Buffer) as Buffer; + buffer = (await socket.zstdEncoder!.encode(buffer as Buffer)) as Buffer; } return new Promise((res, rej) => { diff --git a/src/gateway/util/Utils.ts b/src/gateway/util/Utils.ts
index 54cfaf3d..614b074b 100644 --- a/src/gateway/util/Utils.ts +++ b/src/gateway/util/Utils.ts
@@ -14,11 +14,7 @@ export function parseStreamKey(streamKey: string): { throw new Error(`Invalid stream key type: ${type}`); } - if ( - (type === "guild" && streamKeyArray.length < 3) || - (type === "call" && streamKeyArray.length < 2) - ) - throw new Error(`Invalid stream key: ${streamKey}`); // invalid stream key + if ((type === "guild" && streamKeyArray.length < 3) || (type === "call" && streamKeyArray.length < 2)) throw new Error(`Invalid stream key: ${streamKey}`); // invalid stream key let guildId: string | undefined; if (type === "guild") { @@ -33,12 +29,7 @@ export function parseStreamKey(streamKey: string): { return { type, channelId, guildId, userId }; } -export function generateStreamKey( - type: "guild" | "call", - guildId: string | undefined, - channelId: string, - userId: string, -): string { +export function generateStreamKey(type: "guild" | "call", guildId: string | undefined, channelId: string, userId: string): string { const streamKey = `${type}${type === "guild" ? `:${guildId}` : ""}:${channelId}:${userId}`; return streamKey; diff --git a/src/util/Signing.ts b/src/util/Signing.ts
index 651c3372..17f5d648 100644 --- a/src/util/Signing.ts +++ b/src/util/Signing.ts
@@ -40,26 +40,17 @@ export class NewUrlSignatureData extends NewUrlUserSignatureData { this.path = data.path; this.url = data.url; if (!this.path && !this.url) { - throw new Error( - "Either path or url must be provided for URL signing", - ); + throw new Error("Either path or url must be provided for URL signing"); } if (this.path && this.url) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.warn( - "[Signing] Both path and url are provided, using path for signing", - this, - new Error().stack, - ); + if (process.env["LOG_CDN_SIGNATURES"]) console.warn("[Signing] Both path and url are provided, using path for signing", this, new Error().stack); } if (this.url) { try { const parsedUrl = new URL(this.url); this.path = parsedUrl.pathname; } catch (e) { - throw new Error( - "Invalid URL provided for signing: " + this.url, - ); + throw new Error("Invalid URL provided for signing: " + this.url); } } } @@ -101,15 +92,10 @@ export class UrlSignResult { static fromUrl(url: URL | string): UrlSignResult { if (typeof url === "string") { - if (process.env["LOG_CDN_SIGNATURES"]) - console.debug("[Signing] Parsing URL from string:", url); + if (process.env["LOG_CDN_SIGNATURES"]) console.debug("[Signing] Parsing URL from string:", url); url = new URL(url); } - if (process.env["LOG_CDN_SIGNATURES"]) - console.debug( - "[Signing] Parsing URL from URL object:", - url.toString(), - ); + if (process.env["LOG_CDN_SIGNATURES"]) console.debug("[Signing] Parsing URL from URL object:", url.toString()); const ex = url.searchParams.get("ex"); const is = url.searchParams.get("is"); const hm = url.searchParams.get("hm"); @@ -133,9 +119,7 @@ export const getUrlSignature = (data: NewUrlSignatureData): UrlSignResult => { // calculate the expiration time const now = Date.now(); const issuedAt = now.toString(16); - const expiresAt = (now + ms(cdnSignatureDuration as StringValue)).toString( - 16, - ); + const expiresAt = (now + ms(cdnSignatureDuration as StringValue)).toString(16); // hash the url with the cdnSignatureKey return calculateHash( @@ -160,11 +144,7 @@ function calculateHash(request: UrlSignatureData): UrlSignResult { "[Signing] CDN Signature IP is enabled but we couldn't find the IP field in the request. This may cause issues with signature validation. Please report this to the Spacebar team!", ); else { - if (process.env["LOG_CDN_SIGNATURES"]) - console.log( - "[Signing] CDN Signature IP is enabled, adding IP to hash:", - request.ip, - ); + if (process.env["LOG_CDN_SIGNATURES"]) console.log("[Signing] CDN Signature IP is enabled, adding IP to hash:", request.ip); data.update(request.ip!); } } @@ -175,11 +155,7 @@ function calculateHash(request: UrlSignatureData): UrlSignResult { "[Signing] CDN Signature User-Agent is enabled but we couldn't find the user-agent header in the request. This may cause issues with signature validation. Please report this to the Spacebar team!", ); else { - if (process.env["LOG_CDN_SIGNATURES"]) - console.log( - "[Signing] CDN Signature User-Agent is enabled, adding User-Agent to hash:", - request.userAgent, - ); + if (process.env["LOG_CDN_SIGNATURES"]) console.log("[Signing] CDN Signature User-Agent is enabled, adding User-Agent to hash:", request.userAgent); data.update(request.userAgent!); } } @@ -197,12 +173,8 @@ function calculateHash(request: UrlSignatureData): UrlSignResult { { path: request.path, validity: request.issuedAt + " .. " + request.expiresAt, - ua: Config.get().security.cdnSignatureIncludeUserAgent - ? request.userAgent - : "[disabled]", - ip: Config.get().security.cdnSignatureIncludeIp - ? request.ip - : "[disabled]", + ua: Config.get().security.cdnSignatureIncludeUserAgent ? request.userAgent : "[disabled]", + ip: Config.get().security.cdnSignatureIncludeIp ? request.ip : "[disabled]", }, "->", result, @@ -216,8 +188,7 @@ export const isExpired = (data: UrlSignResult | UrlSignatureData) => { const expiresAt = parseInt(data.expiresAt, 16); if (Number.isNaN(issuedAt) || Number.isNaN(expiresAt)) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.debug("[Signing] Invalid timestamps in query"); + if (process.env["LOG_CDN_SIGNATURES"]) console.debug("[Signing] Invalid timestamps in query"); return true; } @@ -225,38 +196,29 @@ export const isExpired = (data: UrlSignResult | UrlSignatureData) => { const isExpired = expiresAt < currentTime; if (isExpired) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.debug("[Signing] Signature expired"); + if (process.env["LOG_CDN_SIGNATURES"]) console.debug("[Signing] Signature expired"); return true; } const isValidIssuedAt = issuedAt < currentTime; if (!isValidIssuedAt) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.debug("[Signing] Signature issued in the future"); + if (process.env["LOG_CDN_SIGNATURES"]) console.debug("[Signing] Signature issued in the future"); return true; } return false; }; -export const hasValidSignature = ( - req: NewUrlUserSignatureData, - sig: UrlSignResult, -) => { +export const hasValidSignature = (req: NewUrlUserSignatureData, sig: UrlSignResult) => { // if the required query parameters are not present, return false if (!sig.expiresAt || !sig.issuedAt || !sig.hash) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.warn( - "[Signing] Missing required query parameters for signature validation", - ); + if (process.env["LOG_CDN_SIGNATURES"]) console.warn("[Signing] Missing required query parameters for signature validation"); return false; } // check if the signature is expired if (isExpired(sig)) { - if (process.env["LOG_CDN_SIGNATURES"]) - console.warn("[Signing] Signature is expired"); + if (process.env["LOG_CDN_SIGNATURES"]) console.warn("[Signing] Signature is expired"); return false; } @@ -273,42 +235,26 @@ export const hasValidSignature = ( const calculated = Buffer.from(calcd); const received = Buffer.from(sig.hash as string); - console.assert( - sig.issuedAt == calcResult.issuedAt, - "[Signing] Mismatched issuedAt", - { - is: sig.issuedAt, - calculated: calcResult.issuedAt, - }, - ); + console.assert(sig.issuedAt == calcResult.issuedAt, "[Signing] Mismatched issuedAt", { + is: sig.issuedAt, + calculated: calcResult.issuedAt, + }); - console.assert( - sig.expiresAt == calcResult.expiresAt, - "[Signing] Mismatched expiresAt", - { - ex: sig.expiresAt, - calculated: calcResult.expiresAt, - }, - ); + console.assert(sig.expiresAt == calcResult.expiresAt, "[Signing] Mismatched expiresAt", { + ex: sig.expiresAt, + calculated: calcResult.expiresAt, + }); - console.assert( - calculated.length === received.length, - "[Signing] Mismatched hash length", - { - calculated: calculated.length, - received: received.length, - }, - ); + console.assert(calculated.length === received.length, "[Signing] Mismatched hash length", { + calculated: calculated.length, + received: received.length, + }); - const isHashValid = - calculated.length === received.length && - timingSafeEqual(calculated, received); + const isHashValid = calculated.length === received.length && timingSafeEqual(calculated, received); if (!isHashValid) if (process.env["LOG_CDN_SIGNATURES"]) - console.warn( - `Signature validation for ${sig.path} (is=${sig.issuedAt}, ex=${sig.expiresAt}) failed: calculated: ${calcd}, received: ${sig.hash}`, - ); + console.warn(`Signature validation for ${sig.path} (is=${sig.issuedAt}, ex=${sig.expiresAt}) failed: calculated: ${calcd}, received: ${sig.hash}`); return isHashValid; };