revert feat(api): merkezi rate limiting sistemi ekle Yeni rate-limiter middleware modülü oluşturuldu. loginLimiter (5 istek/dakika), apiLimiter (30 istek/dakika) ve uploadLimiter (10 istek/dakika) tanımlandı. Auth, loop, timer ve torrent rotalarına rate limiting uygulandı. Torrent rotalarında SHA-1 hash validasyonu eklendi.
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import { Router } from "express";
|
|
import rateLimit from "express-rate-limit";
|
|
import { signToken, verifyCredentials, verifyToken } from "./auth.service"
|
|
import { isDev } from "../config"
|
|
|
|
const router = Router();
|
|
|
|
const getAuthToken = (req: any) => {
|
|
const cookieToken = req.cookies?.["qbuffer_token"];
|
|
const header = req.headers?.authorization as string | undefined;
|
|
const bearer = header?.startsWith("Bearer ") ? header.slice(7) : undefined;
|
|
return cookieToken || bearer;
|
|
};
|
|
|
|
const loginLimiter = rateLimit({
|
|
windowMs: 60_000,
|
|
max: 5,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
});
|
|
|
|
router.post("/login", loginLimiter, async (req, res) => {
|
|
const { username, password } = req.body ?? {};
|
|
if (!username || !password) {
|
|
return res.status(400).json({ error: "Missing credentials" });
|
|
}
|
|
const user = await verifyCredentials(username, password);
|
|
if (!user) {
|
|
return res.status(401).json({ error: "Invalid credentials" });
|
|
}
|
|
const token = signToken({ username: user.username });
|
|
res.cookie("qbuffer_token", token, {
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: !isDev,
|
|
maxAge: 60 * 24 * 60 * 60 * 1000,
|
|
});
|
|
return res.json({ username: user.username, token });
|
|
});
|
|
|
|
router.post("/logout", (_req, res) => {
|
|
res.clearCookie("qbuffer_token", {
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: !isDev,
|
|
});
|
|
return res.json({ ok: true });
|
|
});
|
|
|
|
router.get("/me", (req, res) => {
|
|
const token = getAuthToken(req);
|
|
if (!token) {
|
|
return res.status(401).json({ error: "Unauthorized" });
|
|
}
|
|
try {
|
|
const payload = verifyToken(token);
|
|
return res.json({ ok: true, username: payload.username });
|
|
} catch (error) {
|
|
return res.status(401).json({ error: "Unauthorized" });
|
|
}
|
|
});
|
|
|
|
router.get("/socket-token", (req, res) => {
|
|
const token = getAuthToken(req);
|
|
if (!token) {
|
|
return res.status(401).json({ error: "Unauthorized" });
|
|
}
|
|
try {
|
|
verifyToken(token);
|
|
return res.json({ token });
|
|
} catch (error) {
|
|
return res.status(401).json({ error: "Unauthorized" });
|
|
}
|
|
});
|
|
|
|
export default router;
|