diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php index a450187dd094b..b159e7fbd3e42 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Details.php @@ -5,20 +5,26 @@ */ namespace Magento\AsynchronousOperations\Controller\Adminhtml\Bulk; +use Magento\AsynchronousOperations\Model\AccessManager; +use Magento\Framework\View\Result\PageFactory; +use Magento\Backend\App\Action\Context; +use Magento\Backend\App\Action; +use Magento\Framework\App\Action\HttpGetActionInterface; + /** * 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 AccessManager */ - private $accessValidator; + private $accessManager; /** * @var string @@ -27,19 +33,20 @@ class Details extends \Magento\Backend\App\Action implements \Magento\Framework\ /** * Details constructor. - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory - * @param \Magento\AsynchronousOperations\Model\AccessValidator $accessValidator + * + * @param Context $context + * @param PageFactory $resultPageFactory + * @param AccessManager $accessManager * @param string $menuId */ public function __construct( - \Magento\Backend\App\Action\Context $context, - \Magento\Framework\View\Result\PageFactory $resultPageFactory, - \Magento\AsynchronousOperations\Model\AccessValidator $accessValidator, + Context $context, + PageFactory $resultPageFactory, + AccessManager $accessManager, $menuId = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations' ) { $this->resultPageFactory = $resultPageFactory; - $this->accessValidator = $accessValidator; + $this->accessManager = $accessManager; $this->menuId = $menuId; parent::__construct($context); } @@ -49,10 +56,9 @@ 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->accessManager->isAllowedForBulkUuid($this->getRequest()->getParam('uuid')); } - + /** * Bulk details action * diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php index 62e6b9ba4551b..484af0dbe32eb 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Bulk/Retry.php @@ -10,13 +10,14 @@ 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\AsynchronousOperations\Model\AccessManager; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\App\Action\HttpPostActionInterface; /** * Class Bulk Retry Controller */ -class Retry extends Action +class Retry extends Action implements HttpPostActionInterface { /** * @var BulkManagement @@ -29,27 +30,28 @@ class Retry extends Action private $notificationManagement; /** - * @var \Magento\AsynchronousOperations\Model\AccessValidator + * @var AccessManager */ - private $accessValidator; + private $accessManager; /** * Retry constructor. + * * @param Context $context * @param BulkManagement $bulkManagement * @param BulkNotificationManagement $notificationManagement - * @param AccessValidator $accessValidator + * @param AccessManager $accessManager */ public function __construct( Context $context, BulkManagement $bulkManagement, BulkNotificationManagement $notificationManagement, - AccessValidator $accessValidator + AccessManager $accessManager ) { parent::__construct($context); $this->bulkManagement = $bulkManagement; $this->notificationManagement = $notificationManagement; - $this->accessValidator = $accessValidator; + $this->accessManager = $accessManager; } /** @@ -57,12 +59,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->accessManager->isAllowedForBulkUuid($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..292f9a95594af 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Index/Index.php @@ -6,38 +6,40 @@ namespace Magento\AsynchronousOperations\Controller\Adminhtml\Index; -class Index extends \Magento\Backend\App\Action +use Magento\Backend\App\Action\Context; +use Magento\Framework\View\Result\PageFactory; +use Magento\Framework\View\Result\Page; +use Magento\AsynchronousOperations\Model\AccessManager; +use Magento\Backend\App\Action; +use Magento\Framework\App\Action\HttpGetActionInterface; + +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 BULK_OPERATIONS_MENU_ID = "Magento_AsynchronousOperations::system_magento_logging_bulk_operations"; /** - * @var \Magento\Framework\View\Result\PageFactory + * @var PageFactory */ private $resultPageFactory; /** - * @var string + * @var AccessManager */ - private $menuId; + private $accessManager; /** * Details constructor. - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory - * @param string $menuId + * @param Context $context + * @param PageFactory $resultPageFactory + * @param AccessManager $accessManager */ public function __construct( - \Magento\Backend\App\Action\Context $context, - \Magento\Framework\View\Result\PageFactory $resultPageFactory, - $menuId = 'Magento_AsynchronousOperations::system_magento_logging_bulk_operations' + Context $context, + PageFactory $resultPageFactory, + AccessManager $accessManager ) { $this->resultPageFactory = $resultPageFactory; - $this->menuId = $menuId; + $this->accessManager = $accessManager; parent::__construct($context); } @@ -46,19 +48,19 @@ public function __construct( */ protected function _isAllowed() { - return parent::_isAllowed(); + return $this->accessManager->isOwnActionsAllowed(); } /** * Bulk list action * - * @return \Magento\Framework\View\Result\Page + * @return Page */ public function execute() { $resultPage = $this->resultPageFactory->create(); $resultPage->initLayout(); - $this->_setActiveMenu($this->menuId); + $this->_setActiveMenu(self::BULK_OPERATIONS_MENU_ID); $resultPage->getConfig()->getTitle()->prepend(__('Bulk Actions Log')); return $resultPage; } diff --git a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php index 0a71c130fb20a..bb38733546ecd 100644 --- a/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php +++ b/app/code/Magento/AsynchronousOperations/Controller/Adminhtml/Notification/Dismiss.php @@ -9,29 +9,39 @@ use Magento\Backend\App\Action\Context; use Magento\Backend\App\Action; use Magento\Framework\Controller\ResultFactory; +use Magento\AsynchronousOperations\Model\AccessManager; +use Magento\Framework\App\Action\HttpGetActionInterface; /** * Class Bulk Notification Dismiss Controller */ -class Dismiss extends Action +class Dismiss extends Action implements HttpGetActionInterface { /** * @var BulkNotificationManagement */ private $notificationManagement; + /** + * @var AccessManager + */ + private $accessManager; + /** * Class constructor. * * @param Context $context * @param BulkNotificationManagement $notificationManagement + * @param AccessManager $accessManager */ public function __construct( Context $context, - BulkNotificationManagement $notificationManagement + BulkNotificationManagement $notificationManagement, + AccessManager $accessManager ) { parent::__construct($context); $this->notificationManagement = $notificationManagement; + $this->accessManager = $accessManager; } /** @@ -39,11 +49,11 @@ public function __construct( */ protected function _isAllowed() { - return $this->_authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations'); + return $this->accessManager->isOwnActionsAllowed(); } /** - * {@inheritdoc} + * @inheritdoc */ public function execute() { diff --git a/app/code/Magento/AsynchronousOperations/Model/AccessManager.php b/app/code/Magento/AsynchronousOperations/Model/AccessManager.php new file mode 100644 index 0000000000000..7b420f10f03ab --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/AccessManager.php @@ -0,0 +1,137 @@ +userContext = $userContext; + $this->entityManager = $entityManager; + $this->bulkSummaryFactory = $bulkSummaryFactory; + $this->authorization = $authorization; + $this->allowedUserTypes = $this->getGlobalAllowedUserTypes(); + } + + /** + * Check if content allowed for current use depends from assigned user roles and bulkUuid + * + * @param int $bulkUuid + * @return bool + */ + public function isAllowedForBulkUuid($bulkUuid) + { + + /** @var BulkSummaryInterface $bulkSummary */ + $bulkSummary = $this->entityManager->load( + $this->bulkSummaryFactory->create(), + $bulkUuid + ); + + if (in_array($bulkSummary->getUserType(), $this->allowedUserTypes)) { + return true; + } + + if ($bulkSummary->getUserType() === $this->userContext->getUserType() + && $bulkSummary->getUserId() === $this->userContext->getUserId()) { + return true; + } + + return false; + } + + /** + * Get Allowed user types for current user + * + * @return array + */ + public function getGlobalAllowedUserTypes() + { + $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; + } + + /** + * Check if it allowed to see own bulk operations. + * + * @return bool + */ + public function isOwnActionsAllowed() + { + return $this->authorization->isAllowed(self::BULK_LOGGING_ACL); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php b/app/code/Magento/AsynchronousOperations/Model/AccessValidator.php index a14ec254cf897..8a5830f6f73a4 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 100.3.0, use Magento\AsynchronousOperations\Model\AccessManager instead */ class AccessValidator { diff --git a/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php b/app/code/Magento/AsynchronousOperations/Model/BulkNotificationManagement.php index 2ba7f7fe5e3ee..d0dd965980100 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/BulkOperationsStatus.php b/app/code/Magento/AsynchronousOperations/Model/BulkOperationsStatus.php index 14ac44fabd305..76e43d47eda28 100644 --- a/app/code/Magento/AsynchronousOperations/Model/BulkOperationsStatus.php +++ b/app/code/Magento/AsynchronousOperations/Model/BulkOperationsStatus.php @@ -95,6 +95,14 @@ public function getBulksByUser($userId) return $this->bulkStatus->getBulksByUser($userId); } + /** + * @inheritDoc + */ + public function getBulksByUserAndType($userId, $userTypeId) + { + return $this->bulkStatus->getBulksByUser($userId, $userTypeId); + } + /** * @inheritDoc */ diff --git a/app/code/Magento/AsynchronousOperations/Model/BulkStatus.php b/app/code/Magento/AsynchronousOperations/Model/BulkStatus.php index be907f114a41e..fc95135ff6e3b 100644 --- a/app/code/Magento/AsynchronousOperations/Model/BulkStatus.php +++ b/app/code/Magento/AsynchronousOperations/Model/BulkStatus.php @@ -134,6 +134,31 @@ public function getBulksByUser($userId) return $collection->getItems(); } + /** + * @inheritDoc + */ + public function getBulksByUserAndType($userId, $userTypeId) + { + /** @var ResourceModel\Bulk\Collection $collection */ + $collection = $this->bulkCollectionFactory->create(); + $operationTableName = $this->resourceConnection->getTableName('magento_operation'); + $statusesArray = [ + OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, + OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, + BulkSummaryInterface::NOT_STARTED, + OperationInterface::STATUS_TYPE_OPEN, + OperationInterface::STATUS_TYPE_COMPLETE + ]; + $select = $collection->getSelect(); + $select->columns(['status' => $this->calculatedStatusSql->get($operationTableName)]) + ->order(new \Zend_Db_Expr('FIELD(status, ' . implode(',', $statusesArray) . ')')); + $collection->addFieldToFilter('user_id', $userId) + ->addFieldToFilter('user_type', $userTypeId) + ->addOrder('start_time'); + + return $collection->getItems(); + } + /** * @inheritDoc */ 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 8457a641ed9a9..bb5c555f42c98 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,92 +5,111 @@ */ 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\AccessManager; +use Magento\AsynchronousOperations\Model\BulkNotificationManagement; +use Magento\AsynchronousOperations\Model\Operation\Details; +use Magento\AsynchronousOperations\Model\StatusMapper; +use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\Bulk\BulkStatusInterface; +use Magento\Framework\Encryption\Encryptor; + /** * Class Plugin to add bulks related notification messages to Synchronized Collection */ class Plugin { /** - * @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 AccessManager */ - private $bulkNotificationManagement; + private $accessManager; /** - * @var \Magento\Framework\AuthorizationInterface + * @var BulkNotificationManagement */ - private $authorization; + private $bulkNotificationManagement; /** - * @var \Magento\AsynchronousOperations\Model\StatusMapper + * @var StatusMapper */ private $statusMapper; + /** + * @var Encryptor + */ + 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 + * @param MessageFactory $messageFactory + * @param BulkStatusInterface $bulkStatus + * @param BulkNotificationManagement $bulkNotificationManagement + * @param UserContextInterface $userContext + * @param Details $operationDetails + * @param StatusMapper $statusMapper + * @param AccessManager $accessManager + * @param Encryptor $encryptor */ 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, + StatusMapper $statusMapper, + AccessManager $accessManager, + Encryptor $encryptor ) { $this->messageFactory = $messageFactory; $this->bulkStatus = $bulkStatus; $this->userContext = $userContext; $this->operationDetails = $operationDetails; $this->bulkNotificationManagement = $bulkNotificationManagement; - $this->authorization = $authorization; $this->statusMapper = $statusMapper; + $this->accessManager = $accessManager; + $this->encryptor = $encryptor; } /** * 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, + Synchronized $collection, $result ) { - if (!$this->authorization->isAllowed('Magento_Logging::system_magento_logging_bulk_operations')) { + if (!$this->accessManager->isOwnActionsAllowed()) { return $result; } $userId = $this->userContext->getUserId(); - $userBulks = $this->bulkStatus->getBulksByUser($userId); + $userType = $this->userContext->getUserType(); + $userBulks = $this->bulkStatus->getBulksByUserAndType($userId, $userType); $acknowledgedBulks = $this->getAcknowledgedBulksUuid( $this->bulkNotificationManagement->getAcknowledgedBulksByUser($userId) ); @@ -108,7 +127,7 @@ public function afterToArray( 'data' => [ 'text' => __('Task "%1": ', $bulk->getDescription()) . $text, 'severity' => \Magento\Framework\Notification\MessageInterface::SEVERITY_MAJOR, - 'identity' => md5('bulk' . $bulkUuid), + 'identity' => $this->encryptor->hash('bulk' . $bulkUuid, Encryptor::HASH_VERSION_SHA256), 'uuid' => $bulkUuid, 'status' => $bulkStatus, 'created_at' => $bulk->getStartTime() diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/AccessManagerTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/AccessManagerTest.php new file mode 100644 index 0000000000000..b50d848c10421 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/AccessManagerTest.php @@ -0,0 +1,94 @@ +userContextMock = $this->createMock(UserContextInterface::class); + $this->entityManagerMock = $this->createMock(EntityManager::class); + $this->bulkSummaryFactoryMock = $this->createPartialMock( + BulkSummaryInterfaceFactory::class, + ['create'] + ); + $this->authorizationMock = $this->createMock(AuthorizationInterface::class); + + $this->model = new AccessManager( + $this->userContextMock, + $this->entityManagerMock, + $this->bulkSummaryFactoryMock, + $this->authorizationMock + ); + } + + /** + * @dataProvider summaryDataProvider + * @param string $bulkUserId + * @param bool $expectedResult + */ + public function testIsAllowedForBulkUuid($bulkUserId, $expectedResult) + { + $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->isAllowedForBulkUuid($uuid), $expectedResult); + } + + /** + * @return array + */ + public static function summaryDataProvider() + { + 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..5327bb727ea0a 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 @@ -23,6 +23,8 @@ use PHPUnit\Framework\TestCase; /** + * Test cases for Plugin implementation + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PluginTest extends TestCase @@ -78,9 +80,14 @@ class PluginTest extends TestCase private $statusMapper; /** - * @var string + * @var \PHPUnit\Framework\MockObject\MockObject */ - private $resourceName = 'Magento_Logging::system_magento_logging_bulk_operations'; + private $accessManager; + + /** + * @var \PHPUnit\Framework\MockObject\MockObject + */ + private $encryptor; protected function setUp(): void { @@ -103,18 +110,18 @@ protected function setUp(): void $this->bulkNotificationMock, $this->userContextMock, $this->operationsDetailsMock, - $this->authorizationMock, - $this->statusMapper + $this->statusMapper, + $this->accessManager, + $this->encryptor ); } public function testAfterToArrayIfNotAllowed() { $result = []; - $this->authorizationMock + $this->accessManager ->expects($this->once()) - ->method('isAllowed') - ->with($this->resourceName) + ->method('isOwnActionsAllowed') ->willReturn(false); $this->assertEquals($result, $this->plugin->afterToArray($this->collectionMock, $result)); } @@ -146,10 +153,9 @@ public function testAfterTo($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); - $this->authorizationMock + $this->accessManager ->expects($this->once()) - ->method('isAllowed') - ->with($this->resourceName) + ->method('isOwnActionsAllowed') ->willReturn(true); $this->userContextMock->expects($this->once())->method('getUserId')->willReturn($userId); $this->bulkNotificationMock @@ -158,7 +164,7 @@ public function testAfterTo($operationDetails) ->with($userId) ->willReturn([]); $this->statusMapper->expects($this->once())->method('operationStatusToBulkSummaryStatus'); - $this->bulkStatusMock->expects($this->once())->method('getBulksByUser')->willReturn($userBulks); + $this->bulkStatusMock->expects($this->once())->method('getBulksByUserAndType')->willReturn($userBulks); $result2 = $this->plugin->afterToArray($this->collectionMock, $result); $this->assertEquals(2, $result2['totalRecords']); } 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..53d4e9fb168aa 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 @@ -10,6 +10,7 @@ use Magento\AdminNotification\Ui\Component\DataProvider\DataProvider; use Magento\AsynchronousOperations\Ui\Component\AdminNotification\Plugin; use Magento\Framework\AuthorizationInterface; +use Magento\AsynchronousOperations\Model\AccessManager; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -23,7 +24,7 @@ class PluginTest extends TestCase /** * @var MockObject */ - private $authorizationMock; + private $accessManagerMock; protected function setUp(): void { diff --git a/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php b/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php index b5670639dce09..69371444d77b9 100644 --- a/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/AdminNotification/Plugin.php @@ -6,15 +6,18 @@ namespace Magento\AsynchronousOperations\Ui\Component\AdminNotification; +use Magento\AdminNotification\Ui\Component\DataProvider\DataProvider; +use Magento\AsynchronousOperations\Model\AccessManager; + /** * Class Plugin to eliminate Bulk related links in the notification area */ class Plugin { /** - * @var \Magento\Framework\AuthorizationInterface + * @var AccessManager */ - private $authorization; + private $accessManager; /** * @var bool @@ -23,30 +26,29 @@ class Plugin /** * Plugin constructor. - * @param \Magento\Framework\AuthorizationInterface $authorization + * + * @param AccessManager $accessManager */ public function __construct( - \Magento\Framework\AuthorizationInterface $authorization + AccessManager $accessManager ) { - $this->authorization = $authorization; + $this->accessManager = $accessManager; } /** * 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, + DataProvider $dataProvider, $result ) { if (!isset($this->isAllowed)) { - $this->isAllowed = $this->authorization->isAllowed( - 'Magento_Logging::system_magento_logging_bulk_operations' - ); + $this->isAllowed = $this->accessManager->isOwnActionsAllowed(); } $result['columns']['arguments']['data']['config']['isAllowed'] = $this->isAllowed; return $result; 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..cae5c66ce4b8b --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/Bulk/DataProvider.php @@ -0,0 +1,95 @@ +filterBuilder = $filterBuilder; + $this->accessManager = $accessManager; + $this->userContext = $userContext; + $this->collection = $collectionFactory->create(); + parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); + } + + /** + * Get data for Bulk Operations Grid + * + * @return array + */ + public function getData() + { + $allowedUserTypes = $this->accessManager->getGlobalAllowedUserTypes(); + $connection = $this->getCollection()->getConnection(); + $whereOr = []; + if (count($allowedUserTypes) > 0) { + $whereOr[] = $connection->quoteInto("user_type IN(?)", $allowedUserTypes); + } + + if ($this->accessManager->isOwnActionsAllowed()) { + $whereOr[] = implode( + ' AND ', + [ + $connection->quoteInto('user_type = ?', $this->userContext->getUserType()), + $connection->quoteInto('user_id = ?', $this->userContext->getUserId()) + ] + ); + } + + $whereCond = '(' . implode(') OR (', $whereOr) . ')'; + $this->getCollection()->getSelect()->where($whereCond); + + return $this->getCollection()->toArray(); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php index 5f2fbd9ea8b11..0a337b620e6ba 100644 --- a/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php +++ b/app/code/Magento/AsynchronousOperations/Ui/Component/DataProvider/SearchResult.php @@ -9,21 +9,15 @@ use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; use Magento\Framework\Event\ManagerInterface as EventManager; use Psr\Log\LoggerInterface as Logger; -use Magento\Authorization\Model\UserContextInterface; use Magento\Framework\Bulk\BulkSummaryInterface; use Magento\AsynchronousOperations\Model\StatusMapper; 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 { - /** - * @var UserContextInterface - */ - private $userContext; - /** * @var StatusMapper */ @@ -45,27 +39,25 @@ class SearchResult extends \Magento\Framework\View\Element\UiComponent\DataProvi * @param Logger $logger * @param FetchStrategy $fetchStrategy * @param EventManager $eventManager - * @param UserContextInterface $userContextInterface * @param StatusMapper $statusMapper * @param CalculatedStatusSql $calculatedStatusSql * @param string $mainTable - * @param null $resourceModel + * @param null|string $resourceModel * @param string $identifierName * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @throws \Magento\Framework\Exception\LocalizedException */ public function __construct( EntityFactory $entityFactory, Logger $logger, FetchStrategy $fetchStrategy, EventManager $eventManager, - UserContextInterface $userContextInterface, StatusMapper $statusMapper, CalculatedStatusSql $calculatedStatusSql, $mainTable = 'magento_bulk', $resourceModel = null, $identifierName = 'uuid' ) { - $this->userContext = $userContextInterface; $this->statusMapper = $statusMapper; $this->calculatedStatusSql = $calculatedStatusSql; parent::__construct( @@ -80,7 +72,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function _initSelect() { @@ -90,15 +82,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 +99,12 @@ protected function _afterLoad() } /** - * {@inheritdoc} + * Add additional field for filter request + * + * @param array|string $field + * @param string|array $condition + * + * @return $this */ public function addFieldToFilter($field, $condition = null) { @@ -133,7 +127,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..7b5d8bbd3d6d5 100644 --- a/app/code/Magento/AsynchronousOperations/etc/di.xml +++ b/app/code/Magento/AsynchronousOperations/etc/di.xml @@ -93,9 +93,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..3b3d28b6aa5db 100644 --- a/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php +++ b/lib/internal/Magento/Framework/Bulk/BulkStatusInterface.php @@ -38,9 +38,20 @@ public function getOperationsCountByBulkIdAndStatus($bulkUuid, $status); * @param int $userId * @return BulkSummaryInterface[] * @since 103.0.0 - */ + * @deprecated 100.3.0 + */ public function getBulksByUser($userId); + /** + * Get all bulks created by user and user type + * + * @param int $userId + * @param int $userTypeId + * @return BulkSummaryInterface[] + * @since 100.2.0 + */ + public function getBulksByUserAndType($userId, $userTypeId); + /** * Computational status based on statuses of belonging operations *