ACL Resource Tree Structure
ACL (Access Control List) defines a hierarchical tree of permissions for admin resources.
acl.xml structure:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Magento_Backend::stores">
<resource id="Magento_Backend::stores_settings">
<resource id="Magento_Backend::config"/>
</resource>
</resource>
<resource id="Vendor_Module::menu">
<resource id="Vendor_Module::menu_items"/>
<resource id="Vendor_Module::menu_settings"/>
</resource>
</resource>
</resources>
</acl>
</config>
Resource hierarchy:
Magento_Backend::admin (root)
├── Magento_Backend::stores
│ └── Magento_Backend::stores_settings
│ └── Magento_Backend::config
├── Vendor_Module::menu
│ ├── Vendor_Module::menu_items
│ └── Vendor_Module::menu_settings
└── Magento_Catalog::products
├── Magento_Catalog::products_create
├── Magento_Catalog::products_edit
└── Magento_Catalog::products_delete
Resource ID naming:
- Format:
Vendor_Module::resource_name - Root:
Magento_Backend::admin - Use underscores, not hyphens
Module ACL Configuration
Each module defines its own ACL resources that extend the main tree.
Module acl.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Vendor_Blog::blog" title="Blog Management">
<resource id="Vendor_Blog::blog_posts" title="Blog Posts"/>
<resource id="Vendor_Blog::blog_categories" title="Blog Categories"/>
<resource id="Vendor_Blog::blog_settings" title="Blog Settings"/>
</resource>
</resource>
</resources>
</acl>
</config>
System configuration ACL:
<!-- system.xml uses ACL for section access -->
<section id="vendor_blog" type="text" sortOrder="300" showInDefault="1">
<label>Blog Settings</label>
<resource>Vendor_Blog::blog_settings</resource>
<!-- Only users with Vendor_Blog::blog_settings permission see this -->
</section>
Menu ACL:
<!-- menu.xml uses ACL for menu visibility -->
<add id="Vendor_Blog::blog" title="Blog" module="Vendor_Blog"
sortOrder="80" resource="Vendor_Blog::blog"/>
Controller ACL:
namespace Vendor\Blog\Controller\Adminhtml\Post;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
class Save extends Action
{
const ADMIN_RESOURCE = 'Vendor_Blog::blog_posts';
public function execute()
{
// Only accessible with Vendor_Blog::blog_posts permission
}
}
API ACL:
<route url="/V1/blog/posts" method="GET">
<service class="Vendor\Blog\Api\PostRepositoryInterface" method="getList"/>
<resources>
<resource ref="Vendor_Blog::blog_posts"/>
</resources>
</route>
Admin Roles and Permissions
Admin roles control what resources each admin user can access.
Role hierarchy:
All (root)
├── Roles
│ ├── Administrator (all permissions)
│ ├── Marketing Manager
│ │ ├── Catalog
│ │ ├── CMS
│ │ └── Blog
│ └── Customer Service
│ ├── Sales
│ └── Customer
Role configuration:
-- Admin roles table
SELECT * FROM acl_role;
-- role_id, role_name, parent_id, tree_level, sort_order, role_type, user_id, is_active
-- Role-resource assignments
SELECT * FROM acl_role_resources;
-- role_id, resource_id, permission (allow/deny)
-- Admin user roles
SELECT * FROM admin_user;
-- user_id, username, ... (roles assigned via admin user form)
Managing roles via CLI:
# Create admin role
php bin/magento admin:user:create --role="Marketing"
# List roles
php bin/magento admin:roles:list
# Assign permissions (typically done via admin UI)
Role-based system config:
<!-- Restrict config section to specific role -->
<section id="vendor_settings" type="text" sortOrder="100">
<label>Vendor Settings</label>
<resource>Vendor_Module::settings</resource>
<!-- Only users with this resource can see/edit -->
</section>
Permission inheritance:
- Child resources inherit parent permissions
- If user has
Vendor_Blog::blog, they have access to all children - Can explicitly deny specific children
ACL Debugging and Best Practices
Debugging ACL issues and best practices for permission design.
Debugging ACL:
# Check ACL tree
php bin/magento setup:di:compile 2>&1 | grep acl
# Verify resource exists
grep -r "Vendor_Module::resource" app/code/Vendor/Module/etc/
# Check role assignments
mysql -u root -p magento -e "SELECT * FROM acl_role_resources WHERE resource_id LIKE '%Vendor%';"
# Test permission in code
if ($this->authorization->isAllowed('Vendor_Module::resource')) {
// User has permission
}
Common ACL issues:
1. Resource not in tree → 403 Forbidden
2. Role doesn't include resource → Access denied
3. Wrong resource ID format → Resource not found
4. Missing parent resource → Children not accessible
Best practices:
<!-- 1. Use descriptive resource names -->
<resource id="Vendor_Blog::posts_manage" title="Manage Posts"/>
<!-- 2. Create granular permissions -->
<resource id="Vendor_Blog::posts">
<resource id="Vendor_Blog::posts_view" title="View"/>
<resource id="Vendor_Blog::posts_create" title="Create"/>
<resource id="Vendor_Blog::posts_edit" title="Edit"/>
<resource id="Vendor_Blog::posts_delete" title="Delete"/>
</resource>
<!-- 3. Follow Magento naming convention -->
<!-- Vendor_Module::resource_subresource -->
<!-- 4. Always add title for UI display -->
<resource id="Vendor_Blog::posts" title="Blog Posts"/>
ACL in controllers:
// Check permission before action
public function execute()
{
if (!$this->_isAllowed()) {
return $this->_redirect('adminhtml/*/denied');
}
// ... action logic
}
protected function _isAllowed(): bool
{
return $this->_authorization->isAllowed(self::ADMIN_RESOURCE);
}
Quiz
1. What is the root ACL resource in Magento?
2. How do you check ACL permission in a controller?
3. What format do ACL resource IDs follow?
4. How does permission inheritance work in ACL?
Flashcards
Question
What is the root ACL resource?
Click to reveal answer
Answer
Magento_Backend::admin
Question
What XML file defines ACL resources?
Click to reveal answer
Answer
acl.xml
Question
How do you check permission in PHP?
Click to reveal answer
Answer
$this->_authorization->isAllowed('Vendor_Module::resource')
Question
What is the resource ID naming format?
Click to reveal answer
Answer
Vendor_Module::resource_name
Question
Where are admin roles stored?
Click to reveal answer
Answer
acl_role and acl_role_resources database tables
Revision Notes
Key Takeaways
- 1. ACL defines a hierarchical permission tree rooted at Magento_Backend::admin
- 2. Each module defines resources in acl.xml
- 3. Resources are referenced in system.xml, menu.xml, controllers, and webapi.xml
- 4. Child resources inherit parent permissions
- 5. Roles assign sets of resources to admin users
- 6. Use isAllowed() in controllers to check permissions
Interview Tips
- • Explain the ACL resource hierarchy
- • Describe how to create custom ACL resources
- • Discuss role-based permission management
- • Know how to check permissions in controllers
Cheat Sheet
ACL Cheat Sheet
Root resource: Magento_Backend::admin
Naming: Vendor_Module::resource_name
File: acl.xml in module etc/ directory
Usage locations:
- system.xml:
tag - menu.xml: resource attribute
- controllers: ADMIN_RESOURCE const
- webapi.xml:
Check permission:
$this->_authorization->isAllowed('Vendor_Module::resource')
Role tables:
- acl_role: Role definitions
- acl_role_resources: Role-resource mapping