Skip to content

Commit 45b1693

Browse files
committed
Merge remote-tracking branch 'origin/LoginAsCustomerGraphQL' into HB-PR-delivery-Dec
2 parents 49fff90 + 5b20227 commit 45b1693

File tree

18 files changed

+1271
-253
lines changed

18 files changed

+1271
-253
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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\LoginAsCustomerGraphQl\Model\LoginAsCustomer;
9+
10+
use Magento\Customer\Model\CustomerFactory;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Integration\Model\Oauth\TokenFactory;
14+
use Magento\Store\Api\Data\StoreInterface;
15+
use Exception;
16+
17+
/**
18+
* Create customer token from customer email
19+
*/
20+
class CreateCustomerToken
21+
{
22+
/**
23+
* @var CustomerFactory
24+
*/
25+
private $customerFactory;
26+
27+
/**
28+
* @var TokenFactory
29+
*/
30+
private $tokenModelFactory;
31+
32+
/**
33+
* @param TokenFactory $tokenModelFactory
34+
* @param CustomerFactory $customerFactory
35+
*/
36+
public function __construct(
37+
TokenFactory $tokenModelFactory,
38+
CustomerFactory $customerFactory
39+
) {
40+
$this->tokenModelFactory = $tokenModelFactory;
41+
$this->customerFactory= $customerFactory;
42+
}
43+
44+
/**
45+
* Get admin user token
46+
*
47+
* @param string $email
48+
* @param StoreInterface $store
49+
* @return array
50+
* @throws GraphQlInputException
51+
* @throws LocalizedException
52+
*/
53+
public function execute(string $email, StoreInterface $store): array
54+
{
55+
$customer = $this->customerFactory->create()->setWebsiteId((int)$store->getId())->loadByEmail($email);
56+
57+
/* Check if customer email exist */
58+
if (!$customer->getId()) {
59+
throw new GraphQlInputException(
60+
__('Customer email provided does not exist')
61+
);
62+
}
63+
64+
try {
65+
return [
66+
"customer_token" => $this->tokenModelFactory->create()
67+
->createCustomerToken($customer->getId())->getToken()
68+
];
69+
} catch (Exception $e) {
70+
throw new LocalizedException(
71+
__(
72+
'Unable to generate tokens. '
73+
. 'Please wait and try again later.'
74+
)
75+
);
76+
}
77+
}
78+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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\LoginAsCustomerGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\AuthorizationInterface;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\Exception\NoSuchEntityException;
13+
use Magento\Framework\GraphQl\Config\Element\Field;
14+
use Magento\Framework\GraphQl\Query\Resolver\Value;
15+
use Magento\Framework\GraphQl\Query\ResolverInterface;
16+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
18+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
19+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
20+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
21+
use Magento\LoginAsCustomerApi\Api\ConfigInterface as LoginAsCustomerConfig;
22+
use Magento\LoginAsCustomerGraphQl\Model\LoginAsCustomer\CreateCustomerToken;
23+
24+
/**
25+
* Gets customer token
26+
*/
27+
class RequestCustomerToken implements ResolverInterface
28+
{
29+
/**
30+
* @var LoginAsCustomerConfig
31+
*/
32+
private $config;
33+
34+
/**
35+
* @var AuthorizationInterface
36+
*/
37+
private $authorization;
38+
39+
/**
40+
* @var CreateCustomerToken
41+
*/
42+
private $createCustomerToken;
43+
44+
/**
45+
* @param AuthorizationInterface $authorization
46+
* @param LoginAsCustomerConfig $config
47+
* @param CreateCustomerToken $createCustomerToken
48+
*/
49+
public function __construct(
50+
AuthorizationInterface $authorization,
51+
LoginAsCustomerConfig $config,
52+
CreateCustomerToken $createCustomerToken
53+
) {
54+
$this->authorization = $authorization;
55+
$this->config = $config;
56+
$this->createCustomerToken = $createCustomerToken;
57+
}
58+
59+
/**
60+
* Get Customer Token using email
61+
*
62+
* @param Field $field
63+
* @param ContextInterface $context
64+
* @param ResolveInfo $info
65+
* @param array|null $value
66+
* @param array|null $args
67+
* @return Value|mixed|void
68+
* @throws GraphQlAuthorizationException|GraphQlNoSuchEntityException|LocalizedException
69+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
70+
*/
71+
public function resolve(
72+
Field $field,
73+
$context,
74+
ResolveInfo $info,
75+
array $value = null,
76+
array $args = null
77+
) {
78+
$isAllowedLogin = $this->authorization->isAllowed('Magento_LoginAsCustomer::login');
79+
$isAlllowedShoppingAssistance = $this->authorization->isAllowed('Magento_LoginAsCustomer::allow_shopping_assistance');
80+
$isEnabled = $this->config->isEnabled();
81+
82+
/* Get input params */
83+
try {
84+
$args = $args['input'];
85+
} catch (NoSuchEntityException $e) {
86+
throw new GraphQlInputException(__('Check input params.'));
87+
}
88+
89+
if (empty(trim($args['customer_email'], " "))) {
90+
throw new GraphQlInputException(__('Specify the "customer email" value.'));
91+
}
92+
93+
$this->validateUser($context);
94+
95+
if (!$isAllowedLogin || !$isEnabled) {
96+
throw new GraphQlAuthorizationException(
97+
__('Login as Customer is disabled.')
98+
);
99+
}
100+
101+
if (!$isAlllowedShoppingAssistance) {
102+
throw new GraphQlAuthorizationException(
103+
__('Allow remote shopping assistance is disabled.')
104+
);
105+
}
106+
107+
return $this->createCustomerToken->execute(
108+
$args['customer_email'],
109+
$context->getExtensionAttributes()->getStore()
110+
);
111+
}
112+
113+
/**
114+
* Check if its an admin user
115+
*
116+
* @param ContextInterface $context
117+
* @throws GraphQlAuthorizationException
118+
*/
119+
private function validateUser(ContextInterface $context): void
120+
{
121+
if ($context->getUserType() !== 2 || $context->getUserId() === 0) {
122+
throw new GraphQlAuthorizationException(__('The current customer isn\'t authorized.'));
123+
}
124+
}
125+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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\LoginAsCustomerGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
12+
use Magento\Framework\GraphQl\Query\Resolver\Value;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
use Magento\LoginAsCustomerAssistance\Model\IsAssistanceEnabled;
16+
17+
/**
18+
* Determines if the customer allows remote shopping assistance
19+
*/
20+
class isRemoteShoppingAssistanceAllowed implements ResolverInterface
21+
{
22+
/**
23+
* @var IsAssistanceEnabled
24+
*/
25+
private $isAssistanceEnabled;
26+
27+
/**
28+
* @param IsAssistanceEnabled $isAssistanceEnabled
29+
*/
30+
public function __construct(
31+
IsAssistanceEnabled $isAssistanceEnabled
32+
) {
33+
$this->isAssistanceEnabled = $isAssistanceEnabled;
34+
}
35+
36+
/**
37+
* Determines if remote shopping assistance is allowed for the specified customer
38+
*
39+
* @param Field $field
40+
* @param ContextInterface $context
41+
* @param ResolveInfo $info
42+
* @param array|null $value
43+
* @param array|null $args
44+
* @return Value|mixed|void
45+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
46+
*/
47+
public function resolve(
48+
Field $field,
49+
$context,
50+
ResolveInfo $info,
51+
array $value = null,
52+
array $args = null
53+
) {
54+
return $this->isAssistanceEnabled->execute((int)$value['model']->getId());
55+
}
56+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
8+
namespace Magento\LoginAsCustomerGraphQl\Plugin;
9+
10+
11+
use Magento\Customer\Api\Data\CustomerExtensionFactory;
12+
use Magento\Customer\Api\Data\CustomerInterface;
13+
use Magento\Framework\Api\DataObjectHelper;
14+
use Magento\LoginAsCustomerAssistance\Model\IsAssistanceEnabled;
15+
16+
class DataObjectHelperPlugin
17+
{
18+
/**
19+
* @var CustomerExtensionFactory
20+
*/
21+
private $customerExtensionFactory;
22+
23+
/**
24+
* @param CustomerExtensionFactory $customerExtensionFactory
25+
*/
26+
public function __construct(
27+
CustomerExtensionFactory $customerExtensionFactory
28+
) {
29+
$this->customerExtensionFactory = $customerExtensionFactory;
30+
}
31+
32+
/**
33+
* Add assistance_allowed extension attribute value to Customer instance.
34+
*
35+
* @param DataObjectHelper $subject
36+
* @param DataObjectHelper $result
37+
* @param mixed $dataObject
38+
* @param array $data
39+
* @param string $interfaceName
40+
* @return DataObjectHelper
41+
*
42+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
43+
*/
44+
public function afterPopulateWithArray(
45+
DataObjectHelper $subject,
46+
DataObjectHelper $result,
47+
Object $dataObject,
48+
array $data,
49+
string $interfaceName
50+
) {
51+
if ($interfaceName === CustomerInterface::class
52+
&& array_key_exists('allow_remote_shopping_assistance', $data)) {
53+
$isLoginAsCustomerEnabled = $data['allow_remote_shopping_assistance'];
54+
$extensionAttributes = $dataObject->getExtensionAttributes();
55+
if (null === $extensionAttributes) {
56+
$extensionAttributes = $this->customerExtensionFactory->create();
57+
}
58+
$extensionAttributes->setAssistanceAllowed(
59+
$isLoginAsCustomerEnabled ? IsAssistanceEnabled::ALLOWED : IsAssistanceEnabled::DENIED
60+
);
61+
$dataObject->setExtensionAttributes($extensionAttributes);
62+
}
63+
return $result;
64+
}
65+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# LoginAsCustomerGraphQl
2+
3+
**LoginAsCustomerGraphQl** provides flexible login as a customer so a merchant or merchant admin can log into an end customer's account to assist them with their account.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "magento/module-login-as-customer-graph-ql",
3+
"description": "Flexible login as a customer so a merchant or merchant admin can log into an end customer's account to assist them with their account.",
4+
"require": {
5+
"php": "~7.3.0||~7.4.0",
6+
"magento/framework": "*",
7+
"magento/module-login-as-customer-api": "*",
8+
"magento/module-login-as-customer-assistance": "*",
9+
"magento/module-integration": "*",
10+
"magento/module-store": "*",
11+
"magento/module-customer": "*"
12+
},
13+
"suggest": {
14+
"magento/module-login-as-customer": "*"
15+
},
16+
"type": "magento2-module",
17+
"license": [
18+
"OSL-3.0",
19+
"AFL-3.0"
20+
],
21+
"autoload": {
22+
"files": [
23+
"registration.php"
24+
],
25+
"psr-4": {
26+
"Magento\\LoginAsCustomerGraphQl\\": ""
27+
}
28+
}
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\Framework\Api\DataObjectHelper">
10+
<plugin name="add_allow_remote_shopping_assistance_to_customer"
11+
type="Magento\LoginAsCustomerGraphQl\Plugin\DataObjectHelperPlugin"/>
12+
</type>
13+
</config>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" ?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9+
<module name="Magento_LoginAsCustomerGraphQl">
10+
<sequence>
11+
<module name="Magento_LoginAsCustomerApi"/>
12+
<module name="Magento_Customer"/>
13+
<module name="Magento_Store"/>
14+
<module name="Magento_CatalogGraphQl"/>
15+
</sequence>
16+
</module>
17+
</config>

0 commit comments

Comments
 (0)