This commit is contained in:
Kirill
2026-05-24 15:10:24 +05:00
parent 8d4ff3ef62
commit 88fedd675a
18 changed files with 347 additions and 32 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
import { createAvatar } from '@dicebear/core'
import { avataaars } from '@dicebear/collection'
import { createAvatar } from '@dicebear/core'
const DEFAULT_STYLE = avataaars
+34 -9
View File
@@ -1,26 +1,51 @@
const windows = new Map()
const MAX_ATTEMPTS = 5
const WINDOW_MS = 60_000
const DEFAULT_MAX_ATTEMPTS = 5
const DEFAULT_WINDOW_MS = 60_000
// Per-endpoint rate limits
const LIMITS = {
login: { maxAttempts: 5, windowMs: 60_000 },
codeRequest: { maxAttempts: 3, windowMs: 60_000 },
codeVerify: { maxAttempts: 5, windowMs: 60_000 },
}
setInterval(() => {
const now = Date.now()
for (const [ip, entry] of windows) {
if (now - entry.start > WINDOW_MS) windows.delete(ip)
if (now - entry.start > DEFAULT_WINDOW_MS) windows.delete(ip)
}
}, 5 * 60_000).unref()
export function checkLoginRateLimit(ip) {
function getKey(ip, scope) {
return `${scope}:${ip}`
}
function checkRateLimit(ip, scope) {
const limit = LIMITS[scope] || { maxAttempts: DEFAULT_MAX_ATTEMPTS, windowMs: DEFAULT_WINDOW_MS }
const key = getKey(ip, scope)
const now = Date.now()
const entry = windows.get(ip)
if (!entry || now - entry.start > WINDOW_MS) {
windows.set(ip, { start: now, count: 1 })
const entry = windows.get(key)
if (!entry || now - entry.start > limit.windowMs) {
windows.set(key, { start: now, count: 1 })
return { allowed: true }
}
entry.count += 1
if (entry.count > MAX_ATTEMPTS) {
const retryAfter = Math.ceil((entry.start + WINDOW_MS - now) / 1000)
if (entry.count > limit.maxAttempts) {
const retryAfter = Math.ceil((entry.start + limit.windowMs - now) / 1000)
return { allowed: false, retryAfter }
}
return { allowed: true }
}
export function checkLoginRateLimit(ip) {
return checkRateLimit(ip, 'login')
}
export function checkCodeRequestRateLimit(ip) {
return checkRateLimit(ip, 'codeRequest')
}
export function checkCodeVerifyRateLimit(ip) {
return checkRateLimit(ip, 'codeVerify')
}