Prettier u10

This commit is contained in:
Rory& committed 2025-12-17 09:27:18 +01:00
1 parent 5a3c1a3f53
commit c323e55290
5 files changed
+52 -149

No files matched your search

+10 -30
View File
@@ -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") || "";
+4 -11
View File
@@ -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);
+6 -13
View File
@@ -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) => {
+2 -11
View File
@@ -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;
+30 -84
View File
@@ -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;
};