From 202cc248119fc369a43fb6e1a91c8023dc69041e Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Thu, 12 Aug 2021 18:57:25 +0200 Subject: [PATCH] :sparkles: rate limit now configurable in the config --- src/Server.ts | 8 ++------ src/middlewares/RateLimit.ts | 32 +++++++++++++++++++++++++++++--- src/routes/auth/login.ts | 1 - src/routes/auth/register.ts | 1 - 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/Server.ts b/src/Server.ts index 3e20695a..7299425a 100644 --- a/src/Server.ts +++ b/src/Server.ts @@ -12,7 +12,7 @@ import { BodyParser } from "./middlewares/BodyParser"; import express, { Router, Request, Response } from "express"; import mongoose from "mongoose"; import path from "path"; -import RateLimit from "./middlewares/RateLimit"; +import { initRateLimits } from "./middlewares/RateLimit"; import TestClient from "./middlewares/TestClient"; // this will return the new updated document for findOneAndUpdate @@ -86,12 +86,8 @@ export class FosscordServer extends Server { const api = Router(); // @ts-ignore this.app = api; - api.use(RateLimit({ bucket: "global", count: 10, window: 5, bot: 250 })); - api.use(RateLimit({ bucket: "error", count: 5, error: true, window: 5, bot: 15, onlyIp: true })); - api.use("/guilds/:id", RateLimit({ count: 5, window: 5 })); - api.use("/webhooks/:id", RateLimit({ count: 5, window: 5 })); - api.use("/channels/:id", RateLimit({ count: 5, window: 5 })); + initRateLimits(api); this.routes = await this.registerRoutes(path.join(__dirname, "routes", "/")); app.use("/api/v8", api); app.use("/api/v9", api); diff --git a/src/middlewares/RateLimit.ts b/src/middlewares/RateLimit.ts index 0858744a..c8fdeba2 100644 --- a/src/middlewares/RateLimit.ts +++ b/src/middlewares/RateLimit.ts @@ -1,5 +1,5 @@ -import { db, MongooseCache, Bucket } from "@fosscord/server-util"; -import { IRouterHandler, NextFunction, Request, Response } from "express"; +import { db, MongooseCache, Bucket, Config } from "@fosscord/server-util"; +import { NextFunction, Request, Response, Router } from "express"; import { getIpAdress } from "../util/ipAddress"; import { API_PREFIX_TRAILING_SLASH } from "./Authentication"; @@ -65,7 +65,7 @@ export default function RateLimit(opts: { const global = bucket_id === "global"; if (resetAfterMs > 0) { - console.log("blocked", { resetAfterMs }); + console.log("blocked bucket: " + bucket_id, { resetAfterMs }); return ( res .status(429) @@ -105,6 +105,32 @@ export default function RateLimit(opts: { }; } +export function initRateLimits(app: Router) { + const { routes, global, ip, error } = Config.get().limits.rate; + + app.use( + RateLimit({ + bucket: "global", + onlyIp: true, + ...ip + }) + ); + app.use(RateLimit({ bucket: "global", ...global })); + app.use( + RateLimit({ + bucket: "error", + error: true, + onlyIp: true, + ...error + }) + ); + app.use("/guilds/:id", RateLimit(routes.guild)); + app.use("/webhooks/:id", RateLimit(routes.webhook)); + app.use("/channels/:id", RateLimit(routes.channel)); + app.use("/auth/login", RateLimit(routes.auth.login)); + app.use("/auth/register", RateLimit({ onlyIp: true, success: true, ...routes.auth.register })); +} + function hitRoute(opts: { user_id: string; bucket_id: string; max_hits: number; window: number }) { return db.collection("ratelimits").updateOne( { id: opts.bucket_id, user_id: opts.user_id }, diff --git a/src/routes/auth/login.ts b/src/routes/auth/login.ts index 6c4e5e3e..c3661608 100644 --- a/src/routes/auth/login.ts +++ b/src/routes/auth/login.ts @@ -13,7 +13,6 @@ export default router; router.post( "/", - RateLimit({ count: 5, window: 60, onlyIp: true }), check({ login: new Length(String, 2, 100), // email or telephone password: new Length(String, 8, 72), diff --git a/src/routes/auth/register.ts b/src/routes/auth/register.ts index 0dd92e16..66a1fc8d 100644 --- a/src/routes/auth/register.ts +++ b/src/routes/auth/register.ts @@ -12,7 +12,6 @@ const router: Router = Router(); router.post( "/", - RateLimit({ count: 2, window: 60 * 60 * 12, onlyIp: true, success: true }), check({ username: new Length(String, 2, 32), // TODO: check min password length in config