diff --git a/vendor/magento/module-admin-gws/Model/ForceWhitelistRegistry.php b/vendor/magento/module-admin-gws/Model/ForceWhitelistRegistry.php new file mode 100644 index 000000000000..eab184198bf3 --- /dev/null +++ b/vendor/magento/module-admin-gws/Model/ForceWhitelistRegistry.php @@ -0,0 +1,62 @@ +disabledList[$entityClassName] = $this->disabledList[$entityClassName] ?? 0; + $this->disabledList[$entityClassName] += 1; + } + + /** + * Enable temporary disabled check back + * + * @param string $entityClassName + * @return void + */ + public function restore(string $entityClassName): void + { + if (isset($this->disabledList[$entityClassName])) { + $this->disabledList[$entityClassName] -= 1; + } + } + + /** + * Checking is there any force allow for the model + * + * @param object $model + * @return bool + */ + public function isLoadingForceAllowed(object $model): bool + { + foreach ($this->disabledList as $class => $counter) { + if ($counter <= 0) { + continue; + } + + if ($model instanceof $class) { + return true; + } + } + + return false; + } +} diff --git a/vendor/magento/module-admin-gws/Model/Plugin/Store/StoreSwitcher/ManageStoreCookie.php b/vendor/magento/module-admin-gws/Model/Plugin/Store/StoreSwitcher/ManageStoreCookie.php new file mode 100644 index 000000000000..34531758209f --- /dev/null +++ b/vendor/magento/module-admin-gws/Model/Plugin/Store/StoreSwitcher/ManageStoreCookie.php @@ -0,0 +1,98 @@ +role = $role; + $this->storeManager = $storeManager; + $this->storeCookieManager = $storeCookieManager; + $this->httpContext = $httpContext; + } + + /** + * Store switch logic for restricted admin user + * + * @param ManageStoreCookieClass $subject + * @param Closure $proceed + * @param StoreInterface $fromStore + * @param StoreInterface $targetStore + * @param string $redirectUrl + * + * @return array|mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @throws LocalizedException + */ + public function aroundSwitch( + ManageStoreCookieClass $subject, + Closure $proceed, + StoreInterface $fromStore, + StoreInterface $targetStore, + string $redirectUrl + ) { + if (!$this->role->getIsAll()) { + $website = $this->storeManager->getWebsite($targetStore->getWebsiteId()); + if ($website->getIsDefault() && $targetStore->isDefault()) { + $this->storeCookieManager->deleteStoreCookie($targetStore); + } else { + $this->httpContext->setValue(Store::ENTITY, $targetStore->getCode(), $fromStore->getCode()); + $this->storeCookieManager->setStoreCookie($targetStore); + } + return $redirectUrl; + } else { + return $proceed($fromStore, $targetStore, $redirectUrl); + } + } +} diff --git a/vendor/magento/module-admin-gws/Observer/SetDataBeforeRoleSave.php b/vendor/magento/module-admin-gws/Observer/SetDataBeforeRoleSave.php index 9bd430151f68..ce27d50873ec 100644 --- a/vendor/magento/module-admin-gws/Observer/SetDataBeforeRoleSave.php +++ b/vendor/magento/module-admin-gws/Observer/SetDataBeforeRoleSave.php @@ -10,9 +10,7 @@ use \Magento\Framework\Exception\LocalizedException; /** - * Class SetDataBeforeRoleSave - * - * @package Magento\AdminGws\Observer + * Set data before save role */ class SetDataBeforeRoleSave implements ObserverInterface { @@ -87,14 +85,23 @@ public function execute(\Magento\Framework\Event\Observer $observer) } } } - if (!empty($storeGroupIds)) { - if (!is_array($storeGroupIds)) { - $storeGroupIds = explode(',', $storeGroupIds); - } - $allStoreGroups = []; - foreach ($this->storeManager->getWebsites() as $website) { - $allStoreGroups = array_merge($allStoreGroups, $website->getGroupIds()); + + if (!empty($storeGroupIds) && !is_array($storeGroupIds)) { + $storeGroupIds = explode(',', $storeGroupIds); + } + + $allStoreGroups = []; + $allStoreGroupIds = []; + $gwsStoreGroupIds = []; + foreach ($this->storeManager->getWebsites() as $website) { + $allStoreGroupIds[] = $website->getGroupIds(); + if (!empty($websiteIds) && in_array($website->getId(), $websiteIds)) { + $gwsStoreGroupIds[] = $website->getGroupIds(); } + } + $allStoreGroups = array_merge($allStoreGroups, ...$allStoreGroupIds); + $storeGroupIds = array_merge($storeGroupIds, ...$gwsStoreGroupIds); + if (!empty($storeGroupIds)) { if ($notExistStoreGroups = array_diff($storeGroupIds, $allStoreGroups)) { throw new LocalizedException( __( diff --git a/vendor/magento/module-admin-gws/Observer/ValidateModelLoadAfter.php b/vendor/magento/module-admin-gws/Observer/ValidateModelLoadAfter.php index 77fe4f3c8b06..759bff65d078 100644 --- a/vendor/magento/module-admin-gws/Observer/ValidateModelLoadAfter.php +++ b/vendor/magento/module-admin-gws/Observer/ValidateModelLoadAfter.php @@ -5,38 +5,50 @@ */ namespace Magento\AdminGws\Observer; +use Magento\AdminGws\Model\CallbackInvoker; +use Magento\AdminGws\Model\ConfigInterface; +use Magento\AdminGws\Model\ForceWhitelistRegistry; +use Magento\AdminGws\Model\Role; use Magento\Framework\Event\ObserverInterface; class ValidateModelLoadAfter implements ObserverInterface { /** - * @var \Magento\AdminGws\Model\Role + * @var Role */ protected $role; /** - * @var \Magento\AdminGws\Model\CallbackInvoker + * @var CallbackInvoker */ protected $callbackInvoker; /** - * @var \Magento\AdminGws\Model\ConfigInterface + * @var ConfigInterface */ protected $config; /** - * @param \Magento\AdminGws\Model\Role $role - * @param \Magento\AdminGws\Model\CallbackInvoker $callbackInvoker - * @param \Magento\AdminGws\Model\ConfigInterface $config + * @var ForceWhitelistRegistry + */ + private ForceWhitelistRegistry $forceWhitelistRegistry; + + /** + * @param Role $role + * @param CallbackInvoker $callbackInvoker + * @param ConfigInterface $config + * @param ForceWhitelistRegistry $forceWhitelistRegistry */ public function __construct( - \Magento\AdminGws\Model\Role $role, - \Magento\AdminGws\Model\CallbackInvoker $callbackInvoker, - \Magento\AdminGws\Model\ConfigInterface $config + Role $role, + CallbackInvoker $callbackInvoker, + ConfigInterface $config, + ForceWhitelistRegistry $forceWhitelistRegistry ) { $this->callbackInvoker = $callbackInvoker; $this->role = $role; $this->config = $config; + $this->forceWhitelistRegistry = $forceWhitelistRegistry; } /** @@ -58,6 +70,10 @@ public function execute(\Magento\Framework\Event\Observer $observer) return; } + if ($this->forceWhitelistRegistry->isLoadingForceAllowed($model)) { + return; + } + $this->callbackInvoker ->invoke( $callback, diff --git a/vendor/magento/module-admin-gws/Plugin/Customer/Block/Adminhtml/Group/IsCustomerAllowedToAddCustomerGroupButtonPlugin.php b/vendor/magento/module-admin-gws/Plugin/Customer/Block/Adminhtml/Group/IsCustomerAllowedToAddCustomerGroupButtonPlugin.php new file mode 100644 index 000000000000..25e5209924ab --- /dev/null +++ b/vendor/magento/module-admin-gws/Plugin/Customer/Block/Adminhtml/Group/IsCustomerAllowedToAddCustomerGroupButtonPlugin.php @@ -0,0 +1,48 @@ +role = $role; + } + + /** + * After plugin to determine if current customer is allowed to add new customer group + * + * @param AddCustomerGroupButton $subject + * @param array $result + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetButtonData( + AddCustomerGroupButton $subject, + array $result + ): array { + if (!$this->role->getIsAll()) { + $result = []; + } + return $result; + } +} diff --git a/vendor/magento/module-admin-gws/Plugin/Customer/Model/ResourceModel/Grid/Collection.php b/vendor/magento/module-admin-gws/Plugin/Customer/Model/ResourceModel/Grid/Collection.php new file mode 100644 index 000000000000..85f9ac25445a --- /dev/null +++ b/vendor/magento/module-admin-gws/Plugin/Customer/Model/ResourceModel/Grid/Collection.php @@ -0,0 +1,105 @@ +filterCollection($collection); + + return [$printQuery, $logQuery]; + } + + /** + * Adds allowed websites to query filter. + * + * @param CustomerGridCollection $collection + * @throws Zend_Db_Select_Exception + */ + public function beforeGetSelectCountSql(CustomerGridCollection $collection) + { + $this->filterCollection($collection); + } + + /** + * Add website filter to a customer grid collection. + * + * @param CustomerGridCollection $collection + * @throws Zend_Db_Select_Exception + */ + private function filterCollection(CustomerGridCollection $collection) + { + $role = $this->backendAuthSession->getUser() ? + $this->backendAuthSession->getUser()->getRole() : null; + if ($role && !$role->getIsAll() && $collection->getFlag(self::FILTERED_FLAG_NAME)) { + $this->resetWebsiteConditions($collection); + $whereCondition = 'main_table.website_id IN (?) OR main_table.website_id IS NULL'; + $collection->getSelect()->where($whereCondition, $role->getGwsWebsites()); + } + } + + /** + * Reset website conditions. + * + * @param CustomerGridCollection $collection + * @return void + * @throws Zend_Db_Select_Exception + */ + private function resetWebsiteConditions(CustomerGridCollection $collection): void + { + $where = $collection->getSelect()->getPart(Select::WHERE); + foreach ($where as $key => $value) { + if (str_contains($value, 'main_table.website_id')) { + unset($where[$key]); + } + } + $collection->getSelect()->setPart(Select::WHERE, $where); + } +} diff --git a/vendor/magento/module-admin-gws/Plugin/Customer/Ui/Component/Listing/Column/CanHideDeleteButton.php b/vendor/magento/module-admin-gws/Plugin/Customer/Ui/Component/Listing/Column/CanHideDeleteButton.php new file mode 100644 index 000000000000..c27e073f570a --- /dev/null +++ b/vendor/magento/module-admin-gws/Plugin/Customer/Ui/Component/Listing/Column/CanHideDeleteButton.php @@ -0,0 +1,48 @@ +role = $role; + } + + /** + * After plugin to determine if current customer is allowed to view delete button + * + * @param GroupActions $subject + * @param bool $result + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterCanHideDeleteButton( + GroupActions $subject, + bool $result + ): bool { + if (!$this->role->getIsAll()) { + $result = true; + } + return $result; + } +} diff --git a/vendor/magento/module-admin-gws/Plugin/CustomerBalance/Model/Creditmemo/BalancePlugin.php b/vendor/magento/module-admin-gws/Plugin/CustomerBalance/Model/Creditmemo/BalancePlugin.php new file mode 100644 index 000000000000..b596c0ed330f --- /dev/null +++ b/vendor/magento/module-admin-gws/Plugin/CustomerBalance/Model/Creditmemo/BalancePlugin.php @@ -0,0 +1,57 @@ +forceWhitelistRegistry = $forceWhitelistRegistry; + } + + /** + * Before customer balance save processing. + * + * @param Balance $subject + * @param Creditmemo $creditmemo + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeSave(Balance $subject, Creditmemo $creditmemo): void + { + $this->forceWhitelistRegistry->forceAllowLoading(Customer::class); + } + + /** + * After customer balance save processing. + * + * @param Balance $subject + * @param mixed $result + * @return mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterSave(Balance $subject, mixed $result) + { + $this->forceWhitelistRegistry->restore(Customer::class); + + return $result; + } +} diff --git a/vendor/magento/module-admin-gws/Plugin/StoreFilter.php b/vendor/magento/module-admin-gws/Plugin/StoreFilter.php index 5abebcad5a90..c5b945ab8a43 100644 --- a/vendor/magento/module-admin-gws/Plugin/StoreFilter.php +++ b/vendor/magento/module-admin-gws/Plugin/StoreFilter.php @@ -8,6 +8,8 @@ namespace Magento\AdminGws\Plugin; use Magento\AdminGws\Model\Role; +use Magento\Backend\Block\System\Store\Store; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Api\Data\GroupInterface; use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Api\Data\WebsiteInterface; @@ -118,9 +120,11 @@ public function afterGetWebsites( * Retrieve default store for default group and website * * @param StoreManagerInterface $storeManager - * @param GroupInterface|null $defaultStore - * @return GroupInterface|null + * @param StoreInterface|null $defaultStore + * + * @return StoreInterface|null * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @throws NoSuchEntityException */ public function afterGetDefaultStoreView(StoreManagerInterface $storeManager, $defaultStore) { @@ -128,11 +132,21 @@ public function afterGetDefaultStoreView(StoreManagerInterface $storeManager, $d return $defaultStore; } - if (null === $defaultStore) { - return null; - } + return $defaultStore && $this->role->hasStoreAccess($defaultStore->getId()) ? + $defaultStore : $this->getAnyAllowedStore($storeManager); + } - $roleStoreIds = $this->role->getStoreIds(); - return in_array($defaultStore->getId(), $roleStoreIds) ? $defaultStore : null; + /** + * Get any allowed store view. + * + * @param StoreManagerInterface $storeManager + * + * @return StoreInterface + * @throws NoSuchEntityException + */ + private function getAnyAllowedStore(StoreManagerInterface $storeManager): StoreInterface + { + $firstStoreId = current($this->role->getStoreIds()); + return $storeManager->getStore($firstStoreId); } } diff --git a/vendor/magento/module-admin-gws/etc/adminhtml/di.xml b/vendor/magento/module-admin-gws/etc/adminhtml/di.xml index ab8a78797ad5..ec583667b1c0 100644 --- a/vendor/magento/module-admin-gws/etc/adminhtml/di.xml +++ b/vendor/magento/module-admin-gws/etc/adminhtml/di.xml @@ -108,4 +108,19 @@ + + + + + + + + + + + + + + + diff --git a/vendor/magento/module-support/Console/Command/BackupDbCommand.php b/vendor/magento/module-support/Console/Command/BackupDbCommand.php index 910846828bed..3ee0af95a696 100644 --- a/vendor/magento/module-support/Console/Command/BackupDbCommand.php +++ b/vendor/magento/module-support/Console/Command/BackupDbCommand.php @@ -20,7 +20,7 @@ class BackupDbCommand extends AbstractBackupDumpCommand /** * Name of input argument */ - const INPUT_KEY_IGNORE_SANITIZE = 'ignore-sanitize'; + public const INPUT_KEY_IGNORE_SANITIZE = 'ignore-sanitize'; /** * @var array @@ -67,7 +67,7 @@ class BackupDbCommand extends AbstractBackupDumpCommand protected $ignoredTables = []; /** - * {@inheritdoc} + * @inheritdoc */ protected function configure() { @@ -79,7 +79,7 @@ protected function configure() } /** - * {@inheritdoc} + * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -154,6 +154,7 @@ protected function getSanitizeSubCommand() $this->getConnectionParams(), $sanitizedTables, $this->shellHelper->getUtility(ShellHelper::UTILITY_PHP), + //phpcs:ignore Magento2.Functions.DiscouragedFunction escapeshellarg($this->getSanitizeCode()) ); } @@ -216,22 +217,26 @@ protected function getIgnoredTablesSubCommand() protected function getSanitizeCode() { $code = <<<'PHP_CODE' - while ($line=fgets(STDIN)) { - if (preg_match("/(^INSERT INTO\s+\S+\s+VALUES\s+)\((.*)\);$/",$line,$matches)) { - $row = str_getcsv($matches[2],",","\x27"); - foreach($row as $key=>$field) { - if ($field == "NULL") { - continue; - } elseif ( preg_match("/[A-Z]/i", $field)) { - $field = md5($field . rand()); - } - $row[$key] = "\x27" . $field . "\x27"; - } - echo $matches[1] . "(" . implode(",", $row) . ");\n"; - continue; - } - echo $line; - }; +while ($line=fgets(STDIN)) { + if (preg_match("/(^INSERT INTO\s+\S+\s+VALUES\s+)\((.*)\);$/",$line,$matches)) { + $row = str_getcsv($matches[2],",","\x27"); + foreach($row as $key => $field) { + if ($field == "NULL") { + continue; + } elseif (preg_match("/[A-Z]/i", $field)) { + $field = md5($field . rand()); + } elseif (preg_match("/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/", $field)) { + $field = date("Y-m-d H:i:s"); + } elseif (preg_match("/\d{4}-\d{2}-\d{2}/", $field)) { + $field = date("Y-m-d"); + } + $row[$key] = "\x27" . $field . "\x27"; + } + echo $matches[1] . "(" . implode(",", $row) . ");\n"; + continue; + } + echo $line; +}; PHP_CODE; return trim($code); }