7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial

# How to Use CakePHP's Access Control Lists

Read Time: 17 mins

If you're building a CMS, you'll probably need different user roles—superusers, admins, users—with different permission levels. Too complicated to code? Enter CakePHP's ACL (Access Control Lists). With the right setup, you'll be checking user permissions with just one line.

## Introduction: What Are Access Control Lists?

The ACL lets you create a hierarchy of users with their respective roles. Here's a quick example.

• Super Users
• User #1
• User #2
• User #3
• Users
• User #4
• User #5
• User #6
• ....

In this tutorial, we will be setting up an ACL for a simple blog. If you haven't yet checked out Getting Started With CakePHP (and Part 2) here on Nettuts+, please do so and then return, as we will be taking for granted the framework basics.

With this hierarchy, we can assign several permissions for each role:

• The Super Users can create, read, update and delete Posts and Users.
• The Admins can create, read, update and delete Posts.
• The Users can create and read Posts.
• Everyone else can just read Posts.

Each permission will be given to the group, not to the user; so if user #6 is promoted to Admin, he will be checked against the group permission --not his. These roles and child nodes (users) are called Access Requests Objects, or AROs.

Now, on the other side, we have the Access Control Objects, or ACOs. These are the objects to be controlled. Above I mentioned Posts and Users. Normally, these objects are directly linked with the models, so if we have a Post model, we will need an ACO for this model.

Each ACO has four basic permissions: create, read, update and delete. You can remember them with the keyword CRUD. There's a fifth permission, the asterisk, that is a shortcut for full access.

We will be using just two ACOs for this tutorial: Post and User, but you can create as many as you need.

### The ACL Tables

Let's proceed to create the database tables. You can find this code in db_acl.sql inside your app's config/sql directory.

We can begin now creating ARO and ACO nodes, but hey, we don't have users! We'll have to create a basic authentication system.

## Step 1: A Basic Authentication System

As this tutorial is intended for CakePHP developers with a basic to moderate knowledge of the framework, I will be supplying the code and a brief explanation. However, the authentication system is not the goal of this tutorial.

The MySQL table:

The User model (models/user.php)

The Users controller (controllers/users_controller.php)

Our check() method will need just two parameters: the ACO and the action (which is optional). The ARO will be the current user for each session. The action parameter will default to *, which is full access for the ARO. The function begins by checking if the $this->user is not empty (which really tells us if a user is logged in) and then we go to ACL. We have already covered this. We can now include the Access component in our Posts controller and check the permissions with just one line. The same result is achieved with less code, but the error message is ugly. You'd better replace the die() with the CakePHP error handler: ### Permissions in views This might be ugly, but it works. We'll have to create a helper that loads a component with a custom method for use in the helper. Add this function in the Access component (controllers/components/access.php). Now,let's rewrite the access helper (views/helpers/access.php). The beforeRender() method is a callback, similar to the component's startup(). We are loading two components and since these will be used in most functions, it's a good idea to start all at once, than to manually start them each time the method is called. Now on your index.ctp view in views/posts you can replace this line. With this one. Just don't forget to check permissions, both in the views and the controllers! ### User data You can access the user data for a logged user with the user() method in the Auth component. Then you can access the array and get the info you want. But there must be a better way. Let's add the following function in the Access component. This is quite useful when you need to save a Post with a user_id relationship. And in the view, we can do something similar with the helper. In your template file you can do something like below to greet a user by his username. ## Step 5: Modifying Permissions Let's say we need to switch roles for the user #4: he needs to be a Super User. So, User's id is 4 and Aro's id is 1. Now we need to find the User's Aro in order to modify its parent Aro. Finally, if the $aro_user variable is not empty, let's update the Aro.parent_id field.

Please note that you have to validate both the user's id and the new aro's id. If one of these do not exist, it will create a mess in your ACL tables.

## Step 6: Optimization

Although the component we just created are both simple and useful, the database is queried with each and every check. It is not ready for production yet. First, the database should be queried as little as possible. To optimize this, we should take advantage of CakePHP's Cache.

Using Cache will reduce the load quite a bit, but if we have ten posts showing up in the index, and, for each one, we are checking if the user has update permissions for the Post Aco, the framework will be reading and parsing a file to return the same result...ten times for each page load.

That's the second point: a variable inside the class and some conditionals will make the work lighter, so that a repeated request will be checking against Cache just once.

Both these changes are reflected in access_cache.php, inside the controllers/components directory. So make sure you download the source!

## Conclusions

Access Control Lists are a basic features that most apps need. CakePHP has a nice implementation, but lacks in both good documentation and examples. I hope that, with this tutorial, these two issues will now be covered. Thanks for reading!