Magento ACL Permissions

Magento ACL Permissions are used with the admin area and check to see whether a user has permission to access a particular area.

Within the preDispatch() method of the Mage_Adminhtml_Controller_Action class, a call to the _isAllowed() method is made.

if ($this->getRequest()->isDispatched()
    && $this->getRequest()->getActionName() !== 'denied'
    && !$this->_isAllowed()) {
    $this->_forward('denied');
    $this->setFlag('', self::FLAG_NO_DISPATCH, true);
    return $this;
}
protected function _isAllowed()
{
    return Mage::getSingleton('admin/session')->isAllowed('admin');
}

The isAllowed() method is usually overridden in module’s individual controller file, such as the ProductController.php file.

protected function _isAllowed()
{
    return Mage::getSingleton('admin/session')->isAllowed('catalog/products');
}

The catalog/products is a parameter that gets passed in as the $resource within the isAllowed() method of the Mage_Admin_Model_Session class.

public function isAllowed($resource, $privilege = null)
{
    $user = $this->getUser();
    $acl = $this->getAcl();

    if ($user && $acl) {
        if (!preg_match('/^admin/', $resource)) {
            $resource = 'admin/' . $resource;
        }

        try {
            return $acl->isAllowed($user->getAclRole(), $resource, $privilege);
        } catch (Exception $e) {
            try {
                if (!$acl->has($resource)) {
                    return $acl->isAllowed($user->getAclRole(), null, $privilege);
                }
            } catch (Exception $e) { }
        }
    }
    return false;
}

We then load the user and ACL configuration.

A check if made to see if the $resource variable contains the admin string and if it doesn’t, we add it at the front of our resource. For example, the catalog product resource, catalog/products, becomes admin/catalog/products.

We then delegate to the isAllowed() method, passing in the user’s ACL role, the resource and any privileges that have been set. Firstly, we need to get the user’s ACL role.

public function getAclRole()
{
    return 'U' . $this->getUserId();
}

We can then proceed to the isAllowed() method in the Zend_Acl class. We won’t go into this library class in detail, but Magento makes use of this class to help validate users permissions within the admin area.

So how do we set up ACL permissions? For this, we’ll need to create a custom module. To start with, set up the module declaration file:

<?xml version="1.0"?>
<config>
    <modules>
        <Custom_Acl>
            <codePool>local</codePool>
            <active>true</active>
        </Custom_Acl>
    </modules>
</config>

Our config.xml should look like the below example to start with. The ACL permissions will be added shortly.

<?xml version="1.0"?>
<config>
    <global>
        <helpers>
            <acl>
                <class>Custom_Acl_Helper</class>
            </acl>
        </helpers>
    </global>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <Custom_Acl after="Mage_Adminhtml">Custom_Acl</Custom_Acl>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
</config>

We then should add a helper file.

<?php
class Custom_Acl_Helper_Data extends Mage_Core_Helper_Abstract {

}

Our adminhtml.xml file consists of our new menu item that we will add to test our ACL permissions.

<?xml version="1.0"?>
<config>
    <menu>
        <acl module="acl" translate="label">
            <title>ACL</title>
            <sort_order>1000</sort_order>
            <children&gt;
                <manageacl module="acl" translate="label">
                    <title>Manage ACL</title>
                    <sort_order>10</sort_order>
                    <action>adminhtml/acl/index</action>
                </manageacl>
            </children>
        </acl>
    </menu>
</config>

And finally, our controller file that contains an indexAction() method. The method will not be used for anything in particular. It will just print some text that will let us know if we can view the page.

<?php
class Custom_Acl_AclController extends Mage_Adminhtml_Controller_Action {
    public function indexAction() {
        echo "We are allowed here"; exit();
    }
}

So we should get a new menu item appearing in the admin, and if we click on the sub menu item of this, we should be presented with the following:

Magento ACL Permissions

So we see the contents of this page because we haven’t added the relevant ACL permissions yet. To do this, we need to add some ACL configuration within the adminhtml.xml file.

<?xml version="1.0"?>
<config>
    <menu>
        ....
    </menu>
    <acl>
        <resources>
            <all>
                <title>Allow Everything</title>
            </all>
            <admin>
                <children>
                    <aclmenu translate="title" module="acl">
                        <title>ACL</title>
                        <sort_order>1000</sort_order>
                        <children>
                            <manageacl translate="title" module="acl">
                                <title>ACL Test</title>
                            </manageacl>
                        </children>
                    </aclmenu>
                </children>
            </admin>
        </resources>
    </acl>
</config>

All ACL configuration is configured within a pair of acl and resources nodes.

Our new custom menu item should be added as a child within the children nodes within the admin nodes.

The name of your nodes should match the name given to them under the pair of menu nodes defined within the same adminhtml.xml file.

The sort_order nodes can be used to position the checkboxes within System -> Permissions -> Roles.

This works well, however we need to test another scenario. If a custom role is set up to view the custom menu item, along with a new user assigned to the custom role, when the user logs in and tries to view the page, we are presented with the following.

Magento ACL Permissions

Remember the _isAllowed() method from earlier? Currently we do not have this in our AclController.php file, and so the method from the parent Mage_Adminhtml_Controller_Action class is used. So we need to add in this method into our controller file and change the following line.

protected function _isAllowed()
{
    return Mage::getSingleton('admin/session')->isAllowed('admin');
}

To this:

protected function _isAllowed()
{
    return Mage::getSingleton('admin/session')->isAllowed('aclmenu/manageacl');
}

We can now see that our custom menu item is viewable to this user. Note that the aclmenu and manageacl words match the names of our nodes in our ACL configuration.

Magento also gives us the ability to add ACL permissions for sections within System -> Configuration. We can test this out by adding a system.xml file and adding a section within a tab.

<?xml version="1.0"?>
<config>
    <tabs>
        <acltab translate="label" module="acl">
            <label>ACL Tab</label>
            <sort_order>101</sort_order>
        </acltab>
    </tabs>
    <sections>
        <aclsection translate="label" module="acl">
            <label>ACL Section</label>
            <tab>acltab</tab>
            <frontend_type>text</frontend_type>
            <sort_order>1000</sort_order>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>1</show_in_store>
        </aclsection>
    </sections>
</config>

This adds a new tab and section within System -> Configuration.

Magento ACL Permissions

However, when clicking on the section, we’re presented with a 404 error.

Magento ACL Permissions

We should set up ACL Permissions for this section.

<?xml version="1.0"?>
<config>
    ....
    <acl>
        <resources>
            ....
            <admin>
                <children>
                    ....
                    <system>
                        <children>
                            <config>
                                <children>
                                    <aclsection>
                                        <title>ACL Section</title>
                                    </aclsection>
                                </children>
                            </config>
                        </children>
                    </system>
                </children>
            </admin>
        </resources>
    </acl>
</config>

Magento caches certain roles in the session, so a logout and login of the admin area should be enough for the permissions to take effect and allow you to view the section.

Note: This article is based on Magento Community/Open Source version 1.9.