feat: rate limiting — login 10req/15min, admin 50req/min, trust proxy
This commit is contained in:
@@ -10,10 +10,13 @@ import playlistRoutes from "./routes/playlist.routes";
|
|||||||
import adminRoutes from "./routes/admin.routes";
|
import adminRoutes from "./routes/admin.routes";
|
||||||
import streamRoutes from "./routes/stream.routes";
|
import streamRoutes from "./routes/stream.routes";
|
||||||
import userRoutes from "./routes/user.routes";
|
import userRoutes from "./routes/user.routes";
|
||||||
|
import logger from "./utils/logger";
|
||||||
|
import { loginRateLimiter, adminRateLimiter } from "./middleware/rateLimiter";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
app.set("trust proxy", 1);
|
||||||
const PORT = parseInt(process.env.PORT ?? "4000");
|
const PORT = parseInt(process.env.PORT ?? "4000");
|
||||||
|
|
||||||
const allowedOrigins = (process.env.FRONTEND_URL ?? "http://localhost:5173")
|
const allowedOrigins = (process.env.FRONTEND_URL ?? "http://localhost:5173")
|
||||||
@@ -35,21 +38,22 @@ app.get("/api/health", (_req, res) => {
|
|||||||
res.json({ status: "ok", timestamp: new Date().toISOString() });
|
res.json({ status: "ok", timestamp: new Date().toISOString() });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use("/api/auth/login", loginRateLimiter);
|
||||||
app.use("/api/auth", authRoutes);
|
app.use("/api/auth", authRoutes);
|
||||||
app.use("/api/videos", videoRoutes);
|
app.use("/api/videos", videoRoutes);
|
||||||
app.use("/api/playlists", playlistRoutes);
|
app.use("/api/playlists", playlistRoutes);
|
||||||
app.use("/api/admin", adminRoutes);
|
app.use("/api/admin", adminRateLimiter, adminRoutes);
|
||||||
app.use("/api/stream", streamRoutes);
|
app.use("/api/stream", streamRoutes);
|
||||||
app.use("/api/users", userRoutes);
|
app.use("/api/users", userRoutes);
|
||||||
|
|
||||||
AppDataSource.initialize()
|
AppDataSource.initialize()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log("Database connected");
|
logger.info("Database connected");
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server running on port ${PORT}`);
|
logger.info(`Server running on port ${PORT}`);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err: unknown) => {
|
||||||
console.error("Database connection failed:", err);
|
logger.error("Database connection failed", { err });
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
25
backend/src/middleware/rateLimiter.ts
Normal file
25
backend/src/middleware/rateLimiter.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import rateLimit from "express-rate-limit";
|
||||||
|
|
||||||
|
const rateLimitResponse = { error: "RATE_LIMIT_EXCEEDED" };
|
||||||
|
|
||||||
|
/** POST /api/auth/login — 10 req / 15 min par IP */
|
||||||
|
export const loginRateLimiter = rateLimit({
|
||||||
|
windowMs: 15 * 60 * 1000,
|
||||||
|
max: 10,
|
||||||
|
standardHeaders: true,
|
||||||
|
legacyHeaders: false,
|
||||||
|
handler: (_req, res) => {
|
||||||
|
res.status(429).json(rateLimitResponse);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** /api/admin/* — 50 req / min par IP */
|
||||||
|
export const adminRateLimiter = rateLimit({
|
||||||
|
windowMs: 60 * 1000,
|
||||||
|
max: 50,
|
||||||
|
standardHeaders: true,
|
||||||
|
legacyHeaders: false,
|
||||||
|
handler: (_req, res) => {
|
||||||
|
res.status(429).json(rateLimitResponse);
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user