Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I restrict certain content in CakePHP?

I'm pretty new to using CakePHP but I'm already finding incredibly useful for rapidly developing web apps.

However, I was wondering if there is a way to restrict access to certain objects in a non-standard way. For example, if I was to create a single CMS system allows users to create a "site", how can I assert that the users (multiples) have access to that particular site?

I could check this in my site controller but would I need to check this for every single controller on my site - for example, I would need to check that the current Page, News, Contacts, Files etc being edited belongs to the site ID and the user has access to edit it?

ie, thecms.com/pages/edit/123 (how can I be sure user 9 can edit page 123 which belongs to site 2)

I'm assuming this is outside of what ACL can offer as they're entity specific. Is there any easy way to do this?

like image 904
Jamie Chapman Avatar asked Mar 19 '11 13:03

Jamie Chapman


1 Answers

I assume that you already know about CakePHP's Auth and ACL component, which can provide ways for restricting content. But it's also true what you say: that CakePHP's ACL is 'entity-specific' and not the best option for a 'per-record' basis (e.g. user 3 shouldn't access article 7). So I propose this code; try it and let me know:

Within the app/app_controller.php file:

<?php
class AppController extends Controller {
    function checkPermission($aro, $aco, $loggedUserRole = 'User') {
        if ($loggedUserRole != 'Admin') {
            $permission = ($aro == $aco);
            if (!$permission) {
                $this->Session->setFlash('You cannot access that.');
                $this->redirect('/somewhere');
            }
        }
    }
}

Then, within the action that you want to restrict, put:

$this->checkPermission($this->Auth->user('id'), $someId, $this->Auth->user('role'));

So, the checkPermission() function does the following:

When called, you pass an id for the user you want to authorize, an id of the thing the user is trying to access, and also a role (so it is assumed that there is a column of 'Role' within the users table; also, $this->Auth->user('id') means the user session data automatically stored by the Auth component). The checkPermission() method then checks if the passed role is not an admin (supposing there will be admins who will have access to all), and then checks equality of both the $aro and $aco parameters. If not, then it redirects somewhere with a message of 'forbidden'.

Now, the $aco parameter can be a variety of things. For example, suppose you are making a function for editing a user's account, which takes an argument of $userId. So you compare the logged-in user's id (from $this->Auth->user('id')) with the passed $userId. If not equal, it means the logged-in user should not be editing that user record.

Another example: You have an action for deleting an article, which accepts an $articleId argument. You can fetch the article from the database and then pass the article's user_id value as the $aco, before deleting the article. Again, the logged-in user would be kicked out if such user_id is not him.

I hope this solution serves you well.

like image 84
YOMorales Avatar answered Sep 28 '22 04:09

YOMorales