One shared 100 req / 10 min limiter counted everything — 401s, CORS preflights, even /health — so a bad-token burst from a second frontend burned the budget and 429'd POST /api/auth/login too, leaving no way back in short of waiting out the window or restarting (MemoryStore reset). New middleware/rateLimit.js holds two limiters, verified against express-rate-limit@5.5.1: - apiLimiter (300 / 15 min) skips OPTIONS, /health, and the public auth endpoints, so preflights, probes, and login attempts never drain real API budget. - authLimiter (20 / 15 min, successful logins free) guards register/login/forgotpassword/resetpassword against brute force. 429 there means 20 wrong passwords, never a busy API. Storm-tested with live server: 320 bad-token hits burn the global budget yet login still returns 200; 25 bad logins trip only the login limiter while API traffic is untouched.
55 lines
1.4 KiB
JavaScript
55 lines
1.4 KiB
JavaScript
import 'dotenv/config'
|
|
import 'colors'
|
|
import express from 'express'
|
|
import cors from 'cors'
|
|
import helmet from 'helmet'
|
|
import cookieParser from 'cookie-parser'
|
|
import mongoSanitize from 'express-mongo-sanitize'
|
|
import xss from 'xss-clean'
|
|
import hpp from 'hpp'
|
|
import morgan from 'morgan'
|
|
import errorHandler from './middleware/error.js'
|
|
import { apiLimiter } from './middleware/rateLimit.js'
|
|
|
|
|
|
|
|
import games from './routes/games.js'
|
|
import adminGames from './routes/adminGames.js'
|
|
import tags from './routes/tags.js'
|
|
import auth from './routes/auth.js'
|
|
import users from './routes/users.js'
|
|
import createAdmin from './scripts/adminUser.js'
|
|
import connectDB from './config/db.js'
|
|
|
|
connectDB().then(x => x)
|
|
|
|
const app = express()
|
|
|
|
const whitelist = ['http://localhost:3000', 'http://localhost:5173','https://games.linuxhg.com', 'http://localhost:8000']
|
|
const corsOptions = {
|
|
origin: (origin, callback) => {
|
|
if (whitelist.indexOf(origin) !== -1 || !origin) {
|
|
callback(null, true)
|
|
} else {
|
|
callback(new Error('Not allowed by CORS'))
|
|
}
|
|
},
|
|
}
|
|
|
|
app.use(express.json(), cookieParser(), morgan('dev'), mongoSanitize(), helmet(), xss(), apiLimiter, hpp(), cors())
|
|
|
|
app.get('/health', (req, res) => res.status(200).json({ status: 'ok' }))
|
|
|
|
app.use('/api/admin/games', adminGames)
|
|
app.use('/api/games', games)
|
|
app.use('/api/tags', tags)
|
|
app.use('/api/auth', auth)
|
|
app.use('/api/admin/users', users)
|
|
|
|
app.use(errorHandler)
|
|
|
|
|
|
createAdmin()
|
|
|
|
export default app
|