diff options
-rw-r--r-- | .prettierignore | 14 | ||||
-rw-r--r-- | assets/locales/en/auth.json | 3 | ||||
-rw-r--r-- | src/api/routes/auth/register.ts | 21 | ||||
-rw-r--r-- | src/util/config/types/LimitConfigurations.ts | 3 | ||||
-rw-r--r-- | src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts | 10 | ||||
-rw-r--r-- | src/util/config/types/subconfigurations/limits/index.ts | 1 |
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"; |