diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
index 4c4daccb9017..8afbdf7425ca 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorInfo.php
@@ -49,6 +49,7 @@ class ValidatorInfo extends Validator
* @var IoFile
*/
private $ioFile;
+
/**
* @var NotProtectedExtension
*/
@@ -147,12 +148,14 @@ private function validatePath(array $optionValuePath): bool
{
foreach ([$optionValuePath['quote_path'], $optionValuePath['order_path']] as $path) {
$pathInfo = $this->ioFile->getPathInfo($path);
- if (isset($pathInfo['extension'])) {
- if (!$this->fileValidator->isValid($pathInfo['extension'])) {
- return false;
- }
+
+ if (isset($pathInfo['extension'])
+ && (empty($pathInfo['extension']) || !$this->fileValidator->isValid($pathInfo['extension']))
+ ) {
+ return false;
}
}
+
return true;
}
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertActiveProductImageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertActiveProductImageActionGroup.xml
index 0e7da54bd402..c2f0b7f11636 100644
--- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertActiveProductImageActionGroup.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertActiveProductImageActionGroup.xml
@@ -12,6 +12,6 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml
index 393a45f0973d..6d44eed04c1e 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml
@@ -216,7 +216,7 @@
-
+
diff --git a/app/code/Magento/Config/Model/Config/Backend/File.php b/app/code/Magento/Config/Model/Config/Backend/File.php
index 6a6b0257f7b3..560ce351e69a 100644
--- a/app/code/Magento/Config/Model/Config/Backend/File.php
+++ b/app/code/Magento/Config/Model/Config/Backend/File.php
@@ -278,8 +278,10 @@ protected function _getAllowedExtensions()
*/
private function setValueAfterValidation(string $value): void
{
- // avoid intercepting value
- if (preg_match('/[^a-z0-9_\/\\-\\.]+/i', $value)) {
+ if (preg_match('/[^a-z0-9_\/\\-\\.]+/i', $value)
+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
+ || !$this->_mediaDirectory->isFile($this->_getUploadDir() . DIRECTORY_SEPARATOR . basename($value))
+ ) {
throw new LocalizedException(__('Invalid file name'));
}
diff --git a/app/code/Magento/Customer/Model/Plugin/UpdateCustomer.php b/app/code/Magento/Customer/Model/Plugin/UpdateCustomer.php
index e8d4bdaec2d2..28b9bd5cc651 100644
--- a/app/code/Magento/Customer/Model/Plugin/UpdateCustomer.php
+++ b/app/code/Magento/Customer/Model/Plugin/UpdateCustomer.php
@@ -63,7 +63,9 @@ public function beforeSave(
$customerId === $customerSessionId
) {
$customer = $this->getUpdatedCustomer($customerRepository->getById($customerId), $customer);
- } elseif ($userType === UserContextInterface::USER_TYPE_ADMIN && $customerId) {
+ } elseif ($customerId && in_array($userType, [UserContextInterface::USER_TYPE_ADMIN,
+ UserContextInterface::USER_TYPE_INTEGRATION], true)
+ ) {
$customer = $this->getUpdatedCustomer($customerRepository->getById($customerId), $customer);
}
diff --git a/app/code/Magento/EncryptionKey/Console/Command/UpdateEncryptionKeyCommand.php b/app/code/Magento/EncryptionKey/Console/Command/UpdateEncryptionKeyCommand.php
new file mode 100644
index 000000000000..cd6ffb432316
--- /dev/null
+++ b/app/code/Magento/EncryptionKey/Console/Command/UpdateEncryptionKeyCommand.php
@@ -0,0 +1,135 @@
+encryptor = $encryptor;
+ $this->cache = $cache;
+ $this->writer = $writer;
+ $this->random = $random;
+
+ parent::__construct();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function configure()
+ {
+ $this->setName('encryption:key:change');
+ $this->setDescription('Change the encryption key inside the env.php file.');
+ $this->addOption(
+ 'key',
+ 'k',
+ InputOption::VALUE_OPTIONAL,
+ 'Key has to be a 32 characters long string. If not provided, a random key will be generated.'
+ );
+
+ parent::configure();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ try {
+ $key = $input->getOption('key');
+
+ if (!empty($key)) {
+ $this->encryptor->validateKey($key);
+ }
+
+ $this->updateEncryptionKey($key);
+ $this->cache->clean();
+
+ $output->writeln('Encryption key has been updated successfully.');
+
+ return Command::SUCCESS;
+ } catch (\Exception $e) {
+ $output->writeln('' . $e->getMessage() . '');
+ return Command::FAILURE;
+ }
+ }
+
+ /**
+ * Update encryption key
+ *
+ * @param string|null $key
+ * @return void
+ * @throws FileSystemException
+ */
+ private function updateEncryptionKey(string $key = null): void
+ {
+ // prepare new key, encryptor and new configuration segment
+ if (!$this->writer->checkIfWritable()) {
+ throw new FileSystemException(__('Deployment configuration file is not writable.'));
+ }
+
+ if (null === $key) {
+ $key = ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX .
+ $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE);
+ }
+
+ $this->encryptor->setNewKey($key);
+
+ $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV);
+ $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys());
+
+ $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()];
+
+ $this->writer->saveConfig($configData);
+ }
+}
diff --git a/app/code/Magento/EncryptionKey/etc/di.xml b/app/code/Magento/EncryptionKey/etc/di.xml
index b4e471f4e40e..495234759a7f 100644
--- a/app/code/Magento/EncryptionKey/etc/di.xml
+++ b/app/code/Magento/EncryptionKey/etc/di.xml
@@ -11,4 +11,11 @@
Magento\Config\Model\Config\Structure\Proxy
+
+
+
+ - Magento\EncryptionKey\Console\Command\UpdateEncryptionKeyCommand
+
+
+
diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php
index 75022e2b8ad9..d23dc61e497e 100644
--- a/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php
+++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Export/File/Download.php
@@ -16,6 +16,8 @@
use Magento\Framework\Filesystem;
use Magento\ImportExport\Model\LocalizedFileName;
use Throwable;
+use Magento\Framework\Controller\Result\Redirect;
+use Magento\Framework\App\ResponseInterface;
/**
* Controller that download file by name.
@@ -25,7 +27,7 @@ class Download extends ExportController implements HttpGetActionInterface
/**
* Url to this controller
*/
- const URL = 'adminhtml/export_file/download/';
+ public const URL = 'adminhtml/export_file/download/';
/**
* @var FileFactory
@@ -64,13 +66,24 @@ public function __construct(
/**
* Controller basic method implementation.
*
- * @return \Magento\Framework\Controller\Result\Redirect | \Magento\Framework\App\ResponseInterface
+ * @return Redirect|ResponseInterface
*/
public function execute()
{
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('adminhtml/export/index');
+
$fileName = $this->getRequest()->getParam('filename');
+
+ if (empty($fileName)) {
+ $this->messageManager->addErrorMessage(__('Please provide valid export file name'));
+
+ return $resultRedirect;
+ }
+
+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
+ $fileName = basename($fileName);
+
$exportDirectory = $this->filesystem->getDirectoryRead(DirectoryList::VAR_IMPORT_EXPORT);
try {
diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php b/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
index 6fd229f26a1a..f6dbf4eaa443 100644
--- a/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
+++ b/app/code/Magento/ImportExport/Controller/Adminhtml/History/Download.php
@@ -3,11 +3,18 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
+declare(strict_types=1);
+
namespace Magento\ImportExport\Controller\Adminhtml\History;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Controller\ResultInterface;
+use Magento\ImportExport\Helper\Report;
use Magento\ImportExport\Model\Import;
+use Magento\Framework\Controller\Result\Redirect;
+use Magento\Framework\App\ResponseInterface;
/**
* Download history controller
@@ -44,20 +51,27 @@ public function __construct(
/**
* Download backup action
*
- * @return void|\Magento\Backend\App\Action
+ * @return ResponseInterface|Redirect|ResultInterface
+ * @throws \Exception
*/
public function execute()
{
+ $resultRedirect = $this->resultRedirectFactory->create();
+ $resultRedirect->setPath('*/history');
+
+ $fileName = $this->getRequest()->getParam('filename');
+
+ if (empty($fileName)) {
+ return $resultRedirect;
+ }
+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
- $fileName = basename($this->getRequest()->getParam('filename'));
+ $fileName = basename($fileName);
- /** @var \Magento\ImportExport\Helper\Report $reportHelper */
- $reportHelper = $this->_objectManager->get(\Magento\ImportExport\Helper\Report::class);
+ /** @var Report $reportHelper */
+ $reportHelper = $this->_objectManager->get(Report::class);
if (!$reportHelper->importFileExists($fileName)) {
- /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
- $resultRedirect = $this->resultRedirectFactory->create();
- $resultRedirect->setPath('*/history');
return $resultRedirect;
}
diff --git a/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php b/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
index 7c8e06d3f681..ba4bb9c53de6 100644
--- a/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
+++ b/app/code/Magento/ImportExport/Test/Unit/Controller/Adminhtml/History/DownloadTest.php
@@ -8,13 +8,13 @@
namespace Magento\ImportExport\Test\Unit\Controller\Adminhtml\History;
use Magento\Backend\App\Action\Context;
-use Magento\Backend\Model\View\Result\Redirect;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\Response\Http\FileFactory;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Raw;
use Magento\Framework\Controller\Result\RawFactory;
+use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\Result\RedirectFactory;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
use Magento\ImportExport\Controller\Adminhtml\History\Download;
@@ -181,8 +181,7 @@ public function executeDataProvider()
{
return [
'Normal file name' => ['filename.csv', 'filename.csv'],
- 'Relative file name' => ['../../../../../../../../etc/passwd', 'passwd'],
- 'Empty file name' => ['', ''],
+ 'Relative file name' => ['../../../../../../../../etc/passwd', 'passwd']
];
}
@@ -196,4 +195,27 @@ public function testExecuteFileNotFound()
$this->resultRaw->expects($this->never())->method('setContents');
$this->downloadController->execute();
}
+
+ /**
+ * Test execute() with return Redirect
+ * @param string|null $requestFilename
+ * @dataProvider executeWithRedirectDataProvider
+ */
+ public function testExecuteWithRedirect(?string $requestFilename): void
+ {
+ $this->request->method('getParam')->with('filename')->willReturn($requestFilename);
+ $this->resultRaw->expects($this->never())->method('setContents');
+ $this->assertSame($this->redirect, $this->downloadController->execute());
+ }
+
+ /**
+ * @return array
+ */
+ public function executeWithRedirectDataProvider(): array
+ {
+ return [
+ 'null file name' => [null],
+ 'empty file name' => [''],
+ ];
+ }
}
diff --git a/app/code/Magento/Integration/Block/Adminhtml/Integration/Edit/Tab/Info.php b/app/code/Magento/Integration/Block/Adminhtml/Integration/Edit/Tab/Info.php
index 89cad471933e..b97182156d3e 100644
--- a/app/code/Magento/Integration/Block/Adminhtml/Integration/Edit/Tab/Info.php
+++ b/app/code/Magento/Integration/Block/Adminhtml/Integration/Edit/Tab/Info.php
@@ -3,6 +3,9 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
+declare(strict_types=1);
+
namespace Magento\Integration\Block\Adminhtml\Integration\Edit\Tab;
use Magento\Integration\Controller\Adminhtml\Integration;
@@ -19,23 +22,23 @@ class Info extends \Magento\Backend\Block\Widget\Form\Generic implements \Magent
/**#@+
* Form elements names.
*/
- const HTML_ID_PREFIX = 'integration_properties_';
+ public const HTML_ID_PREFIX = 'integration_properties_';
- const DATA_ID = 'integration_id';
+ public const DATA_ID = 'integration_id';
- const DATA_NAME = 'name';
+ public const DATA_NAME = 'name';
- const DATA_EMAIL = 'email';
+ public const DATA_EMAIL = 'email';
- const DATA_ENDPOINT = 'endpoint';
+ public const DATA_ENDPOINT = 'endpoint';
- const DATA_IDENTITY_LINK_URL = 'identity_link_url';
+ public const DATA_IDENTITY_LINK_URL = 'identity_link_url';
- const DATA_SETUP_TYPE = 'setup_type';
+ public const DATA_SETUP_TYPE = 'setup_type';
- const DATA_CONSUMER_ID = 'consumer_id';
+ public const DATA_CONSUMER_ID = 'consumer_id';
- const DATA_CONSUMER_PASSWORD = 'current_password';
+ public const DATA_CONSUMER_PASSWORD = 'current_password';
/**#@-*/
@@ -161,6 +164,7 @@ protected function _addGeneralFieldset($form, $integrationData)
'label' => __('Identity link URL'),
'name' => self::DATA_IDENTITY_LINK_URL,
'disabled' => $disabled,
+ 'class' => 'validate-url',
'note' => __(
'URL to redirect user to link their 3rd party account with this Magento integration credentials.'
)
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
index c061911f804e..11508f8bc4d0 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php
@@ -3,10 +3,14 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
+declare(strict_types=1);
+
namespace Magento\Integration\Controller\Adminhtml;
use Magento\Backend\App\Action;
-use Magento\Integration\Api\OauthServiceInterface as IntegrationOauthService;
+use Magento\Framework\Url\Validator;
+use Magento\Framework\App\ObjectManager;
/**
* Controller for integrations management.
@@ -20,18 +24,18 @@ abstract class Integration extends Action
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Integration::integrations';
+ public const ADMIN_RESOURCE = 'Magento_Integration::integrations';
/** Param Key for extracting integration id from Request */
- const PARAM_INTEGRATION_ID = 'id';
+ public const PARAM_INTEGRATION_ID = 'id';
/** Reauthorize flag is used to distinguish activation from reauthorization */
- const PARAM_REAUTHORIZE = 'reauthorize';
+ public const PARAM_REAUTHORIZE = 'reauthorize';
- const REGISTRY_KEY_CURRENT_INTEGRATION = 'current_integration';
+ public const REGISTRY_KEY_CURRENT_INTEGRATION = 'current_integration';
/** Saved API form data session key */
- const REGISTRY_KEY_CURRENT_RESOURCE = 'current_resource';
+ public const REGISTRY_KEY_CURRENT_RESOURCE = 'current_resource';
/**
* @var \Magento\Framework\Registry
@@ -73,6 +77,11 @@ abstract class Integration extends Action
*/
protected $escaper;
+ /**
+ * @var Validator
+ */
+ protected $urlValidator;
+
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Registry $registry
@@ -83,6 +92,9 @@ abstract class Integration extends Action
* @param \Magento\Integration\Helper\Data $integrationData
* @param \Magento\Framework\Escaper $escaper
* @param \Magento\Integration\Model\ResourceModel\Integration\Collection $integrationCollection
+ * @param Validator|null $urlValidator
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
@@ -93,7 +105,8 @@ public function __construct(
\Magento\Framework\Json\Helper\Data $jsonHelper,
\Magento\Integration\Helper\Data $integrationData,
\Magento\Framework\Escaper $escaper,
- \Magento\Integration\Model\ResourceModel\Integration\Collection $integrationCollection
+ \Magento\Integration\Model\ResourceModel\Integration\Collection $integrationCollection,
+ Validator $urlValidator = null
) {
parent::__construct($context);
$this->_registry = $registry;
@@ -104,6 +117,7 @@ public function __construct(
$this->_integrationData = $integrationData;
$this->escaper = $escaper;
$this->_integrationCollection = $integrationCollection;
+ $this->urlValidator = $urlValidator ?: ObjectManager::getInstance()->get(Validator::class);
parent::__construct($context);
}
diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
index ac237750e715..f3af359ab5df 100644
--- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
+++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/Save.php
@@ -3,6 +3,9 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
+declare(strict_types=1);
+
namespace Magento\Integration\Controller\Adminhtml\Integration;
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
@@ -30,6 +33,7 @@ class Save extends \Magento\Integration\Controller\Adminhtml\Integration impleme
*
* @return SecurityCookie
* @deprecated 100.1.0
+ * @see we don't recommend this approach anymore
*/
private function getSecurityCookie()
{
@@ -76,7 +80,7 @@ public function execute()
$this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage()));
$this->_getSession()->setIntegrationData($this->getRequest()->getPostValue());
$this->_redirectOnSaveError();
- } catch (\Magento\Framework\Exception\LocalizedException $e) {
+ } catch (LocalizedException $e) {
$this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage()));
$this->_redirectOnSaveError();
} catch (\Exception $e) {
@@ -148,6 +152,8 @@ protected function _redirectOnSaveError()
*
* @param array $integrationData
* @return void
+ * @throws IntegrationException
+ * @throws LocalizedException
*/
private function processData($integrationData)
{
@@ -157,7 +163,15 @@ private function processData($integrationData)
if (!isset($data['resource'])) {
$integrationData['resource'] = [];
}
+
$integrationData = array_merge($integrationData, $data);
+
+ // Check if the Identity Link URL field is not empty and then validate it
+ $url = $integrationData[Info::DATA_IDENTITY_LINK_URL] ?? null;
+ if (!empty($url) && !$this->urlValidator->isValid($url)) {
+ throw new LocalizedException(__('Invalid Identity Link URL'));
+ }
+
if (!isset($integrationData[Info::DATA_ID])) {
$integration = $this->_integrationService->create($integrationData);
} else {
diff --git a/app/code/Magento/Integration/i18n/en_US.csv b/app/code/Magento/Integration/i18n/en_US.csv
index b225ad2766ff..e26d36157ff0 100644
--- a/app/code/Magento/Integration/i18n/en_US.csv
+++ b/app/code/Magento/Integration/i18n/en_US.csv
@@ -125,3 +125,4 @@ OAuth,OAuth
"Integrations API configuration file","Integrations API configuration file"
"We couldn't find any records.","We couldn't find any records."
Status,Status
+"Invalid Identity Link URL", "Invalid Identity Link URL"
diff --git a/app/code/Magento/JwtUserToken/Model/SecretBasedJwksFactory.php b/app/code/Magento/JwtUserToken/Model/SecretBasedJwksFactory.php
index 5032db90aba3..b6941b067b32 100644
--- a/app/code/Magento/JwtUserToken/Model/SecretBasedJwksFactory.php
+++ b/app/code/Magento/JwtUserToken/Model/SecretBasedJwksFactory.php
@@ -35,6 +35,7 @@ class SecretBasedJwksFactory
public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkFactory)
{
$this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key')));
+ $this->keys = [end($this->keys)];
//Making sure keys are large enough.
foreach ($this->keys as &$key) {
$key = str_pad($key, 2048, '&', STR_PAD_BOTH);
@@ -48,6 +49,8 @@ public function __construct(DeploymentConfig $deploymentConfig, JwkFactory $jwkF
* @param string $algorithm
* @return Jwk[]
* @throws \InvalidArgumentException When algorithm is not recognized.
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function createFor(string $algorithm): array
{
diff --git a/app/code/Magento/Newsletter/Controller/Adminhtml/Queue.php b/app/code/Magento/Newsletter/Controller/Adminhtml/Queue.php
index 7ed184aaa384..cc2577e24e40 100644
--- a/app/code/Magento/Newsletter/Controller/Adminhtml/Queue.php
+++ b/app/code/Magento/Newsletter/Controller/Adminhtml/Queue.php
@@ -18,5 +18,14 @@ abstract class Queue extends \Magento\Backend\App\Action
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Newsletter::queue';
+ public const ADMIN_RESOURCE = 'Magento_Newsletter::queue';
+
+ /**
+ * @inheritDoc
+ */
+ protected function _isAllowed()
+ {
+ return ($this->_authorization->isAllowed(self::ADMIN_RESOURCE) &&
+ $this->_authorization->isAllowed('Magento_Newsletter::template'));
+ }
}
diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AdminPayPalPayflowProWithValutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AdminPayPalPayflowProWithValutActionGroup.xml
index 26a19d6e2957..38e48f93a475 100644
--- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AdminPayPalPayflowProWithValutActionGroup.xml
+++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AdminPayPalPayflowProWithValutActionGroup.xml
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/DeleteSavedWithPayflowProCreditCardFromCustomerAccountTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/DeleteSavedWithPayflowProCreditCardFromCustomerAccountTest.xml
index e1ec8ec69c23..6cb29988df0d 100644
--- a/app/code/Magento/Paypal/Test/Mftf/Test/DeleteSavedWithPayflowProCreditCardFromCustomerAccountTest.xml
+++ b/app/code/Magento/Paypal/Test/Mftf/Test/DeleteSavedWithPayflowProCreditCardFromCustomerAccountTest.xml
@@ -23,9 +23,7 @@
-
-
-
+
diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/EditOrderFromAdminWithSavedWithinPayPalPayflowProCreditCardForRegisteredCustomerTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/EditOrderFromAdminWithSavedWithinPayPalPayflowProCreditCardForRegisteredCustomerTest.xml
index 931be9866331..a9bdf7103ee2 100644
--- a/app/code/Magento/Paypal/Test/Mftf/Test/EditOrderFromAdminWithSavedWithinPayPalPayflowProCreditCardForRegisteredCustomerTest.xml
+++ b/app/code/Magento/Paypal/Test/Mftf/Test/EditOrderFromAdminWithSavedWithinPayPalPayflowProCreditCardForRegisteredCustomerTest.xml
@@ -28,9 +28,7 @@
-
-
-
+
diff --git a/app/code/Magento/Quote/i18n/en_US.csv b/app/code/Magento/Quote/i18n/en_US.csv
index 6563651ba5ac..dc7cfaaaa5a7 100644
--- a/app/code/Magento/Quote/i18n/en_US.csv
+++ b/app/code/Magento/Quote/i18n/en_US.csv
@@ -75,3 +75,4 @@ Carts,Carts
"Identity type not found","Identity type not found"
"Invalid order backpressure limit config","Invalid order backpressure limit config"
"Please check input parameters.","Please check input parameters."
+"Please check input parameters.","Please check input parameters."
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Review.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Review.php
index e42fbc1c754f..05c398864ccc 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Review.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Review.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
/**
* Review reports admin controller
@@ -11,24 +12,29 @@
*/
namespace Magento\Reports\Controller\Adminhtml\Report;
+use Magento\Backend\App\Action;
+use Magento\Backend\App\Action\Context;
+use Magento\Framework\App\Response\Http\FileFactory;
+
/**
+ * phpcs:disable Magento2.Classes.AbstractApi
* @api
* @since 100.0.2
*/
-abstract class Review extends \Magento\Backend\App\Action
+abstract class Review extends Action
{
/**
- * @var \Magento\Framework\App\Response\Http\FileFactory
+ * @var FileFactory
*/
protected $_fileFactory;
/**
- * @param \Magento\Backend\App\Action\Context $context
- * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
+ * @param Context $context
+ * @param FileFactory $fileFactory
*/
public function __construct(
- \Magento\Backend\App\Action\Context $context,
- \Magento\Framework\App\Response\Http\FileFactory $fileFactory
+ Context $context,
+ FileFactory $fileFactory
) {
$this->_fileFactory = $fileFactory;
parent::__construct($context);
@@ -54,16 +60,20 @@ public function _initAction()
*/
protected function _isAllowed()
{
- switch ($this->getRequest()->getActionName()) {
- case 'customer':
- return $this->_authorization->isAllowed('Magento_Reports::review_customer');
- break;
- case 'product':
- return $this->_authorization->isAllowed('Magento_Reports::review_product');
- break;
- default:
- return $this->_authorization->isAllowed('Magento_Reports::review');
- break;
- }
+ return match ($this->getRequest()->getActionName()) {
+ 'exportCustomerCsv',
+ 'exportCustomerExcel',
+ 'customer' =>
+ $this->_authorization->isAllowed('Magento_Reports::review_customer'),
+ 'exportProductCsv',
+ 'exportProductExcel',
+ 'exportProductDetailCsv',
+ 'exportProductDetailExcel',
+ 'productDetail',
+ 'product' =>
+ $this->_authorization->isAllowed('Magento_Reports::review_product'),
+ default =>
+ $this->_authorization->isAllowed('Magento_Reports::review'),
+ };
}
}
diff --git a/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php b/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
index c77ff5c26b04..ac5b1db76045 100644
--- a/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
+++ b/app/code/Magento/Reports/Controller/Adminhtml/Report/Sales.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
/**
* Sales report admin controller
@@ -13,6 +14,7 @@
/**
* @SuppressWarnings(PHPMD.NumberOfChildren)
+ * phpcs:disable Magento2.Classes.AbstractApi
* @api
* @since 100.0.2
*/
@@ -37,31 +39,23 @@ public function _initAction()
*/
protected function _isAllowed()
{
- switch ($this->getRequest()->getActionName()) {
- case 'sales':
- return $this->_authorization->isAllowed('Magento_Reports::salesroot_sales');
- break;
- case 'tax':
- return $this->_authorization->isAllowed('Magento_Reports::tax');
- break;
- case 'shipping':
- return $this->_authorization->isAllowed('Magento_Reports::shipping');
- break;
- case 'invoiced':
- return $this->_authorization->isAllowed('Magento_Reports::invoiced');
- break;
- case 'refunded':
- return $this->_authorization->isAllowed('Magento_Reports::refunded');
- break;
- case 'coupons':
- return $this->_authorization->isAllowed('Magento_Reports::coupons');
- break;
- case 'bestsellers':
- return $this->_authorization->isAllowed('Magento_Reports::bestsellers');
- break;
- default:
- return $this->_authorization->isAllowed('Magento_Reports::salesroot');
- break;
- }
+ return match (strtolower($this->getRequest()->getActionName())) {
+ 'exportsalescsv', 'exportsalesexcel', 'sales' =>
+ $this->_authorization->isAllowed('Magento_Reports::salesroot_sales'),
+ 'exporttaxcsv', 'exporttaxexcel', 'tax' =>
+ $this->_authorization->isAllowed('Magento_Reports::tax'),
+ 'exportshippingcsv', 'exportshippingexcel', 'shipping' =>
+ $this->_authorization->isAllowed('Magento_Reports::shipping'),
+ 'exportinvoicedcsv', 'exportinvoicedexcel', 'invoiced' =>
+ $this->_authorization->isAllowed('Magento_Reports::invoiced'),
+ 'exportrefundedcsv', 'exportrefundedexcel', 'refunded' =>
+ $this->_authorization->isAllowed('Magento_Reports::refunded'),
+ 'exportcouponscsv', 'exportcouponsexcel', 'coupons' =>
+ $this->_authorization->isAllowed('Magento_Reports::coupons'),
+ 'exportbestsellerscsv', 'exportbestsellersexcel', 'bestsellers' =>
+ $this->_authorization->isAllowed('Magento_Reports::bestsellers'),
+ default =>
+ $this->_authorization->isAllowed('Magento_Reports::salesroot'),
+ };
}
}
diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View.php
index d70df8003819..fc6edd9b6adc 100644
--- a/app/code/Magento/Sales/Block/Adminhtml/Order/View.php
+++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View.php
@@ -16,29 +16,21 @@
class View extends \Magento\Backend\Block\Widget\Form\Container
{
/**
- * Block group
- *
* @var string
*/
protected $_blockGroup = 'Magento_Sales';
/**
- * Core registry
- *
* @var \Magento\Framework\Registry
*/
protected $_coreRegistry = null;
/**
- * Sales config
- *
* @var \Magento\Sales\Model\Config
*/
protected $_salesConfig;
/**
- * Reorder helper
- *
* @var \Magento\Sales\Helper\Reorder
*/
protected $_reorderHelper;
@@ -121,7 +113,7 @@ protected function _construct()
);
}
- if ($this->_isAllowedAction('Magento_Sales::emails') && !$order->isCanceled()) {
+ if ($this->_isAllowedAction('Magento_Sales::email') && !$order->isCanceled()) {
$message = __('Are you sure you want to send an order email to customer?');
$this->addButton(
'send_notification',
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php
index 1ca0b53ee878..0da7c4d8cb5a 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php
@@ -6,15 +6,16 @@
namespace Magento\Sales\Controller\Adminhtml\Order\Creditmemo;
use Magento\Backend\App\Action;
+use Magento\Framework\App\Action\HttpPostActionInterface;
-class Cancel extends \Magento\Backend\App\Action
+class Cancel extends \Magento\Backend\App\Action implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* @var \Magento\Backend\Model\View\Result\ForwardFactory
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/NewAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/NewAction.php
index 3ac3abda82cd..e071444fef0a 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/NewAction.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/NewAction.php
@@ -15,7 +15,7 @@ class NewAction extends \Magento\Backend\App\Action implements HttpGetActionInte
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* @var \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
index 63558c0290e2..a0cb5a4dc8ac 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php
@@ -5,10 +5,9 @@
*/
namespace Magento\Sales\Controller\Adminhtml\Order\Creditmemo;
-use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Backend\App\Action;
use Magento\Sales\Helper\Data as SalesData;
-use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender;
class Save extends \Magento\Backend\App\Action implements HttpPostActionInterface
@@ -18,7 +17,7 @@ class Save extends \Magento\Backend\App\Action implements HttpPostActionInterfac
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* @var \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Start.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Start.php
index 3dc4aa6dcd50..0fc96d4cfc8f 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Start.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Start.php
@@ -14,7 +14,7 @@ class Start extends \Magento\Backend\App\Action implements HttpGetActionInterfac
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* Start create creditmemo action
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/UpdateQty.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/UpdateQty.php
index 47a936672791..8d1e627b4339 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/UpdateQty.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/UpdateQty.php
@@ -15,7 +15,7 @@ class UpdateQty extends \Magento\Backend\App\Action implements HttpPostActionInt
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* @var \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/VoidAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/VoidAction.php
index 146514265517..225f57251bf2 100644
--- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/VoidAction.php
+++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/VoidAction.php
@@ -6,15 +6,16 @@
namespace Magento\Sales\Controller\Adminhtml\Order\Creditmemo;
use Magento\Backend\App\Action;
+use Magento\Framework\App\Action\HttpPostActionInterface;
-class VoidAction extends Action
+class VoidAction extends Action implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
- const ADMIN_RESOURCE = 'Magento_Sales::sales_creditmemo';
+ public const ADMIN_RESOURCE = 'Magento_Sales::creditmemo';
/**
* @var \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader
diff --git a/app/code/Magento/Sales/ViewModel/Order/Create/SidebarPermissionCheck.php b/app/code/Magento/Sales/ViewModel/Order/Create/SidebarPermissionCheck.php
new file mode 100644
index 000000000000..cf7f8ff72636
--- /dev/null
+++ b/app/code/Magento/Sales/ViewModel/Order/Create/SidebarPermissionCheck.php
@@ -0,0 +1,42 @@
+authorization = $authorization;
+ }
+
+ /**
+ * To check customer permission
+ *
+ * @return bool
+ */
+ public function isAllowed(): bool
+ {
+ return $this->authorization->isAllowed('Magento_Customer::customer');
+ }
+}
diff --git a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
index c2178429e30c..9d56e806a10c 100644
--- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
+++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
@@ -36,6 +36,9 @@