Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoginAsCustomer GraphQL #30130

Merged
merged 21 commits into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\LoginAsCustomerGraphQl\Model\LoginAsCustomer;

use Magento\Customer\Model\CustomerFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Integration\Model\Oauth\TokenFactory;
use Magento\Store\Api\Data\StoreInterface;
use Exception;

/**
* Create customer token from customer email
*
* Class CreateCustomerToken
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, remove the unnecessary comments. These comments are auto-generated and the only purpose is to add extra lines to your code.

Suggested change
* Class CreateCustomerToken

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

*/
class CreateCustomerToken
{
/**
* @var CustomerFactory
*/
private $customerFactory;

/**
* @var TokenFactory
*/
private $tokenModelFactory;

/**
* CreateCustomerToken constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, remove unecessary comments

Suggested change
* CreateCustomerToken constructor.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

* @param TokenFactory $tokenModelFactory
* @param CustomerFactory $customerFactory
*/
public function __construct(
TokenFactory $tokenModelFactory,
CustomerFactory $customerFactory
) {
$this->tokenModelFactory = $tokenModelFactory;
$this->customerFactory= $customerFactory;
}

/**
* Get admin user token
*
* @param string $email
* @param StoreInterface $store
* @return array
* @throws GraphQlInputException
* @throws LocalizedException
*/
public function execute(string $email, StoreInterface $store): array
{
$customer = $this->customerFactory->create()->setWebsiteId((int)$store->getId())->loadByEmail($email);

/* Check if customer email exist */
if (!$customer->getId()) {
throw new GraphQlInputException(
__('Customer email provided does not exist')
);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to validate that the 'allow_remote_shopping_assistance' setting is enabled for the customer. See https://github.com/magento/architecture/pull/414/files#diff-ccdc60253a5ea983cb68248c51500c3cdc077232bd52ded6cb08d4af9cba8d2bR39

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

try {
return [
"customer_token" => $this->tokenModelFactory->create()
->createCustomerToken($customer->getId())->getToken()
];
} catch (Exception $e) {
throw new LocalizedException(
__(
'Unable to generate tokens. '
. 'Please wait and try again later.'
)
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\LoginAsCustomerGraphQl\Model\Resolver;

use Magento\Framework\AuthorizationInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\Resolver\Value;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\LoginAsCustomerApi\Api\ConfigInterface as LoginAsCustomerConfig;
use Magento\LoginAsCustomerGraphQl\Model\LoginAsCustomer\CreateCustomerToken;

/**
* Gets customer token
*/
class RequestCustomerToken implements ResolverInterface
{
/**
* @var LoginAsCustomerConfig
*/
private $config;

/**
* @var AuthorizationInterface
*/
private $authorization;

/**
* @var CreateCustomerToken
*/
private $createCustomerToken;

/**
* RequestCustomerToken constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, omit a short description of constructors. They don't provide useful information but use one more line of the file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, remove unnecessary comments

* @param AuthorizationInterface $authorization
* @param LoginAsCustomerConfig $config
* @param CreateCustomerToken $createCustomerToken
*/
public function __construct(
AuthorizationInterface $authorization,
LoginAsCustomerConfig $config,
CreateCustomerToken $createCustomerToken
) {
$this->authorization = $authorization;
$this->config = $config;
$this->createCustomerToken = $createCustomerToken;
}

/**
* Get Customer Token using email
*
* @param Field $field
* @param ContextInterface $context
* @param ResolveInfo $info
* @param array|null $value
* @param array|null $args
* @return Value|mixed|void
* @throws GraphQlAuthorizationException|GraphQlNoSuchEntityException|LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
$isAllowedLogin = $this->authorization->isAllowed('Magento_LoginAsCustomer::login');
$isEnabled = $this->config->isEnabled();

/* Get input params */
try {
$args = $args['input'];
} catch (NoSuchEntityException $e) {
throw new GraphQlInputException(__('Check input params.'));
}

if (empty(trim($args['customer_email'], " "))) {
throw new GraphQlInputException(__('Specify the "customer email" value.'));
}

$this->validateUser($context);

if (!$isAllowedLogin || !$isEnabled) {
throw new GraphQlAuthorizationException(
__('Login as Customer is disabled.')
);
}
return $this->createCustomerToken->execute(
$args['customer_email'],
$context->getExtensionAttributes()->getStore()
);
}

/**
* Check if its an admin user
*
* @param ContextInterface $context
* @throws GraphQlAuthorizationException
*/
private function validateUser(ContextInterface $context): void
{
if ($context->getUserType() !== 2 || $context->getUserId() === 0) {
throw new GraphQlAuthorizationException(__('The current customer isn\'t authorized.'));
}
}
}
51 changes: 51 additions & 0 deletions app/code/Magento/LoginAsCustomerGraphQl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Module Magento LoginAsCustomerGraphQl

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is all of the info in this README relevant for this module?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keharper I have formatted readme file with the relevant content, Thanks

``magento/module-loginascustomergraphql``

- [Main Functionalities](#markdown-header-main-functionalities)
- [Installation](#markdown-header-installation)
- [Configuration](#markdown-header-configuration)
- [Specifications](#markdown-header-specifications)
- [Attributes](#markdown-header-attributes)


## Main Functionalities
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.

## Installation
\* = in production please use the `--keep-generated` option

### Type 1: Zip file

- Unzip the zip file in `app/code/Magento`
- Enable the module by running `php bin/magento module:enable Magento_LoginAsCustomerGraphQl`
- Apply database updates by running `php bin/magento setup:upgrade`\*
- Flush the cache by running `php bin/magento cache:flush`

### Type 2: Composer

- Make the module available in a composer repository for example:
- private repository `repo.magento.com`
- public repository `packagist.org`
- public github repository as vcs
- Add the composer repository to the configuration by running `composer config repositories.repo.magento.com composer https://repo.magento.com/`
- Install the module composer by running `composer require magento/module-loginascustomergraphql`
- enable the module by running `php bin/magento module:enable Magento_LoginAsCustomerGraphQl`
- apply database updates by running `php bin/magento setup:upgrade`\*
- Flush the cache by running `php bin/magento cache:flush`


## Configuration




## Specifications




## Attributes



26 changes: 26 additions & 0 deletions app/code/Magento/LoginAsCustomerGraphQl/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "magento/module-login-as-customer-graph-ql",
"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.",
"require": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, provide all the dependencies you use within the scope of the module. Like LoginAsCustomerApi, Customer, Store etc

"php": "~7.3.0||~7.4.0",
"magento/framework": "*",
"magento/module-login-as-customer-api": "*",
"magento/module-integration": "*",
"magento/module-store": "*",
"magento/module-customer": "*",
"magento/module-catalog-graph-ql": "*"
},
"type": "magento2-module",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Magento\\LoginAsCustomerGraphQl\\": ""
}
}
}
17 changes: 17 additions & 0 deletions app/code/Magento/LoginAsCustomerGraphQl/etc/module.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" ?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_LoginAsCustomerGraphQl">
<sequence>
<module name="Magento_LoginAsCustomer"/>
<module name="Magento_Customer"/>
<module name="Magento_Authorization"/>
<module name="Magento_GraphQl"/>
</sequence>
</module>
</config>
30 changes: 30 additions & 0 deletions app/code/Magento/LoginAsCustomerGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright © Magento, Inc. All rights reserved.
# See COPYING.txt for license details.

type Mutation {
generateCustomerTokenAsAdmin(
input: GenerateCustomerTokenAsAdminInput!
): GenerateCustomerTokenAsAdminOutput
@resolver(class: "Magento\\LoginAsCustomerGraphQl\\Model\\Resolver\\RequestCustomerToken")
@doc(description: "Request a token using Customer email")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@doc(description: "Request a token using Customer email")
@doc(description: "Request a customer token so that an administrator can perform remote shopping assistance")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

input GenerateCustomerTokenAsAdminInput {
customer_email: String!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
customer_email: String!
customer_email: String! @doc(description: "The email address of the customer requesting remote shopping assistance")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

type GenerateCustomerTokenAsAdminOutput {
customer_token: String!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
customer_token: String!
customer_token: String! @doc(description: "The generated customer token")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

type Customer {
allow_remote_shopping_assistance: Boolean!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allow_remote_shopping_assistance: Boolean!
allow_remote_shopping_assistance: Boolean! @doc(description: "Indicates whether the customer has enabled remote shopping assistance")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

input CustomerCreateInput {
allow_remote_shopping_assistance: Boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allow_remote_shopping_assistance: Boolean
allow_remote_shopping_assistance: Boolean @doc(description: "Indicates whether the customer has enabled remote shopping assistance")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

input CustomerUpdateInput {
allow_remote_shopping_assistance: Boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allow_remote_shopping_assistance: Boolean
allow_remote_shopping_assistance: Boolean @doc(description: "Indicates whether the customer has enabled remote shopping assistance")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolvers using these inputs will need to be updated to ensure allow_remote_shopping_assistance is persisted.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@cspruiell cspruiell Dec 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the changes for this. The createCustomer & updateCustomer mutations need to be updated so that allow_remote_shopping_assistance is persisted

mutation { createCustomerV2(input: { email: "test@example.com" firstname: "Test" lastname: "Magento" password: "T3stP4ssw0rd" allow_remote_shopping_assistance: true}) { customer { firstname lastname email allow_remote_shopping_assistance } } }

14 changes: 14 additions & 0 deletions app/code/Magento/LoginAsCustomerGraphQl/registration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Magento_LoginAsCustomerGraphQl',
__DIR__
);
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
"magento/module-integration": "*",
"magento/module-layered-navigation": "*",
"magento/module-login-as-customer": "*",
"magento/module-login-as-customer-graph-ql": "*",
"magento/module-login-as-customer-admin-ui": "*",
"magento/module-login-as-customer-api": "*",
"magento/module-login-as-customer-assistance": "*",
Expand Down
Loading