diff --git a/vendor/magento/module-backup/Controller/Adminhtml/Index/Rollback.php b/vendor/magento/module-backup/Controller/Adminhtml/Index/Rollback.php index 25da907e4ca32..41a4e5755b413 100644 --- a/vendor/magento/module-backup/Controller/Adminhtml/Index/Rollback.php +++ b/vendor/magento/module-backup/Controller/Adminhtml/Index/Rollback.php @@ -16,6 +16,11 @@ */ class Rollback extends \Magento\Backup\Controller\Adminhtml\Index implements HttpPostActionInterface { + /** + * @see _isAllowed() + */ + public const ADMIN_RESOURCE = 'Magento_Backup::rollback'; + /** * Rollback Action * @@ -26,10 +31,6 @@ class Rollback extends \Magento\Backup\Controller\Adminhtml\Index implements Htt */ public function execute() { - if (!$this->_objectManager->get(\Magento\Backup\Helper\Data::class)->isRollbackAllowed()) { - $this->_forward('denied'); - } - if (!$this->getRequest()->isAjax()) { return $this->_redirect('*/*/index'); } diff --git a/vendor/magento/module-customer/i18n/en_US.csv b/vendor/magento/module-customer/i18n/en_US.csv index 3417da0141feb..308cb9b05cb0e 100644 --- a/vendor/magento/module-customer/i18n/en_US.csv +++ b/vendor/magento/module-customer/i18n/en_US.csv @@ -551,3 +551,4 @@ T,T F,F VAT,VAT "Something went wrong while logging out customer.","Something went wrong while logging out customer." +"Address not found.","Address not found." diff --git a/vendor/magento/module-customer-graph-ql/Model/Context/AddUserInfoToContext.php b/vendor/magento/module-customer-graph-ql/Model/Context/AddUserInfoToContext.php index 53ae01a04e430..3c3b4e94f5547 100644 --- a/vendor/magento/module-customer-graph-ql/Model/Context/AddUserInfoToContext.php +++ b/vendor/magento/module-customer-graph-ql/Model/Context/AddUserInfoToContext.php @@ -12,9 +12,12 @@ use Magento\Customer\Model\Config\Share; use Magento\Customer\Model\ResourceModel\CustomerRepository; use Magento\Customer\Model\Session; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\ObjectManager\ResetAfterRequestInterface; use Magento\GraphQl\Model\Query\ContextParametersInterface; use Magento\GraphQl\Model\Query\UserContextParametersProcessorInterface; +use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Model\StoreManagerInterface; /** @@ -51,19 +54,27 @@ class AddUserInfoToContext implements UserContextParametersProcessorInterface, R * @var StoreManagerInterface */ private $storeManager; + + /** + * @var HttpRequest + */ + private $request; + /** * @param UserContextInterface $userContext * @param Session $session * @param CustomerRepository $customerRepository * @param Share $configShare * @param StoreManagerInterface $storeManager + * @param HttpRequest|null $request */ public function __construct( UserContextInterface $userContext, Session $session, CustomerRepository $customerRepository, Share $configShare, - StoreManagerInterface $storeManager + StoreManagerInterface $storeManager, + ?HttpRequest $request = null ) { $this->userContext = $userContext; $this->userContextFromConstructor = $userContext; @@ -71,6 +82,7 @@ public function __construct( $this->customerRepository = $customerRepository; $this->configShare = $configShare; $this->storeManager = $storeManager; + $this->request = $request ?? ObjectManager::getInstance()->get(HttpRequest::class); } /** @@ -109,6 +121,13 @@ public function execute(ContextParametersInterface $contextParameters): ContextP $isCustomer = $this->isCustomer($currentUserId, $currentUserType); $contextParameters->addExtensionAttribute('is_customer', $isCustomer); + if (!$isCustomer + && !empty($currentUserId) + && $currentUserType === UserContextInterface::USER_TYPE_CUSTOMER + ) { + $contextParameters->setUserId(0); + } + if ($isCustomer) { $customer = $this->customerRepository->getById($currentUserId); $this->session->setCustomerData($customer); @@ -142,8 +161,22 @@ private function isCustomer(?int $customerId, ?int $customerType): bool if ($result && $this->configShare->isWebsiteScope()) { $customer = $this->customerRepository->getById($customerId); - return (int)$customer->getWebsiteId() === (int)$this->storeManager->getStore()->getWebsiteId(); + return (int)$customer->getWebsiteId() === (int)$this->getEffectiveStore()->getWebsiteId(); } return $result; } + + /** + * Resolve the store to use for website-scope validation. + * + * @return StoreInterface + */ + private function getEffectiveStore(): StoreInterface + { + $storeCode = trim((string) $this->request->getHeader('Store')); + if (!empty($storeCode)) { + return $this->storeManager->getStore($storeCode); + } + return $this->storeManager->getStore(); + } } diff --git a/vendor/magento/module-import-export/Controller/Adminhtml/Export/File/Delete.php b/vendor/magento/module-import-export/Controller/Adminhtml/Export/File/Delete.php index 00d569c6fedd0..d3b7aebdd40f5 100644 --- a/vendor/magento/module-import-export/Controller/Adminhtml/Export/File/Delete.php +++ b/vendor/magento/module-import-export/Controller/Adminhtml/Export/File/Delete.php @@ -11,2 +11,3 @@ use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\FileSystemException; @@ -16,6 +17,7 @@ use Magento\Framework\Filesystem; use Magento\Framework\Controller\ResultInterface; use Magento\Framework\Filesystem\Directory\WriteFactory; +use Magento\ImportExport\Model\Export\FileInfo; /** * Controller that delete file by name. @@ -37,20 +39,28 @@ class Delete extends ExportController implements HttpPostActionInterface */ private $writeFactory; + /** + * @var FileInfo + */ + private $fileInfo; + /** * Delete constructor. * * @param Action\Context $context * @param Filesystem $filesystem * @param WriteFactory $writeFactory + * @param FileInfo|null $fileInfo */ public function __construct( Action\Context $context, Filesystem $filesystem, - WriteFactory $writeFactory + WriteFactory $writeFactory, + ?FileInfo $fileInfo = null ) { $this->filesystem = $filesystem; $this->writeFactory = $writeFactory; + $this->fileInfo = $fileInfo ?? ObjectManager::getInstance()->get(FileInfo::class); parent::__construct($context); } @@ -72,7 +82,15 @@ public function execute() } $directoryWrite = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_IMPORT_EXPORT); try { - $directoryWrite->delete($directoryWrite->getAbsolutePath() . 'export/' . $fileName); + $fileName = $directoryWrite->getDriver()->getRealPathSafety(DIRECTORY_SEPARATOR . $fileName); + $fileExist = $directoryWrite->isFile('export' . $fileName); + if (!$fileExist || !$this->isAllowedExportFile($fileName)) { + $this->messageManager->addErrorMessage(__( + 'Sorry, but the data is invalid or the file is not uploaded.' + )); + return $resultRedirect; + } + $directoryWrite->delete($directoryWrite->getAbsolutePath() . 'export' . $fileName); $this->messageManager->addSuccessMessage(__('File %1 deleted', $fileName)); } catch (ValidatorException $exception) { $this->messageManager->addErrorMessage( @@ -89,4 +107,15 @@ public function execute() return $resultRedirect; } + + /** + * Check whether requested file is a completed export file. + * + * @param string $fileName + * @return bool + */ + private function isAllowedExportFile(string $fileName): bool + { + return $this->fileInfo->isExportFile($fileName); + } } diff --git a/vendor/magento/module-instant-purchase/Model/InstantPurchaseOptionLoadingFactory.php b/vendor/magento/module-instant-purchase/Model/InstantPurchaseOptionLoadingFactory.php index e770b9df6116e..9937b9f4a2c3c 100644 --- a/vendor/magento/module-instant-purchase/Model/InstantPurchaseOptionLoadingFactory.php +++ b/vendor/magento/module-instant-purchase/Model/InstantPurchaseOptionLoadingFactory.php @@ -10,2 +10,3 @@ use Magento\Customer\Model\AddressFactory; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Api\Data\ShippingMethodInterfaceFactory; @@ -85,6 +86,11 @@ public function create( $paymentToken = $this->paymentTokenManagement->getByPublicHash($paymentTokenPublicHash, $customerId); $shippingAddress = $this->getAddress($shippingAddressId); $billingAddress = $this->getAddress($billingAddressId); + if ((int)$shippingAddress->getCustomerId() !== $customerId || + (int)$billingAddress->getCustomerId() !== $customerId) { + throw new NoSuchEntityException(__('Address not found.')); + } + $shippingMethod = $this->shippingMethodFactory->create() ->setCarrierCode($carrierCode) ->setMethodCode($shippingMethodCode); diff --git a/vendor/magento/module-paypal/Controller/Express/AbstractExpress.php b/vendor/magento/module-paypal/Controller/Express/AbstractExpress.php index 670215c6954dd..be18ba62478ef 100644 --- a/vendor/magento/module-paypal/Controller/Express/AbstractExpress.php +++ b/vendor/magento/module-paypal/Controller/Express/AbstractExpress.php @@ -151,7 +151,7 @@ public function __construct( protected function _initCheckout(?CartInterface $quoteObject = null) { $quote = $quoteObject ? $quoteObject : $this->_getQuote(); - if ($quote->getId()) { + if ($quote->getId() && $this->isQuoteAllowedForUser($quote)) { $this->_getCheckoutSession()->setPayPalQuoteId($quote->getId()); } if (!$quote->hasItems() || $quote->getHasError()) { @@ -259,6 +259,22 @@ protected function _getQuote() return $this->_quote; } + /** + * Checks if the quote is allowed for the current user. + * + * @param CartInterface $quote + * @return bool + */ + private function isQuoteAllowedForUser(CartInterface $quote): bool + { + if ((int)$quote->getId() === (int)$this->_getCheckoutSession()->getQuoteId()) { + return true; + } + + return $this->_customerSession->isLoggedIn() + && (int)$quote->getCustomerId() === (int)$this->_customerSession->getCustomerId(); + } + /** * @inheritdoc */ diff --git a/vendor/magento/module-sales/view/adminhtml/web/order/create/scripts.js b/vendor/magento/module-sales/view/adminhtml/web/order/create/scripts.js index bd6516af7737e..8a768ab8da775 100644 --- a/vendor/magento/module-sales/view/adminhtml/web/order/create/scripts.js +++ b/vendor/magento/module-sales/view/adminhtml/web/order/create/scripts.js @@ -5,6 +5,7 @@ define([ 'jquery', + 'underscore', 'Magento_Ui/js/modal/confirm', 'Magento_Ui/js/modal/alert', 'mage/template', @@ -14,7 +15,7 @@ 'prototype', 'Magento_Catalog/catalog/product/composite/configure', 'Magento_Ui/js/lib/view/utils/async' -], function (jQuery, confirm, alert, template, shippingTemplate, paymentTemplate) { +], function (jQuery, _, confirm, alert, template, shippingTemplate, paymentTemplate) { window.AdminOrder = new Class.create(); @@ -1496,6 +1497,7 @@ country: $(parameters.countryElementId).value, vat: $(parameters.vatElementId).value }; + var escapedVat = _.escape(params.vat); if (this.storeId !== false) { params.store_id = this.storeId; @@ -1516,7 +1518,7 @@ if (true === response.valid) { message = parameters.vatValidMessage; } else if (true === response.success) { - message = parameters.vatInvalidMessage.replace(/%s/, params.vat); + message = parameters.vatInvalidMessage.replace(/%s/, escapedVat); } else { message = parameters.vatValidationFailedMessage; } @@ -1531,7 +1533,7 @@ groupActionRequired = 'change'; } } else if (response.success) { - message = parameters.vatInvalidMessage.replace(/%s/, params.vat); + message = parameters.vatInvalidMessage.replace(/%s/, escapedVat); groupActionRequired = 'inform'; } else { message = parameters.vatValidationFailedMessage; diff --git a/vendor/magento/framework/Escaper.php b/vendor/magento/framework/Escaper.php index 241fb7bb293c2..26a1a57adc90b 100644 --- a/vendor/magento/framework/Escaper.php +++ b/vendor/magento/framework/Escaper.php @@ -389,7 +389,7 @@ public function escapeJsQuote($data, $quote = '\'') */ public function escapeXssInUrl($data) { - $data = html_entity_decode((string)$data); + $data = $this->decodeHtmlEntitiesToFixedPoint((string)$data); $this->getTranslateInline()->processResponseBody($data); return htmlspecialchars( @@ -400,6 +400,26 @@ public function escapeXssInUrl($data) ); } + /** + * Decode HTML entities repeatedly until stable, or return empty if still decoding at the cap. + * + * @param string $data + * @return string + */ + private function decodeHtmlEntitiesToFixedPoint(string $data): string + { + $iterationCap = 10; + for ($iteration = 0; $iteration < $iterationCap; $iteration++) { + $decoded = html_entity_decode($data); + if ($decoded === $data) { + return $data; + } + $data = $decoded; + } + + return ''; + } + /** * Remove `javascript:`, `vbscript:`, `data:` words from the string. *