Skip to content

Commit

Permalink
New feature: UI to list and remove orphaned ACL resources in backend. (
Browse files Browse the repository at this point in the history
…#3647)

Co-authored-by: Sven Reichel <github-sr@hotmail.com>
Co-authored-by: Fabrizio Balliano <fabrizio.balliano@gmail.com>
  • Loading branch information
3 people authored Feb 16, 2024
1 parent 8371adc commit 1a842ec
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 0 deletions.
1 change: 1 addition & 0 deletions .phpstorm.meta.php/magento_blocks.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
'adminhtml/permissions_role' => \Mage_Adminhtml_Block_Permissions_Role::class,
'adminhtml/permissions_role_grid_user' => \Mage_Adminhtml_Block_Permissions_Role_Grid_User::class,
'adminhtml/permissions_roles' => \Mage_Adminhtml_Block_Permissions_Roles::class,
'adminhtml/permissions_orphanedResource' => \Mage_Adminhtml_Block_Permissions_OrphanedResource::class,
'adminhtml/permissions_tab_roleinfo' => \Mage_Adminhtml_Block_Permissions_Tab_Roleinfo::class,
'adminhtml/permissions_tab_rolesedit' => \Mage_Adminhtml_Block_Permissions_Tab_Rolesedit::class,
'adminhtml/permissions_tab_rolesusers' => \Mage_Adminhtml_Block_Permissions_Tab_Rolesusers::class,
Expand Down
2 changes: 2 additions & 0 deletions .phpstorm.meta.php/magento_blocks_methods.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
'adminhtml/permissions_role' => \Mage_Adminhtml_Block_Permissions_Role::class,
'adminhtml/permissions_role_grid_user' => \Mage_Adminhtml_Block_Permissions_Role_Grid_User::class,
'adminhtml/permissions_roles' => \Mage_Adminhtml_Block_Permissions_Roles::class,
'adminhtml/permissions_orphanedResource' => \Mage_Adminhtml_Block_Permissions_OrphanedResource::class,
'adminhtml/permissions_tab_roleinfo' => \Mage_Adminhtml_Block_Permissions_Tab_Roleinfo::class,
'adminhtml/permissions_tab_rolesedit' => \Mage_Adminhtml_Block_Permissions_Tab_Rolesedit::class,
'adminhtml/permissions_tab_rolesusers' => \Mage_Adminhtml_Block_Permissions_Tab_Rolesusers::class,
Expand Down Expand Up @@ -554,6 +555,7 @@
'adminhtml/sales_order_view_tab_history' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_History::class,
'adminhtml/sales_order_view_tab_info' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_Info::class,
'adminhtml/sales_order_view_tab_invoices' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_Invoices::class,
'adminhtml/sales_order_view_tab_prova' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_Prova::class,
'adminhtml/sales_order_view_tab_shipments' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_Shipments::class,
'adminhtml/sales_order_view_tab_transactions' => \Mage_Adminhtml_Block_Sales_Order_View_Tab_Transactions::class,
'adminhtml/sales_order_view_tabs' => \Mage_Adminhtml_Block_Sales_Order_View_Tabs::class,
Expand Down
17 changes: 17 additions & 0 deletions app/code/core/Mage/Admin/Model/Resource/Acl.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Mage_Admin_Model_Resource_Acl extends Mage_Core_Model_Resource_Db_Abstract
{
public const ACL_ALL_RULES = 'all';

protected $_orphanedResources = [];

/**
* Initialize resource
*
Expand Down Expand Up @@ -131,12 +133,27 @@ public function loadRules(Mage_Admin_Model_Acl $acl, array $rulesArr)
} elseif ($rule['permission'] == 'deny') {
$acl->deny($role, $resource, $privileges, $assert);
}
} catch (Zend_Acl_Exception $e) {
if (!in_array($resource, $this->_orphanedResources) && strpos($e->getMessage(), "Resource '$resource' not found") !== false) {
$this->_orphanedResources[] = $resource;
}
} catch (Exception $e) {
if (Mage::getIsDeveloperMode()) {
Mage::logException($e);
}
}
}

if ($this->_orphanedResources !== []) {
Mage::getSingleton('adminhtml/session')->addNotice(
Mage::helper('adminhtml')->__(
'The following role resources are no longer available in the system: %s. You can delete them by <a href="%s">clicking here</a>.',
implode(', ', $this->_orphanedResources),
Mage::helper("adminhtml")->getUrl('adminhtml/permissions_orphanedResource')
)
);
}

return $this;
}
}
41 changes: 41 additions & 0 deletions app/code/core/Mage/Admin/Model/Resource/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,45 @@ public function saveRel(Mage_Admin_Model_Rules $rule)
Mage::logException($e);
}
}

/**
* Set resource ID as ID field name
* @see Mage_Adminhtml_Block_Permissions_OrphanedResource_Grid::_prepareCollection()
*
* @return $this
*/
public function setResourceIdAsIdFieldName()
{
$this->_idFieldName = 'resource_id';
return $this;
}

/**
* Delete orphaned resources
*
* @param array $orphanedIds
* @return int
* @throws Mage_Core_Exception
*/
public function deleteOrphanedResources(array $orphanedIds): int
{
if ($orphanedIds === []) {
return 0;
}

$resourceIds = Mage::getModel('admin/roles')->getResourcesList2D();
// Validate orphaned IDs are not in the list of valid resource IDs.
$validIds = array_intersect($orphanedIds, $resourceIds);
if ($validIds !== []) {
throw new Mage_Core_Exception(
Mage::helper('adminhtml')->__(
'The following role resource(s) are not orphaned: %s',
implode(', ', $validIds)
)
);
}

return $this->_getWriteAdapter()
->delete($this->getMainTable(), ['resource_id IN (?)' => $orphanedIds]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* OpenMage
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available at https://opensource.org/license/osl-3-0-php
*
* @category Mage
* @package Mage_Adminhtml
* @copyright Copyright (c) 2024 The OpenMage Contributors (https://www.openmage.org)
* @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/

/**
* Adminhtml permissions orphaned resource block
*
* @category Mage
* @package Mage_Adminhtml
*/
class Mage_Adminhtml_Block_Permissions_OrphanedResource extends Mage_Adminhtml_Block_Widget_Grid_Container
{
public function __construct()
{
$this->_controller = 'permissions_orphanedResource';
$this->_headerText = Mage::helper('adminhtml')->__('Orphaned Role Resources');
parent::__construct();
$this->_removeButton('add');
}

/**
* @return string
*/
protected function _toHtml(): string
{
Mage::dispatchEvent('permissions_orphanedresource_html_before', ['block' => $this]);
return parent::_toHtml();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

/**
* OpenMage
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available at https://opensource.org/license/osl-3-0-php
*
* @category Mage
* @package Mage_Adminhtml
* @copyright Copyright (c) 2024 The OpenMage Contributors (https://www.openmage.org)
* @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/

/**
* Adminhtml permissions orphanedResource grid
*
* @category Mage
* @package Mage_Adminhtml
*/
class Mage_Adminhtml_Block_Permissions_OrphanedResource_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
public function __construct()
{
parent::__construct();
$this->setId('permissionsOrphanedResourceGrid');
$this->setDefaultSort('resource_id');
$this->setDefaultDir('asc');
}

/**
* @inheritdoc
*/
protected function _prepareCollection()
{
/** @var Mage_Admin_Model_Resource_Rules_Collection */
$collection = Mage::getResourceModel('admin/rules_collection')
->addFieldToFilter('resource_id', ['nin' => Mage::getModel('admin/roles')->getResourcesList2D()])
->addFieldToSelect('resource_id');
$collection->getSelect()->group('resource_id');

/**
* In order for mass action selection to work properly, we need to overwrite
* the model resource $_idFieldName, from the default 'rule_id' to 'resource_id'.
* @see Mage_Adminhtml_Block_Widget_Grid_Massaction_Abstract::getGridIdsJson()
* @var Mage_Admin_Model_Resource_Rules $resource
*/
$resource = $collection->getResource();
$resource->setResourceIdAsIdFieldName();

$this->setCollection($collection);
return parent::_prepareCollection();
}

/**
* @inheritdoc
*/
protected function _prepareColumns()
{
$this->addColumn('resource_id', [
'header' => Mage::helper('adminhtml')->__('Orphaned Role Resource'),
'index' => 'resource_id'
]);

return parent::_prepareColumns();
}

/**
* @inheritdoc
*/
protected function _prepareMassaction()
{
$this->setMassactionIdField('resource_id');
$this->getMassactionBlock()->setFormFieldName('resource_id');

$this->getMassactionBlock()->addItem('delete', [
'label' => Mage::helper('adminhtml')->__('Delete'),
'url' => $this->getUrl('*/*/massDelete'),
'confirm' => Mage::helper('adminhtml')->__('Are you sure you want to do this?')
]);

return $this;
}

public function getRowUrl($row): string
{
return '';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);

/**
* OpenMage
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available at https://opensource.org/license/osl-3-0-php
*
* @category Mage
* @package Mage_Adminhtml
* @copyright Copyright (c) 2024 The OpenMage Contributors (https://www.openmage.org)
* @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
class Mage_Adminhtml_Permissions_OrphanedResourceController extends Mage_Adminhtml_Controller_Action
{
/**
* ACL resource
* @see Mage_Adminhtml_Controller_Action::_isAllowed()
*/
public const ADMIN_RESOURCE = 'system/acl/orphaned_resources';

/**
* @return $this
*/
protected function _initAction()
{
$this->loadLayout()
->_setActiveMenu('system/acl')
->_addBreadcrumb($this->__('System'), $this->__('System'))
->_addBreadcrumb($this->__('Permissions'), $this->__('Permissions'))
->_addBreadcrumb($this->__('Orphaned Resources'), $this->__('Orphaned Role Resources'));
return $this;
}

/**
* Index action
*/
public function indexAction()
{
$this->_title($this->__('System'))
->_title($this->__('Permissions'))
->_title($this->__('Orphaned Role Resources'));

/** @var Mage_Adminhtml_Block_Permissions_OrphanedResource $block */
$block = $this->getLayout()->createBlock('adminhtml/permissions_orphanedResource');
$this->_initAction()
->_addContent($block)
->renderLayout();
}

/**
* Mass delete action
*/
public function massDeleteAction()
{
$resourceIds = $this->getRequest()->getParam('resource_id');
try {
$deletedRows = Mage::getResourceSingleton('admin/rules')->deleteOrphanedResources($resourceIds);
$this->_getSession()->addSuccess($this->__('Total of %d record(s) have been deleted.', $deletedRows));
} catch (Mage_Core_Exception $e) {
$this->_getSession()->addError($e->getMessage());
} catch (Exception $e) {
$error = Mage::getIsDeveloperMode()
? $e->getMessage()
: $this->__('An error occurred while deleting record(s).');
$this->_getSession()->addError($error);
Mage::logException($e);
}

$this->_redirect('*/*/');
}

/**
* @inheritdoc
*/
public function preDispatch()
{
$this->_setForcedFormKeyActions('massDelete');
return parent::preDispatch();
}
}
7 changes: 7 additions & 0 deletions app/code/core/Mage/Adminhtml/etc/adminhtml.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@
<title>Blocks</title>
<action>adminhtml/permissions_block</action>
</blocks>
<orphaned_resources translate="title">
<title>Orphaned Role Resources</title>
<action>adminhtml/permissions_orphanedResource</action>
</orphaned_resources>
</children>
</acl>
<cache translate="title">
Expand Down Expand Up @@ -145,6 +149,9 @@
<blocks translate="title">
<title>Blocks</title>
</blocks>
<orphaned_resources translate="title">
<title>Orphaned Role Resources</title>
</orphaned_resources>
</children>
</acl>
<store translate="title">
Expand Down
4 changes: 4 additions & 0 deletions app/locale/en_US/Mage_Adminhtml.csv
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,8 @@
"Order Updated Date report is real-time, does not need statistics refreshing.","Order Updated Date report is real-time, does not need statistics refreshing."
"Orders","Orders"
"Original Magento attribute names in first row:","Original Magento attribute names in first row:"
"Orphaned Role Resource","Orphaned Role Resource"
"Orphaned Role Resources","Orphaned Role Resources"
"Out of stock","Out of stock"
"PDT (Payment Data Transfer) Only","PDT (Payment Data Transfer) Only"
"Pages","Pages"
Expand Down Expand Up @@ -1025,6 +1027,7 @@
"The CatalogInventory Stock Status has been rebuilt.","The CatalogInventory Stock Status has been rebuilt."
"The Comment Text field cannot be empty.","The Comment Text field cannot be empty."
"The Flat Catalog Product was rebuilt","The Flat Catalog Product was rebuilt"
"The following role resource(s) are not orphaned: %s","The following role resource(s) are not orphaned: %s"
"The JavaScript/CSS cache has been cleaned.","The JavaScript/CSS cache has been cleaned."
"The JavaScript/CSS cache has been cleared.","The JavaScript/CSS cache has been cleared."
"The Layered Navigation indexing has been queued.","The Layered Navigation indexing has been queued."
Expand Down Expand Up @@ -1061,6 +1064,7 @@
"The email template has been deleted.","The email template has been deleted."
"The email template has been saved.","The email template has been saved."
"The flat catalog category has been rebuilt.","The flat catalog category has been rebuilt."
"The following role resources are no longer available in the system: %s. You can delete them by <a href="%s">clicking here</a>.","The following role resources are no longer available in the system: %s. You can delete them by <a href="%s">clicking here</a>."
"The group node name must be specified with field node name.","The group node name must be specified with field node name."
"The image cache was cleaned.","The image cache was cleaned."
"The image cache was cleared.","The image cache was cleared."
Expand Down
1 change: 1 addition & 0 deletions docs/EVENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
| paypal_prepare_line_items | 1.9.4.5 |
| pdf_item_draw_after | 1.9.4.5 |
| permissions_block_html_before | 1.9.4.5 |
| permissions_orphanedresource_html_before | 20.2.1 |
| permissions_user_html_before | 1.9.4.5 |
| permissions_variable_html_before | 1.9.4.5 |
| poll_vote_add | 1.9.4.5 |
Expand Down

0 comments on commit 1a842ec

Please sign in to comment.