diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php index a450187dd094b..27258efee4c54 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php @@ -5,18 +5,28 @@ */ namespace Magento\AsynchronousOperations\Controller\Adminhtml\Bulk; +use Magento\AsynchronousOperations\Model\AccessValidator; +use Magento\AsynchronousOperations\Model\IsAllowedForBulkUuid; +use Magento\Backend\App\Action; +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\Result\Page; +use Magento\Framework\View\Result\PageFactory; + /** * Class View Operation Details Controller */ -class Details extends \Magento\Backend\App\Action implements \Magento\Framework\App\Action\HttpGetActionInterface +class Details extends Action implements HttpGetActionInterface { /** - * @var \Magento\Framework\View\Result\PageFactory + * @var PageFactory */ private $resultPageFactory; /** - * @var \Magento\AsynchronousOperations\Model\AccessValidator + * @var AccessValidator + * @deprecated */ private $accessValidator; @@ -26,21 +36,29 @@ class Details extends \Magento\Backend\App\Action implements \Magento\Framework\ private $menuId; /** - * Details constructor. - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory - * @param \Magento\AsynchronousOperations\Model\AccessValidator $accessValidator + * @var IsAllowedForBulkUuid + */ + private $isAllowedForBulkUuid; + + /** + * @param Context $context + * @param PageFactory $resultPageFactory + * @param AccessValidator $accessValidator * @param string $menuId + * @param IsAllowedForBulkUuid|null $isAllowedForBulkUuid */ public function __construct( - \Magento\Backend\App\Action\Context $context, - \Magento\Framework\View\Result\PageFactory $resultPageFactory, - \Magento\AsynchronousOperations\Model\AccessValidator $accessValidator, - $menuId = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations' + Context $context, + PageFactory $resultPageFactory, + AccessValidator $accessValidator, + $menuId = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations', + ?IsAllowedForBulkUuid $isAllowedForBulkUuid = null ) { $this->resultPageFactory = $resultPageFactory; $this->accessValidator = $accessValidator; $this->menuId = $menuId; + $this->isAllowedForBulkUuid = $isAllowedForBulkUuid + ?: ObjectManager::getInstance()->get(IsAllowedForBulkUuid::class); parent::__construct($context); } @@ -49,14 +67,13 @@ public function __construct( */ protected function _isAllowed() { - return $this->_authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations') - && $this->accessValidator->isAllowed($this->getRequest()->getParam('uuid')); + return $this->isAllowedForBulkUuid->execute($this->getRequest()->getParam('uuid')); } - + /** * Bulk details action * - * @return \Magento\Framework\View\Result\Page + * @return Page */ public function execute() { diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php index 62e6b9ba4551b..15b93d98dd732 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php @@ -7,16 +7,19 @@ use Magento\AsynchronousOperations\Model\BulkManagement; use Magento\AsynchronousOperations\Model\BulkNotificationManagement; +use Magento\AsynchronousOperations\Model\IsAllowedForBulkUuid; use Magento\Backend\App\Action\Context; use Magento\Backend\Model\View\Result\Redirect; use Magento\Backend\App\Action; use Magento\AsynchronousOperations\Model\AccessValidator; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Controller\ResultFactory; /** * Class Bulk Retry Controller */ -class Retry extends Action +class Retry extends Action implements HttpPostActionInterface { /** * @var BulkManagement @@ -29,27 +32,35 @@ class Retry extends Action private $notificationManagement; /** - * @var \Magento\AsynchronousOperations\Model\AccessValidator + * @var AccessValidator */ private $accessValidator; /** - * Retry constructor. + * @var IsAllowedForBulkUuid + */ + private $isAllowedForBulkUuid; + + /** * @param Context $context * @param BulkManagement $bulkManagement * @param BulkNotificationManagement $notificationManagement * @param AccessValidator $accessValidator + * @param IsAllowedForBulkUuid|null $isAllowedForBulkUuid */ public function __construct( Context $context, BulkManagement $bulkManagement, BulkNotificationManagement $notificationManagement, - AccessValidator $accessValidator + AccessValidator $accessValidator, + ?IsAllowedForBulkUuid $isAllowedForBulkUuid = null ) { parent::__construct($context); $this->bulkManagement = $bulkManagement; $this->notificationManagement = $notificationManagement; $this->accessValidator = $accessValidator; + $this->isAllowedForBulkUuid = $isAllowedForBulkUuid + ?: ObjectManager::getInstance()->get(IsAllowedForBulkUuid::class); } /** @@ -57,12 +68,11 @@ public function __construct( */ protected function _isAllowed() { - return $this->_authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations') - && $this->accessValidator->isAllowed($this->getRequest()->getParam('uuid')); + return $this->isAllowedForBulkUuid->execute($this->getRequest()->getParam('uuid')); } /** - * {@inheritdoc} + * @inheritdoc */ public function execute() { diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php index 5a2b9c0a34e64..87e2941bff255 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php @@ -6,17 +6,18 @@ namespace Magento\AsynchronousOperations\Controller\Adminhtml\Index; -class Index extends \Magento\Backend\App\Action +use Magento\Backend\App\Action; +use Magento\Backend\App\Action\Context; +use Magento\Framework\View\Result\Page; +use \Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\View\Result\PageFactory; + +class Index extends Action implements HttpGetActionInterface { - /** - * Authorization level of a basic admin session - * - * @see _isAllowed() - */ - const ADMIN_RESOURCE = 'Magento_Logging::system_magento_logging_bulk_operations'; + public const ADMIN_RESOURCE = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations'; /** - * @var \Magento\Framework\View\Result\PageFactory + * @var PageFactory */ private $resultPageFactory; @@ -26,14 +27,13 @@ class Index extends \Magento\Backend\App\Action private $menuId; /** - * Details constructor. - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory + * @param Context $context + * @param PageFactory $resultPageFactory * @param string $menuId */ public function __construct( - \Magento\Backend\App\Action\Context $context, - \Magento\Framework\View\Result\PageFactory $resultPageFactory, + Context $context, + PageFactory $resultPageFactory, $menuId = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations' ) { $this->resultPageFactory = $resultPageFactory; @@ -41,18 +41,10 @@ public function __construct( parent::__construct($context); } - /** - * @inheritDoc - */ - protected function _isAllowed() - { - return parent::_isAllowed(); - } - /** * Bulk list action * - * @return \Magento\Framework\View\Result\Page + * @return Page */ public function execute() { diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php index 0a71c130fb20a..ac75d09974b7d 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php @@ -6,44 +6,36 @@ namespace Magento\AsynchronousOperations\Controller\Adminhtml\Notification; use Magento\AsynchronousOperations\Model\BulkNotificationManagement; -use Magento\Backend\App\Action\Context; use Magento\Backend\App\Action; +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Json; use Magento\Framework\Controller\ResultFactory; /** * Class Bulk Notification Dismiss Controller */ -class Dismiss extends Action +class Dismiss extends Action implements HttpGetActionInterface { + public const ADMIN_RESOURCE = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations'; + /** * @var BulkNotificationManagement */ private $notificationManagement; /** - * Class constructor. - * * @param Context $context * @param BulkNotificationManagement $notificationManagement */ - public function __construct( - Context $context, - BulkNotificationManagement $notificationManagement - ) { + public function __construct(Context $context, BulkNotificationManagement $notificationManagement) + { parent::__construct($context); $this->notificationManagement = $notificationManagement; } /** - * @inheritDoc - */ - protected function _isAllowed() - { - return $this->_authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations'); - } - - /** - * {@inheritdoc} + * @inheritdoc */ public function execute() { @@ -54,7 +46,7 @@ public function execute() $isAcknowledged = $this->notificationManagement->acknowledgeBulks($bulkUuids); - /** @var \Magento\Framework\Controller\Result\Json $result */ + /** @var Json $result */ $result = $this->resultFactory->create(ResultFactory::TYPE_JSON); if (!$isAcknowledged) { $result->setHttpResponseCode(400); diff --git a/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php b/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php index 6f908a4c5b218..214487e191cd2 100644 --- a/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php +++ b/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php @@ -7,7 +7,8 @@ namespace Magento\AsynchronousOperations\Model; /** - * Class AccessValidator + * Class AccessValidator. Used to validate if user has an access to Bulk Operation + * @deprecated see \Magento\AsynchronousOperations\Model\IsAllowedForBulkUuid */ class AccessValidator { diff --git a/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php b/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php index 2ba7f7fe5e3ee..212c841642b46 100644 --- a/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php +++ b/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php @@ -10,6 +10,7 @@ use Magento\Framework\EntityManager\MetadataPool; use Magento\AsynchronousOperations\Model\ResourceModel\Bulk\CollectionFactory as BulkCollectionFactory; use Magento\Framework\Data\Collection; +use Magento\Authorization\Model\UserContextInterface; /** * Class for bulk notification manager @@ -58,10 +59,12 @@ public function __construct( /** * Mark given bulks as acknowledged. + * * Notifications related to these bulks will not appear in notification area. * * @param array $bulkUuids * @return bool true on success or false on failure + * @throws \Exception */ public function acknowledgeBulks(array $bulkUuids) { @@ -83,6 +86,7 @@ public function acknowledgeBulks(array $bulkUuids) /** * Remove given bulks from acknowledged list. + * * Notifications related to these bulks will appear again in notification area. * * @param array $bulkUuids @@ -119,6 +123,7 @@ public function getAcknowledgedBulksByUser($userId) 'main_table.uuid = acknowledged_bulk.bulk_uuid', [] )->addFieldToFilter('user_id', $userId) + ->addFieldToFilter('user_type', UserContextInterface::USER_TYPE_ADMIN) ->addOrder('start_time', Collection::SORT_ORDER_DESC) ->getItems(); @@ -141,6 +146,7 @@ public function getIgnoredBulksByUser($userId) ['acknowledged_bulk.bulk_uuid'] ); $bulks = $bulkCollection->addFieldToFilter('user_id', $userId) + ->addFieldToFilter('user_type', UserContextInterface::USER_TYPE_ADMIN) ->addFieldToFilter('acknowledged_bulk.bulk_uuid', ['null' => true]) ->addOrder('start_time', Collection::SORT_ORDER_DESC) ->getItems(); diff --git a/app/code/Magento/AsynchronousOperations/Model/GetBulksByUserAndType.php b/app/code/Magento/AsynchronousOperations/Model/GetBulksByUserAndType.php new file mode 100644 index 0000000000000..a8b2f086027cb --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/GetBulksByUserAndType.php @@ -0,0 +1,83 @@ +calculatedStatusSql = $calculatedStatusSql; + $this->resourceConnection = $resourceConnection; + $this->bulkCollectionFactory = $bulkCollection; + } + + /** + * @inheritDoc + */ + public function execute($userId, $userTypeId): array + { + /** @var Collection $collection */ + $collection = $this->bulkCollectionFactory->create(); + $operationTableName = $this->resourceConnection->getTableName('magento_operation'); + + $select = $collection->getSelect(); + $select->columns(['status' => $this->calculatedStatusSql->get($operationTableName)]) + ->order(new \Zend_Db_Expr('FIELD(status, ' . implode(',', $this->statusesArray) . ')')); + $collection->addFieldToFilter('user_id', $userId) + ->addFieldToFilter('user_type', $userTypeId) + ->addOrder('start_time'); + + return $collection->getItems(); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/GetGlobalAllowedUserTypes.php b/app/code/Magento/AsynchronousOperations/Model/GetGlobalAllowedUserTypes.php new file mode 100644 index 0000000000000..367aa6f8e9527 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/GetGlobalAllowedUserTypes.php @@ -0,0 +1,64 @@ +authorization = $authorization; + } + + /** + * Returns allowed user types + * + * @return array + */ + public function execute(): array + { + $userTypes = [ + self::BULK_LOGGING_ACL_GUESTS => UserContextInterface::USER_TYPE_GUEST, + self::BULK_LOGGING_ACL_INTEGRATIONS => UserContextInterface::USER_TYPE_INTEGRATION, + self::BULK_LOGGING_ACL_ADMIN => UserContextInterface::USER_TYPE_ADMIN, + self::BULK_LOGGING_ACL_CUSTOMERS => UserContextInterface::USER_TYPE_CUSTOMER + ]; + + $allowedUserTypes = []; + foreach ($userTypes as $resourceId => $userTypeId) { + if ($this->authorization->isAllowed($resourceId)) { + $allowedUserTypes[] = $userTypeId; + } + } + + return $allowedUserTypes; + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/IsAllowedForBulkUuid.php b/app/code/Magento/AsynchronousOperations/Model/IsAllowedForBulkUuid.php new file mode 100644 index 0000000000000..2c98b0cc33ecc --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/IsAllowedForBulkUuid.php @@ -0,0 +1,84 @@ +userContext = $userContext; + $this->entityManager = $entityManager; + $this->bulkSummaryFactory = $bulkSummaryFactory; + $this->allowedUserTypes = $getGlobalAllowedUserTypes->execute(); + } + + /** + * Returns is content allowed + * + * @param string $bulkUuid + * @return bool + */ + public function execute(string $bulkUuid): bool + { + /** @var BulkSummaryInterface $bulkSummary */ + $bulkSummary = $this->entityManager->load($this->bulkSummaryFactory->create(), $bulkUuid); + + return in_array($bulkSummary->getUserType(), $this->allowedUserTypes) || $this->isAllowedForUser($bulkSummary); + } + + /** + * Returns is bulk allowed for user + * + * @param BulkSummaryInterface $bulkSummary + * @return bool + */ + private function isAllowedForUser(BulkSummaryInterface $bulkSummary): bool + { + return $bulkSummary->getUserType() === $this->userContext->getUserType() + && $bulkSummary->getUserId() === $this->userContext->getUserId(); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php b/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php index bd357e101328a..f14452b8caf1f 100644 --- a/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php +++ b/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php @@ -5,65 +5,94 @@ */ namespace Magento\AsynchronousOperations\Model\ResourceModel\System\Message\Collection\Synchronized; +use Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized; +use Magento\AdminNotification\Model\System\MessageFactory; +use Magento\AsynchronousOperations\Model\BulkNotificationManagement; +use Magento\AsynchronousOperations\Model\Operation\Details; +use Magento\AsynchronousOperations\Model\StatusMapper; +use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\AuthorizationInterface; +use Magento\Framework\Bulk\BulkStatusInterface; +use Magento\Framework\Bulk\BulkSummaryInterface; +use Magento\Framework\Bulk\GetBulksByUserAndTypeInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Encryption\Encryptor; +use Magento\Framework\Notification\MessageInterface; + /** * Class Plugin to add bulks related notification messages to Synchronized Collection + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Plugin { + private const BULK_LOGGING_ACL = "Magento_AsynchronousOperations::system_magento_logging_bulk_operations"; + /** - * @var \Magento\AdminNotification\Model\System\MessageFactory + * @var MessageFactory */ private $messageFactory; /** - * @var \Magento\Framework\Bulk\BulkStatusInterface + * @var BulkStatusInterface */ private $bulkStatus; /** - * @var \Magento\Authorization\Model\UserContextInterface + * @var UserContextInterface */ private $userContext; /** - * @var \Magento\AsynchronousOperations\Model\Operation\Details + * @var Details */ private $operationDetails; /** - * @var \Magento\AsynchronousOperations\Model\BulkNotificationManagement + * @var BulkNotificationManagement */ private $bulkNotificationManagement; /** - * @var \Magento\Framework\AuthorizationInterface + * @var StatusMapper + */ + private $statusMapper; + + /** + * @var AuthorizationInterface|mixed|null */ private $authorization; /** - * @var \Magento\AsynchronousOperations\Model\StatusMapper + * @var Encryptor */ - private $statusMapper; + private $encryptor; /** - * Plugin constructor. - * - * @param \Magento\AdminNotification\Model\System\MessageFactory $messageFactory - * @param \Magento\Framework\Bulk\BulkStatusInterface $bulkStatus - * @param \Magento\AsynchronousOperations\Model\BulkNotificationManagement $bulkNotificationManagement - * @param \Magento\Authorization\Model\UserContextInterface $userContext - * @param \Magento\AsynchronousOperations\Model\Operation\Details $operationDetails - * @param \Magento\Framework\AuthorizationInterface $authorization - * @param \Magento\AsynchronousOperations\Model\StatusMapper $statusMapper + * @var GetBulksByUserAndTypeInterface|null + */ + private $getBulksByUserAndType; + + /** + * @param MessageFactory $messageFactory + * @param BulkStatusInterface $bulkStatus + * @param BulkNotificationManagement $bulkNotificationManagement + * @param UserContextInterface $userContext + * @param Details $operationDetails + * @param AuthorizationInterface $authorization + * @param StatusMapper $statusMapper + * @param Encryptor|null $encryptor + * @param GetBulksByUserAndTypeInterface|null $getBulksByUserAndType */ public function __construct( - \Magento\AdminNotification\Model\System\MessageFactory $messageFactory, - \Magento\Framework\Bulk\BulkStatusInterface $bulkStatus, - \Magento\AsynchronousOperations\Model\BulkNotificationManagement $bulkNotificationManagement, - \Magento\Authorization\Model\UserContextInterface $userContext, - \Magento\AsynchronousOperations\Model\Operation\Details $operationDetails, - \Magento\Framework\AuthorizationInterface $authorization, - \Magento\AsynchronousOperations\Model\StatusMapper $statusMapper + MessageFactory $messageFactory, + BulkStatusInterface $bulkStatus, + BulkNotificationManagement $bulkNotificationManagement, + UserContextInterface $userContext, + Details $operationDetails, + AuthorizationInterface $authorization, + StatusMapper $statusMapper, + ?Encryptor $encryptor = null, + ?GetBulksByUserAndTypeInterface $getBulksByUserAndType = null ) { $this->messageFactory = $messageFactory; $this->bulkStatus = $bulkStatus; @@ -72,25 +101,27 @@ public function __construct( $this->bulkNotificationManagement = $bulkNotificationManagement; $this->authorization = $authorization; $this->statusMapper = $statusMapper; + $this->encryptor = $encryptor ?: ObjectManager::getInstance()->get(Encryptor::class); + $this->getBulksByUserAndType = $getBulksByUserAndType + ?: ObjectManager::getInstance()->get(GetBulksByUserAndTypeInterface::class); } /** * Adding bulk related messages to notification area * - * @param \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized $collection + * @param Synchronized $collection * @param array $result * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterToArray( - \Magento\AdminNotification\Model\ResourceModel\System\Message\Collection\Synchronized $collection, - $result - ) { - if (!$this->authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations')) { + public function afterToArray(Synchronized $collection, $result) + { + if (!$this->isAllowed()) { return $result; } - $userId = $this->userContext->getUserId(); - $userBulks = $this->bulkStatus->getBulksByUser($userId); + $userId = (int) $this->userContext->getUserId(); + $userType = (int) $this->userContext->getUserType(); + $userBulks = $this->getBulksByUserAndType->execute($userId, $userType); $acknowledgedBulks = $this->getAcknowledgedBulksUuid( $this->bulkNotificationManagement->getAcknowledgedBulksByUser($userId) ); @@ -101,13 +132,13 @@ public function afterToArray( $details = $this->operationDetails->getDetails($bulkUuid); $text = $this->getText($details); $bulkStatus = $this->statusMapper->operationStatusToBulkSummaryStatus($bulk->getStatus()); - if ($bulkStatus === \Magento\Framework\Bulk\BulkSummaryInterface::IN_PROGRESS) { + if ($bulkStatus === BulkSummaryInterface::IN_PROGRESS) { $text = __('%1 item(s) are currently being updated.', $details['operations_total']) . $text; } $data = [ 'data' => [ 'text' => __('Task "%1": ', $bulk->getDescription()) . $text, - 'severity' => \Magento\Framework\Notification\MessageInterface::SEVERITY_MAJOR, + 'severity' => MessageInterface::SEVERITY_MAJOR, // md5() here is not for cryptographic use. // phpcs:ignore Magento2.Security.InsecureFunction 'identity' => md5('bulk' . $bulkUuid), @@ -125,6 +156,7 @@ public function afterToArray( $bulkMessages = array_slice($bulkMessages, 0, 5); $result['items'] = array_merge($bulkMessages, $result['items']); } + return $result; } @@ -170,4 +202,14 @@ private function getAcknowledgedBulksUuid($acknowledgedBulks) } return $acknowledgedBulksArray; } + + /** + * Check if it allowed to see bulk operations. + * + * @return bool + */ + private function isAllowed(): bool + { + return $this->authorization->isAllowed(self::BULK_LOGGING_ACL); + } } diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/IsAllowedForBulkUuidTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/IsAllowedForBulkUuidTest.php new file mode 100644 index 0000000000000..37f610e752be0 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/IsAllowedForBulkUuidTest.php @@ -0,0 +1,111 @@ +userContextMock = $this->createMock(UserContextInterface::class); + $this->entityManagerMock = $this->createMock(EntityManager::class); + $this->bulkSummaryFactoryMock = $this->createPartialMock( + BulkSummaryInterfaceFactory::class, + ['create'] + ); + $this->getGlobalAllowedUserTypes = $this->createMock(GetGlobalAllowedUserTypes::class); + + $this->model = new IsAllowedForBulkUuid( + $this->userContextMock, + $this->entityManagerMock, + $this->bulkSummaryFactoryMock, + $this->getGlobalAllowedUserTypes + ); + } + + /** + * @dataProvider summaryDataProvider + * @param int $bulkUserId + * @param bool $expectedResult + * @return void + */ + public function testIsAllowedForBulkUuid(int $bulkUserId, bool $expectedResult): void + { + $adminId = 1; + $uuid = 'test-001'; + $bulkSummaryMock = $this->createMock(BulkSummaryInterface::class); + + $this->bulkSummaryFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($bulkSummaryMock); + $this->entityManagerMock->expects($this->once()) + ->method('load') + ->with($bulkSummaryMock, $uuid) + ->willReturn($bulkSummaryMock); + + $bulkSummaryMock->expects($this->once()) + ->method('getUserId') + ->willReturn($bulkUserId); + $this->userContextMock->expects($this->once()) + ->method('getUserId') + ->willReturn($adminId); + + $this->assertEquals($this->model->execute($uuid), $expectedResult); + } + + /** + * @return array + */ + public static function summaryDataProvider(): array + { + return [ + [2, false], + [1, true] + ]; + } +} diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/ResourceModel/System/Message/Collection/Synchronized/PluginTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/ResourceModel/System/Message/Collection/Synchronized/PluginTest.php index 5365cb64c19c1..ce2703856c31e 100644 --- a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/ResourceModel/System/Message/Collection/Synchronized/PluginTest.php +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/ResourceModel/System/Message/Collection/Synchronized/PluginTest.php @@ -19,6 +19,8 @@ use Magento\Authorization\Model\UserContextInterface; use Magento\Framework\AuthorizationInterface; use Magento\Framework\Bulk\BulkStatusInterface; +use Magento\Framework\Bulk\GetBulksByUserAndTypeInterface; +use Magento\Framework\Encryption\Encryptor; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -78,10 +80,18 @@ class PluginTest extends TestCase private $statusMapper; /** - * @var string + * @var GetBulksByUserAndTypeInterface|MockObject */ - private $resourceName = 'Magento_Logging::system_magento_logging_bulk_operations'; + private $getBulksByUserAndTypeMock; + /** + * @var Encryptor|MockObject + */ + private $encryptor; + + /** + * @inheritDoc + */ protected function setUp(): void { $this->messagefactoryMock = $this->createPartialMock( @@ -90,13 +100,16 @@ protected function setUp(): void ); $this->bulkStatusMock = $this->getMockForAbstractClass(BulkStatusInterface::class); + $this->bulkNotificationMock = $this->createMock(BulkNotificationManagement::class); $this->userContextMock = $this->getMockForAbstractClass(UserContextInterface::class); $this->operationsDetailsMock = $this->createMock(Details::class); $this->authorizationMock = $this->getMockForAbstractClass(AuthorizationInterface::class); $this->messageMock = $this->createMock(Message::class); $this->collectionMock = $this->createMock(Synchronized::class); - $this->bulkNotificationMock = $this->createMock(BulkNotificationManagement::class); $this->statusMapper = $this->createMock(StatusMapper::class); + $this->encryptor = $this->createMock(Encryptor::class); + $this->getBulksByUserAndTypeMock = $this->createMock(GetBulksByUserAndTypeInterface::class); + $this->plugin = new Plugin( $this->messagefactoryMock, $this->bulkStatusMock, @@ -104,17 +117,23 @@ protected function setUp(): void $this->userContextMock, $this->operationsDetailsMock, $this->authorizationMock, - $this->statusMapper + $this->statusMapper, + $this->encryptor, + $this->getBulksByUserAndTypeMock, ); } - public function testAfterToArrayIfNotAllowed() + /** + * After toArray when not allowed + * + * @return void + */ + public function testAfterToArrayIfNotAllowed(): void { $result = []; $this->authorizationMock ->expects($this->once()) ->method('isAllowed') - ->with($this->resourceName) ->willReturn(false); $this->assertEquals($result, $this->plugin->afterToArray($this->collectionMock, $result)); } @@ -122,8 +141,9 @@ public function testAfterToArrayIfNotAllowed() /** * @param array $operationDetails * @dataProvider afterToDataProvider + * @return void */ - public function testAfterTo($operationDetails) + public function testAfterTo(array $operationDetails): void { $bulkMock = $this->getMockBuilder(BulkSummary::class) ->addMethods(['getStatus']) @@ -143,30 +163,39 @@ public function testAfterTo($operationDetails) ->method('getDetails') ->with($bulkUuid) ->willReturn($operationDetails); - $bulkMock->expects($this->once())->method('getDescription')->willReturn('Bulk Description'); - $this->messagefactoryMock->expects($this->once())->method('create')->willReturn($this->messageMock); - $this->messageMock->expects($this->once())->method('toArray')->willReturn($bulkArray); + $bulkMock->expects($this->once()) + ->method('getDescription') + ->willReturn('Bulk Description'); + $this->messagefactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->messageMock); + $this->messageMock->expects($this->once()) + ->method('toArray') + ->willReturn($bulkArray); $this->authorizationMock ->expects($this->once()) ->method('isAllowed') - ->with($this->resourceName) ->willReturn(true); - $this->userContextMock->expects($this->once())->method('getUserId')->willReturn($userId); + $this->userContextMock->expects($this->once()) + ->method('getUserId') + ->willReturn($userId); $this->bulkNotificationMock ->expects($this->once()) ->method('getAcknowledgedBulksByUser') ->with($userId) ->willReturn([]); - $this->statusMapper->expects($this->once())->method('operationStatusToBulkSummaryStatus'); - $this->bulkStatusMock->expects($this->once())->method('getBulksByUser')->willReturn($userBulks); + $this->getBulksByUserAndTypeMock->expects($this->once()) + ->method('execute') + ->willReturn($userBulks); $result2 = $this->plugin->afterToArray($this->collectionMock, $result); + $this->assertEquals(2, $result2['totalRecords']); } /** * @return array */ - public function afterToDataProvider() + public function afterToDataProvider(): array { return [ [ diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Ui/Component/AdminNotification/PluginTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Ui/Component/AdminNotification/PluginTest.php index 93e77d271414f..84be15403e737 100644 --- a/app/code/Magento/AsynchronousOperations/Test/Unit/Ui/Component/AdminNotification/PluginTest.php +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Ui/Component/AdminNotification/PluginTest.php @@ -21,19 +21,25 @@ class PluginTest extends TestCase private $plugin; /** - * @var MockObject + * @var AuthorizationInterface|MockObject */ private $authorizationMock; + /** + * @inheritDoc + */ protected function setUp(): void { $this->authorizationMock = $this->getMockForAbstractClass(AuthorizationInterface::class); - $this->plugin = new Plugin( - $this->authorizationMock - ); + $this->plugin = new Plugin($this->authorizationMock); } - public function testAfterGetMeta() + /** + * After getMeta test + * + * @return void + */ + public function testAfterGetMeta(): void { $result = []; $expectedResult = [ @@ -48,7 +54,10 @@ public function testAfterGetMeta() ] ]; $dataProviderMock = $this->createMock(DataProvider::class); - $this->authorizationMock->expects($this->once())->method('isAllowed')->willReturn(true); + $this->authorizationMock->expects($this->once()) + ->method('isAllowed') + ->willReturn(true); + $this->assertEquals($expectedResult, $this->plugin->afterGetMeta($dataProviderMock, $result)); } } diff --git a/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php b/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php index b5670639dce09..49402644406ad 100644 --- a/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php @@ -6,13 +6,18 @@ namespace Magento\AsynchronousOperations\Ui\Component\AdminNotification; +use Magento\AdminNotification\Ui\Component\DataProvider\DataProvider; +use Magento\Framework\AuthorizationInterface; + /** * Class Plugin to eliminate Bulk related links in the notification area */ class Plugin { + private const BULK_LOGGING_ACL = "Magento_AsynchronousOperations::system_magento_logging_bulk_operations"; + /** - * @var \Magento\Framework\AuthorizationInterface + * @var AuthorizationInterface */ private $authorization; @@ -22,33 +27,38 @@ class Plugin private $isAllowed; /** - * Plugin constructor. - * @param \Magento\Framework\AuthorizationInterface $authorization + * @param AuthorizationInterface $authorization */ - public function __construct( - \Magento\Framework\AuthorizationInterface $authorization - ) { + public function __construct(AuthorizationInterface $authorization) + { $this->authorization = $authorization; } /** * Prepares Meta * - * @param \Magento\AdminNotification\Ui\Component\DataProvider\DataProvider $dataProvider + * @param DataProvider $dataProvider * @param array $result * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterGetMeta( - \Magento\AdminNotification\Ui\Component\DataProvider\DataProvider $dataProvider, - $result - ) { + public function afterGetMeta(DataProvider $dataProvider, $result) + { if (!isset($this->isAllowed)) { - $this->isAllowed = $this->authorization->isAllowed( - 'Magento_Logging::system_magento_logging_bulk_operations' - ); + $this->isAllowed = $this->isAllowed(); } $result['columns']['arguments']['data']['config']['isAllowed'] = $this->isAllowed; + return $result; } + + /** + * Check if it allowed to see bulk operations. + * + * @return bool + */ + private function isAllowed(): bool + { + return $this->authorization->isAllowed(self::BULK_LOGGING_ACL); + } } diff --git a/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/Bulk/DataProvider.php b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/Bulk/DataProvider.php new file mode 100644 index 0000000000000..482a4bc3b4420 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/Bulk/DataProvider.php @@ -0,0 +1,109 @@ +collection = $collectionFactory->create(); + $this->authorization = $authorization; + $this->getGlobalAllowedUserTypes = $getGlobalAllowedUserTypes; + $this->userContext = $userContext; + parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); + } + + /** + * Get data for Bulk Operations Grid + * + * @return array + */ + public function getData(): array + { + $allowedUserTypes = $this->getGlobalAllowedUserTypes->execute(); + $connection = $this->getCollection()->getConnection(); + + $whereOr = []; + if ($allowedUserTypes) { + $whereOr[] = $connection->quoteInto('user_type IN (?)', $allowedUserTypes); + } + + if ($this->isAllowed()) { + $whereOr[] = implode( + ' AND ', + [ + $connection->quoteInto('user_type = ?', $this->userContext->getUserType()), + $connection->quoteInto('user_id = ?', $this->userContext->getUserId()) + ] + ); + } + + $this->getCollection() + ->getSelect() + ->where('(' . implode(') OR (', $whereOr) . ')'); + + return $this->getCollection()->toArray(); + } + + /** + * Check if it allowed to see own bulk operations. + * + * @return bool + */ + private function isAllowed(): bool + { + return $this->authorization->isAllowed(self::BULK_LOGGING_ACL); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php index 5f2fbd9ea8b11..68d6512395f58 100644 --- a/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php @@ -15,7 +15,7 @@ use Magento\AsynchronousOperations\Model\BulkStatus\CalculatedStatusSql; /** - * Class SearchResult + * Implementing of Search Results for Bulk Operations */ class SearchResult extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult { @@ -49,7 +49,7 @@ class SearchResult extends \Magento\Framework\View\Element\UiComponent\DataProvi * @param StatusMapper $statusMapper * @param CalculatedStatusSql $calculatedStatusSql * @param string $mainTable - * @param null $resourceModel + * @param null|string $resourceModel * @param string $identifierName * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -80,7 +80,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function _initSelect() { @@ -90,15 +90,12 @@ protected function _initSelect() '*', 'status' => $this->calculatedStatusSql->get($this->getTable('magento_operation')) ] - )->where( - 'user_id=?', - $this->userContext->getUserId() ); return $this; } /** - * {@inheritdoc} + * @inheritdoc */ protected function _afterLoad() { @@ -110,7 +107,7 @@ protected function _afterLoad() } /** - * {@inheritdoc} + * @inheritdoc */ public function addFieldToFilter($field, $condition = null) { @@ -133,7 +130,7 @@ public function addFieldToFilter($field, $condition = null) } /** - * {@inheritdoc} + * @inheritdoc */ public function getSelectCountSql() { diff --git a/app/code/Magento/AsynchronousOperations/etc/acl.xml b/app/code/Magento/AsynchronousOperations/etc/acl.xml index 42521ad40ff63..b49d327a78fba 100644 --- a/app/code/Magento/AsynchronousOperations/etc/acl.xml +++ b/app/code/Magento/AsynchronousOperations/etc/acl.xml @@ -10,9 +10,14 @@ - - - + + + + + + + + diff --git a/app/code/Magento/AsynchronousOperations/etc/adminhtml/menu.xml b/app/code/Magento/AsynchronousOperations/etc/adminhtml/menu.xml index 2e9fe34c45cec..455041f7d01ec 100644 --- a/app/code/Magento/AsynchronousOperations/etc/adminhtml/menu.xml +++ b/app/code/Magento/AsynchronousOperations/etc/adminhtml/menu.xml @@ -13,7 +13,7 @@ module="Magento_AsynchronousOperations" sortOrder="70" parent="Magento_Backend::system" dependsOnModule="Magento_AsynchronousOperations" - resource="Magento_Logging::magento_logging"/> + resource="Magento_AsynchronousOperations::magento_logging"/> + resource="Magento_AsynchronousOperations::system_magento_logging_bulk_operations"/> diff --git a/app/code/Magento/AsynchronousOperations/etc/di.xml b/app/code/Magento/AsynchronousOperations/etc/di.xml index 820bdd26e62b2..f335c5f570c38 100644 --- a/app/code/Magento/AsynchronousOperations/etc/di.xml +++ b/app/code/Magento/AsynchronousOperations/etc/di.xml @@ -6,6 +6,7 @@ */ --> + @@ -93,9 +94,6 @@ - diff --git a/app/code/Magento/AsynchronousOperations/etc/extension_attributes.xml b/app/code/Magento/AsynchronousOperations/etc/extension_attributes.xml index 6eeda62373f06..dbbeda4900006 100644 --- a/app/code/Magento/AsynchronousOperations/etc/extension_attributes.xml +++ b/app/code/Magento/AsynchronousOperations/etc/extension_attributes.xml @@ -9,7 +9,7 @@ - + start_time diff --git a/app/code/Magento/AsynchronousOperations/etc/webapi.xml b/app/code/Magento/AsynchronousOperations/etc/webapi.xml index 4c10a5756c8d6..97b6c09f88285 100644 --- a/app/code/Magento/AsynchronousOperations/etc/webapi.xml +++ b/app/code/Magento/AsynchronousOperations/etc/webapi.xml @@ -11,28 +11,28 @@ - + - + - + - + diff --git a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/bulk_listing.xml b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/bulk_listing.xml index 87dc0525eb1c0..25b9c76fd5e3e 100644 --- a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/bulk_listing.xml +++ b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/bulk_listing.xml @@ -24,8 +24,8 @@ - Magento_Logging::system_magento_logging_bulk_operations - + Magento_AsynchronousOperations::system_magento_logging_bulk_operations + id id diff --git a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_listing.xml b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_listing.xml index 2ac762e398521..dc8e1d2d689c8 100644 --- a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_listing.xml +++ b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_listing.xml @@ -24,7 +24,7 @@ - Magento_Logging::system_magento_logging_bulk_operations + Magento_AsynchronousOperations::system_magento_logging_bulk_operations id diff --git a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_modal_listing.xml b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_modal_listing.xml index 62a4935da8ba7..c10c9e7b3b63c 100644 --- a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_modal_listing.xml +++ b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/failed_operation_modal_listing.xml @@ -24,7 +24,7 @@ - Magento_Logging::system_magento_logging_bulk_operations + Magento_AsynchronousOperations::system_magento_logging_bulk_operations id diff --git a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_listing.xml b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_listing.xml index 3618e10ee77d8..ab2bf3542d8c4 100644 --- a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_listing.xml +++ b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_listing.xml @@ -24,7 +24,7 @@ - Magento_Logging::system_magento_logging_bulk_operations + Magento_AsynchronousOperations::system_magento_logging_bulk_operations id diff --git a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_modal_listing.xml b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_modal_listing.xml index 97e3e897c2533..6014c14281e47 100644 --- a/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_modal_listing.xml +++ b/app/code/Magento/AsynchronousOperations/view/adminhtml/ui_component/retriable_operation_modal_listing.xml @@ -24,7 +24,7 @@ - Magento_Logging::system_magento_logging_bulk_operations + Magento_AsynchronousOperations::system_magento_logging_bulk_operations id diff --git a/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php b/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php index 45352af9c5c8c..b8506bdc795f0 100644 --- a/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php +++ b/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php @@ -38,6 +38,7 @@ public function getOperationsCountByBulkIdAndStatus($bulkUuid, $status); * @param int $userId * @return BulkSummaryInterface[] * @since 103.0.0 + * @deprecated see \Magento\Framework\Bulk\GetBulksByUserAndTypeInterface */ public function getBulksByUser($userId); diff --git a/lib/internal/Magento/Framework/Bulk/GetBulksByUserAndTypeInterface.php b/lib/internal/Magento/Framework/Bulk/GetBulksByUserAndTypeInterface.php new file mode 100644 index 0000000000000..4984b23d4fcb1 --- /dev/null +++ b/lib/internal/Magento/Framework/Bulk/GetBulksByUserAndTypeInterface.php @@ -0,0 +1,24 @@ +