From 5cb95a5abbcb38ddf0aef3c04073a1752533dba7 Mon Sep 17 00:00:00 2001 From: Rik Willems <> Date: Tue, 31 Oct 2023 11:15:11 +0100 Subject: [PATCH 1/2] [#225] Setup whitelist default pool and use that for first install & restore defaults --- Block/Adminhtml/Settings/Whitelist.php | 24 ++-- .../Adminhtml/Manage/RestoreDefault.php | 71 ++++-------- Model/WhitelistDefaultInstaller.php | 50 +++++++++ Model/WhitelistDefaultPool.php | 44 ++++++++ Setup/Patch/Data/Patch501.php | 74 ++----------- etc/di.xml | 104 ++++++++++++++---- etc/module.xml | 2 +- 7 files changed, 227 insertions(+), 142 deletions(-) create mode 100644 Model/WhitelistDefaultInstaller.php create mode 100644 Model/WhitelistDefaultPool.php diff --git a/Block/Adminhtml/Settings/Whitelist.php b/Block/Adminhtml/Settings/Whitelist.php index f019cb6..e3b733d 100644 --- a/Block/Adminhtml/Settings/Whitelist.php +++ b/Block/Adminhtml/Settings/Whitelist.php @@ -22,14 +22,14 @@ class Whitelist extends \Magento\Backend\Block\Widget\Container /** * @inheritDoc */ - protected function _prepareLayout() + protected function _prepareLayout(): self { $restoreDefautsButtonProps = [ 'id' => 'restore_defaults', 'label' => __('Restore Defaults'), 'class' => 'primary add', 'button_class' => '', - 'onclick' => "setLocation('" . $this->getRestoreDefaultsUrl() . "')", + 'on_click' => "deleteConfirm('{$this->getRestoreDefaultsConfirmationText()}', '{$this->getRestoreDefaultsUrl()}')", 'class_name' => 'Magento\Backend\Block\Widget\Button' ]; $this->buttonList->add('restore_defaults', $restoreDefautsButtonProps); @@ -47,12 +47,22 @@ protected function _prepareLayout() return parent::_prepareLayout(); } + /** + * Retrieve restore defaults confirmation text + */ + protected function getRestoreDefaultsConfirmationText(): string + { + return sprintf( + '

%s

%s

', + __('You will remove all existing whitelist entries and restore the defaults.'), + __('Are you sure you want to do this?') + ); + } + /** * Retrieve restore defaults url - * - * @return string */ - protected function getRestoreDefaultsUrl() + protected function getRestoreDefaultsUrl(): string { return $this->getUrl( 'ForceCustomerLogin/Manage/RestoreDefault' @@ -61,10 +71,8 @@ protected function getRestoreDefaultsUrl() /** * Retrieve create url - * - * @return string */ - protected function getCreateUrl() + protected function getCreateUrl(): string { return $this->getUrl( 'ForceCustomerLogin/Manage/Create' diff --git a/Controller/Adminhtml/Manage/RestoreDefault.php b/Controller/Adminhtml/Manage/RestoreDefault.php index 32286eb..8019bae 100644 --- a/Controller/Adminhtml/Manage/RestoreDefault.php +++ b/Controller/Adminhtml/Manage/RestoreDefault.php @@ -11,8 +11,9 @@ namespace BitExpert\ForceCustomerLogin\Controller\Adminhtml\Manage; -use BitExpert\ForceCustomerLogin\Api\Repository\WhitelistRepositoryInterface; -use BitExpert\ForceCustomerLogin\Model\WhitelistEntry; +use BitExpert\ForceCustomerLogin\Model\WhitelistDefaultInstaller; +use BitExpert\ForceCustomerLogin\Model\ResourceModel\WhitelistEntry as WhitelistEntryResource; +use BitExpert\ForceCustomerLogin\Model\ResourceModel\WhitelistEntry\CollectionFactory as WhitelistEntryCollectionFactory; use Magento\Framework\Controller\Result\RedirectFactory; use Magento\Backend\App\Action\Context; use Magento\Framework\App\ResponseInterface; @@ -26,35 +27,25 @@ */ class RestoreDefault extends \Magento\Backend\App\Action { - /** - * @var WhitelistRepositoryInterface - */ - private $whitelistRepository; - /** - * @var RedirectFactory - */ - private $redirectFactory; - /** - * @var array Default routes - */ - private $defaultRoutes; + private RedirectFactory $redirectFactory; + private WhitelistDefaultInstaller $whitelistDefaultInstaller; + private WhitelistEntryResource $whitelistEntryResource; + private WhitelistEntryCollectionFactory $whitelistEntryCollectionFactory; /** - * Save constructor. - * - * @param WhitelistRepositoryInterface $whitelistRepository - * @param Context $context - * @param array $defaultRoutes + * RestoreDefault constructor. */ public function __construct( - WhitelistRepositoryInterface $whitelistRepository, Context $context, - array $defaultRoutes + WhitelistDefaultInstaller $whitelistDefaultInstaller, + WhitelistEntryResource $whitelistEntryResource, + WhitelistEntryCollectionFactory $whitelistEntryCollectionFactory ) { parent::__construct($context); - $this->whitelistRepository = $whitelistRepository; $this->redirectFactory = $context->getResultRedirectFactory(); - $this->defaultRoutes = $defaultRoutes; + $this->whitelistDefaultInstaller = $whitelistDefaultInstaller; + $this->whitelistEntryResource = $whitelistEntryResource; + $this->whitelistEntryCollectionFactory = $whitelistEntryCollectionFactory; } /** @@ -67,16 +58,16 @@ public function execute() $result = $this->redirectFactory->create(); $result->setPath('ForceCustomerLogin/Manage/index'); - $whiteLists = $this->getWhiteListEntriesIndexedByPath(); - try { - foreach ($this->defaultRoutes as $route => $description) { - if (\array_key_exists($route, $whiteLists)) { - continue; - } + $resource = $this->whitelistEntryResource; + $collection = $this->whitelistEntryCollectionFactory->create(); - $this->whitelistRepository->createEntry(null, $description, $route); - } + $resource->beginTransaction(); + $collection->walk(function ($entry) { + $entry->delete(); + }); + $this->whitelistDefaultInstaller->install(); + $resource->commit(); } catch (\Exception $e) { $result->setHttpResponseCode(\Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR); $this->messageManager->addErrorMessage( @@ -93,24 +84,6 @@ public function execute() return $result; } - /** - * Get all current whitelists indexed by it's url rule - * - * @return array - */ - protected function getWhiteListEntriesIndexedByPath() - { - $whiteListCollection = $this->whitelistRepository->getCollection(); - $whiteLists = []; - - foreach ($whiteListCollection->getItems() as $whiteList) { - $whiteLists[$whiteList->getData(WhitelistEntry::KEY_URL_RULE)] = - $whiteList->getData(WhitelistEntry::KEY_LABEL); - } - - return $whiteLists; - } - /** * @inheritDoc * @codeCoverageIgnore diff --git a/Model/WhitelistDefaultInstaller.php b/Model/WhitelistDefaultInstaller.php new file mode 100644 index 0000000..09fbf6c --- /dev/null +++ b/Model/WhitelistDefaultInstaller.php @@ -0,0 +1,50 @@ +whitelistDefaultPool = $whitelistDefaultPool; + $this->whitelistRepository = $whitelistRepository; + } + + public function install(): void + { + foreach ($this->whitelistDefaultPool->getEntries() as $route => $data) { + $this->whitelistRepository->createEntry( + null, + $data['label'], + $route, + $data['strategy'] ?: 'default', + ); + } + } +} diff --git a/Model/WhitelistDefaultPool.php b/Model/WhitelistDefaultPool.php new file mode 100644 index 0000000..4c7be9c --- /dev/null +++ b/Model/WhitelistDefaultPool.php @@ -0,0 +1,44 @@ +entries = $entries; + } + + /** + * Get default entries from pool + * + * @return array[string, array] + */ + public function getEntries(): array + { + return $this->entries; + } +} diff --git a/Setup/Patch/Data/Patch501.php b/Setup/Patch/Data/Patch501.php index 828c832..e606c50 100644 --- a/Setup/Patch/Data/Patch501.php +++ b/Setup/Patch/Data/Patch501.php @@ -11,6 +11,7 @@ namespace BitExpert\ForceCustomerLogin\Setup\Patch\Data; +use BitExpert\ForceCustomerLogin\Model\WhitelistDefaultInstaller; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\Patch\DataPatchInterface; @@ -21,12 +22,20 @@ class Patch501 implements DataPatchInterface */ private ModuleDataSetupInterface $moduleDataSetup; + /** + * @var WhitelistDefaultInstaller + */ + private WhitelistDefaultInstaller $whitelistDefaultInstaller; + /** * @param ModuleDataSetupInterface $moduleDataSetup */ - public function __construct(ModuleDataSetupInterface $moduleDataSetup) - { + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + WhitelistDefaultInstaller $whitelistDefaultInstaller + ) { $this->moduleDataSetup = $moduleDataSetup; + $this->whitelistDefaultInstaller = $whitelistDefaultInstaller; } /** @@ -36,42 +45,7 @@ public function apply() { $this->moduleDataSetup->getConnection()->startSetup(); - $whitelistEntries = [ - $this->getWhitelistEntryAsArray(0, 'Rest API', '/rest', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Login', '/customer/account/login', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Logout', '/customer/account/logout', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Logout Success', '/customer/account/logoutSuccess', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Create', '/customer/account/create', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Create Password', '/customer/account/createPassword', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Forgot Password', '/customer/account/forgotpassword', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Forgot Password Post', '/customer/account/forgotpasswordpost', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Section Load', '/customer/section/load', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Contact Us', '/contact', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Help', '/help', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Sitemap.xml', '/sitemap.xml', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Robots.txt', '/robots.txt', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Dashboard', '/customer/account', true, 'regex-all'), - $this->getWhitelistEntryAsArray(0, 'Customer Account Reset Password Post', '/customer/account/resetpasswordpost'), - $this->getWhitelistEntryAsArray(0, 'Varnish ESI url', '/page_cache/block/esi/blocks'), - $this->getWhitelistEntryAsArray(0, 'Store-Switcher Redirect', '/stores/store/redirect'), - $this->getWhitelistEntryAsArray(0, 'Store-Switcher Switch', '/stores/store/switch'), - $this->getWhitelistEntryAsArray(0, 'Customer Create (Post)', '/customer/account/createpost'), - $this->getWhitelistEntryAsArray(0, 'Paypal', '/paypal/ipn/'), - ]; - - foreach ($whitelistEntries as $entry) { - try { - // if the migration happens from an older version of the module, an exception will be thrown since the - // label needs to be unique. Splitting this patch into chunks and bind them to the specific module - // version as in UpgradeData.php does not seem to apply the older patches for a fresh install. This - // seems the only way to solve the issue for now. - $this->moduleDataSetup->getConnection()->insert( - $this->moduleDataSetup->getTable('bitexpert_forcelogin_whitelist'), - $entry - ); - } catch (\Exception $e) { - } - } + $this->whitelistDefaultInstaller->install(); $this->moduleDataSetup->getConnection()->endSetup(); @@ -93,28 +67,4 @@ public static function getDependencies() { return []; } - - /** - * @param int $storeId - * @param string $label - * @param string $urlRule - * @param boolean $editable - * @param string $strategy - * @return array - */ - public static function getWhitelistEntryAsArray( - $storeId, - $label, - $urlRule, - $editable = false, - $strategy = 'default' - ) { - return [ - 'store_id' => $storeId, - 'label' => $label, - 'url_rule' => $urlRule, - 'editable' => $editable, - 'strategy' => $strategy - ]; - } } diff --git a/etc/di.xml b/etc/di.xml index 9bb0f74..237d3db 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -16,29 +16,89 @@ - + - - Rest API - Customer Account Login - Customer Account Logout - Customer Account Logout Success - Customer Account Create - Customer Account Create Password - Customer Account Reset Password Post - Customer Account Forgot Password - Customer Account Forgot Password Post - Customer Section Load - Contact Us - Help - Sitemap.xml - Robots.txt - Customer Account Dashboard - Varnish ESI url - Store-Switcher Redirect - Store-Switcher Switch - Customer Create (Post) - Paypal + + + Rest API + regex-all + + + Customer Account Login + regex-all + + + Customer Account Logout + regex-all + + + Customer Account Logout Success + regex-all + + + Customer Account Create + regex-all + + + Customer Account Create Password + regex-all + + + Customer Account Forgot Password + regex-all + + + Customer Account Forgot Password Post + regex-all + + + Customer Section Load + regex-all + + + Contact Us + regex-all + + + Help + regex-all + + + Sitemap.xml + regex-all + + + Robots.txt + regex-all + + + Customer Account Dashboard + regex-all + + + Customer Account Reset Password Post + + + + Varnish ESI url + + + + Store-Switcher Redirect + + + + Store-Switcher Switch + + + + Customer Create (Post) + + + + Paypal + + diff --git a/etc/module.xml b/etc/module.xml index 6c1f4b7..39e5d20 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -11,7 +11,7 @@ --> - + From 663d337205a80586cd132be53e1671794e37d8dc Mon Sep 17 00:00:00 2001 From: Rik Willems <> Date: Wed, 1 Nov 2023 13:52:13 +0100 Subject: [PATCH 2/2] Add unit tests --- Test/DataProviders/WhitelistDataProvider.php | 24 ++++++++++ .../WhitelistDefaultInstallerUnitTest.php | 47 +++++++++++++++++++ .../Model/WhitelistDefaultPoolUnitTest.php | 34 ++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 Test/DataProviders/WhitelistDataProvider.php create mode 100644 Test/Unit/Model/WhitelistDefaultInstallerUnitTest.php create mode 100644 Test/Unit/Model/WhitelistDefaultPoolUnitTest.php diff --git a/Test/DataProviders/WhitelistDataProvider.php b/Test/DataProviders/WhitelistDataProvider.php new file mode 100644 index 0000000..9a583ae --- /dev/null +++ b/Test/DataProviders/WhitelistDataProvider.php @@ -0,0 +1,24 @@ + [ + [ + '/url1' => [ + 'label' => 'label 1', + 'strategy' => '', + ], + '/url2' => [ + 'label' => 'label 2', + 'strategy' => 'regex-all', + ], + ], + ], + ]; + } +} diff --git a/Test/Unit/Model/WhitelistDefaultInstallerUnitTest.php b/Test/Unit/Model/WhitelistDefaultInstallerUnitTest.php new file mode 100644 index 0000000..0e22e50 --- /dev/null +++ b/Test/Unit/Model/WhitelistDefaultInstallerUnitTest.php @@ -0,0 +1,47 @@ +createMock(WhitelistDefaultPool::class); + $poolMock->expects($this->once()) + ->method('getEntries') + ->willReturn($entries); + + $repositoryMock = $this->createMock(WhitelistRepositoryInterface::class); + $repositoryMock->expects($this->exactly(count($entries))) + ->method('createEntry'); + + $installer = new WhitelistDefaultInstaller($poolMock, $repositoryMock); + $installer->install(); + } +} diff --git a/Test/Unit/Model/WhitelistDefaultPoolUnitTest.php b/Test/Unit/Model/WhitelistDefaultPoolUnitTest.php new file mode 100644 index 0000000..3fa999b --- /dev/null +++ b/Test/Unit/Model/WhitelistDefaultPoolUnitTest.php @@ -0,0 +1,34 @@ +assertEquals($entries, $pool->getEntries()); + } +}