diff --git a/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php b/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php index 2cd761f746f78..c332440276083 100644 --- a/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php +++ b/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php @@ -8,6 +8,11 @@ class ListAction extends \Magento\Backend\App\AbstractAction { + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_AdminNotification::show_list'; + /** * @var \Magento\Framework\Json\Helper\Data */ diff --git a/app/code/Magento/AdminNotification/Model/Feed.php b/app/code/Magento/AdminNotification/Model/Feed.php index ea08cc13800de..1766425fb19b1 100644 --- a/app/code/Magento/AdminNotification/Model/Feed.php +++ b/app/code/Magento/AdminNotification/Model/Feed.php @@ -148,9 +148,9 @@ public function checkUpdate() $feedData[] = [ 'severity' => (int)$item->severity, 'date_added' => date('Y-m-d H:i:s', $itemPublicationDate), - 'title' => (string)$item->title, - 'description' => (string)$item->description, - 'url' => (string)$item->link, + 'title' => $this->escapeString($item->title), + 'description' => $this->escapeString($item->description), + 'url' => $this->escapeString($item->link), ]; } } @@ -246,4 +246,15 @@ public function getFeedXml() return $xml; } + + /** + * Converts incoming data to string format and escapes special characters. + * + * @param \SimpleXMLElement $data + * @return string + */ + private function escapeString(\SimpleXMLElement $data) + { + return htmlspecialchars((string)$data); + } } diff --git a/app/code/Magento/AdminNotification/Test/Unit/Model/FeedTest.php b/app/code/Magento/AdminNotification/Test/Unit/Model/FeedTest.php index 6dea86d1f5892..2b3eb6247e899 100644 --- a/app/code/Magento/AdminNotification/Test/Unit/Model/FeedTest.php +++ b/app/code/Magento/AdminNotification/Test/Unit/Model/FeedTest.php @@ -145,8 +145,27 @@ public function testCheckUpdate($callInbox, $curlRequest) ->will($this->returnValue('Sat, 6 Sep 2014 16:46:11 UTC')); if ($callInbox) { $this->inboxFactory->expects($this->once())->method('create') - ->will(($this->returnValue($this->inboxModel))); - $this->inboxModel->expects($this->once())->method('parse')->will($this->returnSelf()); + ->will($this->returnValue($this->inboxModel)); + $this->inboxModel->expects($this->once()) + ->method('parse') + ->with( + $this->callback( + function ($data) { + $fieldsToCheck = ['title', 'description', 'url']; + return array_reduce( + $fieldsToCheck, + function ($initialValue, $item) use ($data) { + $haystack = $data[0][$item] ?? false; + return $haystack + ? $initialValue && !strpos($haystack, '<') && !strpos($haystack, '>') + : true; + }, + true + ); + } + ) + ) + ->will($this->returnSelf()); } else { $this->inboxFactory->expects($this->never())->method('create'); $this->inboxModel->expects($this->never())->method('parse'); @@ -196,7 +215,27 @@ public function checkUpdateDataProvider() ' - ] + ], + [ + true, + // @codingStandardsIgnoreStart + 'HEADER + + + + + MagentoCommerce + + <![CDATA[<script>alert("Hello!");</script>Test Title]]> + alert("Hello!");]]> + 4 + alert("Hello!");Description]]> + Tue, 20 Jun 2017 13:14:47 UTC + + + ' + // @codingStandardsIgnoreEnd + ], ]; } } diff --git a/app/code/Magento/AdminNotification/etc/config.xml b/app/code/Magento/AdminNotification/etc/config.xml index b30cec378ca71..fd423cc554499 100644 --- a/app/code/Magento/AdminNotification/etc/config.xml +++ b/app/code/Magento/AdminNotification/etc/config.xml @@ -12,7 +12,7 @@ notifications.magentocommerce.com/magento2/community/notifications.rss widgets.magentocommerce.com/notificationPopup widgets.magentocommerce.com/%s/%s.gif - 0 + 1 1 0 diff --git a/app/code/Magento/AdminNotification/view/adminhtml/ui_component/notification_area.xml b/app/code/Magento/AdminNotification/view/adminhtml/ui_component/notification_area.xml index f58b368e2b0f5..dcf2e996892fb 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/ui_component/notification_area.xml +++ b/app/code/Magento/AdminNotification/view/adminhtml/ui_component/notification_area.xml @@ -24,6 +24,7 @@ + Magento_AdminNotification::show_list identity diff --git a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/BackendResponse.php b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/BackendResponse.php index 5d9ac20869fe1..3ad9f470909bf 100644 --- a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/BackendResponse.php +++ b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/BackendResponse.php @@ -6,8 +6,48 @@ */ namespace Magento\Authorizenet\Controller\Directpost\Payment; +use Magento\Authorizenet\Helper\DataFactory; +use Magento\Authorizenet\Model\Directpost; +use Magento\Authorizenet\Model\DirectpostFactory; +use Magento\Framework\App\Action\Context; +use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Registry; +use Psr\Log\LoggerInterface; + class BackendResponse extends \Magento\Authorizenet\Controller\Directpost\Payment { + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var DirectpostFactory + */ + private $directpostFactory; + + /** + * BackendResponse constructor. + * + * @param Context $context + * @param Registry $coreRegistry + * @param DataFactory $dataFactory + * @param DirectpostFactory $directpostFactory + * @param LoggerInterface|null $logger + */ + public function __construct( + Context $context, + Registry $coreRegistry, + DataFactory $dataFactory, + DirectpostFactory $directpostFactory, + LoggerInterface $logger = null + ) { + parent::__construct($context, $coreRegistry, $dataFactory); + $this->directpostFactory = $directpostFactory ?: $this->_objectManager->create(DirectpostFactory::class); + $this->logger = $logger ?: $this->_objectManager->get(LoggerInterface::class); + } + /** * Response action. * Action for Authorize.net SIM Relay Request. @@ -16,7 +56,20 @@ class BackendResponse extends \Magento\Authorizenet\Controller\Directpost\Paymen */ public function execute() { + $data = $this->getRequest()->getParams(); + /** @var Directpost $paymentMethod */ + $paymentMethod = $this->directpostFactory->create(); + if (!empty($data['store_id'])) { + $paymentMethod->setStore($data['store_id']); + } + $paymentMethod->setResponseData($data); + try { + $paymentMethod->validateResponse(); + } catch (LocalizedException $e) { + $this->logger->critical($e->getMessage()); + return $this->_redirect('noroute'); + } $this->_responseAction('adminhtml'); - return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE); + return $this->resultFactory->create(ResultFactory::TYPE_PAGE); } } diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column.php b/app/code/Magento/Backend/Block/Widget/Grid/Column.php index 246750a096256..1ab88bf11031e 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column.php @@ -5,6 +5,7 @@ */ namespace Magento\Backend\Block\Widget\Grid; +use Magento\Backend\Block\Widget; use Magento\Backend\Block\Widget\Grid\Column\Filter\AbstractFilter; /** @@ -14,7 +15,7 @@ * @deprecated 100.2.0 in favour of UI component implementation * @since 100.0.2 */ -class Column extends \Magento\Backend\Block\Widget +class Column extends Widget { /** * Parent grid @@ -289,12 +290,30 @@ public function getRowField(\Magento\Framework\DataObject $row) */ $frameCallback = $this->getFrameCallback(); if (is_array($frameCallback)) { + $this->validateFrameCallback($frameCallback); $renderedValue = call_user_func($frameCallback, $renderedValue, $row, $this, false); } return $renderedValue; } + /** + * Validate frame callback + * + * @throws \InvalidArgumentException + * + * @param array $callback + * @return void + */ + private function validateFrameCallback(array $callback) + { + if (!is_object($callback[0]) || !$callback[0] instanceof Widget) { + throw new \InvalidArgumentException( + "Frame callback host must be instance of Magento\\Backend\\Block\\Widget" + ); + } + } + /** * Retrieve row column field value for export * @@ -314,6 +333,7 @@ public function getRowFieldExport(\Magento\Framework\DataObject $row) */ $frameCallback = $this->getFrameCallback(); if (is_array($frameCallback)) { + $this->validateFrameCallback($frameCallback); $renderedValue = call_user_func($frameCallback, $renderedValue, $row, $this, true); } diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Ajax/Translate.php b/app/code/Magento/Backend/Controller/Adminhtml/Ajax/Translate.php index 21c4efd246908..b7cb62c45e617 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Ajax/Translate.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Ajax/Translate.php @@ -20,6 +20,11 @@ class Translate extends \Magento\Backend\App\Action */ protected $resultJsonFactory; + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_Backend::content_translation'; + /** * @param Action\Context $context * @param \Magento\Framework\Translate\Inline\ParserInterface $inlineParser diff --git a/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/ColumnTest.php b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/ColumnTest.php index cd5bcdf412f05..da13af87b71ea 100644 --- a/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/ColumnTest.php +++ b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/ColumnTest.php @@ -3,12 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - -/** - * Test class for \Magento\Backend\Block\Widget\Grid\Column - */ namespace Magento\Backend\Test\Unit\Block\Widget\Grid; +use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer; +use Magento\Framework\DataObject; + class ColumnTest extends \PHPUnit\Framework\TestCase { /** @@ -379,4 +378,97 @@ public function columnGroupedDataProvider() { return [[[], false], [['grouped' => 0], false], [['grouped' => 1], true]]; } + + /** + * Testing row field export with valid frame callback + */ + public function testGetRowFieldAndExportWithFrameCallback() + { + $row = new DataObject(['id' => '2', 'title' => 'some item']); + /** @var $rendererMock */ + $rendererMock = $this->getMockBuilder(AbstractRenderer::class) + ->disableOriginalConstructor() + ->setMethods(['renderExport', 'render']) + ->getMock(); + + $rendererMock->expects($this->any())->method('renderExport')->willReturnCallback( + function (DataObject $row) { + return $row->getData('title'); + } + ); + + $rendererMock->expects($this->any())->method('render')->willReturnCallback( + function (DataObject $row) { + return $row->getData('title'); + } + ); + + $frameCallbackHostObject = $this->getMockBuilder(\Magento\Backend\Block\Widget::class) + ->disableOriginalConstructor() + ->setMethods(['decorate']) + ->getMock(); + + $frameCallbackHostObject->expects($this->any()) + ->method('decorate') + ->willReturnCallback( + function ($renderValue) { + return '__callback_decorated_' . $renderValue; + } + ); + + $this->_block->setRenderer($rendererMock); + $this->_block->setFrameCallback([$frameCallbackHostObject, 'decorate']); + $renderResult = $this->_block->getRowField($row); + $exportResult = $this->_block->getRowFieldExport($row); + $this->assertEquals('__callback_decorated_some item', $exportResult); + $this->assertEquals('__callback_decorated_some item', $renderResult); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Frame callback host must be instance of Magento\Backend\Block\Widget + */ + public function testGetRowFieldExportWithInvalidCallback() + { + $row = new DataObject(['id' => '2', 'title' => 'some item']); + /** @var $rendererMock */ + $rendererMock = $this->getMockBuilder(AbstractRenderer::class) + ->disableOriginalConstructor() + ->setMethods(['renderExport', 'render']) + ->getMock(); + + $rendererMock->expects($this->any())->method('renderExport')->willReturnCallback( + function (DataObject $row) { + return $row->getData('title'); + } + ); + + $this->_block->setRenderer($rendererMock); + $this->_block->setFrameCallback([$this, 'testGetRowFieldExportWithFrameCallback']); + $this->_block->getRowFieldExport($row); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Frame callback host must be instance of Magento\Backend\Block\Widget + */ + public function testGetRowFieldWithInvalidCallback() + { + $row = new DataObject(['id' => '2', 'title' => 'some item']); + /** @var $rendererMock */ + $rendererMock = $this->getMockBuilder(AbstractRenderer::class) + ->disableOriginalConstructor() + ->setMethods(['render']) + ->getMock(); + + $rendererMock->expects($this->any())->method('render')->willReturnCallback( + function (DataObject $row) { + return $row->getData('title'); + } + ); + + $this->_block->setRenderer($rendererMock); + $this->_block->setFrameCallback([$this, 'testGetRowFieldExportWithFrameCallback']); + $this->_block->getRowField($row); + } } diff --git a/app/code/Magento/Backend/etc/acl.xml b/app/code/Magento/Backend/etc/acl.xml index 433b3df6ccac4..af4ab5856e94c 100644 --- a/app/code/Magento/Backend/etc/acl.xml +++ b/app/code/Magento/Backend/etc/acl.xml @@ -22,6 +22,7 @@ + diff --git a/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml b/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml index fbb2a24fb9d86..f039fe51a4ee0 100644 --- a/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml +++ b/app/code/Magento/Braintree/view/adminhtml/ui_component/braintree_report.xml @@ -26,6 +26,7 @@ + Magento_Braintree::settlement_report id diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js index b88a61db30cfa..a1a1c81d27c3d 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js @@ -109,7 +109,7 @@ define([ $('body').trigger('processStart'); - $.get(self.nonceUrl, { + $.getJSON(self.nonceUrl, { 'public_hash': self.publicHash }).done(function (response) { self.setPaymentDetails(response.paymentMethodNonce); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js index 5868236ef94ca..933f20867168c 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal-vault.js @@ -49,7 +49,7 @@ define([ var self = this; fullScreenLoader.startLoader(); - $.get(self.nonceUrl, { + $.getJSON(self.nonceUrl, { 'public_hash': self.publicHash }) .done(function (response) { diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js index 84f5657b9d540..85e531706d62e 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/vault.js @@ -69,7 +69,7 @@ define([ var self = this; fullScreenLoader.startLoader(); - $.get(self.nonceUrl, { + $.getJSON(self.nonceUrl, { 'public_hash': self.publicHash }) .done(function (response) { diff --git a/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Grid.php b/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Grid.php index b86ad1a3f3174..c9ddd677e2b46 100644 --- a/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Grid.php +++ b/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Grid.php @@ -6,7 +6,9 @@ */ namespace Magento\Bundle\Controller\Adminhtml\Bundle\Selection; -class Grid extends \Magento\Backend\App\Action +use Magento\Catalog\Controller\Adminhtml\Product; + +class Grid extends Product { /** * @return mixed diff --git a/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Search.php b/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Search.php index e2d863b4a28e0..28257ca4894b2 100644 --- a/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Search.php +++ b/app/code/Magento/Bundle/Controller/Adminhtml/Bundle/Selection/Search.php @@ -6,7 +6,9 @@ */ namespace Magento\Bundle\Controller\Adminhtml\Bundle\Selection; -class Search extends \Magento\Backend\App\Action +use Magento\Catalog\Controller\Adminhtml\Product; + +class Search extends Product { /** * @return mixed diff --git a/app/code/Magento/Bundle/view/adminhtml/ui_component/bundle_product_listing.xml b/app/code/Magento/Bundle/view/adminhtml/ui_component/bundle_product_listing.xml index 22758cf16ce32..b259e3280bfd5 100644 --- a/app/code/Magento/Bundle/view/adminhtml/ui_component/bundle_product_listing.xml +++ b/app/code/Magento/Bundle/view/adminhtml/ui_component/bundle_product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Captcha/etc/config.xml b/app/code/Magento/Captcha/etc/config.xml index f754bdbe60ea3..71c474de90ff4 100644 --- a/app/code/Magento/Captcha/etc/config.xml +++ b/app/code/Magento/Captcha/etc/config.xml @@ -17,10 +17,10 @@ default - 0 + 1 linlibertine after_fail - backend_forgotpassword + backend_forgotpassword,backend_login 3 1000 7 @@ -36,10 +36,10 @@ default - 0 + 1 linlibertine after_fail - user_forgotpassword + user_forgotpassword,user_login 3 1000 7 diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Widget.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Widget.php index 991f7617ea3d2..4feaa706d42fb 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category/Widget.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category/Widget.php @@ -14,6 +14,13 @@ */ abstract class Widget extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Catalog::categories'; + /** * @var \Magento\Framework\View\LayoutFactory */ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Datafeeds/Index.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Datafeeds/Index.php index b4fda40dfe7b1..39035c8c7af1b 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Datafeeds/Index.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Datafeeds/Index.php @@ -8,6 +8,13 @@ class Index extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Catalog::products'; + /** * @return void */ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php index 59d50e57f7110..933b5eaafbb39 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Widget/Chooser.php @@ -8,6 +8,11 @@ class Chooser extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_Widget::widget_instance'; + /** * @var \Magento\Framework\Controller\Result\RawFactory */ diff --git a/app/code/Magento/Catalog/Model/ImageUploader.php b/app/code/Magento/Catalog/Model/ImageUploader.php index ad8fb4ecde0b1..6aa76ca8c1e43 100644 --- a/app/code/Magento/Catalog/Model/ImageUploader.php +++ b/app/code/Magento/Catalog/Model/ImageUploader.php @@ -223,11 +223,13 @@ public function saveFileToTmpDir($fileId) { $baseTmpPath = $this->getBaseTmpPath(); + /** @var \Magento\MediaStorage\Model\File\Uploader $uploader */ $uploader = $this->uploaderFactory->create(['fileId' => $fileId]); $uploader->setAllowedExtensions($this->getAllowedExtensions()); $uploader->setAllowRenameFiles(true); $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath)); + unset($result['path']); if (!$result) { throw new \Magento\Framework\Exception\LocalizedException( @@ -239,7 +241,6 @@ public function saveFileToTmpDir($fileId) * Workaround for prototype 1.7 methods "isJSON", "evalJSON" on Windows OS */ $result['tmp_name'] = str_replace('\\', '/', $result['tmp_name']); - $result['path'] = str_replace('\\', '/', $result['path']); $result['url'] = $this->storeManager ->getStore() ->getBaseUrl( diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php index f78247bedce9a..03d418f3ba0d9 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php @@ -328,7 +328,7 @@ protected function duplicate($product) */ protected function moveImageFromTmp($file) { - $file = $this->getFilenameFromTmp($file); + $file = $this->getFilenameFromTmp($this->getSafeFilename($file)); $destinationFile = $this->getUniqueFileName($file); if ($this->fileStorageDb->checkDbUsage()) { @@ -349,6 +349,19 @@ protected function moveImageFromTmp($file) return str_replace('\\', '/', $destinationFile); } + /** + * Returns safe filename for posted image + * + * @param string $file + * @return string + */ + private function getSafeFilename($file) + { + $file = DIRECTORY_SEPARATOR . ltrim($file, DIRECTORY_SEPARATOR); + + return $this->mediaDirectory->getDriver()->getRealPathSafety($file); + } + /** * @param string $file * @return string diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php new file mode 100644 index 0000000000000..b8196fcd8bea3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php @@ -0,0 +1,138 @@ +coreFileStorageDatabaseMock = $this->createMock( + \Magento\MediaStorage\Helper\File\Storage\Database::class + ); + $this->mediaDirectoryMock = $this->createMock( + \Magento\Framework\Filesystem::class + ); + $this->mediaWriteDirectoryMock = $this->createMock( + \Magento\Framework\Filesystem\Directory\WriteInterface::class + ); + $this->mediaDirectoryMock->expects($this->any())->method('getDirectoryWrite')->willReturn( + $this->mediaWriteDirectoryMock + ); + $this->uploaderFactoryMock = $this->createMock( + \Magento\MediaStorage\Model\File\UploaderFactory::class + ); + $this->storeManagerMock = $this->createMock( + \Magento\Store\Model\StoreManagerInterface::class + ); + $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); + $this->baseTmpPath = 'base/tmp/'; + $this->basePath = 'base/real/'; + $this->allowedExtensions = ['.jpg']; + + $this->imageUploader = + new \Magento\Catalog\Model\ImageUploader( + $this->coreFileStorageDatabaseMock, + $this->mediaDirectoryMock, + $this->uploaderFactoryMock, + $this->storeManagerMock, + $this->loggerMock, + $this->baseTmpPath, + $this->basePath, + $this->allowedExtensions + ); + } + + public function testSaveFileToTmpDir() + { + $fileId = 'file.jpg'; + /** @var \Magento\MediaStorage\Model\File\Uploader|\PHPUnit_Framework_MockObject_MockObject $uploader */ + $uploader = $this->createMock(\Magento\MediaStorage\Model\File\Uploader::class); + $this->uploaderFactoryMock->expects($this->once())->method('create')->willReturn($uploader); + $uploader->expects($this->once())->method('setAllowedExtensions')->with($this->allowedExtensions); + $uploader->expects($this->once())->method('setAllowRenameFiles')->with(true); + $this->mediaWriteDirectoryMock->expects($this->once())->method('getAbsolutePath')->with($this->baseTmpPath) + ->willReturn($this->basePath); + $uploader->expects($this->once())->method('save')->with($this->basePath) + ->willReturn(['tmp_name' => $this->baseTmpPath, 'file' => $fileId, 'path' => $this->basePath]); + $storeMock = $this->createPartialMock( + \Magento\Store\Model\Store::class, + ['getBaseUrl'] + ); + $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($storeMock); + $storeMock->expects($this->once())->method('getBaseUrl'); + $this->coreFileStorageDatabaseMock->expects($this->once())->method('saveFile'); + + $result = $this->imageUploader->saveFileToTmpDir($fileId); + + $this->assertArrayNotHasKey('path', $result); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php index c1d4c25f0dbe0..921a8dcdfe6b8 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php @@ -157,6 +157,27 @@ public function testModifyMeta() $this->assertArrayHasKey(CustomOptions::GROUP_CUSTOM_OPTIONS_NAME, $this->getModel()->modifyMeta([])); } + /** + * Tests if Compatible File Extensions is required when Option Type "File" is selected in Customizable Options. + */ + public function testFileExtensionRequired() + { + $this->productOptionsConfigMock->expects($this->once()) + ->method('getAll') + ->willReturn([]); + + $meta = $this->getModel()->modifyMeta([]); + + $config = $meta['custom_options']['children']['options']['children']['record']['children']['container_option'] + ['children']['container_type_static']['children']['file_extension']['arguments']['data']['config']; + + $scope = $config['dataScope']; + $required = $config['validation']['required-entry']; + + $this->assertEquals(CustomOptions::FIELD_FILE_EXTENSION_NAME, $scope); + $this->assertTrue($required); + } + /** * Get ProductOption mock object * diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php index b3e0f1174aad9..73fecd17c69ce 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php @@ -1050,6 +1050,9 @@ protected function getFileExtensionFieldConfig($sortOrder) 'dataScope' => static::FIELD_FILE_EXTENSION_NAME, 'dataType' => Text::NAME, 'sortOrder' => $sortOrder, + 'validation' => [ + 'required-entry' => true, + ], ], ], ], diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml index b67a98a26992f..1473b043e1edc 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/crosssell_product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml index 2e3e791095c2a..0cf3d60d47205 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attributes_grid.xml @@ -25,6 +25,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml index d293c223287d0..0df70675ffd4f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_custom_options_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index 79986e53be9e7..09332d66633f1 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml index 9fa7cc41ff0a4..c62a39b5658c5 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/related_product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml index bb1c7e6ff1db4..fce4cc1dac8cf 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/upsell_product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index e394b13ceb4ac..6ae553b028a98 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -172,6 +172,7 @@ public function move($fileName, $renameFileOff = false) $this->_setUploadFile($filePath); $destDir = $this->_directory->getAbsolutePath($this->getDestDir()); $result = $this->save($destDir); + unset($result['path']); $result['name'] = self::getCorrectFileName($result['name']); return $result; } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php index 9c57d78d3d81a..e28c2e1f3c01d 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -127,10 +127,12 @@ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName) $this->uploader->expects($this->any())->method('getTmpDir')->will($this->returnValue('')); $this->uploader->expects($this->once())->method('_setUploadFile')->will($this->returnSelf()); $this->uploader->expects($this->once())->method('save')->with($destDir . '/' . $expectedFileName) - ->willReturn(['name' => $expectedFileName]); + ->willReturn(['name' => $expectedFileName, 'path' => 'absPath']); $this->uploader->setDestDir($destDir); - $this->assertEquals(['name' => $expectedFileName], $this->uploader->move($fileUrl)); + $result = $this->uploader->move($fileUrl); + $this->assertEquals(['name' => $expectedFileName], $result); + $this->assertArrayNotHasKey('path', $result); } public function testMoveFileName() diff --git a/app/code/Magento/CatalogSearch/etc/acl.xml b/app/code/Magento/CatalogSearch/etc/acl.xml new file mode 100644 index 0000000000000..dd82addc2e304 --- /dev/null +++ b/app/code/Magento/CatalogSearch/etc/acl.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Checkout/Controller/Cart/Addgroup.php b/app/code/Magento/Checkout/Controller/Cart/Addgroup.php index 046dd0b8082c1..8654bdbde5893 100644 --- a/app/code/Magento/Checkout/Controller/Cart/Addgroup.php +++ b/app/code/Magento/Checkout/Controller/Cart/Addgroup.php @@ -6,6 +6,8 @@ */ namespace Magento\Checkout\Controller\Cart; +use Magento\Sales\Model\Order\Item; + class Addgroup extends \Magento\Checkout\Controller\Cart { /** @@ -13,7 +15,7 @@ class Addgroup extends \Magento\Checkout\Controller\Cart */ public function execute() { - $orderItemIds = $this->getRequest()->getParam('order_items', []); + $orderItemIds = $this->getRequest()->getPost('order_items'); if (is_array($orderItemIds)) { $itemsCollection = $this->_objectManager->create(\Magento\Sales\Model\Order\Item::class) ->getCollection() @@ -22,7 +24,7 @@ public function execute() /* @var $itemsCollection \Magento\Sales\Model\ResourceModel\Order\Item\Collection */ foreach ($itemsCollection as $item) { try { - $this->cart->addOrderItem($item, 1); + $this->addOrderItem($item); } catch (\Magento\Framework\Exception\LocalizedException $e) { if ($this->_checkoutSession->getUseNotice(true)) { $this->messageManager->addNotice($e->getMessage()); @@ -42,4 +44,25 @@ public function execute() } return $this->_goBack(); } + + /** + * Add item to cart. + * + * Add item to cart only if it's belongs to customer. + * + * @param Item $item + * @return void + */ + private function addOrderItem(Item $item) + { + /** @var \Magento\Customer\Model\Session $session */ + $session = $this->cart->getCustomerSession(); + if ($session->isLoggedIn()) { + $orderCustomerId = $item->getOrder()->getCustomerId(); + $currentCustomerId = $session->getCustomer()->getId(); + if ($orderCustomerId == $currentCustomerId) { + $this->cart->addOrderItem($item, 1); + } + } + } } diff --git a/app/code/Magento/Cms/Block/Adminhtml/Page/Grid/Renderer/Action/UrlBuilder.php b/app/code/Magento/Cms/Block/Adminhtml/Page/Grid/Renderer/Action/UrlBuilder.php index b40820441604b..67ae137fb4d8e 100644 --- a/app/code/Magento/Cms/Block/Adminhtml/Page/Grid/Renderer/Action/UrlBuilder.php +++ b/app/code/Magento/Cms/Block/Adminhtml/Page/Grid/Renderer/Action/UrlBuilder.php @@ -37,6 +37,7 @@ public function getUrl($routePath, $scope, $store) $routePath, [ '_current' => false, + '_nosid' => true, '_query' => [StoreResolverInterface::PARAM_NAME => $store] ] ); diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Block/InlineEdit.php b/app/code/Magento/Cms/Controller/Adminhtml/Block/InlineEdit.php index 21779c020a715..e267c568fa9e5 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Block/InlineEdit.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Block/InlineEdit.php @@ -12,6 +12,13 @@ class InlineEdit extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Cms::block'; + /** * @var \Magento\Cms\Api\BlockRepositoryInterface */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Block/MassDelete.php b/app/code/Magento/Cms/Controller/Adminhtml/Block/MassDelete.php index c606c7180046e..cff9c8a39b746 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Block/MassDelete.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Block/MassDelete.php @@ -16,6 +16,13 @@ */ class MassDelete extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Cms::block'; + /** * @var Filter */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Block/Widget/Chooser.php b/app/code/Magento/Cms/Controller/Adminhtml/Block/Widget/Chooser.php index a390e0612e45b..8277aef781303 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Block/Widget/Chooser.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Block/Widget/Chooser.php @@ -12,6 +12,11 @@ class Chooser extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_Widget::widget_instance'; + /** * @var \Magento\Framework\View\LayoutFactory */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDisable.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDisable.php index 9402ae9283a0f..e39c2115f961e 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDisable.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassDisable.php @@ -15,6 +15,13 @@ */ class MassDisable extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Cms::save'; + /** * @var Filter */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassEnable.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassEnable.php index 0cbec4da8dfba..8278c28a1e696 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/MassEnable.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/MassEnable.php @@ -15,6 +15,13 @@ */ class MassEnable extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Cms::save'; + /** * @var Filter */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/Save.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/Save.php index e335ad59ee14e..5644e25dd4c4a 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/Save.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/Save.php @@ -91,6 +91,12 @@ public function execute() $id = $this->getRequest()->getParam('page_id'); if ($id) { $model->load($id); + if (!$model->getId()) { + $this->messageManager->addErrorMessage(__('This page no longer exists.')); + /** \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $resultRedirect = $this->resultRedirectFactory->create(); + return $resultRedirect->setPath('*/*/'); + } } $model->setData($data); diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/Widget/Chooser.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/Widget/Chooser.php index ba0b0c25862f6..1c46ac6807eef 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/Widget/Chooser.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/Widget/Chooser.php @@ -10,6 +10,11 @@ class Chooser extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_Widget::widget_instance'; + /** * @var \Magento\Framework\View\LayoutFactory */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php index 896c73c456269..807bdcb015ad6 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php @@ -10,6 +10,14 @@ class Directive extends \Magento\Backend\App\Action { + + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Cms::media_gallery'; + /** * @var \Magento\Framework\Url\DecoderInterface */ diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php index 40a3dd9a722a2..19dc989620b89 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php @@ -1,6 +1,5 @@ _objectManager->get(\Magento\Framework\Filesystem::class); $dir = $filesystem->getDirectoryRead(DirectoryList::MEDIA); - $filePath = $path . '/' . $file; + $filePath = $path . '/' . \Magento\Framework\File\Uploader::getCorrectFileName($file); if ($dir->isFile($dir->getRelativePath($filePath))) { $this->getStorage()->deleteFile($filePath); } diff --git a/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Page/SaveTest.php b/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Page/SaveTest.php index 03a8fc0969064..4013dc91d770c 100644 --- a/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Page/SaveTest.php +++ b/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Page/SaveTest.php @@ -277,4 +277,51 @@ public function testSaveActionThrowsException() $this->assertSame($this->resultRedirect, $this->saveController->execute()); } + + /** + * Test for saving page after edit of it if page_id does not exists in the system + * + * @security-private + */ + public function testSaveNotExistingPage() + { + $this->pageId = 1111111111111111111111111; + $this->requestMock->expects($this->any())->method('getPostValue')->willReturn(['page_id' => $this->pageId]); + $this->requestMock->expects($this->atLeastOnce()) + ->method('getParam') + ->willReturnMap( + [ + ['page_id', null, $this->pageId], + ['back', null, true], + ] + ); + + $this->dataProcessorMock->expects($this->any()) + ->method('filter') + ->willReturnArgument(0); + $page = $this->getMockBuilder(\Magento\Cms\Model\Page::class) + ->disableOriginalConstructor() + ->getMock(); + $this->pageFactory->expects($this->atLeastOnce()) + ->method('create') + ->willReturn($page); + + $page->expects($this->any()) + ->method('load') + ->willReturnSelf(); + $page->expects($this->any()) + ->method('getId') + ->willReturn(null); + + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with(__('This page no longer exists.')); + + $this->resultRedirect->expects($this->atLeastOnce()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->assertSame($this->resultRedirect, $this->saveController->execute()); + } } diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml index 5943caa906087..9f886f6f1345e 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml @@ -31,6 +31,7 @@ + Magento_Cms::block id diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml index ac66a4df2c560..846356adf9429 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -31,6 +31,7 @@ + Magento_Cms::page id diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/AddAttribute.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/AddAttribute.php index 19f4d1e0ee91d..5991097e456f2 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/AddAttribute.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/AddAttribute.php @@ -11,6 +11,13 @@ class AddAttribute extends Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Catalog::products'; + /** * @var \Magento\Catalog\Controller\Adminhtml\Product\Builder */ diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Associated/Grid.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Associated/Grid.php index eacca230335bd..7e9b163541bea 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Associated/Grid.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Associated/Grid.php @@ -12,6 +12,13 @@ class Grid extends Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Catalog::products'; + /** * @var LayoutFactory */ diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Wizard.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Wizard.php index a065914ae01be..8adfdea96102c 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Wizard.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Wizard.php @@ -15,6 +15,13 @@ */ class Wizard extends Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Catalog::products'; + /** * @var Builder */ diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/configurable_associated_product_listing.xml b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/configurable_associated_product_listing.xml index 6a628b8e8ad36..2a40caaabae04 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/configurable_associated_product_listing.xml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/configurable_associated_product_listing.xml @@ -24,6 +24,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml index 61c7645a5eb57..ea80c218516c3 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/ui_component/product_attributes_listing.xml @@ -25,6 +25,7 @@ + Magento_Catalog::products id diff --git a/app/code/Magento/Customer/Controller/Account/CreatePost.php b/app/code/Magento/Customer/Controller/Account/CreatePost.php index 675338f9fed7a..27d8ddd99344c 100644 --- a/app/code/Magento/Customer/Controller/Account/CreatePost.php +++ b/app/code/Magento/Customer/Controller/Account/CreatePost.php @@ -11,6 +11,7 @@ use Magento\Framework\App\Action\Context; use Magento\Customer\Model\Session; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; use Magento\Store\Model\StoreManagerInterface; use Magento\Customer\Api\AccountManagementInterface; @@ -27,8 +28,10 @@ use Magento\Customer\Model\CustomerExtractor; use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\InputException; +use Magento\Framework\Data\Form\FormKey\Validator; /** + * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CreatePost extends \Magento\Customer\Controller\AbstractAccount @@ -118,6 +121,11 @@ class CreatePost extends \Magento\Customer\Controller\AbstractAccount */ private $cookieMetadataManager; + /** + * @var Validator + */ + private $formKeyValidator; + /** * @param Context $context * @param Session $customerSession @@ -137,6 +145,7 @@ class CreatePost extends \Magento\Customer\Controller\AbstractAccount * @param CustomerExtractor $customerExtractor * @param DataObjectHelper $dataObjectHelper * @param AccountRedirect $accountRedirect + * @param Validator $formKeyValidator * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -158,7 +167,8 @@ public function __construct( Escaper $escaper, CustomerExtractor $customerExtractor, DataObjectHelper $dataObjectHelper, - AccountRedirect $accountRedirect + AccountRedirect $accountRedirect, + Validator $formKeyValidator = null ) { $this->session = $customerSession; $this->scopeConfig = $scopeConfig; @@ -177,6 +187,7 @@ public function __construct( $this->urlModel = $urlFactory->create(); $this->dataObjectHelper = $dataObjectHelper; $this->accountRedirect = $accountRedirect; + $this->formKeyValidator = $formKeyValidator ?: ObjectManager::getInstance()->get(Validator::class); parent::__construct($context); } @@ -189,7 +200,7 @@ public function __construct( private function getCookieManager() { if (!$this->cookieMetadataManager) { - $this->cookieMetadataManager = \Magento\Framework\App\ObjectManager::getInstance()->get( + $this->cookieMetadataManager = ObjectManager::getInstance()->get( \Magento\Framework\Stdlib\Cookie\PhpCookieManager::class ); } @@ -205,7 +216,7 @@ private function getCookieManager() private function getCookieMetadataFactory() { if (!$this->cookieMetadataFactory) { - $this->cookieMetadataFactory = \Magento\Framework\App\ObjectManager::getInstance()->get( + $this->cookieMetadataFactory = ObjectManager::getInstance()->get( \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class ); } @@ -278,7 +289,7 @@ public function execute() return $resultRedirect; } - if (!$this->getRequest()->isPost()) { + if (!$this->getRequest()->isPost() || !$this->formKeyValidator->validate($this->getRequest())) { $url = $this->urlModel->getUrl('*/*/create', ['_secure' => true]); $resultRedirect->setUrl($this->_redirect->error($url)); return $resultRedirect; diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Locks/Unlock.php b/app/code/Magento/Customer/Controller/Adminhtml/Locks/Unlock.php index 864e9af6d8bcc..1fd06a3182948 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Locks/Unlock.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Locks/Unlock.php @@ -15,6 +15,13 @@ */ class Unlock extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Customer::manage'; + /** * Authentication * diff --git a/app/code/Magento/Customer/Controller/Adminhtml/System/Config/Validatevat.php b/app/code/Magento/Customer/Controller/Adminhtml/System/Config/Validatevat.php index 87fcfc09ffbb6..31d23c9e3694e 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/System/Config/Validatevat.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/System/Config/Validatevat.php @@ -12,6 +12,13 @@ */ abstract class Validatevat extends \Magento\Backend\App\Action { + /** + * Authorization level of a basic admin session + * + * @see _isAllowed() + */ + const ADMIN_RESOURCE = 'Magento_Customer::manage'; + /** * Perform customer VAT ID validation * diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php index 2cd142b7526f6..ce976d3f62c74 100644 --- a/app/code/Magento/Customer/Model/Customer/DataProvider.php +++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php @@ -29,7 +29,6 @@ use Magento\Ui\DataProvider\EavValidationRules; /** - * Class DataProvider * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * * @api @@ -125,6 +124,17 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider ]; /** + * Customer fields that must be removed + * + * @var array + */ + private $forbiddenCustomerFields = [ + 'password_hash', + 'rp_token', + 'confirmation', + ]; + + /* * @var ContextInterface */ private $context; @@ -186,7 +196,6 @@ public function __construct( * Get session object * * @return SessionManagerInterface - * * @deprecated 100.1.3 * @since 100.1.0 */ @@ -217,6 +226,10 @@ public function getData() $this->overrideFileUploaderData($customer, $result['customer']); + $result['customer'] = array_diff_key( + $result['customer'], + array_flip($this->forbiddenCustomerFields) + ); unset($result['address']); /** @var Address $address */ @@ -406,8 +419,8 @@ private function canShowAttribute(AbstractAttribute $customerAttribute) /** * Retrieve Country With Websites Source * - * @deprecated 100.2.0 * @return CountryWithWebsites + * @deprecated 100.2.0 */ private function getCountryWithWebsiteSource() { @@ -421,8 +434,8 @@ private function getCountryWithWebsiteSource() /** * Retrieve Customer Config Share * - * @deprecated 100.1.3 * @return \Magento\Customer\Model\Config\Share + * @deprecated 100.1.3 */ private function getShareConfig() { @@ -592,7 +605,6 @@ protected function prepareAddressData($addressId, array &$addresses, array $cust * Get FileProcessorFactory instance * * @return FileProcessorFactory - * * @deprecated 100.1.3 */ private function getFileProcessorFactory() diff --git a/app/code/Magento/Customer/Model/FileProcessor.php b/app/code/Magento/Customer/Model/FileProcessor.php index d482d00748324..2d6917efdaf56 100644 --- a/app/code/Magento/Customer/Model/FileProcessor.php +++ b/app/code/Magento/Customer/Model/FileProcessor.php @@ -181,6 +181,7 @@ public function saveTemporaryFile($fileId) ); $result = $uploader->save($path); + unset($result['path']); if (!$result) { throw new \Magento\Framework\Exception\LocalizedException( __('File can not be saved to the destination folder.') diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php index ab5afbab5e5ce..029949c5f35b0 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php @@ -547,6 +547,20 @@ function ($origName) { */ public function testGetData() { + $customerData = [ + 'email' => 'test@test.ua', + 'default_billing' => 2, + 'default_shipping' => 2, + 'password_hash' => 'password_hash', + 'rp_token' => 'rp_token', + 'confirmation' => 'confirmation', + ]; + $addressData = [ + 'firstname' => 'firstname', + 'lastname' => 'lastname', + 'street' => "street\nstreet", + ]; + $customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) ->disableOriginalConstructor() ->getMock(); @@ -570,11 +584,7 @@ public function testGetData() ->willReturn([$customer]); $customer->expects($this->once()) ->method('getData') - ->willReturn([ - 'email' => 'test@test.ua', - 'default_billing' => 2, - 'default_shipping' => 2, - ]); + ->willReturn($customerData); $customer->expects($this->once()) ->method('getAddresses') ->willReturn([$address]); @@ -591,11 +601,7 @@ public function testGetData() ->willReturnSelf(); $address->expects($this->once()) ->method('getData') - ->willReturn([ - 'firstname' => 'firstname', - 'lastname' => 'lastname', - 'street' => "street\nstreet", - ]); + ->willReturn($addressData); $address->expects($this->once()) ->method('getAttributes') ->willReturn([]); diff --git a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php index 22df0f0584e72..f2db8c6cab6be 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php @@ -183,7 +183,10 @@ public function testSaveTemporaryFile() $expectedResult = [ 'file' => 'filename.ext1', - 'path' => 'filepath', + ]; + $resultWithPath = [ + 'file' => 'filename.ext1', + 'path' => 'filepath' ]; $uploaderMock = $this->getMockBuilder(\Magento\MediaStorage\Model\File\Uploader::class) @@ -208,7 +211,7 @@ public function testSaveTemporaryFile() $uploaderMock->expects($this->once()) ->method('save') ->with($absolutePath) - ->willReturn($expectedResult); + ->willReturn($resultWithPath); $this->uploaderFactory->expects($this->once()) ->method('create') diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml index a1363fe0e6089..f8aa078f45e4d 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_listing.xml @@ -28,6 +28,7 @@ + Magento_Customer::manage id diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml index 8182a213ee6e7..c818f9c1271ab 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_online_grid.xml @@ -24,6 +24,7 @@ + Magento_Customer::online id diff --git a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml index 70ffef4ce86a6..43e4e92fd0904 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -12,6 +12,7 @@ getChildHtml('customer.form.register.extra') ?>