summary refs log tree commit diff
path: root/src/util/Config.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/Config.ts')
-rw-r--r--src/util/Config.ts363
1 files changed, 272 insertions, 91 deletions
diff --git a/src/util/Config.ts b/src/util/Config.ts

index f1f0f458..e2e0d312 100644 --- a/src/util/Config.ts +++ b/src/util/Config.ts
@@ -1,19 +1,7 @@ -import { Config, Snowflake } from "@fosscord/server-util"; -import crypto from "crypto"; - -export default { - init() { - return Config.init({ api: DefaultOptions }); - }, - get(): DefaultOptions { - return Config.getAll().api; - }, - set(val: any) { - return Config.setAll({ api: val }); - }, - getAll: Config.getAll, - setAll: Config.setAll, -}; +// @ts-nocheck +import Ajv, { JSONSchemaType } from "ajv"; +import { getConfigPathForFile } from "@fosscord/server-util/dist/util/Config"; +import { Config } from "@fosscord/server-util"; export interface RateLimitOptions { count: number; @@ -21,6 +9,7 @@ export interface RateLimitOptions { } export interface DefaultOptions { + gateway: string; general: { instance_id: string; }; @@ -64,7 +53,7 @@ export interface DefaultOptions { login?: RateLimitOptions; register?: RateLimitOptions; }; - channel?: {}; + channel?: string; // TODO: rate limit configuration for all routes }; }; @@ -84,13 +73,13 @@ export interface DefaultOptions { }; register: { email: { - required: boolean; + necessary: boolean; allowlist: boolean; blocklist: boolean; domains: string[]; }; dateOfBirth: { - required: boolean; + necessary: boolean; minimum: number; // in years }; requireCaptcha: boolean; @@ -107,85 +96,277 @@ export interface DefaultOptions { }; } -export const DefaultOptions: DefaultOptions = { - general: { - instance_id: Snowflake.generate(), - }, - permissions: { - user: { - createGuilds: true, - }, +const schema: JSONSchemaType<DefaultOptions> & { + definitions: { + rateLimitOptions: JSONSchemaType<RateLimitOptions>; + }; +} = { + type: "object", + definitions: { + rateLimitOptions: { + type: "object", + properties: { + count: { type: "number" }, + timespan: { type: "number" } + }, + required: ["count", "timespan"] + } }, - limits: { - user: { - maxGuilds: 100, - maxUsername: 32, - maxFriends: 1000, - }, - guild: { - maxRoles: 250, - maxMembers: 250000, - maxChannels: 500, - maxChannelsInCategory: 50, - hideOfflineMember: 1000, - }, - message: { - characters: 2000, - ttsCharacters: 200, - maxReactions: 20, - maxAttachmentSize: 8388608, - maxBulkDelete: 100, - }, - channel: { - maxPins: 50, - maxTopic: 1024, + properties: { + gateway: { + type: "string" }, - rate: { - ip: { - enabled: true, - count: 1000, - timespan: 1000 * 60 * 10, + general: { + type: "object", + properties: { + instance_id: { + type: "string" + } }, - routes: {}, + required: ["instance_id"], + additionalProperties: false }, - }, - security: { - jwtSecret: crypto.randomBytes(256).toString("base64"), - forwadedFor: null, - // forwadedFor: "X-Forwarded-For" // nginx/reverse proxy - // forwadedFor: "CF-Connecting-IP" // cloudflare: - captcha: { - enabled: false, - service: null, - sitekey: null, - secret: null, + permissions: { + type: "object", + properties: { + user: { + type: "object", + properties: { + createGuilds: { + type: "boolean" + } + }, + required: ["createGuilds"], + additionalProperties: false + } + }, + required: ["user"], + additionalProperties: false }, - }, - login: { - requireCaptcha: false, - }, - register: { - email: { - required: true, - allowlist: false, - blocklist: true, - domains: [], // TODO: efficiently save domain blocklist in database - // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"), + limits: { + type: "object", + properties: { + user: { + type: "object", + properties: { + maxFriends: { + type: "number" + }, + maxGuilds: { + type: "number" + }, + maxUsername: { + type: "number" + } + }, + required: ["maxFriends", "maxGuilds", "maxUsername"], + additionalProperties: false + }, + guild: { + type: "object", + properties: { + maxRoles: { + type: "number" + }, + maxMembers: { + type: "number" + }, + maxChannels: { + type: "number" + }, + maxChannelsInCategory: { + type: "number" + }, + hideOfflineMember: { + type: "number" + } + }, + required: ["maxRoles", "maxMembers", "maxChannels", "maxChannelsInCategory", "hideOfflineMember"], + additionalProperties: false + }, + message: { + type: "object", + properties: { + characters: { + type: "number" + }, + ttsCharacters: { + type: "number" + }, + maxReactions: { + type: "number" + }, + maxAttachmentSize: { + type: "number" + }, + maxBulkDelete: { + type: "number" + } + }, + required: ["characters", "ttsCharacters", "maxReactions", "maxAttachmentSize", "maxBulkDelete"], + additionalProperties: false + }, + channel: { + type: "object", + properties: { + maxPins: { + type: "number" + }, + maxTopic: { + type: "number" + } + }, + required: ["maxPins", "maxTopic"], + additionalProperties: false + }, + rate: { + type: "object", + properties: { + ip: { + type: "object", + properties: { + enabled: { type: "boolean" }, + count: { type: "number" }, + timespan: { type: "number" } + }, + required: ["enabled", "count", "timespan"], + additionalProperties: false + }, + routes: { + type: "object", + properties: { + auth: { + type: "object", + properties: { + login: { $ref: "#/definitions/rateLimitOptions" }, + register: { $ref: "#/definitions/rateLimitOptions" } + }, + nullable: true, + required: [], + additionalProperties: false + }, + channel: { + type: "string", + nullable: true + } + }, + required: [], + additionalProperties: false + } + }, + required: ["ip", "routes"] + } + }, + required: ["channel", "guild", "message", "rate", "user"], + additionalProperties: false }, - dateOfBirth: { - required: true, - minimum: 13, + security: { + type: "object", + properties: { + jwtSecret: { + type: "string" + }, + forwadedFor: { + type: "string", + nullable: true + }, + captcha: { + type: "object", + properties: { + enabled: { type: "boolean" }, + service: { + type: "string", + enum: ["hcaptcha", "recaptcha", null], + nullable: true + }, + sitekey: { + type: "string", + nullable: true + }, + secret: { + type: "string", + nullable: true + } + }, + required: ["enabled", "secret", "service", "sitekey"], + additionalProperties: false + } + }, + required: ["captcha", "forwadedFor", "jwtSecret"], + additionalProperties: false }, - requireInvite: false, - requireCaptcha: true, - allowNewRegistration: true, - allowMultipleAccounts: true, - password: { - minLength: 8, - minNumbers: 2, - minUpperCase: 2, - minSymbols: 0, - blockInsecureCommonPasswords: false, + login: { + type: "object", + properties: { + requireCaptcha: { type: "boolean" } + }, + required: ["requireCaptcha"], + additionalProperties: false }, + register: { + type: "object", + properties: { + email: { + type: "object", + properties: { + necessary: { type: "boolean" }, + allowlist: { type: "boolean" }, + blocklist: { type: "boolean" }, + domains: { + type: "array", + items: { + type: "string" + } + } + }, + required: ["allowlist", "blocklist", "domains", "necessary"], + additionalProperties: false + }, + dateOfBirth: { + type: "object", + properties: { + necessary: { type: "boolean" }, + minimum: { type: "number" } + }, + required: ["minimum", "necessary"], + additionalProperties: false + }, + requireCaptcha: { type: "boolean" }, + requireInvite: { type: "boolean" }, + allowNewRegistration: { type: "boolean" }, + allowMultipleAccounts: { type: "boolean" }, + password: { + type: "object", + properties: { + minLength: { type: "number" }, + minNumbers: { type: "number" }, + minUpperCase: { type: "number" }, + minSymbols: { type: "number" }, + blockInsecureCommonPasswords: { type: "boolean" } + }, + required: ["minLength", "minNumbers", "minUpperCase", "minSymbols", "blockInsecureCommonPasswords"], + additionalProperties: false + } + }, + required: [ + "allowMultipleAccounts", + "allowNewRegistration", + "dateOfBirth", + "email", + "password", + "requireCaptcha", + "requireInvite" + ], + additionalProperties: false + } }, + required: ["gateway", "general", "limits", "login", "permissions", "register", "security"], + additionalProperties: false }; + +const ajv = new Ajv(); +const validator = ajv.compile(schema); + +const configPath = getConfigPathForFile("fosscord", "api", ".json"); + +export const apiConfig = new Config<DefaultOptions>({ path: configPath, schemaValidator: validator, schema: schema });