Files
kaffeekasse-saas/app/rate-limit.php
T

34 lines
1.2 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
function app_client_ip(): string
{
return (string)($_SERVER['REMOTE_ADDR'] ?? 'unknown');
}
/**
* Records an attempt in the given bucket and reports whether the caller is
* still within the allowed rate. Call before doing the sensitive work (auth
* check, mail dispatch, account creation); if this returns false, show a
* generic "too many attempts" message without processing the request, so a
* bucket also can't be used to enumerate valid accounts by timing.
*/
function app_rate_limit_check(PDO $pdo, string $bucket, int $maxAttempts, int $windowSeconds): bool
{
$pdo->prepare('INSERT INTO rate_limit_attempts (bucket) VALUES (?)')->execute([$bucket]);
// Globaler Maximalhorizont: unabhängig davon, ob derselbe Bucket je wieder
// benutzt wird, bleibt keine IP-basierte Rate-Limit-Zeile länger als 24h.
$pdo->exec('DELETE FROM rate_limit_attempts WHERE created_at < DATE_SUB(NOW(), INTERVAL 24 HOUR)');
$stmt = $pdo->prepare(
'SELECT COUNT(*) FROM rate_limit_attempts WHERE bucket = ? AND created_at >= DATE_SUB(NOW(), INTERVAL ? SECOND)'
);
$stmt->execute([$bucket, $windowSeconds]);
return (int)$stmt->fetchColumn() <= $maxAttempts;
}