Skip to content

Commit 54a5835

Browse files
Merge pull request #91 from utopia-php/add-support-for-sharding-adapter
chore: update tests and change timestamp type
2 parents 25b9654 + 82f77e2 commit 54a5835

13 files changed

+245
-162
lines changed

docker-compose.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ services:
4848
- REDIS_HOSTS=redis-cluster-0:6379
4949
ports:
5050
- "8081:5540"
51+
volumes:
52+
- redisinsight:/data
5153

5254
redis-cluster-0:
5355
image: docker.io/bitnami/redis-cluster:7.4
@@ -88,4 +90,6 @@ services:
8890
- abuse
8991

9092
networks:
91-
abuse:
93+
abuse:
94+
volumes:
95+
redisinsight:

phpunit.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
convertNoticesToExceptions="true"
77
convertWarningsToExceptions="true"
88
processIsolation="false"
9-
stopOnFailure="true"
9+
stopOnFailure="false"
1010
>
1111
<testsuites>
1212
<testsuite name="Application Test Suite">

src/Abuse/Abuse.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ public function getLogs(?int $offset = null, ?int $limit = 25): array
4444
}
4545

4646
/**
47-
* Delete all logs older than $datetime
47+
* Delete all logs older than $timestamp
4848
*
49-
* @param string $datetime
49+
* @param int $timestamp
5050
* @return bool
5151
*/
52-
public function cleanup(string $datetime): bool
52+
public function cleanup(int $timestamp): bool
5353
{
54-
return $this->adapter->cleanup($datetime);
54+
return $this->adapter->cleanup($timestamp);
5555
}
5656
}

src/Abuse/Adapter.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ abstract public function getLogs(?int $offset = null, ?int $limit = 25): array;
7979
/**
8080
* Delete all logs older than $datetime
8181
*
82-
* @param string $datetime
82+
* @param int $timestamp
8383
* @return bool
8484
*/
85-
abstract public function cleanup(string $datetime): bool;
85+
abstract public function cleanup(int $timestamp): bool;
8686
}

src/Abuse/Adapters/ReCaptcha.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ public function check(float $score = 0.5): bool
9090
}
9191

9292
/**
93-
* Delete logs older than $datetime
93+
* Delete logs older than $timestamp
9494
*
95-
* @param string $datetime
95+
* @param int $timestamp
9696
* @return bool
9797
*
9898
* @throws Exception
9999
*/
100-
public function cleanup(string $datetime): bool
100+
public function cleanup(int $timestamp): bool
101101
{
102102
throw new Exception('Method not supported');
103103
}

src/Abuse/Adapters/TimeLimit.php

+12-12
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,24 @@ abstract class TimeLimit extends Adapter
1818
protected ?int $count = null;
1919

2020
/**
21-
* @var string
21+
* @var int
2222
*/
23-
protected string $time;
23+
protected int $timestamp;
2424

2525
/**
2626
* Check
2727
*
2828
* Checks if number of counts is bigger or smaller than current limit
2929
*
3030
* @param string $key
31-
* @param string $datetime
31+
* @param int $timestamp
3232
* @return int
3333
*
3434
* @throws \Exception
3535
*/
36-
abstract protected function count(string $key, string $datetime): int;
36+
abstract protected function count(string $key, int $timestamp): int;
3737

38-
abstract protected function hit(string $key, string $datetime): void;
38+
abstract protected function hit(string $key, int $timestamp): void;
3939

4040
/**
4141
* Check
@@ -54,8 +54,8 @@ public function check(): bool
5454

5555
$key = $this->parseKey();
5656

57-
if ($this->limit > $this->count($key, $this->time)) {
58-
$this->hit($key, $this->time);
57+
if ($this->limit > $this->count($key, $this->timestamp)) {
58+
$this->hit($key, $this->timestamp);
5959

6060
return false;
6161
}
@@ -74,7 +74,7 @@ public function check(): bool
7474
*/
7575
public function remaining(): int
7676
{
77-
$left = $this->limit - ($this->count($this->parseKey(), $this->time) + 1); // Add one because we need to say how many left not how many done
77+
$left = $this->limit - ($this->count($this->parseKey(), $this->timestamp) + 1); // Add one because we need to say how many left not how many done
7878

7979
return (0 > $left) ? 0 : $left;
8080
}
@@ -94,12 +94,12 @@ public function limit(): int
9494
/**
9595
* Time
9696
*
97-
* Return the Datetime
97+
* Return the timestamp
9898
*
99-
* @return string
99+
* @return int
100100
*/
101-
public function time(): string
101+
public function time(): int
102102
{
103-
return $this->time;
103+
return $this->timestamp;
104104
}
105105
}

