diff --git a/package-lock.json b/package-lock.json index c9428dd1..b7bb7da6 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/package.json b/package.json index e98a04d3..78fd3939 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "author": "Fosscord", "license": "ISC", "dependencies": { - "@fosscord/server-util": "^1.2.6", + "@fosscord/server-util": "^1.3.1", + "ajv": "^8.5.0", "dotenv": "^8.2.0", "jsonwebtoken": "^8.5.1", "lambert-server": "^1.1.7", diff --git a/src/Server.ts b/src/Server.ts index 46ff56a3..46130b29 100644 --- a/src/Server.ts +++ b/src/Server.ts @@ -4,7 +4,6 @@ dotenv.config(); import { db } from "@fosscord/server-util"; import { Server as WebSocketServer } from "ws"; import { Connection } from "./events/Connection"; -import Config from "./util/Config"; // TODO: only listen/start the server if everything got initalized // https://www.npmjs.com/package/ws use "External HTTP/S server" and listen manually at the end of listen() @@ -38,7 +37,6 @@ export class Server { await (db as Promise); await this.setupSchema(); console.log("[DB] connected"); - await Config.init(); console.log(`[Gateway] online on 0.0.0.0:${port}`); } } diff --git a/src/events/Message.ts b/src/events/Message.ts index 2c3305cb..51c5a294 100644 --- a/src/events/Message.ts +++ b/src/events/Message.ts @@ -21,6 +21,7 @@ export async function Message(this: WebSocket, buffer: Data) { if (this.encoding === "etf" && buffer instanceof Buffer) data = erlpack.unpack(buffer); else if (this.encoding === "json" && typeof buffer === "string") data = JSON.parse(buffer); + else return; check.call(this, PayloadSchema, data); diff --git a/src/listener/listener.ts b/src/listener/listener.ts index 8183f70c..b8ee84fd 100644 --- a/src/listener/listener.ts +++ b/src/listener/listener.ts @@ -19,7 +19,7 @@ export interface DispatchOpts { function getPipeline(this: WebSocket, guilds: string[], channels: string[] = []) { if (this.shard_count) { - guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count === this.shard_id); + guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count! === this.shard_id); } return [ @@ -37,7 +37,7 @@ function getPipeline(this: WebSocket, guilds: string[], channels: string[] = []) export async function setupListener(this: WebSocket) { const user = await UserModel.findOne({ id: this.user_id }).lean().exec(); - var guilds = user.guilds; + var guilds = user!.guilds; const eventStream = new MongooseCache(db.collection("events"), getPipeline.call(this, guilds), { onlyEvents: true, @@ -60,7 +60,7 @@ export async function dispatch(this: WebSocket, document: Event, { eventStream, guilds.push(document.data.id); eventStream.changeStream(getPipeline.call(this, guilds)); } else if (document.event === "GUILD_DELETE") { - guilds.remove(document.guild_id); + guilds.remove(document.guild_id!); eventStream.changeStream(getPipeline.call(this, guilds)); } else if (document.event === "CHANNEL_DELETE") channel_id = null; if (document.guild_id && !this.intents.has("GUILDS")) return; diff --git a/src/opcodes/Identify.ts b/src/opcodes/Identify.ts index f31eebfe..0781afde 100644 --- a/src/opcodes/Identify.ts +++ b/src/opcodes/Identify.ts @@ -17,6 +17,7 @@ import { IdentifySchema } from "../schema/Identify"; import { Send } from "../util/Send"; import experiments from "./experiments.json"; import { check } from "./instanceOf"; +import * as Config from "../util/Config"; // TODO: bot sharding // TODO: check priviliged intents @@ -29,7 +30,8 @@ export async function onIdentify(this: WebSocket, data: Payload) { const identify: IdentifySchema = data.d; try { - var decoded = await checkToken(identify.token); // will throw an error if invalid + const { jwtSecret } = Config.gatewayConfig.getAll().security; + var decoded = await checkToken(identify.token, jwtSecret); // will throw an error if invalid } catch (error) { console.error("invalid token", error); return this.close(CLOSECODES.Authentication_failed); diff --git a/src/util/Config.ts b/src/util/Config.ts index eee20e1d..8489888c 100644 --- a/src/util/Config.ts +++ b/src/util/Config.ts @@ -1,21 +1,36 @@ import { Config } from "@fosscord/server-util"; - -export default { - init() { - return Config.init({ gateway: DefaultOptions }); - }, - get() { - return Config.getAll().gateway; - }, - set(val: any) { - return Config.setAll({ gateway: val }); - }, - getAll: Config.getAll, - setAll: Config.setAll, -}; +import { getConfigPathForFile } from "@fosscord/server-util/dist/util/Config"; +import Ajv, { JSONSchemaType } from "ajv"; export interface DefaultOptions { endpoint?: string; + security: { + jwtSecret: string; + } } -export const DefaultOptions: DefaultOptions = {}; +const schema: JSONSchemaType = { + type: "object", + properties: { + endpoint: { + type: "string", + nullable: true + }, + security: { + type: "object", + properties: { + jwtSecret: { + type: "string" + } + }, + required: ["jwtSecret"] + }, + }, + required: ["security"] +} + +const ajv = new Ajv(); +const validator = ajv.compile(schema); + +const configPath = getConfigPathForFile("fosscord", "gateway", ".json"); +export const gatewayConfig = new Config({path: configPath, schemaValidator: validator, schema: schema}) \ No newline at end of file diff --git a/src/util/Send.ts b/src/util/Send.ts index 09e947a5..be25ac4f 100644 --- a/src/util/Send.ts +++ b/src/util/Send.ts @@ -11,7 +11,7 @@ export async function Send(socket: WebSocket, data: Payload) { if (socket.encoding === "etf") buffer = erlpack.pack(data); // TODO: encode circular object else if (socket.encoding === "json") buffer = JSON.stringify(data); - + else return; // TODO: compression if (socket.deflate) { socket.deflate.write(buffer); diff --git a/tsconfig.json b/tsconfig.json index 279cbbf1..fd2c21ea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,7 +29,7 @@ /* Strict Type-Checking Options */ "strict": false /* Enable all strict type-checking options. */, "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, - // "strictNullChecks": true, /* Enable strict null checks. */ + "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,