diff options
author | Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> | 2021-08-12 20:09:35 +0200 |
---|---|---|
committer | Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> | 2021-08-12 20:09:35 +0200 |
commit | 524b5df7231635682053d0c028b0a24189b875ab (patch) | |
tree | 38bdb481e6149a825170cb67cb961410de92efdd /api/src/util/Config.ts | |
parent | npm i @fosscord/server-util@1.3.52 (diff) | |
download | server-524b5df7231635682053d0c028b0a24189b875ab.tar.xz |
:sparkles: api
Diffstat (limited to 'api/src/util/Config.ts')
-rw-r--r-- | api/src/util/Config.ts | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/api/src/util/Config.ts b/api/src/util/Config.ts new file mode 100644 index 00000000..e2e0d312 --- /dev/null +++ b/api/src/util/Config.ts @@ -0,0 +1,372 @@ +// @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; + timespan: number; +} + +export interface DefaultOptions { + gateway: string; + general: { + instance_id: string; + }; + permissions: { + user: { + createGuilds: boolean; + }; + }; + limits: { + user: { + maxGuilds: number; + maxUsername: number; + maxFriends: number; + }; + guild: { + maxRoles: number; + maxMembers: number; + maxChannels: number; + maxChannelsInCategory: number; + hideOfflineMember: number; + }; + message: { + characters: number; + ttsCharacters: number; + maxReactions: number; + maxAttachmentSize: number; + maxBulkDelete: number; + }; + channel: { + maxPins: number; + maxTopic: number; + }; + rate: { + ip: { + enabled: boolean; + count: number; + timespan: number; + }; + routes: { + auth?: { + login?: RateLimitOptions; + register?: RateLimitOptions; + }; + channel?: string; + // TODO: rate limit configuration for all routes + }; + }; + }; + security: { + jwtSecret: string; + forwadedFor: string | null; + captcha: { + enabled: boolean; + service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom + sitekey: string | null; + secret: string | null; + }; + }; + login: { + requireCaptcha: boolean; + }; + register: { + email: { + necessary: boolean; + allowlist: boolean; + blocklist: boolean; + domains: string[]; + }; + dateOfBirth: { + necessary: boolean; + minimum: number; // in years + }; + requireCaptcha: boolean; + requireInvite: boolean; + allowNewRegistration: boolean; + allowMultipleAccounts: boolean; + password: { + minLength: number; + minNumbers: number; + minUpperCase: number; + minSymbols: number; + blockInsecureCommonPasswords: boolean; // TODO: efficiently save password blocklist in database + }; + }; +} + +const schema: JSONSchemaType<DefaultOptions> & { + definitions: { + rateLimitOptions: JSONSchemaType<RateLimitOptions>; + }; +} = { + type: "object", + definitions: { + rateLimitOptions: { + type: "object", + properties: { + count: { type: "number" }, + timespan: { type: "number" } + }, + required: ["count", "timespan"] + } + }, + properties: { + gateway: { + type: "string" + }, + general: { + type: "object", + properties: { + instance_id: { + type: "string" + } + }, + required: ["instance_id"], + additionalProperties: false + }, + permissions: { + type: "object", + properties: { + user: { + type: "object", + properties: { + createGuilds: { + type: "boolean" + } + }, + required: ["createGuilds"], + additionalProperties: false + } + }, + required: ["user"], + additionalProperties: false + }, + 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 + }, + 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 + }, + 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 }); |