src/Abuse/Adapters/TimeLimit/Database.php

+25-16
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ class Database extends TimeLimit
8080
public function __construct(string $key, int $limit, int $seconds, UtopiaDB $db)
8181
{
8282
$this->key = $key;
83-
$time = (int) \date('U', (int) (\floor(\time() / $seconds)) * $seconds); // todo: any good Idea without time()?
84-
$this->time = DateTime::format((new \DateTime())->setTimestamp($time));
83+
$now = \time();
84+
$this->timestamp = (int)($now - ($now % $seconds));
8585
$this->limit = $limit;
8686
$this->db = $db;
8787
}
@@ -121,12 +121,12 @@ public function setup(): void
121121
* Checks if number of counts is bigger or smaller than current limit
122122
*
123123
* @param string $key
124-
* @param string $datetime
124+
* @param int $timestamp
125125
* @return int
126126
*
127127
* @throws \Exception
128128
*/
129-
protected function count(string $key, string $datetime): int
129+
protected function count(string $key, int $timestamp): int
130130
{
131131
if (0 == $this->limit) { // No limit no point for counting
132132
return 0;
@@ -136,11 +136,13 @@ protected function count(string $key, string $datetime): int
136136
return $this->count;
137137
}
138138

139+
$timestamp = $this->toDateTime($timestamp);
140+
139141
/** @var array<Document> $result */
140-
$result = Authorization::skip(function () use ($key, $datetime) {
142+
$result = Authorization::skip(function () use ($key, $timestamp) {
141143
return $this->db->find(self::COLLECTION, [
142144
Query::equal('key', [$key]),
143-
Query::equal('time', [$datetime]),
145+
Query::equal('time', [$timestamp]),
144146
]);
145147
});
146148

@@ -158,28 +160,29 @@ protected function count(string $key, string $datetime): int
158160

159161
/**
160162
* @param string $key
161-
* @param string $datetime
163+
* @param int $timestamp
162164
* @return void
163165
*
164166
* @throws AuthorizationException|Structure|\Exception|\Throwable
165167
*/
166-
protected function hit(string $key, string $datetime): void
168+
protected function hit(string $key, int $timestamp): void
167169
{
168170
if (0 == $this->limit) { // No limit no point for counting
169171
return;
170172
}
171173

172-
Authorization::skip(function () use ($datetime, $key) {
174+
$timestamp = $this->toDateTime($timestamp);
175+
Authorization::skip(function () use ($timestamp, $key) {
173176
$data = $this->db->findOne(self::COLLECTION, [
174177
Query::equal('key', [$key]),
175-
Query::equal('time', [$datetime]),
178+
Query::equal('time', [$timestamp]),
176179
]);
177180

178181
if ($data->isEmpty()) {
179182
$data = [
180183
'$permissions' => [],
181184
'key' => $key,
182-
'time' => $datetime,
185+
'time' => $timestamp,
183186
'count' => 1,
184187
'$collection' => self::COLLECTION,
185188
];
@@ -190,7 +193,7 @@ protected function hit(string $key, string $datetime): void
190193
// Duplicate in case of race condition
191194
$data = $this->db->findOne(self::COLLECTION, [
192195
Query::equal('key', [$key]),
193-
Query::equal('time', [$datetime]),
196+
Query::equal('time', [$timestamp]),
194197
]);
195198

196199
if (!$data->isEmpty()) {
@@ -246,17 +249,18 @@ public function getLogs(?int $offset = null, ?int $limit = 25): array
246249
/**
247250
* Delete logs older than $timestamp seconds
248251
*
249-
* @param string $datetime
252+
* @param int $timestamp
250253
* @return bool
251254
*
252255
* @throws AuthorizationException|\Exception
253256
*/
254-
public function cleanup(string $datetime): bool
257+
public function cleanup(int $timestamp): bool
255258
{
256-
Authorization::skip(function () use ($datetime) {
259+
$timestamp = $this->toDateTime($timestamp);
260+
Authorization::skip(function () use ($timestamp) {
257261
do {
258262
$documents = $this->db->find(self::COLLECTION, [
259-
Query::lessThan('time', $datetime),
263+
Query::lessThan('time', $timestamp),
260264
]);
261265

262266
foreach ($documents as $document) {
@@ -267,4 +271,9 @@ public function cleanup(string $datetime): bool
267271

268272
return true;
269273
}
274+
275+
protected function toDateTime(int $timestamp): string
276+
{
277+
return DateTime::format((new \DateTime())->setTimestamp($timestamp));
278+
}
270279
}

src/Abuse/Adapters/TimeLimit/Redis.php

+13-13
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ public function __construct(string $key, int $limit, int $seconds, \Redis $redis
1717
{
1818
$this->redis = $redis;
1919
$this->key = $key;
20-
$time = (int) \date('U', (int) (\floor(\time() / $seconds)) * $seconds);
21-
$this->time = strval($time);
20+
$now = \time();
21+
$this->timestamp = (int)($now - ($now % $seconds));
2222
$this->limit = $limit;
2323
}
2424

2525
/**
2626
* Undocumented function
2727
*
2828
* @param string $key
29-
* @param string $datetime
29+
* @param int $timestamp
3030
* @return integer
3131
*/
32-
protected function count(string $key, string $datetime): int
32+
protected function count(string $key, int $timestamp): int
3333
{
3434
if (0 == $this->limit) { // No limit no point for counting
3535
return 0;
@@ -40,7 +40,7 @@ protected function count(string $key, string $datetime): int
4040
}
4141

4242
/** @var string $count */
43-
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $datetime);
43+
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $timestamp);
4444
if (!$count) {
4545
$this->count = 0;
4646
} else {
@@ -52,25 +52,25 @@ protected function count(string $key, string $datetime): int
5252

5353
/**
5454
* @param string $key
55-
* @param string $datetime
55+
* @param int $timestamp
5656
* @return void
5757
*
5858
*/
59-
protected function hit(string $key, string $datetime): void
59+
protected function hit(string $key, int $timestamp): void
6060
{
6161
if (0 == $this->limit) { // No limit no point for counting
6262
return;
6363
}
6464

6565
/** @var string $count */
66-
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $datetime);
66+
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $timestamp);
6767
if (!$count) {
6868
$this->count = 0;
6969
} else {
7070
$this->count = intval($count);
7171
}
7272

73-
$this->redis->incr(self::NAMESPACE . '__'. $key .'__'. $datetime);
73+
$this->redis->incr(self::NAMESPACE . '__'. $key .'__'. $timestamp);
7474
$this->count++;
7575
}
7676

@@ -100,17 +100,17 @@ public function getLogs(?int $offset = null, ?int $limit = 25): array
100100
}
101101

102102
/**
103-
* Delete all logs older than $datetime
103+
* Delete all logs older than $timestamp
104104
*
105-
* @param string $datetime
105+
* @param int $timestamp
106106
* @return bool
107107
*/
108-
public function cleanup(string $datetime): bool
108+
public function cleanup(int $timestamp): bool
109109
{
110110
$iterator = null;
111111
while ($iterator !== 0) {
112112
$keys = $this->redis->scan($iterator, self::NAMESPACE . '__*__*', 1000);
113-
$keys = $this->filterKeys($keys ? $keys : [], (int) $datetime);
113+
$keys = $this->filterKeys($keys ? $keys : [], $timestamp);
114114
$this->redis->del($keys);
115115
}
116116
return true;

0 commit comments

Comments
 (0)