summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.prettierignore14
-rw-r--r--assets/locales/en/auth.json3
-rw-r--r--src/api/routes/auth/register.ts21
-rw-r--r--src/util/config/types/LimitConfigurations.ts3
-rw-r--r--src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts10
-rw-r--r--src/util/config/types/subconfigurations/limits/index.ts1
6 files changed, 49 insertions, 3 deletions
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..036ed868
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,14 @@
+.DS_STORE
+db/
+dist/
+node_modules
+tsconfig.tsbuildinfo
+*.log
+*.log.ansi
+bundle/depclean.*
+*.tmp
+tmp/
+assets/cache/
+*.generated
+.yarn/
+yarn.lock
\ No newline at end of file
diff --git a/assets/locales/en/auth.json b/assets/locales/en/auth.json
index b6264a43..2178548e 100644
--- a/assets/locales/en/auth.json
+++ b/assets/locales/en/auth.json
@@ -14,6 +14,7 @@
 		"DATE_OF_BIRTH_UNDERAGE": "You need to be {{years}} years or older",
 		"CONSENT_REQUIRED": "You must agree to the Terms of Service and Privacy Policy.",
 		"USERNAME_TOO_MANY_USERS": "Too many users have this username, please try another",
-		"GUESTS_DISABLED": "Guest users are disabled"
+		"GUESTS_DISABLED": "Guest users are disabled",
+		"TOO_MANY_REGISTRATIONS": "Too many registrations, please try again later"
 	}
 }
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index 5cc28f7a..638b6b79 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -1,6 +1,8 @@
 import { getIpAdress, IPAnalysis, isProxy, route, verifyCaptcha } from "@fosscord/api";
 import { adjustEmail, Config, FieldErrors, generateToken, HTTPError, Invite, RegisterSchema, User } from "@fosscord/util";
 import { Request, Response, Router } from "express";
+import { yellow } from "picocolors";
+import { MoreThan } from "typeorm";
 
 let bcrypt: any;
 try {
@@ -14,7 +16,7 @@ const router: Router = Router();
 
 router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as RegisterSchema;
-	const { register, security } = Config.get();
+	const { register, security, limits } = Config.get();
 	const ip = getIpAdress(req);
 
 	// email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick
@@ -153,6 +155,23 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
 		});
 	}
 
+	if (
+		limits.absoluteRate.register.enabled &&
+		(await await User.count({ where: { created_at: MoreThan(new Date(Date.now() - limits.absoluteRate.register.window)) } })) >=
+			limits.absoluteRate.register.limit
+	) {
+		console.log(
+			yellow(
+				`Global register rate limit exceeded for ${getIpAdress(req)}: ${
+					process.env.LOG_SENSITIVE ? req.body.email : "<email redacted>"
+				}, ${req.body.username}, ${req.body.invite ?? "No invite given"}`
+			)
+		);
+		throw FieldErrors({
+			email: { code: "TOO_MANY_REGISTRATIONS", message: req.t("auth:register.TOO_MANY_REGISTRATIONS") }
+		});
+	}
+
 	const user = await User.register({ ...body, req });
 
 	if (body.invite) {
diff --git a/src/util/config/types/LimitConfigurations.ts b/src/util/config/types/LimitConfigurations.ts
index a3a52cf5..105fd1d6 100644
--- a/src/util/config/types/LimitConfigurations.ts
+++ b/src/util/config/types/LimitConfigurations.ts
@@ -1,4 +1,4 @@
-import { ChannelLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from ".";
+import { ChannelLimits, GlobalRateLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from ".";
 
 export class LimitsConfiguration {
 	user: UserLimits = new UserLimits();
@@ -6,4 +6,5 @@ export class LimitsConfiguration {
 	message: MessageLimits = new MessageLimits();
 	channel: ChannelLimits = new ChannelLimits();
 	rate: RateLimits = new RateLimits();
+	absoluteRate: GlobalRateLimits = new GlobalRateLimits();
 }
diff --git a/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts b/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts
new file mode 100644
index 00000000..85280d3a
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts
@@ -0,0 +1,10 @@
+export class GlobalRateLimits {
+	register: GlobalRateLimit = { limit: 25, window: 60 * 60 * 1000, enabled: true };
+	sendMessage: GlobalRateLimit = { limit: 50, window: 60 * 1000, enabled: true };
+}
+
+export class GlobalRateLimit {
+	limit: number = 100;
+	window: number = 60 * 60 * 1000;
+	enabled: boolean = true;
+}
diff --git a/src/util/config/types/subconfigurations/limits/index.ts b/src/util/config/types/subconfigurations/limits/index.ts
index a4911542..d2d24ccb 100644
--- a/src/util/config/types/subconfigurations/limits/index.ts
+++ b/src/util/config/types/subconfigurations/limits/index.ts
@@ -1,4 +1,5 @@
 export * from "./ChannelLimits";
+export * from "./GlobalRateLimits";
 export * from "./GuildLimits";
 export * from "./MessageLimits";
 export * from "./RateLimits";