wa-dev-tools/lib/limits.js
treamz dabc26d70f Sync prod: owner-реестр результатов, общая фабрика лимитов, crash-guard ffmpeg/gs, водяной знак PDF
Незакоммиченная работа сессии 2026-09-05 (уже на проде):
- lib/owner.js — реестр владельцев файлов-результатов, owner-check во всех download-роутах (IDOR)
- lib/limits.js — createLimiter(): skip для админа, ipKeyGenerator (фикс ERR_ERL_KEY_GEN_IPV6)
- video: обработчики 'error' у ffmpeg/ffprobe (spawn ENOENT больше не роняет сервер), таймауты
- pdf: runGhostscript/gsUnavailable, водяной знак с кириллицей (fontkit + TTF)
- снятие лимитов размера/количества для админа в pdf/video
- журнал сессии docs/sessions/2026-09-05-0231.md
2026-09-22 20:37:39 +03:00

37 lines
1.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Общая фабрика rate-limit'ов.
*
* Зачем: у каждого роута был свой keyGenerator по req.ip, из-за чего
* express-rate-limit при старте сыпал ERR_ERL_KEY_GEN_IPV6 (IPv6-клиент мог обойти лимит),
* а лимиты применялись в том числе к администратору.
*/
const { rateLimit, ipKeyGenerator } = require('express-rate-limit');
function isAdmin(req) {
return !!(req.session && req.session.user && req.session.user.role === 'admin');
}
// Ключ: залогиненный — по пользователю, гость — по IP (через хелпер, он корректно
// сворачивает IPv6 в /64-подсеть).
function keyGenerator(req) {
const id = req.session && req.session.user && req.session.user.id;
return id ? 'user_' + id : ipKeyGenerator(req.ip);
}
// Админ не ограничивается ничем: skipAdmin: false — только там, где лимит защищает
// не сервис, а самого пользователя (например, брутфорс логина).
function createLimiter({ windowMs = 60000, max = 30, message = { error: 'Слишком много запросов' }, skipAdmin = true } = {}) {
return rateLimit({
windowMs,
max,
message,
standardHeaders: true,
legacyHeaders: false,
keyGenerator,
skip: skipAdmin ? isAdmin : () => false,
});
}
module.exports = { createLimiter, isAdmin, keyGenerator };