Skip to content

Commit a432c27

Browse files
committed
AC-1271: Add rate limiting for payment information endpoint and mutation
1 parent b1cedbb commit a432c27

File tree

7 files changed

+78
-35
lines changed

7 files changed

+78
-35
lines changed

app/code/Magento/Quote/Model/Backpressure/Config/LimitValue.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
use Magento\Framework\Exception\LocalizedException;
1313

1414
/**
15-
* Handles backpressure limit config value.
15+
* Handles backpressure limit config value
1616
*/
1717
class LimitValue extends Value
1818
{
1919
/**
2020
* @inheritDoc
21+
*
22+
* @throws LocalizedException
2123
*/
2224
public function beforeSave()
2325
{

app/code/Magento/Quote/Model/Backpressure/Config/PeriodSource.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use Magento\Framework\Data\OptionSourceInterface;
1212

1313
/**
14-
* Provides selection of limited periods.
14+
* Provides selection of limited periods
1515
*/
1616
class PeriodSource implements OptionSourceInterface
1717
{

app/code/Magento/Quote/Model/Backpressure/Config/PeriodValue.php

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88

99
namespace Magento\Quote\Model\Backpressure\Config;
1010

11+
use Magento\Framework\App\Cache\TypeListInterface;
1112
use Magento\Framework\App\Config\ScopeConfigInterface;
1213
use Magento\Framework\App\Config\Value;
14+
use Magento\Framework\Data\Collection\AbstractDb;
1315
use Magento\Framework\Exception\LocalizedException;
16+
use Magento\Framework\Model\Context;
17+
use Magento\Framework\Model\ResourceModel\AbstractResource;
18+
use Magento\Framework\Registry;
1419

1520
/**
16-
* Handles backpressure "period" config value.
21+
* Handles backpressure "period" config value
1722
*/
1823
class PeriodValue extends Value
1924
{
@@ -23,24 +28,23 @@ class PeriodValue extends Value
2328
private PeriodSource $source;
2429

2530
/**
26-
* PeriodValue constructor.
27-
* @param \Magento\Framework\Model\Context $context
28-
* @param \Magento\Framework\Registry $registry
31+
* @param Context $context
32+
* @param Registry $registry
2933
* @param ScopeConfigInterface $config
30-
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
34+
* @param TypeListInterface $cacheTypeList
3135
* @param PeriodSource $source
32-
* @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
33-
* @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
36+
* @param AbstractResource|null $resource
37+
* @param AbstractDb|null $resourceCollection
3438
* @param array $data
3539
*/
3640
public function __construct(
37-
\Magento\Framework\Model\Context $context,
38-
\Magento\Framework\Registry $registry,
41+
Context $context,
42+
Registry $registry,
3943
ScopeConfigInterface $config,
40-
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
44+
TypeListInterface $cacheTypeList,
4145
PeriodSource $source,
42-
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
43-
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
46+
AbstractResource $resource = null,
47+
AbstractDb $resourceCollection = null,
4448
array $data = []
4549
) {
4650
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
@@ -55,7 +59,7 @@ public function __construct(
5559
public function beforeSave()
5660
{
5761
if ($this->isValueChanged()) {
58-
$value = (string) $this->getValue();
62+
$value = (string)$this->getValue();
5963
if (!array_key_exists($value, $this->source->toOptionArray())) {
6064
throw new LocalizedException(__('Please select a valid rate limit period'));
6165
}

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

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
use Magento\Framework\App\Backpressure\SlidingWindow\LimitConfig;
1313
use Magento\Framework\App\Backpressure\SlidingWindow\LimitConfigManagerInterface;
1414
use Magento\Framework\App\Config\ScopeConfigInterface;
15+
use Magento\Framework\App\ObjectManager;
16+
use Magento\Framework\Exception\RuntimeException;
1517
use Magento\Store\Model\ScopeInterface;
1618

1719
/**
18-
* Provides backpressure limits for ordering.
20+
* Provides backpressure limits for ordering
1921
*/
2022
class OrderLimitConfigManager implements LimitConfigManagerInterface
2123
{
@@ -36,20 +38,34 @@ public function __construct(ScopeConfigInterface $config)
3638

3739
/**
3840
* @inheritDoc
41+
*
42+
* @throws RuntimeException
3943
*/
4044
public function readLimit(ContextInterface $context): LimitConfig
4145
{
42-
if ($context->getIdentityType() === ContextInterface::IDENTITY_TYPE_IP) {
43-
$limit = $this->fetchGuestLimit();
44-
} else {
45-
$limit = $this->fetchAuthenticatedLimit();
46+
switch ($context->getIdentityType()) {
47+
case ContextInterface::IDENTITY_TYPE_ADMIN:
48+
case ContextInterface::IDENTITY_TYPE_CUSTOMER:
49+
$limit = $this->fetchAuthenticatedLimit();
50+
break;
51+
case ContextInterface::IDENTITY_TYPE_IP:
52+
$limit = $this->fetchGuestLimit();
53+
break;
54+
default:
55+
throw new RuntimeException(__("Identity type not found"));
4656
}
4757

48-
return new LimitConfig($limit, $this->fetchPeriod());
58+
return ObjectManager::getInstance()->create(
59+
LimitConfig::class,
60+
[
61+
$limit,
62+
$this->fetchPeriod()
63+
]
64+
);
4965
}
5066

5167
/**
52-
* Is enforcement enabled for current store?
68+
* Checks if enforcement enabled for the current store
5369
*
5470
* @return bool
5571
*/
@@ -64,53 +80,59 @@ public function isEnforcementEnabled(): bool
6480
$this->fetchPeriod();
6581
$this->fetchAuthenticatedLimit();
6682
$this->fetchGuestLimit();
67-
} catch (\RuntimeException $ex) {
83+
} catch (RuntimeException $ex) {
6884
return false;
6985
}
7086

7187
return true;
7288
}
7389

7490
/**
75-
* Limit for authenticated customers.
91+
* Limit for authenticated customers
7692
*
7793
* @return int
94+
* @throws RuntimeException
7895
*/
7996
private function fetchAuthenticatedLimit(): int
8097
{
81-
$value = (int) $this->config->getValue('sales/backpressure/limit', ScopeInterface::SCOPE_STORE);
98+
$value = (int)$this->config->getValue('sales/backpressure/limit', ScopeInterface::SCOPE_STORE);
8299
if ($value <= 0) {
83-
throw new \RuntimeException("Invalid order backpressure config");
100+
throw new RuntimeException(__("Invalid order backpressure limit config"));
84101
}
85102

86103
return $value;
87104
}
88105

89106
/**
90-
* Limit for guests.
107+
* Limit for guests
91108
*
92109
* @return int
110+
* @throws RuntimeException
93111
*/
94112
private function fetchGuestLimit(): int
95113
{
96-
$value = (int) $this->config->getValue('sales/backpressure/guest_limit', ScopeInterface::SCOPE_STORE);
114+
$value = (int)$this->config->getValue(
115+
'sales/backpressure/guest_limit',
116+
ScopeInterface::SCOPE_STORE
117+
);
97118
if ($value <= 0) {
98-
throw new \RuntimeException("Invalid order backpressure config");
119+
throw new RuntimeException(__("Invalid order backpressure guest limit config"));
99120
}
100121

101122
return $value;
102123
}
103124

104125
/**
105-
* Counter reset preiod.
126+
* Counter reset period
106127
*
107128
* @return int
129+
* @throws RuntimeException
108130
*/
109131
private function fetchPeriod(): int
110132
{
111-
$value = (int) $this->config->getValue('sales/backpressure/period', ScopeInterface::SCOPE_STORE);
133+
$value = (int)$this->config->getValue('sales/backpressure/period', ScopeInterface::SCOPE_STORE);
112134
if ($value <= 0) {
113-
throw new \RuntimeException("Invalid order backpressure config");
135+
throw new RuntimeException(__("Invalid order backpressure counter reset period config"));
114136
}
115137

116138
return $value;

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
use Magento\Quote\Api\GuestCartManagementInterface;
1414

1515
/**
16-
* Identifies which checkout related functionality needs backpressure management.
16+
* Identifies which checkout related functionality needs backpressure management
1717
*/
1818
class WebapiRequestTypeExtractor implements BackpressureRequestTypeExtractorInterface
1919
{
20+
private const METHOD = 'placeOrder';
21+
2022
/**
2123
* @var OrderLimitConfigManager
2224
*/
@@ -35,8 +37,8 @@ public function __construct(OrderLimitConfigManager $config)
3537
*/
3638
public function extract(string $service, string $method, string $endpoint): ?string
3739
{
38-
if (($service === CartManagementInterface::class || $service === GuestCartManagementInterface::class)
39-
&& $method === 'placeOrder'
40+
if (in_array($service, [CartManagementInterface::class, GuestCartManagementInterface::class])
41+
&& $method === self::METHOD
4042
&& $this->config->isEnforcementEnabled()
4143
) {
4244
return OrderLimitConfigManager::REQUEST_TYPE_ID;

app/code/Magento/Quote/etc/adminhtml/system.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,24 @@
2727
<field id="limit" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
2828
<label>Requests limit per authenticated customer</label>
2929
<backend_model>Magento\Quote\Model\Backpressure\Config\LimitValue</backend_model>
30+
<depends>
31+
<field id="enabled">1</field>
32+
</depends>
3033
</field>
3134
<field id="guest_limit" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
3235
<label>Requests limit per guest</label>
3336
<backend_model>Magento\Quote\Model\Backpressure\Config\LimitValue</backend_model>
37+
<depends>
38+
<field id="enabled">1</field>
39+
</depends>
3440
</field>
3541
<field id="period" translate="label" type="select" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
3642
<label>Counter resets in a ...</label>
3743
<source_model>Magento\Quote\Model\Backpressure\Config\PeriodSource</source_model>
3844
<backend_model>Magento\Quote\Model\Backpressure\Config\PeriodValue</backend_model>
45+
<depends>
46+
<field id="enabled">1</field>
47+
</depends>
3948
</field>
4049
</group>
4150
</section>

app/code/Magento/Quote/i18n/en_US.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ Carts,Carts
6969
"Validated Country Code","Validated Country Code"
7070
"Validated Vat Number","Validated Vat Number"
7171
"Invalid Quote Item id %1","Invalid Quote Item id %1"
72+
"Number above 0 is required for the limit","Number above 0 is required for the limit"
73+
"Please select a valid rate limit period","Please select a valid rate limit period"
74+
"Identity type not found","Identity type not found"
75+
"Invalid order backpressure limit config","Invalid order backpressure limit config"

0 commit comments

Comments
 (0)