A very simple CakePHP 3 ACL plugin usage example. This example is based on Simple Acl controlled Application for CakePHP 2. The differences are described in this document. The files in this repository contain the changes and implementations of functions discuessed below.
- Assuming you are using composer, get a copy of the latest cakephp release by running
composer create-project --prefer-dist cakephp/app acl-example. This will create an empty CakePHP project in theacl-exampledirectory. Answer YES when asked if folder permissions should be set. - Navigate to the CakePHP project directory (
acl-examplein this case)cd acl-example - Install the CakePHP ACL plugin by running
composer require cakephp/acl - Include the ACL plugin in
app/config/bootstrap.php
Plugin::load('Acl', ['bootstrap' => true]);###Example schema An example schema taken from the CakePHP 2 ACL tutorial:
CREATE TABLE users (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password CHAR(60) NOT NULL,
group_id INT(11) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE groups (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE posts (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id INT(11) NOT NULL,
title VARCHAR(255) NOT NULL,
body TEXT,
created DATETIME,
modified DATETIME
);
CREATE TABLE widgets (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
part_no VARCHAR(12),
quantity INT(11)
);After the schema is created, proceed to "bake" the application.
bin/cake bake all groups
bin/cake bake all users
bin/cake bake all posts
bin/cake bake all widgetsAdd UsersController::login function
public function login() {
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Your username or password was incorrect.'));
}
}Add UsersController::logout function
public function logout() {
$this->Flash->success(__('Good-Bye'));
$this->redirect($this->Auth->logout());
}Add src/Templates/Users/login.ctp
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Login') ?></legend>
<?= $this->Form->input('username') ?>
<?= $this->Form->input('password') ?>
<?= $this->Form->submit(__('Login')) ?>
</fieldset>
<?= $this->Form->end() ?>Modify UsersTable::beforeSave to hash the password before saving
use Cake\Auth\DefaultPasswordHasher;
...
public function beforeSave(\Cake\Event\Event $event, \Cake\ORM\Entity $entity,
\ArrayObject $options)
{
$hasher = new DefaultPasswordHasher;
$entity->password = $hasher->hash($entity->password);
return true;
}Include and configure the AuthComponent and the AclComponent in the AppController
public $components = [
'Acl' => [
'className' => 'Acl.Acl'
]
];
...
$this->loadComponent('Auth', [
'authorize' => [
'Acl.Actions' => ['actionPath' => 'controllers/']
],
'loginAction' => [
'plugin' => false,
'controller' => 'Users',
'action' => 'login'
],
'loginRedirect' => [
'plugin' => false,
'controller' => 'Posts',
'action' => 'index'
],
'logoutRedirect' => [
'plugin' => false,
'controller' => 'Users',
'action' => 'login'
],
'unauthorizedRedirect' => [
'controller' => 'Users',
'action' => 'login',
'prefix' => false
],
'authError' => 'You are not authorized to access that location.',
'flash' => [
'element' => 'error'
]
]);Temporarily allow access to UsersController and GroupsController so groups and users can be added. Add the following implementation of beforeFilter to src/Controllers/UsersController.php and src/Controllers/GroupsController.php:
public function initialize()
{
parent::initialize();
$this->Auth->allow();
}- Create the ACL related tables by running
bin/cake Migrations.migrations migrate -p Acl
- Add the requester behavior to
GroupsTableandUsersTable - Add
$this->addBehavior('Acl.Acl', ['type' => 'requester']);to theinitializefunction in the filessrc/Model/Table/UsersTable.phpandsrc/Model/Table/GroupsTable.php
Add the following implementation of parentNode to the file src/Model/Entity/Group.php:
public function parentNode()
{
return null;
}Add the following implementation of parentNode to the file src/Model/Entity/User.php:
public function parentNode()
{
if (!$this->id) {
return null;
}
if (isset($this->group_id)) {
$groupId = $this->group_id;
} else {
$Users = TableRegistry::get('Users');
$user = $Users->find('all', ['fields' => ['group_id']])->where(['id' => $this->id])->first();
$groupId = $user->group_id;
}
if (!$groupId) {
return null;
}
return ['Groups' => ['id' => $groupId]];
}The ACL Extras plugin referred to in the CakePHP 2 ACL tutorial is now integrated into the CakePHP ACL plugin for CakePHP 3.
- Run
bin/cake acl_extras aco_syncto automatically create ACOs. - ACOs and AROs can be managed manually using the ACL shell. Run
bin/cake aclfor more information.
- Navigate to
/groups/addand add the groups- For this example, we will create
Administrator,Manager, andUser
- For this example, we will create
- Navigate to
/users/addand add the users- For this example, we will create one user in each group
test-administratoris anAdministratortest-manageris aManagertest-useris aUser
- For this example, we will create one user in each group
Remove the temporary auth overrides by removing the beforeFilter function or the call to $this->Auth->allow(); in src/Controllers/UsersController.php and src/Controllers/GroupsController.php.
First, find the IDs of each group you want to grant permissions on. There are several ways of doing this. Since we will be at the console anyway, the quickest way is probably to run bin/cake acl view aro to view the ARO tree. In this example, we will assume the Administrator, Manager, and User groups have IDs 1, 2, and 3 respectively.
- Grant members of the
Administratorgroup permission to everything- Run
bin/cake acl grant Groups.1 controllers
- Run
- Grant members of the
Managergroup permission to all actions inPostsandWidgets- Run
bin/cake acl deny Groups.2 controllers - Run
bin/cake acl grant Groups.2 controllers/Posts - Run
bin/cake acl grant Groups.2 controllers/Widgets
- Run
- Grant members of the
Usergroup permission to viewPostsandWidgets- Run
bin/cake acl deny Groups.3 controllers - Run
bin/cake acl grant Groups.3 controllers/Posts/index - Run
bin/cake acl grant Groups.3 controllers/Posts/view - Run
bin/cake acl grant Groups.3 controllers/Widgets/index - Run
bin/cake acl grant Groups.3 controllers/Widgets/view
- Run
- Allow all groups to logout
- Run
bin/cake acl grant Groups.2 controllers/Users/logout - Run
bin/cake acl grant Groups.3 controllers/Users/logout
- Run