added defaults to config

This commit is contained in:
Flam3rboy 2021-02-01 21:49:01 +01:00
parent 7c9c9f2ff6
commit 2026ea5911
14 changed files with 124747 additions and 643 deletions

1
.gitignore vendored
View File

@ -104,3 +104,4 @@ dist
.tern-port
.DS_STORE
src/ready.json

963
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,25 +20,29 @@
"dependencies": {
"@types/express": "^4.17.9",
"@types/node-fetch": "^2.5.7",
"bcrypt": "^5.0.0",
"express": "^4.17.1",
"express-cache-middleware": "^1.0.1",
"express-validator": "^6.9.2",
"faker": "^5.1.0",
"i18next": "^19.8.5",
"i18next-http-middleware": "^3.1.0",
"jsonwebtoken": "^8.5.1",
"jwa": "^2.0.0",
"jws": "^4.0.0",
"lambert-db": "^1.1.0",
"lambert-server": "^1.0.8",
"missing-native-js-functions": "^1.1.6",
"lambert-db": "^1.1.3",
"lambert-server": "^1.0.9",
"missing-native-js-functions": "^1.1.9",
"mongoose": "^5.11.14",
"node-fetch": "^2.6.1",
"rethinkdb-ts": "^2.4.5"
},
"devDependencies": {
"@types/bcrypt": "^3.0.0",
"@types/faker": "^5.1.5",
"@types/jsonwebtoken": "^8.5.0",
"@types/jws": "^3.2.3",
"@types/node": "^14.14.22",
"lambert-server": "file:../../Trenite/Lambert-server",
"ts-node": "^9.1.1",
"typescript": "^4.1.2"
}

View File

