56 lines
1.4 KiB
PHP
56 lines
1.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
function auth_check_rate_limit(string $key): array
|
||
|
|
{
|
||
|
|
$config = require __DIR__ . "/config.php";
|
||
|
|
$window = (int) $config["rate_limit"]["window_seconds"];
|
||
|
|
$max = (int) $config["rate_limit"]["max_attempts"];
|
||
|
|
$dir = __DIR__ . "/ratelimit";
|
||
|
|
|
||
|
|
if (!is_dir($dir)) {
|
||
|
|
@mkdir($dir, 0755, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
$safeKey = hash("sha256", $key);
|
||
|
|
$file = $dir . "/" . $safeKey . ".json";
|
||
|
|
$now = time();
|
||
|
|
|
||
|
|
$data = [
|
||
|
|
"count" => 1,
|
||
|
|
"reset_at" => $now + $window,
|
||
|
|
];
|
||
|
|
|
||
|
|
if (is_file($file)) {
|
||
|
|
$raw = @file_get_contents($file);
|
||
|
|
$decoded = $raw ? json_decode($raw, true) : null;
|
||
|
|
if (is_array($decoded) && isset($decoded["count"], $decoded["reset_at"])) {
|
||
|
|
if ($now <= (int) $decoded["reset_at"]) {
|
||
|
|
$decoded["count"] = (int) $decoded["count"] + 1;
|
||
|
|
$data = $decoded;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$limited = $data["count"] > $max;
|
||
|
|
$retryAfter = max(0, $data["reset_at"] - $now);
|
||
|
|
|
||
|
|
$payload = json_encode($data);
|
||
|
|
if ($payload !== false) {
|
||
|
|
$fh = @fopen($file, "cb+");
|
||
|
|
if ($fh !== false) {
|
||
|
|
if (flock($fh, LOCK_EX)) {
|
||
|
|
ftruncate($fh, 0);
|
||
|
|
fwrite($fh, $payload);
|
||
|
|
fflush($fh);
|
||
|
|
flock($fh, LOCK_UN);
|
||
|
|
}
|
||
|
|
fclose($fh);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return [
|
||
|
|
"limited" => $limited,
|
||
|
|
"retry_after" => $retryAfter,
|
||
|
|
];
|
||
|
|
}
|