-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathRedis.php
More file actions
110 lines (96 loc) · 2.47 KB
/
Redis.php
File metadata and controls
110 lines (96 loc) · 2.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php
namespace Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\TimeLimit;
class Redis extends TimeLimit
{
public const NAMESPACE = 'abuse';
/**
* @var \Redis
*/
protected \Redis $redis;
/**
* @var int
*/
protected int $ttl;
public function __construct(string $key, int $limit, int $seconds, \Redis $redis)
{
$this->redis = $redis;
$this->key = $key;
$this->ttl = $seconds;
$now = \time();
$this->timestamp = (int)($now - ($now % $seconds));
$this->limit = $limit;
}
/**
* Undocumented function
*
* @param string $key
* @param int $timestamp
* @return integer
*/
protected function count(string $key, int $timestamp): int
{
if (0 == $this->limit) { // No limit no point for counting
return 0;
}
/** @var string $count */
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $timestamp);
if (!$count) {
$count = 0;
} else {
$count = intval($count);
}
return $count;
}
/**
* @param string $key
* @param int $timestamp
* @return void
*
*/
protected function hit(string $key, int $timestamp): void
{
if (0 == $this->limit) { // No limit no point for counting
return;
}
$key = self::NAMESPACE . '__' . $key . '__' . $timestamp;
$this->redis->multi()
->incr($key)
->expire($key, $this->ttl)
->exec();
}
/**
* Get abuse logs
*
* Return logs with an offset and limit
*
* @param int|null $offset
* @param int|null $limit
* @return array<string, mixed>
*/
public function getLogs(?int $offset = null, ?int $limit = 25): array
{
// TODO limit potential is SCAN but needs cursor no offset
$cursor = null;
$keys = $this->redis->scan($cursor, self::NAMESPACE . '__*', $limit);
if (!$keys) {
return [];
}
$logs = [];
foreach ($keys as $key) {
$logs[$key] = $this->redis->get($key);
}
return $logs;
}
/**
* Delete all logs older than $timestamp
*
* @param int $timestamp
* @return bool
*/
public function cleanup(int $timestamp): bool
{
// No need for manual cleanup - Redis TTL handles this automatically
return true;
}
}