@ -3,6 +3,9 @@ import { Server, ServerOptions } from "lambert-server";
import { Authentication, GlobalRateLimit } from "./middlewares/";
import Config from "./util/Config";
import db from "./util/Database";
import i18next from "i18next";
import i18nextMiddleware from "i18next-http-middleware";
import { Request } from "express";
export interface DiscordServerOptions extends ServerOptions {}
@ -18,7 +21,7 @@ export class DiscordServer extends Server {
public options: DiscordServerOptions;
constructor(opts?: Partial<DiscordServerOptions>) {
super(opts);
super({ ...opts, errorHandler: false });
}
async start() {
@ -28,11 +31,21 @@ export class DiscordServer extends Server {
this.app.use(GlobalRateLimit);
this.app.use(Authentication);
const namespaces = await fs.readdir(__dirname + "/locales/de/");
const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5));
i18next.use(i18nextMiddleware.LanguageDetector).init({
preload: ["en", "de"],
fallbackLng: "en",
ns,
backend: {
loadPath: "locales/{{lng}}/{{ns}}.json",
},
});
this.app.use(i18nextMiddleware.handle(i18next, {}));
// recursively loads files in routes/
this.routes = await this.registerRoutes(__dirname + "/routes/");
// const indexHTML = await (await fetch("https://discord.com/app")).buffer();
const indexHTML = await fs.readFile(__dirname + "/../client/index.html");
const indexHTML = await fs.readFile(__dirname + "/../client_test/index.html");
this.app.get("*", (req, res) => {
res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);

View File

@ -1,27 +1,5 @@
import fetch from "node-fetch";
fetch("https://discord.com/api/v8/auth/login", {
headers: {
authorization: "undefined",
"content-type": "application/json",
"x-fingerprint": "782364413927751692.ex9RorNkBsGynrJCe5Brxtc3Ytc",
"x-super-properties":
"eyJvcyI6Ik1hYyBPUyBYIiwiYnJvd3NlciI6IkNocm9tZSIsImRldmljZSI6IiIsImJyb3dzZXJfdXNlcl9hZ2VudCI6Ik1vemlsbGEvNS4wIChNYWNpbnRvc2g7IEludGVsIE1hYyBPUyBYIDEwXzE1XzcpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS84Ny4wLjQyODAuNjcgU2FmYXJpLzUzNy4zNiIsImJyb3dzZXJfdmVyc2lvbiI6Ijg3LjAuNDI4MC42NyIsIm9zX3ZlcnNpb24iOiIxMC4xNS43IiwicmVmZXJyZXIiOiIiLCJyZWZlcnJpbmdfZG9tYWluIjoiIiwicmVmZXJyZXJfY3VycmVudCI6IiIsInJlZmVycmluZ19kb21haW5fY3VycmVudCI6IiIsInJlbGVhc2VfY2hhbm5lbCI6InN0YWJsZSIsImNsaWVudF9idWlsZF9udW1iZXIiOjcyMzc2LCJjbGllbnRfZXZlbnRfc291cmNlIjpudWxsfQ==",
},
body: JSON.stringify({
login: "email@gmail.com",
password: "cleartextpassword",
undelete: false,
captcha_key: null,
login_source: null,
gift_code_sku_id: null,
}),
method: "POST",
});
/**
* @returns {"token": null, "mfa": true, "sms": true, "ticket": "WzMxMTEyOTM1NzM2MjEzNTA0MSwibG9naW4iXQ.X8LHqg.vTwtZBaLu5W_XMMSvKad1OAaEoA"}
*/
fetch("https://discord.com/api/v8/auth/mfa/totp", {
headers: {
authorization: "undefined",

View File

@ -0,0 +1,26 @@
import { NextFunction, Request, Response } from "express";
import { HTTPError } from "lambert-server";
import { FieldError } from "../util/instanceOf";
export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) {
let code = 400;
let httpcode = code;
let message = error?.toString();
let errors = undefined;
if (error instanceof HTTPError && error.code) code = httpcode = error.code;
else if (error instanceof FieldError) {
code = Number(error.code);
message = error.message;
errors = error.errors;
} else {
console.error(error);
if (req.server.options.production) {
message = "Internal Server Error";
}
code = httpcode = 500;
}
res.status(httpcode).json({ code: code, message, errors });
return next();
}

View File

@ -7,6 +7,7 @@ import { Snowflake } from "../../../../util/Snowflake";
import "missing-native-js-functions";
import { User } from "../../../../models/User";
import { generateToken } from "./login";
import { trim } from "../../../../util/String";
const router: Router = Router();
router.post(
@ -39,7 +40,7 @@ router.post(
let adjusted_email: string = email;
let adjusted_password: string = password;
let adjusted_username: string = username;
let adjusted_username: string = trim(username);
const { register } = Config.get();
if (!register.allowNewRegistration) {

View File

@ -1,8 +1,13 @@
import jwt from "jsonwebtoken";
// console.log(jwt.sign("test", "test"));
const algorithm = "HS256";
const iat = Math.floor(Date.now() / 1000);
jwt.verify(`${"2WmFS_EAdYFCBOFM9pVPo9g4bpuI2I9U_JGTCfrx7Tk".repeat(1000000)}`, "test", (err, decoded) => {
if (err) console.error(err);
console.log(decoded);
// @ts-ignore
const token = jwt.sign({ id: "311129357362135041" }, "secret", {
algorithm,
});
console.log(token);
const decoded = jwt.verify(token, "secret", { algorithms: [algorithm] });
console.log(decoded);

View File

@ -1,7 +1,7 @@
import mongoose from "mongoose";
async function main() {
const mongoConnection = await mongoose.createConnection(
const conn = await mongoose.createConnection(
"mongodb://localhost:27017/lambert?readPreference=secondaryPreferred",
{
useNewUrlParser: true,
@ -9,6 +9,13 @@ async function main() {
}
);
console.log("connected");
const result = await conn
.collection("users")
.find({ $or: [{ email: "samuel.scheit@gmail.com" }, { phone: "samuel.scheit@gmail.com" }] })
.toArray();
// .project(undefined)
console.log(result);
}
main();

0
src/util/Captcha.ts Normal file
View File

View File

@ -5,9 +5,9 @@ import { ProviderCache } from "lambert-db";
var Config: ProviderCache;
async function init() {
Config = db.data.config.cache();
Config = db.data.config({}).cache();
await Config.init();
await Config.set(DefaultOptions.merge(Config.cache));
await Config.set(DefaultOptions.merge(Config.cache || {}));
}
function get() {

View File

@ -1,73 +1,139 @@
import crypto from "crypto";
import { VerifyOptions } from "jsonwebtoken";
import fs from "fs";
export interface RateLimit {
count: number;
timespan: number;
}
export interface DefaultOptions {
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;
};
server: {
jwtSecret: string;
ipRateLimit: {
enabled: boolean;
count: number;
timespan: number;
limits: {
user: {
maxGuilds: number;
maxUsername: number;
maxFriends: number;
};
forwadedFor: false | string;
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;
};
}
export const DefaultOptions: DefaultOptions = {
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,
},
server: {
jwtSecret: crypto.randomBytes(256).toString("base64"),
ipRateLimit: {
enabled: true,
count: 1000,
timespan: 1000 * 60 * 10,
limits: {
user: {
maxGuilds: 100,
maxUsername: 32,
maxFriends: 1000,
},
forwadedFor: false,
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: efficicently 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,
},
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
aol.com
att.net
comcast.net
facebook.com
gmail.com
gmx.com
googlemail.com
google.com
hotmail.com
hotmail.co.uk
mac.com
me.com
mail.com
msn.com
live.com
sbcglobal.net
verizon.net
yahoo.com
yahoo.co.uk
email.com
fastmail.fm
games.com
gmx.net
hush.com
hushmail.com
icloud.com
iname.com
inbox.com
lavabit.com
love.com
outlook.com
pobox.com
protonmail.ch
protonmail.com
tutanota.de
tutanota.com
tutamail.com
tuta.io
keemail.me
rocketmail.com
safe-mail.net
wow.com
ygm.com
ymail.com
zoho.com
yandex.com
bellsouth.net
charter.net
cox.net
earthlink.net
juno.com
btinternet.com
virginmedia.com
blueyonder.co.uk
freeserve.co.uk
live.co.uk
ntlworld.com
o2.co.uk
orange.net
sky.com
talktalk.co.uk
tiscali.co.uk
virgin.net
wanadoo.co.uk
bt.com
sina.com
sina.cn
qq.com
naver.com
hanmail.net
daum.net
nate.com
yahoo.co.jp
yahoo.co.kr
yahoo.co.id
yahoo.co.in
yahoo.com.sg
yahoo.com.ph
163.com
yeah.net
126.com
21cn.com
aliyun.com
foxmail.com
hotmail.fr
live.fr
laposte.net
yahoo.fr
wanadoo.fr
orange.fr
gmx.fr
sfr.fr
neuf.fr
free.fr
gmx.de
hotmail.de
live.de
online.de
t-online.de
web.de
yahoo.de
libero.it
virgilio.it
hotmail.it
aol.it
tiscali.it
alice.it
live.it
yahoo.it
email.it
tin.it
poste.it
teletu.it
mail.ru
rambler.ru
yandex.ru
ya.ru
list.ru
hotmail.be
live.be
skynet.be
voo.be
tvcablenet.be
telenet.be
hotmail.com.ar
live.com.ar
yahoo.com.ar
fibertel.com.ar
speedy.com.ar
arnet.com.ar
yahoo.com.mx
live.com.mx
hotmail.es
hotmail.com.mx
prodigy.net.mx
yahoo.ca
hotmail.ca
bell.net
shaw.ca
sympatico.ca
rogers.com
yahoo.com.br
hotmail.com.br
outlook.com.br
uol.com.br
bol.com.br
terra.com.br
ig.com.br
itelefonica.com.br
r7.com
zipmail.com.br
globo.com
globomail.com
oi.com.br