This is not a specc, but a brainstorm of the permission system to be used by the bakery.
As stated in the users part, Bakery 2.0 will give users permissions based on their group, with the exception of their own content, which they will have a special direct access to. What follows bellow is a suggestion to how to manage each group's rights to do a certain action. For simplicities sake only controller actions are controlled (ie the right to delete an article is controlled by the right to run ArticleController::delete($id).
We will off course use Auth for user authentication and specifying this to use controller to "authorize" the user (http://book.cakephp.org/view/396/authorize) we can move the logic out of the action and take advantage of the function isAuthorized().
In isAuthorized() we have the following information available :
- controller name
- action name
- group_id (through the User session array)
The permissions array is stored in a config file (app/config/permissions.php) with values for each controller action. Access denied for all is assumed for any action not present in this array. Example :
{{{
$config['App']['permissions'] = array(
'Articles' => array(
'view' => 0,
'add' => 10,
'edit' => 50,
'delete' => 80,
'feature' => 50
),
'Comments' => array(
'add' => 10,
'move' => 50
)
);
}}}
{{{
<?php
App::import('Model', 'Users.Group');
$config['App']['permissions'] = array(
'Articles' => array(
'view' => Group::GUEST,
'add' => Group::MEMBER,
'edit' => Group::MODERATOR,
'delete' => Group::COREDEV,
'feature' => Group::MODERATOR
),
'Comments' => array(
'add' => Group::MEMBER,
'move' => Group::MODERATOR
),
'DebugKit.ToolbarAccess' => array(
'history_state' => Group::GUEST
)
);
?>
}}}
**Important** Group.id values are NOT autoincrement. We know in advance what groups we need so we give them an id that doubles as their authority level. ie
- admins = 100
- cakecore developers = 80
- editors = 60
- moderators = 50
- accepted authors = 20
- registered users = 10
- not logged in guests are assumed a value of 0
The reason for leaving gaps is to allow for added groups if more is needed at a later date.
This is enough to decide if the user has access by simply checking if the action is present in the array and if the assigned value is equal or less than the user's group id.
We load the config file in beforeFilter and then the permissions array is accessible throughout the app using Configure::read. In beforeFilter we can allow public actions (accessible by guests) using code like
{{{
Configure::load('permissions');
$permissions = Configure::read('App.permissions');
if (isset($permissions[$this->name][$this->action]) && $permissions[$this->name][$this->action]==0) {
$this->Auth->allow($this->action);
}
}}}
A preview of how the isAuthorized could look:
{{{
public function isAuthorized() {
$group = $this->Auth->user('group_id');
if ($group >= 100)
return true;
$permissions = Configure::read('App.permissions');
if (!isset($permissions[$this->name][$this->action]))
return false;
return ($group >= $permissions[$this->name][$this->action]);
}
}}}
It won't be possible to change permissions dynamically.
