diff --git a/app/code/Magento/AdminAdobeIms/Block/Adminhtml/System/Config/Form/Field/Disabled.php b/app/code/Magento/AdminAdobeIms/Block/Adminhtml/System/Config/Form/Field/Disabled.php new file mode 100644 index 0000000000000..e4c8b99998884 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Block/Adminhtml/System/Config/Form/Field/Disabled.php @@ -0,0 +1,51 @@ +imsConfig = $imsConfig; + } + + /** + * Return an empty string for the render if our module is enabled + * + * @param AbstractElement $element + * @return string + */ + public function render(AbstractElement $element): string + { + if ($this->imsConfig->enabled() === false) { + return parent::render($element); + } + return ''; + } +} diff --git a/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Delete.php b/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Delete.php new file mode 100644 index 0000000000000..db629fecb1567 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Delete.php @@ -0,0 +1,55 @@ +_objectManager->get(Session::class)->getUser(); + $userId = (int)$this->getRequest()->getPost('user_id'); + + if ($userId) { + if ((int)$currentUser->getId() === $userId) { + $this->messageManager->addError(__('You cannot delete your own account.')); + $this->_redirect('adminhtml/*/edit', ['user_id' => $userId]); + return; + } + try { + $currentUserPassword = (string)$this->getRequest()->getPost(UserEdit::CURRENT_USER_PASSWORD_FIELD); + $currentUser->performIdentityCheck($currentUserPassword); + /** @var User $model */ + $model = $this->_userFactory->create(); + $model->setId($userId); + $model->delete(); + $this->messageManager->addSuccess(__('You deleted the user.')); + $this->_redirect('adminhtml/*/'); + return; + } catch (\Exception $e) { + $this->messageManager->addError($e->getMessage()); + $this->_redirect('adminhtml/*/edit', ['user_id' => $this->getRequest()->getParam('user_id')]); + return; + } + } + $this->messageManager->addError(__('We can\'t find a user to delete.')); + $this->_redirect('adminhtml/*/'); + } +} diff --git a/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Save.php b/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Save.php new file mode 100644 index 0000000000000..7db2bd065b3ec --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Save.php @@ -0,0 +1,147 @@ +securityCookie instanceof SecurityCookie)) { + return \Magento\Framework\App\ObjectManager::getInstance()->get(SecurityCookie::class); + } else { + return $this->securityCookie; + } + } + + /** + * @inheritDoc + * @return ResultInterface|ResponseInterface + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function execute() + { + $userId = (int)$this->getRequest()->getParam('user_id'); + $data = $this->getRequest()->getPostValue(); + if (array_key_exists('form_key', $data)) { + unset($data['form_key']); + } + if (!$data) { + $this->_redirect('adminhtml/*/'); + return; + } + + /** @var $model User */ + $model = $this->_userFactory->create()->load($userId); + if ($userId && $model->isObjectNew()) { + $this->messageManager->addError(__('This user no longer exists.')); + $this->_redirect('adminhtml/*/'); + return; + } + $model->setData($this->_getAdminUserData($data)); + $userRoles = $this->getRequest()->getParam('roles', []); + if (count($userRoles)) { + $model->setRoleId($userRoles[0]); + } + + /** @var $currentUser User */ + $currentUser = $this->_objectManager->get(Session::class)->getUser(); + if ($userId == $currentUser->getId() + && $this->_objectManager->get(Locale::class) + ->isValid($data['interface_locale']) + ) { + $this->_objectManager->get( + Manager::class + )->switchBackendInterfaceLocale( + $data['interface_locale'] + ); + } + + /** Before updating admin user data, ensure that password of current admin user is entered and is correct */ + try { + $currentUser->performIdentityCheck($data[Main::CURRENT_USER_PASSWORD_FIELD] ?? ''); + $model->save(); + + $this->messageManager->addSuccess(__('You saved the user.')); + $this->_getSession()->setUserData(false); + $this->_redirect('adminhtml/*/'); + + $model->sendNotificationEmailsIfRequired(); + } catch (UserLockedException $e) { + $this->_auth->logout(); + $this->getSecurityCookie()->setLogoutReasonCookie( + AdminSessionsManager::LOGOUT_REASON_USER_LOCKED + ); + $this->_redirect('*'); + } catch (NotificationExceptionInterface $exception) { + $this->messageManager->addErrorMessage($exception->getMessage()); + } catch (AuthenticationException $e) { + $this->messageManager->addError( + __('The password entered for the current user is invalid. Verify the password and try again.') + ); + $this->redirectToEdit($model, $data); + } catch (Exception $e) { + $messages = $e->getMessages(); + $this->messageManager->addMessages($messages); + $this->redirectToEdit($model, $data); + } catch (LocalizedException $e) { + if ($e->getMessage()) { + $this->messageManager->addError($e->getMessage()); + } + $this->redirectToEdit($model, $data); + } + } + + /** + * Redirect to Edit form. + * + * @param User $model + * @param array $data + * @return void + */ + private function redirectToEdit(User $model, array $data) + { + $this->_getSession()->setUserData($data); + $arguments = $model->getId() ? ['user_id' => $model->getId()] : []; + $arguments = array_merge($arguments, ['_current' => true, 'active_tab' => '']); + $this->_redirect('adminhtml/*/edit', $arguments); + } +} diff --git a/app/code/Magento/AdminAdobeIms/Model/ImsConnection.php b/app/code/Magento/AdminAdobeIms/Model/ImsConnection.php index a415592231a92..319b92249af01 100644 --- a/app/code/Magento/AdminAdobeIms/Model/ImsConnection.php +++ b/app/code/Magento/AdminAdobeIms/Model/ImsConnection.php @@ -31,10 +31,12 @@ class ImsConnection * @var ImsConfig */ private ImsConfig $imsConfig; + /** * @var Json */ private Json $json; + /** * @var GetToken */ @@ -114,12 +116,12 @@ private function getAuthorizationLocation(string $authUrl): string private function validateResponse(Curl $curl): void { if (isset($curl->getHeaders()['location'])) { - if ( - preg_match( - '/error=([a-z_]+)/i', - $curl->getHeaders()['location'], - $error - ) && isset($error[0], $error[1]) + if (preg_match( + '/error=([a-z_]+)/i', + $curl->getHeaders()['location'], + $error + ) + && isset($error[0], $error[1]) ) { throw new InvalidArgumentException( __('Could not connect to Adobe IMS Service: %1.', $error[1]) @@ -135,6 +137,39 @@ private function validateResponse(Curl $curl): void } /** + * Verify if access_token is valid + * + * @param string $code + * @return bool + * @throws AuthorizationException + */ + public function verifyToken(string $code): bool + { + $curl = $this->curlFactory->create(); + + $curl->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + $curl->addHeader('cache-control', 'no-cache'); + $curl->addHeader('Authorization', 'Bearer ' . $code); + + $curl->post( + $this->imsConfig->getVerifyUrl($code), + [] + ); + + if ($curl->getBody() === '') { + throw new AuthorizationException( + __('Could not verify the access_token') + ); + } + + $body = $this->json->unserialize($curl->getBody()); + + return isset($body['valid']) && $body['valid'] === true; + } + + /** + * Get token response + * * @param string $code * @return TokenResponseInterface * @throws AdobeImsTokenAuthorizationException @@ -151,6 +186,8 @@ public function getTokenResponse(string $code): TokenResponseInterface } /** + * Get profile url + * * @param string $code * @return array|bool|float|int|mixed|string|null * @throws AuthorizationException diff --git a/app/code/Magento/AdminAdobeIms/Model/User.php b/app/code/Magento/AdminAdobeIms/Model/User.php index e966326437d86..04c572238166b 100644 --- a/app/code/Magento/AdminAdobeIms/Model/User.php +++ b/app/code/Magento/AdminAdobeIms/Model/User.php @@ -26,6 +26,8 @@ protected function _construct() } /** + * Load user by email + * * @param string $email * @return array */ @@ -50,7 +52,7 @@ public function loginByUsername($username): User } /** - * Authenticate user name and save loaded record + * Authenticate username and save loaded record * * @param string $username * @return bool @@ -67,7 +69,7 @@ public function authenticateByUsername(string $username): bool ['username' => $username, 'user' => $this] ); $this->loadByUsername($username); - $sensitive = $config ? $username == $this->getUserName() : true; + $sensitive = !$config || $username === $this->getUserName(); if ($sensitive && $this->getId()) { $result = $this->verifyIdentityWithoutPassword(); } @@ -87,7 +89,7 @@ public function authenticateByUsername(string $username): bool * Check if the current user account is active. * * @return bool - * @throws \Magento\Framework\Exception\AuthenticationException + * @throws AuthenticationException */ public function verifyIdentityWithoutPassword(): bool { @@ -105,4 +107,4 @@ public function verifyIdentityWithoutPassword(): bool return true; } -} \ No newline at end of file +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/AdminForgotPasswordPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/AdminForgotPasswordPlugin.php index 4d3ddca967568..4a1154d2f7e4b 100644 --- a/app/code/Magento/AdminAdobeIms/Plugin/AdminForgotPasswordPlugin.php +++ b/app/code/Magento/AdminAdobeIms/Plugin/AdminForgotPasswordPlugin.php @@ -9,6 +9,7 @@ namespace Magento\AdminAdobeIms\Plugin; use Magento\AdminAdobeIms\Service\ImsConfig; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\Result\RedirectFactory; use Magento\Framework\Message\ManagerInterface as MessageManagerInterface; use Magento\User\Controller\Adminhtml\Auth\Forgotpassword; @@ -46,14 +47,16 @@ public function __construct( } /** + * Disable forgot password method when AdminAdobeIMS Module is enabled + * * @param Forgotpassword $subject * @param callable $proceed - * @return \Magento\Framework\Controller\Result\Redirect + * @return Redirect + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundExecute(Forgotpassword $subject, callable $proceed) + public function aroundExecute(Forgotpassword $subject, callable $proceed): Redirect { if ($this->imsConfig->enabled()) { - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ $resultRedirect = $this->redirectFactory->create(); $this->messageManager->addErrorMessage(__('Please sign in with Adobe ID')); return $resultRedirect->setPath('admin'); diff --git a/app/code/Magento/AdminAdobeIms/Plugin/CheckUserLoginBackendObserverPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/CheckUserLoginBackendObserverPlugin.php index 25040c9d93cff..87ababed41dd0 100644 --- a/app/code/Magento/AdminAdobeIms/Plugin/CheckUserLoginBackendObserverPlugin.php +++ b/app/code/Magento/AdminAdobeIms/Plugin/CheckUserLoginBackendObserverPlugin.php @@ -28,14 +28,21 @@ public function __construct(ImsConfig $imsConfig) } /** + * Disable login captcha when AdminAdobeIMS Module is enabled + * * @param CheckUserLoginBackendObserver $subject * @param callable $proceed * @param Observer $observer + * @return CheckUserLoginBackendObserver|void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundExecute(CheckUserLoginBackendObserver $subject, callable $proceed, Observer $observer) - { + public function aroundExecute( + CheckUserLoginBackendObserver $subject, + callable $proceed, + Observer $observer + ) { if (!$this->imsConfig->enabled()) { return $proceed($observer); } } -} \ No newline at end of file +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/DisableForcedPasswordChangePlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/DisableForcedPasswordChangePlugin.php new file mode 100644 index 0000000000000..bc358492d5851 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/DisableForcedPasswordChangePlugin.php @@ -0,0 +1,43 @@ +imsConfig = $imsConfig; + } + + /** + * Disable forced password change when our module is active + * + * @param ObserverConfig $subject + * @param bool $result + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterIsPasswordChangeForced(ObserverConfig $subject, bool $result): bool + { + if ($this->imsConfig->enabled() === false) { + return $result; + } + return false; + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/DisablePasswordResetPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/DisablePasswordResetPlugin.php new file mode 100644 index 0000000000000..c6c59cf374fa1 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/DisablePasswordResetPlugin.php @@ -0,0 +1,43 @@ +imsConfig = $imsConfig; + } + + /** + * Since the password reset module treats 0 as disabled we can just return 0 when our module is enabled + * + * @param ObserverConfig $subject + * @param int $result + * @return int + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetAdminPasswordLifetime(ObserverConfig $subject, int $result): int + { + if ($this->imsConfig->enabled() === false) { + return $result; + } + return 0; + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/RemoveCurrentUserVerificationFieldsPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/RemoveCurrentUserVerificationFieldsPlugin.php new file mode 100644 index 0000000000000..820017750e842 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/RemoveCurrentUserVerificationFieldsPlugin.php @@ -0,0 +1,55 @@ +imsConfig = $imsConfig; + } + + /** + * Do not add user verification fieldset when AdminAdobeIms module is enabled + * + * @param Form $subject + * @param callable $proceed + * @param AbstractElement $element + * @param bool $after + * @return Form|void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundAddElement( + Form $subject, + callable $proceed, + AbstractElement $element, + bool $after = false + ) { + if ($this->imsConfig->enabled() !== true) { + return $proceed($element, $after); + } + + if ($element->getId() !== 'current_user_verification_fieldset') { + return $proceed($element, $after); + } + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/RemovePasswordFieldsPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/RemovePasswordFieldsPlugin.php new file mode 100644 index 0000000000000..9d6439b69f237 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/RemovePasswordFieldsPlugin.php @@ -0,0 +1,65 @@ +imsConfig = $imsConfig; + } + + /** + * Remove Password field when AdminAdobeIMS module is enabled + * + * @param Fieldset $subject + * @param AbstractElement $result + * @param string $elementId + * @param string $type + * @param array $config + * @param bool $after + * @param bool $isAdvanced + * @return AbstractElement + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterAddField( + Fieldset $subject, + AbstractElement $result, + $elementId, + $type, + $config, + $after = false, + $isAdvanced = false + ): AbstractElement { + if ($this->imsConfig->enabled() !== true) { + return $result; + } + + if ($subject->getId() === 'base_fieldset' + && ( + $elementId === 'password' + || $elementId === 'confirmation' + ) + ) { + $subject->removeField($elementId); + } + return $result; + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/RemoveUserValidationRulesPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/RemoveUserValidationRulesPlugin.php new file mode 100644 index 0000000000000..18961af4f9ec4 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/RemoveUserValidationRulesPlugin.php @@ -0,0 +1,72 @@ +imsConfig = $imsConfig; + } + + /** + * Remove password rule for validator + * + * @param UserValidationRules $subject + * @param callable $proceed + * @param DataObject $validator + * @return DataObject + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundAddPasswordRules( + UserValidationRules $subject, + callable $proceed, + DataObject $validator + ): DataObject { + if ($this->imsConfig->enabled() !== true) { + return $proceed($validator); + } + + return $validator; + } + + /** + * Remove password confirmation rule for validator + * + * @param UserValidationRules $subject + * @param callable $proceed + * @param DataObject $validator + * @param string $passwordConfirmation + * @return DataObject + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundAddPasswordConfirmationRule( + UserValidationRules $subject, + callable $proceed, + DataObject $validator, + string $passwordConfirmation + ): DataObject { + if ($this->imsConfig->enabled() !== true) { + return $proceed($validator, $passwordConfirmation); + } + + return $validator; + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/ReplaceVerifyIdentityWithImsPlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/ReplaceVerifyIdentityWithImsPlugin.php new file mode 100644 index 0000000000000..59cb4162d7cc1 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/ReplaceVerifyIdentityWithImsPlugin.php @@ -0,0 +1,114 @@ +imsConfig = $imsConfig; + $this->imsConnection = $imsConnection; + $this->userProfileRepository = $userProfileRepository; + $this->encryptor = $encryptor; + } + + /** + * Verify if the current user has a valid access_token as we do not ask for a password + * + * @param User $subject + * @param callable $proceed + * @param string $password + * @return bool + * @throws AuthenticationException + * @throws AuthorizationException + * @throws NoSuchEntityException + */ + public function aroundVerifyIdentity(User $subject, callable $proceed, string $password): bool + { + if ($this->imsConfig->enabled() !== true) { + return $proceed($password); + } + + $valid = $this->verifyImsToken($subject); + if ($valid) { + return true; + } + + throw new AuthenticationException( + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) + ); + } + + /** + * Get and verify IMS Token for current user + * + * @param User $user + * @return bool + * @throws AuthenticationException + * @throws AuthorizationException + * @throws NoSuchEntityException + */ + private function verifyImsToken(User $user): bool + { + $userProfile = $this->userProfileRepository->getByUserId((int) $user->getId()); + if (!$userProfile) { + throw new AuthenticationException( + __( + 'The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.' + ) + ); + } + + $accessToken = $this->encryptor->decrypt($userProfile->getAccessToken()); + return $this->imsConnection->verifyToken($accessToken); + } +} diff --git a/app/code/Magento/AdminAdobeIms/Plugin/UserSavePlugin.php b/app/code/Magento/AdminAdobeIms/Plugin/UserSavePlugin.php new file mode 100644 index 0000000000000..8c2ce36cc0614 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Plugin/UserSavePlugin.php @@ -0,0 +1,72 @@ +imsConfig = $imsConfig; + } + + /** + * Generate a random password for new user when AdminAdobeIMS Module is enabled + * + * We create a random password for the user, because User Object needs to have a password + * and this way we do not need to update the db_schema or add a lot of complex preferences + * + * @param User $subject + * @return array + * @throws Exception + */ + public function beforeBeforeSave(User $subject): array + { + if ($this->imsConfig->enabled() !== true) { + return []; + } + + if (!$subject->getId()) { + $subject->setPassword($this->generateRandomPassword()); + } + + return []; + } + + /** + * Generate random password string + * + * @return string + * @throws Exception + */ + private function generateRandomPassword(): string + { + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.'; + + $pass = []; + $alphaLength = strlen($characters) - 1; + for ($i = 0; $i < 100; $i++) { + $n = random_int(0, $alphaLength); + $pass[] = $characters[$n]; + } + return implode($pass); + } +} diff --git a/app/code/Magento/AdminAdobeIms/README.md b/app/code/Magento/AdminAdobeIms/README.md index 761fee00701ab..b8e69c7277f4d 100644 --- a/app/code/Magento/AdminAdobeIms/README.md +++ b/app/code/Magento/AdminAdobeIms/README.md @@ -120,3 +120,21 @@ Errors are logged into the `/var/log/admin_adobe_ims.log` file. Logging can be enabled or disabled in the config on changing the value for `adobe_ims\integration\logging_enabled` or in the Magento Admin Configuration under `Advanced > Developer > Debug`. \ There you can switch the toggle for `Enable Logging for Admin Adobe IMS Module` + +# Password usage in Admin UI +When the AdobeAdminIMS Module is enabled, we do not need any password fields in the magento admin backend anymore. + +So we removed the "Current User Verification" fields and also the "Password" and "Password Confirmation" fields of the user forms. +This is done by the Plugins `\Magento\AdminAdobeIms\Plugin\RemoveCurrentUserVerificationFieldsPlugin` and `\Magento\AdminAdobeIms\Plugin\RemovePasswordFieldsPlugin` Plugins. +Additionally, we need `\Magento\AdminAdobeIms\Plugin\RemoveUserValidationRulesPlugin` to remove the password from the form validation. + +As we don't need the current user password anymore, we have the `\Magento\AdminAdobeIms\Plugin\ReplaceVerifyIdentityWithImsPlugin` Plugin to verify the `access_token` of the current admin user in AdobeIMS and only proceed when it is still valid. + +For the newly created user will be a random password generated, as we did not modify the admin_user table, where the password field can not be null. +This is done in the `\Magento\AdminAdobeIms\Plugin\UserSavePlugin`. + +We also disabled the "Change password in 30 days" functionally, as we don't need the magento admin user password for the login. +This can be found in the `\Magento\AdminAdobeIms\Plugin\DisableForcedPasswordChangePlugin` and `\Magento\AdminAdobeIms\Plugin\DisablePasswordResetPlugin` Plugins. + +When the AdminAdobeIMS Module is disabled, the user can not be log in when using an empty password. +Instead, the forgot password function must be used to reset the password. diff --git a/app/code/Magento/AdminAdobeIms/Service/ImsConfig.php b/app/code/Magento/AdminAdobeIms/Service/ImsConfig.php index 945d5ea6d7379..25f8b731e53c8 100644 --- a/app/code/Magento/AdminAdobeIms/Service/ImsConfig.php +++ b/app/code/Magento/AdminAdobeIms/Service/ImsConfig.php @@ -27,6 +27,7 @@ class ImsConfig extends Config public const XML_PATH_AUTH_URL_PATTERN = 'adobe_ims/integration/auth_url_pattern'; public const XML_PATH_PROFILE_URL = 'adobe_ims/integration/profile_url'; public const XML_PATH_NEW_ADMIN_EMAIL_TEMPLATE = 'adobe_ims/email/content_template'; + public const XML_PATH_VERIFY_URL = 'adobe_ims/integration/verify_url'; private const OAUTH_CALLBACK_URL = 'adobe_ims_auth/oauth/'; public const XML_PATH_LOGOUT_URL = 'adobe_ims/integration/logout_url'; @@ -161,6 +162,21 @@ public function getProfileUrl(): string ); } + /** + * Get Token verification url + * + * @param string $code + * @return string + */ + public function getVerifyUrl(string $code): string + { + return str_replace( + ['#{token}', '#{client_id}'], + [$code, $this->getApiKey()], + $this->scopeConfig->getValue(self::XML_PATH_VERIFY_URL) + ); + } + /** * Update config using config writer * diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminAdobeImsSignInActionGroup.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminAdobeImsSignInActionGroup.xml new file mode 100644 index 0000000000000..86bb9d082fa1d --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminAdobeImsSignInActionGroup.xml @@ -0,0 +1,33 @@ + + + + + + + Admin Adobe IMS Sign in + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminCreateUserWithoutPasswordActionGroup.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminCreateUserWithoutPasswordActionGroup.xml new file mode 100644 index 0000000000000..9c7d5c6bb5a4c --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/ActionGroup/AdminCreateUserWithoutPasswordActionGroup.xml @@ -0,0 +1,33 @@ + + + + + + + Goes to the Admin Users grid page. Clicks on Create User. Fills in the provided Role and User. + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Data/AdminAdobeImsErrorMessageData.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Data/AdminAdobeImsErrorMessageData.xml deleted file mode 100644 index 6aad8181494ae..0000000000000 --- a/app/code/Magento/AdminAdobeIms/Test/Mftf/Data/AdminAdobeImsErrorMessageData.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - {{_CREDS.magento/admin_adobe_ims/client_id}} - {{_CREDS.magento/admin_adobe_ims/client_key}} - - diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminAdobeImsSignInSection.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminAdobeImsSignInSection.xml new file mode 100644 index 0000000000000..3ad84469136a8 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminAdobeImsSignInSection.xml @@ -0,0 +1,19 @@ + + + + +
+ + + + + + +
+
diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminSignInErrorMessageSection.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminSignInErrorMessageSection.xml index 93ab4fe47be38..8dcdb8b8b8ba3 100644 --- a/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminSignInErrorMessageSection.xml +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Section/AdminSignInErrorMessageSection.xml @@ -11,9 +11,9 @@
+ selector=".admin-adobe-ims-message-container .admin-adobe-ims-message-header"/> + selector=".admin-adobe-ims-message-container .admin-adobe-ims-message-message"/>
diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsDisabledInfoCommandTest.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsDisabledInfoCommandTest.xml index 24a4b77d23dba..d542a273391dc 100644 --- a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsDisabledInfoCommandTest.xml +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsDisabledInfoCommandTest.xml @@ -16,6 +16,7 @@ + diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsEnabledInfoCommandTest.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsEnabledInfoCommandTest.xml index d6726edfdf377..0ed8b0e7e90aa 100644 --- a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsEnabledInfoCommandTest.xml +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/AdminAdobeImsEnabledInfoCommandTest.xml @@ -16,12 +16,13 @@ + - + - + diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CallbackWithoutCodeRedirectsToAdminLoginTest.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CallbackWithoutCodeRedirectsToAdminLoginTest.xml index 5d80dd294cedc..88330c9cd56f6 100644 --- a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CallbackWithoutCodeRedirectsToAdminLoginTest.xml +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CallbackWithoutCodeRedirectsToAdminLoginTest.xml @@ -18,6 +18,7 @@ + diff --git a/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CreateNewUserWithoutPasswordTest.xml b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CreateNewUserWithoutPasswordTest.xml new file mode 100644 index 0000000000000..88883fb7ca6eb --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Mftf/Test/CreateNewUserWithoutPasswordTest.xml @@ -0,0 +1,34 @@ + + + + + + + + + <description value="Create a new admin user without password when AdminAdobeImsModule is enabled"/> + <severity value="CRITICAL"/> + <group value="admin_ims"/> + <testCaseId value="CABPI-227"/> + </annotations> + <before> + <actionGroup ref="AdminEnableAdobeImsActionGroup" stepKey="enableAdminAdobeImsModule" /> + </before> + <after> + <actionGroup ref="AdminDisableAdobeImsActionGroup" stepKey="disableAdminAdobeImsModule" /> + </after> + + <actionGroup ref="AdminAdobeImsSignInActionGroup" stepKey="adminLogin"/> + + <actionGroup ref="AdminCreateUserWithoutPasswordActionGroup" stepKey="createAdminUser"> + <argument name="user" value="activeAdmin"/> + <argument name="role" value="roleDefaultAdministrator"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/AdminAdobeIms/Test/Unit/Command/AdminAdobeImsEnableCommandTest.php b/app/code/Magento/AdminAdobeIms/Test/Unit/Command/AdminAdobeImsEnableCommandTest.php new file mode 100755 index 0000000000000..57261d289b771 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Unit/Command/AdminAdobeImsEnableCommandTest.php @@ -0,0 +1,178 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\AdminAdobeIms\Test\Unit\Command; + +use Exception; +use Magento\AdminAdobeIms\Console\Command\AdminAdobeImsEnableCommand; +use Magento\AdminAdobeIms\Model\ImsConnection; +use Magento\AdminAdobeIms\Service\ImsCommandOptionService; +use Magento\AdminAdobeIms\Service\ImsConfig; +use Magento\Framework\App\Cache\Type\Config; +use Magento\Framework\App\Cache\TypeListInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Helper\DebugFormatterHelper; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\ProcessHelper; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class AdminAdobeImsEnableCommandTest extends TestCase +{ + /** + * @var ImsConfig + */ + private $imsConfigMock; + + /** + * @var ImsConnection + */ + private $imsConnectionMock; + + /** + * @var ImsCommandOptionService + */ + private $imsCommandOptionService; + + /** + * @var TypeListInterface + */ + private $typeListInterface; + + /** + * @var QuestionHelper + */ + private $questionHelperMock; + + /** + * @var AdminAdobeImsEnableCommand + */ + private $enableCommand; + + protected function setUp(): void + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->imsConfigMock = $this->createMock(ImsConfig::class); + $this->imsConnectionMock = $this->createMock(ImsConnection::class); + $this->imsCommandOptionService = $this->createMock(ImsCommandOptionService::class); + $this->typeListInterface = $this->createMock(TypeListInterface::class); + + $this->questionHelperMock = $this->getMockBuilder(QuestionHelper::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->enableCommand = $objectManagerHelper->getObject( + AdminAdobeImsEnableCommand::class, + [ + 'imsConfig' => $this->imsConfigMock, + 'imsConnection' => $this->imsConnectionMock, + 'imsCommandOptionService' => $this->imsCommandOptionService, + 'cacheTypeList' => $this->typeListInterface, + ] + ); + } + + /** + * Test AdminAdobeIms Command calls cache clear and return correct message + * + * @param bool $testAuthMode + * @param InvokedCountMatcher$enableMethodCallExpection + * @param InvokedCountMatcher $cleanMethodCallExpection + * @param string $outputMessage + * @return void + * @throws Exception + * @dataProvider cliCommandProvider + */ + public function testAdminAdobeImsModuleEnableWillClearCacheWhenSuccessful( + bool $testAuthMode, + InvokedCountMatcher $enableMethodCallExpection, + InvokedCountMatcher $cleanMethodCallExpection, + string $outputMessage + ): void { + $inputMock = $this->getMockBuilder(InputInterface::class) + ->getMockForAbstractClass(); + + $outputMock = $this->getMockBuilder(OutputInterface::class) + ->getMockForAbstractClass(); + + $this->questionHelperMock->method('ask')->willReturn('ORGId'); + + $this->imsCommandOptionService->method('getOrganizationId')->willReturn('orgId'); + $this->imsCommandOptionService->method('getClientId')->willReturn('clientId'); + $this->imsCommandOptionService->method('getClientSecret')->willReturn('clientSecret'); + + $this->imsConnectionMock->method('testAuth') + ->willReturn($testAuthMode); + + $this->imsConfigMock + ->expects($enableMethodCallExpection) + ->method('enableModule'); + + $this->typeListInterface + ->expects($cleanMethodCallExpection) + ->method('cleanType') + ->with(Config::TYPE_IDENTIFIER); + + $outputMock->expects($this->once()) + ->method('writeln') + ->with($outputMessage, null) + ->willReturnSelf(); + + $this->enableCommand->setHelperSet($this->getHelperSet()); + $this->enableCommand->run($inputMock, $outputMock); + } + + /** + * DataProvider for CLI Command + * + * @return array[] + */ + public function cliCommandProvider(): array + { + return [ + [ + true, + $this->once(), + $this->once(), + 'Admin Adobe IMS integration is enabled' + ], + [ + false, + $this->never(), + $this->never(), + '<error>The Client ID, Client Secret and Organization ID are required ' . + 'when enabling the Admin Adobe IMS Module</error>' + ], + ]; + } + + /** + * Create a new HelperSet + * + * @return HelperSet + */ + private function getHelperSet(): HelperSet + { + return new HelperSet([ + new FormatterHelper(), + new DebugFormatterHelper(), + new ProcessHelper(), + 'question' => $this->questionHelperMock, + ]); + } +} diff --git a/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/AdminForgotPasswordPluginTest.php b/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/AdminForgotPasswordPluginTest.php new file mode 100644 index 0000000000000..1211b458bbee5 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/AdminForgotPasswordPluginTest.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\AdminAdobeIms\Test\Unit\Plugin; + +use Magento\AdminAdobeIms\Plugin\AdminForgotPasswordPlugin; +use Magento\AdminAdobeIms\Service\ImsConfig; +use Magento\Framework\Controller\Result\Redirect; +use Magento\Framework\Controller\Result\RedirectFactory; +use Magento\Framework\Message\ManagerInterface as MessageManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\User\Controller\Adminhtml\Auth\Forgotpassword; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +class AdminForgotPasswordPluginTest extends TestCase +{ + /** + * @var AdminForgotPasswordPlugin + */ + private $plugin; + + /** + * @var RedirectFactory|MockObject + */ + private $redirectFactory; + + /** + * @var ImsConfig|MockObject + */ + private $imsConfigMock; + + /** + * @var MessageManagerInterface|MockObject + */ + private $messageManagerMock; + + /** + * @return void + */ + protected function setUp(): void + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->redirectFactory = $this->createMock(RedirectFactory::class); + $this->imsConfigMock = $this->createMock(ImsConfig::class); + $this->messageManagerMock = $this->createMock(MessageManagerInterface::class); + + $this->plugin = $objectManagerHelper->getObject( + AdminForgotPasswordPlugin::class, + [ + 'redirectFactory' => $this->redirectFactory, + 'imsConfig' => $this->imsConfigMock, + 'messageManager' => $this->messageManagerMock, + ] + ); + } + + /** + * Test plugin redirects to admin login when AdminAdobeIms Module is enabled + * + * @return void + */ + public function testPluginRedirectsToLoginPageWhenModuleIsEnabled(): void + { + $subject = $this->createMock(Forgotpassword::class); + $redirect = $this->createMock(Redirect::class); + $redirect->method('setPath') + ->willReturnSelf(); + + $this->imsConfigMock + ->expects($this->once()) + ->method('enabled') + ->willReturn(true); + + $this->redirectFactory + ->expects($this->once()) + ->method('create') + ->willReturn($redirect); + + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with('Please sign in with Adobe ID', null) + ->willReturnSelf(); + + $closure = function () { + return $this->createMock(Redirect::class); + }; + + $this->assertEquals($redirect, $this->plugin->aroundExecute($subject, $closure)); + } + + /** + * Test plugin proceeds when AdminAdobeIms Module is disabled + * + * @return void + */ + public function testPluginProceedsWhenModuleIsDisabled(): void + { + $subject = $this->createMock(Forgotpassword::class); + $redirect = $this->createMock(Redirect::class); + + $this->imsConfigMock + ->expects($this->once()) + ->method('enabled') + ->willReturn(false); + + $this->redirectFactory + ->expects($this->never()) + ->method('create') + ->willReturn($redirect); + + $this->messageManagerMock->expects($this->never()) + ->method('addErrorMessage') + ->with('Please sign in with Adobe ID', null) + ->willReturnSelf(); + + $closure = function () { + return $this->createMock(Redirect::class); + }; + + $this->assertEquals($redirect, $this->plugin->aroundExecute($subject, $closure)); + } +} diff --git a/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/ReplaceVerifyIdentityWithImsPluginTest.php b/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/ReplaceVerifyIdentityWithImsPluginTest.php new file mode 100644 index 0000000000000..dfb6802127b8c --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/Test/Unit/Plugin/ReplaceVerifyIdentityWithImsPluginTest.php @@ -0,0 +1,178 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\AdminAdobeIms\Test\Unit\Plugin; + +use Magento\AdminAdobeIms\Model\ImsConnection; +use Magento\AdminAdobeIms\Plugin\ReplaceVerifyIdentityWithImsPlugin; +use Magento\AdminAdobeIms\Service\ImsConfig; +use Magento\AdobeIms\Model\UserProfileRepository; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\AuthenticationException; +use Magento\Framework\Exception\AuthorizationException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\User\Model\User; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +class ReplaceVerifyIdentityWithImsPluginTest extends TestCase +{ + /** + * @var ReplaceVerifyIdentityWithImsPlugin + */ + private $plugin; + + /** + * @var ImsConfig|MockObject + */ + private $imsConfigMock; + + /** + * @var ImsConnection|MockObject + */ + private $imsConnectionMock; + + /** + * @var UserProfileRepository|MockObject + */ + private $userProfileRepository; + + /** + * @var EncryptorInterface|MockObject + */ + private $encryptor; + + /** + * @return void + */ + protected function setUp(): void + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->imsConfigMock = $this->createMock(ImsConfig::class); + $this->imsConnectionMock = $this->createMock(ImsConnection::class); + $this->userProfileRepository = $this->createMock(UserProfileRepository::class); + $this->encryptor = $this->createMock(EncryptorInterface::class); + + $this->plugin = $objectManagerHelper->getObject( + ReplaceVerifyIdentityWithImsPlugin::class, + [ + 'imsConfig' => $this->imsConfigMock, + 'imsConnection' => $this->imsConnectionMock, + 'userProfileRepository' => $this->userProfileRepository, + 'encryptor' => $this->encryptor, + ] + ); + } + + /** + * Test plugin proceeds when AdminAdobeIms Module is disabled + * + * @return void + * @throws AuthenticationException + * @throws AuthorizationException + * @throws NoSuchEntityException + */ + public function testAroundVerifyIdentityCallsProceedWhenModuleIsDisabled(): void + { + $this->imsConfigMock + ->expects($this->once()) + ->method('enabled') + ->willReturn(false); + + $subject = $this->createMock(User::class); + + $expectedResult = true; + + $proceed = function () use ($expectedResult) { + return $expectedResult; + }; + + $this->imsConnectionMock + ->expects($this->never()) + ->method('verifyToken'); + + $this->assertEquals($expectedResult, $this->plugin->aroundVerifyIdentity($subject, $proceed, '')); + } + + /** + * Test Plugin verifies access_token + * + * @return void + * @throws AuthenticationException + * @throws AuthorizationException + * @throws NoSuchEntityException + */ + public function testAroundVerifyIdentityVerifiesAccessTokenWhenModuleIsEnabled(): void + { + $this->imsConfigMock + ->expects($this->once()) + ->method('enabled') + ->willReturn(true); + + $subject = $this->createMock(User::class); + + $this->encryptor + ->expects($this->once()) + ->method('decrypt') + ->willReturn('accessToken'); + + $this->imsConnectionMock + ->expects($this->once()) + ->method('verifyToken') + ->willReturn(true); + + $expectedResult = true; + + $proceed = function () use ($expectedResult) { + return $expectedResult; + }; + + $this->assertEquals($expectedResult, $this->plugin->aroundVerifyIdentity($subject, $proceed, '')); + } + + /** + * Test Plugin throws exception when access_token is invalid + * + * @return void + * @throws AuthenticationException + * @throws AuthorizationException + * @throws NoSuchEntityException + */ + public function testAroundVerifyIdentityThrowsExceptionOnInvalidToken(): void + { + $this->imsConfigMock + ->expects($this->once()) + ->method('enabled') + ->willReturn(true); + + $subject = $this->createMock(User::class); + + $this->encryptor + ->expects($this->once()) + ->method('decrypt') + ->willReturn('accessToken'); + + $this->imsConnectionMock + ->expects($this->once()) + ->method('verifyToken') + ->willReturn(false); + + $this->expectException(AuthenticationException::class); + $this->expectExceptionMessage('The account sign-in was incorrect or your account is disabled temporarily. ' + . 'Please wait and try again later.'); + + $expectedResult = true; + + $proceed = function () use ($expectedResult) { + return $expectedResult; + }; + + $this->assertEquals($expectedResult, $this->plugin->aroundVerifyIdentity($subject, $proceed, '')); + } +} diff --git a/app/code/Magento/AdminAdobeIms/composer.json b/app/code/Magento/AdminAdobeIms/composer.json index d62441957ffbc..722dc22c094d3 100644 --- a/app/code/Magento/AdminAdobeIms/composer.json +++ b/app/code/Magento/AdminAdobeIms/composer.json @@ -17,7 +17,8 @@ "magento/module-user": "*", "magento/module-backend": "*", "magento/module-store": "*", - "magento/module-email": "*" + "magento/module-email": "*", + "magento/module-security": "*" }, "suggest": { "magento/module-theme": "*" diff --git a/app/code/Magento/AdminAdobeIms/etc/adminhtml/di.xml b/app/code/Magento/AdminAdobeIms/etc/adminhtml/di.xml index 9278571218e2f..cbe8e14bb7d5b 100644 --- a/app/code/Magento/AdminAdobeIms/etc/adminhtml/di.xml +++ b/app/code/Magento/AdminAdobeIms/etc/adminhtml/di.xml @@ -12,6 +12,11 @@ <preference for="Magento\Backend\Model\Auth\Credential\StorageInterface" type="Magento\AdminAdobeIms\Model\User" /> + <preference for="Magento\User\Controller\Adminhtml\User\Save" + type="Magento\AdminAdobeIms\Controller\Adminhtml\User\Save"/> + <preference for="Magento\User\Controller\Adminhtml\User\Delete" + type="Magento\AdminAdobeIms\Controller\Adminhtml\User\Delete"/> + <type name="Magento\Framework\View\Result\Layout"> <plugin name="add_adobe_ims_layout_handle" type="Magento\AdminAdobeIms\Plugin\AddAdobeImsLayoutHandlePlugin" /> @@ -29,4 +34,32 @@ </argument> </arguments> </type> + + <type name="Magento\Framework\Data\Form"> + <plugin name="aroundAddElement" + type="Magento\AdminAdobeIms\Plugin\RemoveCurrentUserVerificationFieldsPlugin"/> + </type> + + <type name="Magento\Framework\Data\Form\Element\Fieldset"> + <plugin name="afterAddField" + type="Magento\AdminAdobeIms\Plugin\RemovePasswordFieldsPlugin"/> + </type> + + <type name="Magento\User\Model\User"> + <plugin name="aroundVerifyIdentity" + type="Magento\AdminAdobeIms\Plugin\ReplaceVerifyIdentityWithImsPlugin"/> + <plugin name="user_save" + type="Magento\AdminAdobeIms\Plugin\UserSavePlugin"/> + </type> + + <type name="Magento\User\Model\UserValidationRules"> + <plugin name="remove_user_validation_rules" + type="Magento\AdminAdobeIms\Plugin\RemoveUserValidationRulesPlugin"/> + </type> + <type name="Magento\User\Model\Backend\Config\ObserverConfig"> + <plugin name="disable_password_reset" + type="Magento\AdminAdobeIms\Plugin\DisablePasswordResetPlugin"/> + <plugin name="disable_forced_password_change" + type="Magento\AdminAdobeIms\Plugin\DisableForcedPasswordChangePlugin"/> + </type> </config> diff --git a/app/code/Magento/AdminAdobeIms/etc/adminhtml/system.xml b/app/code/Magento/AdminAdobeIms/etc/adminhtml/system.xml index e80f56f7074b7..7582650a32858 100644 --- a/app/code/Magento/AdminAdobeIms/etc/adminhtml/system.xml +++ b/app/code/Magento/AdminAdobeIms/etc/adminhtml/system.xml @@ -23,5 +23,15 @@ </field> </group> </section> + <section id="admin"> + <group id="security"> + <field id="password_lifetime"> + <frontend_model>Magento\AdminAdobeIms\Block\Adminhtml\System\Config\Form\Field\Disabled</frontend_model> + </field> + <field id="password_is_forced"> + <frontend_model>Magento\AdminAdobeIms\Block\Adminhtml\System\Config\Form\Field\Disabled</frontend_model> + </field> + </group> + </section> </system> </config> diff --git a/app/code/Magento/AdminAdobeIms/etc/config.xml b/app/code/Magento/AdminAdobeIms/etc/config.xml index e543f7fa069ca..9eb3815913115 100644 --- a/app/code/Magento/AdminAdobeIms/etc/config.xml +++ b/app/code/Magento/AdminAdobeIms/etc/config.xml @@ -16,6 +16,7 @@ <token_url>https://ims-na1-stg1.adobelogin.com/ims/token</token_url> <profile_url><![CDATA[https://ims-na1-stg1.adobelogin.com/ims/profile/v1?client_id=#{client_id}]]></profile_url> <logout_url><![CDATA[https://ims-na1-stg1.adobelogin.com/ims/logout/v1?access_token=#{access_token}&client_id=#{client_id}&client_secret=#{client_secret}]]></logout_url> + <verify_url><![CDATA[https://ims-na1-stg1.adobelogin.com/ims/validate_token/v1?token=#{token}&client_id=#{client_id}&type=access_token]]></verify_url> </integration> <email> <header_template>admin_adobe_ims_email_header_template</header_template> diff --git a/app/code/Magento/AdminAdobeIms/etc/module.xml b/app/code/Magento/AdminAdobeIms/etc/module.xml index 45ac5f1e97715..364eac06705d2 100644 --- a/app/code/Magento/AdminAdobeIms/etc/module.xml +++ b/app/code/Magento/AdminAdobeIms/etc/module.xml @@ -16,6 +16,7 @@ <module name="Magento_Captcha"/> <module name="Magento_Store"/> <module name="Magento_Email"/> + <module name="Magento_Security"/> </sequence> </module> </config> diff --git a/app/code/Magento/AdminAdobeIms/view/adminhtml/requirejs-config.js b/app/code/Magento/AdminAdobeIms/view/adminhtml/requirejs-config.js index 8d569daede092..c64fbfd055453 100644 --- a/app/code/Magento/AdminAdobeIms/view/adminhtml/requirejs-config.js +++ b/app/code/Magento/AdminAdobeIms/view/adminhtml/requirejs-config.js @@ -2,6 +2,7 @@ var config = { map: { '*': { loadIcons: 'Magento_AdminAdobeIms/js/loadicons', + deleteUserAccount: 'Magento_AdminAdobeIms/js/delete-user-account' } } }; diff --git a/app/code/Magento/AdminAdobeIms/view/adminhtml/templates/messages/admin_adobe_ims_messages.phtml b/app/code/Magento/AdminAdobeIms/view/adminhtml/templates/messages/admin_adobe_ims_messages.phtml index 14c350e83163d..ed2e2067fa446 100644 --- a/app/code/Magento/AdminAdobeIms/view/adminhtml/templates/messages/admin_adobe_ims_messages.phtml +++ b/app/code/Magento/AdminAdobeIms/view/adminhtml/templates/messages/admin_adobe_ims_messages.phtml @@ -12,7 +12,7 @@ use Magento\Framework\Escaper; * @var $escaper Escaper */ ?> -<div class="spectrum-InLineAlert spectrum-InLineAlert--error"> +<div class="spectrum-InLineAlert spectrum-InLineAlert--error admin-adobe-ims-message-container"> <svg class="spectrum-Icon spectrum-Icon--sizeM spectrum-InLineAlert-icon" focusable="false" aria-hidden="true"> <use xlink:href="#spectrum-icon-18-Alert" /> </svg> diff --git a/app/code/Magento/AdminAdobeIms/view/adminhtml/web/js/delete-user-account.js b/app/code/Magento/AdminAdobeIms/view/adminhtml/web/js/delete-user-account.js new file mode 100644 index 0000000000000..97a5651097451 --- /dev/null +++ b/app/code/Magento/AdminAdobeIms/view/adminhtml/web/js/delete-user-account.js @@ -0,0 +1,26 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery' +], function ($) { + 'use strict'; + + var postData; + + return function (params, elem) { + + elem.on('click', function () { + + postData = { + 'data': { + 'user_id': params.objId, + 'current_password': $('[name="current_password"]').val() + } + }; + + window.deleteConfirm(params.message, params.url, postData); + }); + }; +}); diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt index efc7e669b3605..e3fb20a2d07a1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt @@ -109,3 +109,4 @@ app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/Product/ app/code/Magento/Elasticsearch/Model/Layer/Search/ItemCollectionProvider.php app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml +app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt index 6b0007f58830b..b789dbc101d0e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt @@ -21,3 +21,4 @@ dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTe dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php app/code/Magento/Developer/Test/Unit/Console/Command/DevTestsRunCommandTest.php app/code/Magento/OfflineShipping/Test/Unit/Model/ResourceModel/Carrier/Tablerate/CSV/ColumnResolverTest.php +app/code/Magento/AdminAdobeIms/Controller/Adminhtml/User/Save.php