Skip to content

Commit 2a932eb

Browse files
Merge pull request #8217 from magento-commerce/revert-8139-revert-8122-cia-2.4.7-beta1-bugfixes-02062023
Revert "Revert "Cia 2.4.7 beta1 bugfixes 02062023""
2 parents b4afab3 + 7fcfc31 commit 2a932eb

File tree

99 files changed

+5487
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+5487
-44
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Authorization\Model;
10+
11+
use Magento\Framework\App\Backpressure\ContextInterface;
12+
use Magento\Framework\App\Backpressure\IdentityProviderInterface;
13+
use Magento\Framework\Exception\RuntimeException;
14+
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
15+
16+
/**
17+
* Utilizes UserContext for backpressure identity
18+
*/
19+
class IdentityProvider implements IdentityProviderInterface
20+
{
21+
/**
22+
* User context identity type map
23+
*/
24+
private const USER_CONTEXT_IDENTITY_TYPE_MAP = [
25+
UserContextInterface::USER_TYPE_CUSTOMER => ContextInterface::IDENTITY_TYPE_CUSTOMER,
26+
UserContextInterface::USER_TYPE_ADMIN => ContextInterface::IDENTITY_TYPE_ADMIN
27+
];
28+
29+
/**
30+
* @var UserContextInterface
31+
*/
32+
private UserContextInterface $userContext;
33+
34+
/**
35+
* @var RemoteAddress
36+
*/
37+
private RemoteAddress $remoteAddress;
38+
39+
/**
40+
* @param UserContextInterface $userContext
41+
* @param RemoteAddress $remoteAddress
42+
*/
43+
public function __construct(UserContextInterface $userContext, RemoteAddress $remoteAddress)
44+
{
45+
$this->userContext = $userContext;
46+
$this->remoteAddress = $remoteAddress;
47+
}
48+
49+
/**
50+
* @inheritDoc
51+
*
52+
* @throws RuntimeException
53+
*/
54+
public function fetchIdentityType(): int
55+
{
56+
if (!$this->userContext->getUserId()) {
57+
return ContextInterface::IDENTITY_TYPE_IP;
58+
}
59+
60+
$userType = $this->userContext->getUserType();
61+
if (isset(self::USER_CONTEXT_IDENTITY_TYPE_MAP[$userType])) {
62+
return self::USER_CONTEXT_IDENTITY_TYPE_MAP[$userType];
63+
}
64+
65+
throw new RuntimeException(__('User type not defined'));
66+
}
67+
68+
/**
69+
* @inheritDoc
70+
*
71+
* @throws RuntimeException
72+
*/
73+
public function fetchIdentity(): string
74+
{
75+
$userId = $this->userContext->getUserId();
76+
if ($userId) {
77+
return (string)$userId;
78+
}
79+
80+
$address = $this->remoteAddress->getRemoteAddress();
81+
if (!$address) {
82+
throw new RuntimeException(__('Failed to extract remote address'));
83+
}
84+
85+
return $address;
86+
}
87+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Authorization\Test\Unit\Model;
10+
11+
use Magento\Authorization\Model\IdentityProvider;
12+
use Magento\Authorization\Model\UserContextInterface;
13+
use Magento\Framework\App\Backpressure\ContextInterface;
14+
use Magento\Framework\Exception\RuntimeException;
15+
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
16+
use PHPUnit\Framework\MockObject\MockObject;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Tests the IdentityProvider class
21+
*/
22+
class IdentityProviderTest extends TestCase
23+
{
24+
/**
25+
* @var UserContextInterface|MockObject
26+
*/
27+
private $userContext;
28+
29+
/**
30+
* @var RemoteAddress|MockObject
31+
*/
32+
private $remoteAddress;
33+
34+
/**
35+
* @var IdentityProvider
36+
*/
37+
private $model;
38+
39+
/**
40+
* @inheritDoc
41+
*/
42+
protected function setUp(): void
43+
{
44+
parent::setUp();
45+
46+
$this->userContext = $this->createMock(UserContextInterface::class);
47+
$this->remoteAddress = $this->createMock(RemoteAddress::class);
48+
$this->model = new IdentityProvider($this->userContext, $this->remoteAddress);
49+
}
50+
51+
/**
52+
* Cases for identity provider.
53+
*
54+
* @return array
55+
*/
56+
public function getIdentityCases(): array
57+
{
58+
return [
59+
'empty-user-context' => [null, null, '127.0.0.1', ContextInterface::IDENTITY_TYPE_IP, '127.0.0.1'],
60+
'guest-user-context' => [
61+
UserContextInterface::USER_TYPE_GUEST,
62+
null,
63+
'127.0.0.1',
64+
ContextInterface::IDENTITY_TYPE_IP,
65+
'127.0.0.1'
66+
],
67+
'admin-user-context' => [
68+
UserContextInterface::USER_TYPE_ADMIN,
69+
42,
70+
'127.0.0.1',
71+
ContextInterface::IDENTITY_TYPE_ADMIN,
72+
'42'
73+
],
74+
'customer-user-context' => [
75+
UserContextInterface::USER_TYPE_CUSTOMER,
76+
42,
77+
'127.0.0.1',
78+
ContextInterface::IDENTITY_TYPE_CUSTOMER,
79+
'42'
80+
],
81+
];
82+
}
83+
84+
/**
85+
* Verify identity provider.
86+
*
87+
* @param int|null $userType
88+
* @param int|null $userId
89+
* @param string $remoteAddr
90+
* @param int $expectedType
91+
* @param string $expectedIdentity
92+
* @return void
93+
* @dataProvider getIdentityCases
94+
*/
95+
public function testFetchIdentity(
96+
?int $userType,
97+
?int $userId,
98+
string $remoteAddr,
99+
int $expectedType,
100+
string $expectedIdentity
101+
): void {
102+
$this->userContext->method('getUserType')->willReturn($userType);
103+
$this->userContext->method('getUserId')->willReturn($userId);
104+
$this->remoteAddress->method('getRemoteAddress')->willReturn($remoteAddr);
105+
106+
$this->assertEquals($expectedType, $this->model->fetchIdentityType());
107+
$this->assertEquals($expectedIdentity, $this->model->fetchIdentity());
108+
}
109+
110+
/**
111+
* Tests fetching an identity type when user type can't be defined
112+
*/
113+
public function testFetchIdentityTypeUserTypeNotDefined()
114+
{
115+
$this->userContext->method('getUserId')->willReturn(2);
116+
$this->userContext->method('getUserType')->willReturn(null);
117+
$this->expectException(RuntimeException::class);
118+
$this->expectExceptionMessage(__('User type not defined')->getText());
119+
$this->model->fetchIdentityType();
120+
}
121+
122+
/**
123+
* Tests fetching an identity when user address can't be extracted
124+
*/
125+
public function testFetchIdentityFailedToExtractRemoteAddress()
126+
{
127+
$this->userContext->method('getUserId')->willReturn(null);
128+
$this->remoteAddress->method('getRemoteAddress')->willReturn(false);
129+
$this->expectException(RuntimeException::class);
130+
$this->expectExceptionMessage(__('Failed to extract remote address')->getText());
131+
$this->model->fetchIdentity();
132+
}
133+
}

app/code/Magento/Authorization/etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@
2424
</arguments>
2525
</type>
2626
<preference for="Magento\Authorization\Model\UserContextInterface" type="Magento\Authorization\Model\CompositeUserContext"/>
27+
<preference for="Magento\Framework\App\Backpressure\IdentityProviderInterface"
28+
type="Magento\Authorization\Model\IdentityProvider"/>
2729
</config>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
"We can't find the role for the user you wanted.","We can't find the role for the user you wanted."
22
"Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log.","Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log."
3+
"User type not defined","User type not defined"
4+
"Failed to extract remote address","Failed to extract remote address"
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Checkout\Model\Backpressure;
10+
11+
use Magento\Framework\Webapi\Backpressure\BackpressureRequestTypeExtractorInterface;
12+
use Magento\Quote\Model\Backpressure\OrderLimitConfigManager;
13+
14+
/**
15+
* Identifies which checkout related functionality needs backpressure management
16+
*/
17+
class WebapiRequestTypeExtractor implements BackpressureRequestTypeExtractorInterface
18+
{
19+
private const METHOD = 'savePaymentInformationAndPlaceOrder';
20+
21+
/**
22+
* @var OrderLimitConfigManager
23+
*/
24+
private OrderLimitConfigManager $config;
25+
26+
/**
27+
* @param OrderLimitConfigManager $config
28+
*/
29+
public function __construct(OrderLimitConfigManager $config)
30+
{
31+
$this->config = $config;
32+
}
33+
34+
/**
35+
* @inheritDoc
36+
*/
37+
public function extract(string $service, string $method, string $endpoint): ?string
38+
{
39+
return self::METHOD === $method && $this->config->isEnforcementEnabled()
40+
? OrderLimitConfigManager::REQUEST_TYPE_ID
41+
: null;
42+
}
43+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Checkout\Test\Unit\Model\Backpressure;
9+
10+
use Magento\Checkout\Model\Backpressure\WebapiRequestTypeExtractor;
11+
use Magento\Quote\Model\Backpressure\OrderLimitConfigManager;
12+
use PHPUnit\Framework\MockObject\MockObject;
13+
use PHPUnit\Framework\TestCase;
14+
15+
/**
16+
* Tests the WebapiRequestTypeExtractor class
17+
*/
18+
class WebapiRequestTypeExtractorTest extends TestCase
19+
{
20+
/**
21+
* @var OrderLimitConfigManager|MockObject
22+
*/
23+
private $orderLimitConfigManagerMock;
24+
25+
/**
26+
* @var WebapiRequestTypeExtractor
27+
*/
28+
private WebapiRequestTypeExtractor $webapiRequestTypeExtractor;
29+
30+
/**
31+
* @inheritDoc
32+
*/
33+
protected function setUp(): void
34+
{
35+
$this->orderLimitConfigManagerMock = $this->createMock(OrderLimitConfigManager::class);
36+
37+
$this->webapiRequestTypeExtractor = new WebapiRequestTypeExtractor($this->orderLimitConfigManagerMock);
38+
}
39+
40+
/**
41+
* @param bool $isEnforcementEnabled
42+
* @param string $method
43+
* @param string|null $expected
44+
* @dataProvider dataProvider
45+
*/
46+
public function testExtract(bool $isEnforcementEnabled, string $method, $expected)
47+
{
48+
$this->orderLimitConfigManagerMock->method('isEnforcementEnabled')->willReturn($isEnforcementEnabled);
49+
50+
$this->assertEquals(
51+
$expected,
52+
$this->webapiRequestTypeExtractor->extract('someService', $method, 'someEndpoint')
53+
);
54+
}
55+
56+
/**
57+
* @return array
58+
*/
59+
public function dataProvider(): array
60+
{
61+
return [
62+
[false, 'someMethod', null],
63+
[false, 'savePaymentInformationAndPlaceOrder', null],
64+
[true, 'savePaymentInformationAndPlaceOrder', 'quote-order'],
65+
];
66+
}
67+
}

app/code/Magento/Checkout/etc/di.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@
5454
type="Magento\Checkout\Model\CaptchaPaymentProcessingRateLimiter" />
5555
<preference for="Magento\Checkout\Api\PaymentSavingRateLimiterInterface"
5656
type="Magento\Checkout\Model\CaptchaPaymentSavingRateLimiter" />
57+
<type name="Magento\Framework\Webapi\Backpressure\CompositeRequestTypeExtractor">
58+
<arguments>
59+
<argument name="extractors" xsi:type="array">
60+
<item name="checkout" xsi:type="object">
61+
Magento\Checkout\Model\Backpressure\WebapiRequestTypeExtractor
62+
</item>
63+
</argument>
64+
</arguments>
65+
</type>
5766
<type name="Magento\Customer\Model\ResourceModel\Customer">
5867
<plugin name="recollect_quote_on_customer_group_change" type="Magento\Checkout\Model\Plugin\RecollectQuoteOnCustomerGroupChange"/>
5968
</type>

0 commit comments

Comments
 (0)