Skip to content

Commit 26d8a9c

Browse files
committed
AC-1271: Add rate limiting for payment information endpoint and mutation
1 parent 7937e05 commit 26d8a9c

File tree

11 files changed

+700
-235
lines changed

11 files changed

+700
-235
lines changed

app/code/Magento/Quote/Model/Backpressure/OrderLimitConfigManager.php

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
use Magento\Framework\App\Backpressure\ContextInterface;
1212
use Magento\Framework\App\Backpressure\SlidingWindow\LimitConfig;
1313
use Magento\Framework\App\Backpressure\SlidingWindow\LimitConfigManagerInterface;
14-
use Magento\Framework\App\Backpressure\SlidingWindow\RequestLoggerInterface;
1514
use Magento\Framework\App\Config\ScopeConfigInterface;
16-
use Magento\Framework\App\DeploymentConfig;
17-
use Magento\Framework\Exception\FileSystemException;
1815
use Magento\Framework\Exception\RuntimeException;
1916
use Magento\Store\Model\ScopeInterface;
2017

@@ -30,21 +27,11 @@ class OrderLimitConfigManager implements LimitConfigManagerInterface
3027
*/
3128
private ScopeConfigInterface $config;
3229

33-
/**
34-
* @var DeploymentConfig
35-
*/
36-
private DeploymentConfig $deploymentConfig;
37-
3830
/**
3931
* @param ScopeConfigInterface $config
40-
* @param DeploymentConfig $deploymentConfig
4132
*/
42-
public function __construct(
43-
ScopeConfigInterface $config,
44-
DeploymentConfig $deploymentConfig
45-
) {
33+
public function __construct(ScopeConfigInterface $config) {
4634
$this->config = $config;
47-
$this->deploymentConfig = $deploymentConfig;
4835
}
4936

5037
/**
@@ -73,22 +60,10 @@ public function readLimit(ContextInterface $context): LimitConfig
7360
* Checks if enforcement enabled for the current store
7461
*
7562
* @return bool
76-
* @throws RuntimeException
77-
* @throws FileSystemException
7863
*/
7964
public function isEnforcementEnabled(): bool
8065
{
81-
$loggerType = $this->deploymentConfig->get(RequestLoggerInterface::CONFIG_PATH_BACKPRESSURE_LOGGER);
82-
if (!$loggerType) {
83-
return false;
84-
}
85-
86-
$enabled = $this->config->isSetFlag('sales/backpressure/enabled', ScopeInterface::SCOPE_STORE);
87-
if (!$enabled) {
88-
return false;
89-
}
90-
91-
return true;
66+
return $this->config->isSetFlag('sales/backpressure/enabled', ScopeInterface::SCOPE_STORE);
9267
}
9368

9469
/**
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/**
1717
* Tests CacheRequestLogger class
1818
*/
19-
class CacheRequestLoggerTest extends TestCase
19+
class RedisRequestLoggerTest extends TestCase
2020
{
2121
/**
2222
* @var RedisRequestLogger

lib/internal/Magento/Framework/App/Backpressure/SlidingWindow/RedisRequestLogger.php

Lines changed: 32 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -8,98 +8,51 @@
88
namespace Magento\Framework\App\Backpressure\SlidingWindow;
99

1010
use Magento\Framework\App\Backpressure\ContextInterface;
11-
use Credis_Client;
1211
use Magento\Framework\App\DeploymentConfig;
1312
use Magento\Framework\Exception\FileSystemException;
1413
use Magento\Framework\Exception\RuntimeException;
14+
use Magento\Framework\App\Backpressure\SlidingWindow\RedisRequestLogger\RedisClient;
1515

1616
/**
1717
* Logging requests to Redis
1818
*/
1919
class RedisRequestLogger implements RequestLoggerInterface
2020
{
21-
/**
22-
* Keys for Redis settings
23-
*/
24-
public const KEY_HOST = 'host';
25-
public const KEY_PORT = 'port';
26-
public const KEY_TIMEOUT = 'timeout';
27-
public const KEY_PERSISTENT = 'persistent';
28-
public const KEY_DB = 'db';
29-
public const KEY_PASSWORD = 'password';
30-
public const KEY_USER = 'user';
31-
32-
/**
33-
* Configuration paths for Redis settings
34-
*/
35-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_SERVER = 'backpressure/logger/options/server';
36-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PORT = 'backpressure/logger/options/port';
37-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_TIMEOUT = 'backpressure/logger/options/timeout';
38-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PERSISTENT = 'backpressure/logger/options/persistent';
39-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_DB = 'backpressure/logger/options/db';
40-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PASSWORD = 'backpressure/logger/options/password';
41-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_USER = 'backpressure/logger/options/user';
42-
public const CONFIG_PATH_BACKPRESSURE_LOGGER_ID_PREFIX = 'backpressure/logger/id-prefix';
43-
4421
/**
4522
* Identifier for Redis Logger type
4623
*/
47-
public const VALUE_BACKPRESSURE_LOGGER_REDIS = 'redis';
24+
public const BACKPRESSURE_LOGGER_REDIS = 'redis';
4825

4926
/**
50-
* Redis default settings
27+
* Default prefix id
5128
*/
52-
public const DEFAULT_REDIS_CONFIG_VALUES = [
53-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_SERVER => '127.0.0.1',
54-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PORT => 6379,
55-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_TIMEOUT => null,
56-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PERSISTENT => '',
57-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_DB => 3,
58-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PASSWORD => null,
59-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_USER => null,
60-
];
29+
private const DEFAULT_PREFIX_ID = 'reqlog';
6130

6231
/**
63-
* Config map
32+
* Config path for backpressure logger id prefix
6433
*/
65-
public const KEY_CONFIG_PATH_MAP = [
66-
self::KEY_HOST => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_SERVER,
67-
self::KEY_PORT => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PORT,
68-
self::KEY_TIMEOUT => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_TIMEOUT,
69-
self::KEY_PERSISTENT => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PERSISTENT,
70-
self::KEY_DB => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_DB,
71-
self::KEY_PASSWORD => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PASSWORD,
72-
self::KEY_USER => self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_USER,
73-
];
34+
public const CONFIG_PATH_BACKPRESSURE_LOGGER_ID_PREFIX = 'backpressure/logger/id-prefix';
7435

7536
/**
76-
* @var Credis_Client
37+
* @var RedisClient
7738
*/
78-
private Credis_Client $credisClient;
39+
private $redisClient;
7940

8041
/**
81-
* @var string
42+
* @var DeploymentConfig
8243
*/
83-
private string $prefixId;
44+
private $deploymentConfig;
8445

8546
/**
86-
* @param DeploymentConfig $config
87-
* @throws FileSystemException
88-
* @throws RuntimeException
47+
* @param RedisClient $redisClient
48+
* @param DeploymentConfig $deploymentConfig
8949
*/
90-
public function __construct(DeploymentConfig $config)
91-
{
92-
$this->credisClient = new Credis_Client(
93-
$this->getHost($config),
94-
$this->getPort($config),
95-
$this->getTimeout($config),
96-
$this->getPersistent($config),
97-
$this->getDb($config),
98-
$this->getPassword($config),
99-
$this->getUser($config)
100-
);
101-
102-
$this->prefixId = $config->get(self::CONFIG_PATH_BACKPRESSURE_LOGGER_ID_PREFIX, '');
50+
public function __construct(
51+
RedisClient $redisClient,
52+
DeploymentConfig $deploymentConfig
53+
) {
54+
$this->redisClient = $redisClient;
55+
$this->deploymentConfig = $deploymentConfig;
10356
}
10457

10558
/**
@@ -108,20 +61,18 @@ public function __construct(DeploymentConfig $config)
10861
public function incrAndGetFor(ContextInterface $context, int $timeSlot, int $discardAfter): int
10962
{
11063
$id = $this->generateId($context, $timeSlot);
111-
$redis = $this->credisClient->pipeline();
112-
113-
$redis->incrBy($id, 1);
114-
$redis->expireAt($id, time() + $discardAfter);
64+
$this->redisClient->incrBy($id, 1);
65+
$this->redisClient->expireAt($id, time() + $discardAfter);
11566

116-
return (int)$redis->exec()[0];
67+
return (int)$this->redisClient->exec()[0];
11768
}
11869

11970
/**
12071
* @inheritDoc
12172
*/
12273
public function getFor(ContextInterface $context, int $timeSlot): ?int
12374
{
124-
$value = $this->credisClient->get($this->generateId($context, $timeSlot));
75+
$value = $this->redisClient->get($this->generateId($context, $timeSlot));
12576

12677
return $value ? (int)$value : null;
12778
}
@@ -135,122 +86,26 @@ public function getFor(ContextInterface $context, int $timeSlot): ?int
13586
*/
13687
private function generateId(ContextInterface $context, int $timeSlot): string
13788
{
138-
return $this->prefixId
89+
return $this->getPrefixId()
13990
. $context->getTypeId()
14091
. $context->getIdentityType()
14192
. $context->getIdentity()
14293
. $timeSlot;
14394
}
14495

14596
/**
146-
* Returns Redis host
147-
*
148-
* @param DeploymentConfig $config
149-
* @return string
150-
* @throws FileSystemException
151-
* @throws RuntimeException
152-
*/
153-
private function getHost(DeploymentConfig $config): string
154-
{
155-
return $config->get(
156-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_SERVER,
157-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_SERVER]
158-
);
159-
}
160-
161-
/**
162-
* Returns Redis port
163-
*
164-
* @param DeploymentConfig $config
165-
* @return int
166-
* @throws FileSystemException
167-
* @throws RuntimeException
168-
*/
169-
private function getPort(DeploymentConfig $config): int
170-
{
171-
return (int)$config->get(
172-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PORT,
173-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PORT]
174-
);
175-
}
176-
177-
/**
178-
* Returns Redis timeout
97+
* Returns prefix id
17998
*
180-
* @param DeploymentConfig $config
181-
* @return float|null
182-
* @throws FileSystemException
183-
* @throws RuntimeException
184-
*/
185-
private function getTimeout(DeploymentConfig $config): ?float
186-
{
187-
return (float)$config->get(
188-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_TIMEOUT,
189-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_TIMEOUT]
190-
);
191-
}
192-
193-
/**
194-
* Returns Redis persistent
195-
*
196-
* @param DeploymentConfig $config
19799
* @return string
198-
* @throws FileSystemException
199-
* @throws RuntimeException
200-
*/
201-
private function getPersistent(DeploymentConfig $config): string
202-
{
203-
return $config->get(
204-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PERSISTENT,
205-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PERSISTENT]
206-
);
207-
}
208-
209-
/**
210-
* Returns Redis db
211-
*
212-
* @param DeploymentConfig $config
213-
* @return int
214-
* @throws FileSystemException
215-
* @throws RuntimeException
216-
*/
217-
private function getDb(DeploymentConfig $config): int
218-
{
219-
return (int)$config->get(
220-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_DB,
221-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_DB]
222-
);
223-
}
224-
225-
/**
226-
* Returns Redis password
227-
*
228-
* @param DeploymentConfig $config
229-
* @return string|null
230-
* @throws FileSystemException
231-
* @throws RuntimeException
232-
*/
233-
private function getPassword(DeploymentConfig $config): ?string
234-
{
235-
return $config->get(
236-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PASSWORD,
237-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_PASSWORD]
238-
);
239-
}
240-
241-
/**
242-
* Returns Redis user
243-
*
244-
* @param DeploymentConfig $config
245-
* @return string|null
246-
* @throws FileSystemException
247-
* @throws RuntimeException
248100
*/
249-
private function getUser(DeploymentConfig $config): ?string
101+
private function getPrefixId(): string
250102
{
251-
return $config->get(
252-
self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_USER,
253-
self::DEFAULT_REDIS_CONFIG_VALUES[self::CONFIG_PATH_BACKPRESSURE_LOGGER_REDIS_USER]
254-
);
103+
try {
104+
return (string)$this->deploymentConfig->get(
105+
self::CONFIG_PATH_BACKPRESSURE_LOGGER_ID_PREFIX,
106+
self::DEFAULT_PREFIX_ID);
107+
} catch (RuntimeException | FileSystemException $e) {
108+
return self::DEFAULT_PREFIX_ID;
109+
}
255110
}
256111
}

0 commit comments

Comments
 (0)