diff --git a/package-lock.json b/package-lock.json index a4d73267..01e109d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "discord-server-opensource", + "name": "discord-api", "version": "1.0.0", "lockfileVersion": 1, "requires": true, @@ -466,6 +466,14 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "discord-server-util": { + "version": "git+https://github.com/discord-open-source/discord-server-util.git#7e3d6d1d9d53cedd329b59529575d67198826b50", + "from": "git+https://github.com/discord-open-source/discord-server-util.git", + "requires": { + "jsonwebtoken": "^8.5.1", + "lambert-db": "^1.1.4" + } + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", diff --git a/package.json b/package.json index 45ddcf05..d2744980 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "discord-server-opensource", + "name": "discord-api", "version": "1.0.0", "description": "", "main": "index.js", @@ -10,18 +10,19 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Trenite/discord-server-opensource.git" + "url": "git+https://github.com/discord-open-source/discord-api.git" }, "keywords": [], "author": "", "license": "ISC", "bugs": { - "url": "https://github.com/Trenite/discord-server-opensource/issues" + "url": "https://github.com/discord-open-source/discord-api/issues" }, - "homepage": "https://github.com/Trenite/discord-server-opensource#readme", + "homepage": "https://github.com/discord-open-source/discord-api#readme", "dependencies": { "bcrypt": "^5.0.0", "body-parser": "^1.19.0", + "discord-server-util": "git+https://github.com/discord-open-source/discord-server-util.git", "express": "^4.17.1", "express-validator": "^6.9.2", "i18next": "^19.8.5", diff --git a/src/routes/api/v8/auth/login.ts b/src/routes/api/v8/auth/login.ts index 6820c399..9cccbca5 100644 --- a/src/routes/api/v8/auth/login.ts +++ b/src/routes/api/v8/auth/login.ts @@ -1,11 +1,11 @@ import { Request, Response, Router } from "express"; -import db from "../../../../util/Database"; import { check, FieldErrors, Length } from "../../../../util/instanceOf"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import Config from "../../../../util/Config"; import { User } from "../../../../models/User"; import { adjustEmail } from "./register"; +import { db } from "discord-server-util"; const router: Router = Router(); export default router; diff --git a/src/routes/api/v8/auth/register.ts b/src/routes/api/v8/auth/register.ts index 5c163890..b5800d1f 100644 --- a/src/routes/api/v8/auth/register.ts +++ b/src/routes/api/v8/auth/register.ts @@ -1,6 +1,6 @@ import { NextFunction, Request, Response, Router } from "express"; import Config from "../../../../util/Config"; -import db from "../../../../util/Database"; +import { db } from "discord-server-util"; import bcrypt from "bcrypt"; import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../../../util/instanceOf"; import { Snowflake } from "../../../../util/Snowflake"; diff --git a/src/util/Config.ts b/src/util/Config.ts index 4b644e2f..be0f4a3b 100644 --- a/src/util/Config.ts +++ b/src/util/Config.ts @@ -1,25 +1,166 @@ -import "missing-native-js-functions"; -import db from "./Database"; -import { DefaultOptions } from "./Constants"; -import { ProviderCache } from "lambert-db"; -var Config: ProviderCache; - -async function init() { - Config = db.data.config({}).cache(); - await Config.init(); - await Config.set(DefaultOptions.merge(Config.cache || {})); -} - -function get() { - return Config.get(); -} - -function set(val: any) { - return Config.set(val); -} +import { Config } from "discord-server-util"; +import crypto from "crypto"; +import fs from "fs"; export default { - init, - get: get, - set: set, + init() { + return Config.init({ api: DefaultOptions }); + }, + get() { + return Config.getAll().api; + }, + set(val: any) { + return Config.setAll({ api: val }); + }, + getAll: Config.getAll, + setAll: Config.setAll, +}; + +export interface RateLimit { + count: number; + timespan: number; +} + +export interface DefaultOptions { + 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; + }; + channel: { + maxPins: number; + maxTopic: number; + }; + rate: { + ip: { + enabled: boolean; + count: number; + timespan: number; + }; + routes: { + auth?: { + login?: RateLimit; + register?: RateLimit; + }; + channel?: {}; + // TODO: rate limit configuration for all routes + }; + }; + }; + security: { + jwtSecret: string; + forwadedFor: string | null; + captcha: { + enabled: boolean; + service: "recaptcha" | null; // TODO: hcaptcha, custom + sitekey: string | null; + }; + }; + register: { + email: { + required: boolean; + allowlist: boolean; + blocklist: boolean; + domains: string[]; + }; + dateOfBirth: { + required: 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 + }; + }; +} + +export const DefaultOptions: DefaultOptions = { + 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, + }, + channel: { + maxPins: 50, + maxTopic: 1024, + }, + rate: { + ip: { + enabled: true, + count: 1000, + timespan: 1000 * 60 * 10, + }, + routes: {}, + }, + }, + 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, + }, + }, + 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"), + }, + dateOfBirth: { + required: true, + minimum: 13, + }, + requireInvite: false, + requireCaptcha: true, + allowNewRegistration: true, + allowMultipleAccounts: true, + password: { + minLength: 8, + minNumbers: 2, + minUpperCase: 2, + minSymbols: 0, + blockInsecureCommonPasswords: false, + }, + }, }; diff --git a/src/util/Constants.ts b/src/util/Constants.ts index ec508236..1b0e8dbf 100644 --- a/src/util/Constants.ts +++ b/src/util/Constants.ts @@ -1,158 +1,3 @@ -import crypto from "crypto"; -import { VerifyOptions } from "jsonwebtoken"; -import fs from "fs"; - -export interface RateLimit { - count: number; - timespan: number; -} - -export interface DefaultOptions { - 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; - }; - channel: { - maxPins: number; - maxTopic: number; - }; - rate: { - ip: { - enabled: boolean; - count: number; - timespan: number; - }; - routes: { - auth?: { - login?: RateLimit; - register?: RateLimit; - }; - channel?: {}; - // TODO: rate limit configuration for all routes - }; - }; - }; - security: { - jwtSecret: string; - forwadedFor: string | null; - captcha: { - enabled: boolean; - service: "recaptcha" | null; // TODO: hcaptcha, custom - sitekey: string | null; - }; - }; - register: { - email: { - required: boolean; - allowlist: boolean; - blocklist: boolean; - domains: string[]; - }; - dateOfBirth: { - required: 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 - }; - }; -} - -export const DefaultOptions: DefaultOptions = { - 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, - }, - channel: { - maxPins: 50, - maxTopic: 1024, - }, - rate: { - ip: { - enabled: true, - count: 1000, - timespan: 1000 * 60 * 10, - }, - routes: {}, - }, - }, - 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, - }, - }, - 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"), - }, - dateOfBirth: { - required: true, - minimum: 13, - }, - requireInvite: false, - requireCaptcha: true, - allowNewRegistration: true, - allowMultipleAccounts: true, - password: { - minLength: 8, - minNumbers: 2, - minUpperCase: 2, - minSymbols: 0, - blockInsecureCommonPasswords: false, - }, - }, -}; - -export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] }; - export const WSCodes = { 1000: "WS_CLOSE_REQUESTED", 4004: "TOKEN_INVALID", diff --git a/src/util/Database.ts b/src/util/Database.ts deleted file mode 100644 index af18d679..00000000 --- a/src/util/Database.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { MongoDatabase } from "lambert-db"; - -const db = new MongoDatabase("mongodb://127.0.0.1:27017/lambert?readPreference=secondaryPreferred"); - -export default db;