I have recently updated the code in /darkauth-2 to be compliant with the newly released CakePHP 1.2 RC. Only a small fix, but it made me think about DarkAuth and how it works best.
When I originally wrote it, I recieved some feedback from several different sources syaing that it was difficult to understand and didn't necessarily work as expected.
This was because DarkAuth has a very specific methodology and and is just as much an Access Control component as an Authentication one.
Authentication and Access Control
- Authentication is a method of identifying users.
- Access Control is a method of restricting those user to what they are allowed to do.
DarkAuth has some useful functions that help with both. In the next release of the code I intend to rename all references to "Group" with "Role" as it is really about Role-Based Access Control.
In my usual setup for using DarkAuth I create 5 tables: users, roles, roles_users, groups, groups_roles
The first three are straight forwards, they define the users of the system, any roles that might exist (think roles like "CanAddPosts", "CanEditItems", etc...) and the join table that defines their relationship.
The next two is where I define Groups of Roles. The whole point of this is simply a helper - I can pick which roles I give to my users explicitly, or I can choose a group which contains a certain array of roles. It just makes it easier to manage. Enough talk, on to an example.
Let's see it it action...
Using the following tables:
- CREATE TABLE IF NOT EXISTS `users` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `created` DATETIME DEFAULT NULL,
- `modified` DATETIME DEFAULT NULL,
- `email` VARCHAR(64) NOT NULL,
- `pswd` VARCHAR(32) character SET utf8 COLLATE utf8_bin NOT NULL,
- `live` TINYINT(1) NOT NULL DEFAULT '0',
- PRIMARY KEY (`id`)
- ) ENGINE='MyISAM' DEFAULT CHARSET='utf8';
-
- CREATE TABLE IF NOT EXISTS `roles` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `name` VARCHAR(32) NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE='MyISAM' DEFAULT CHARSET='utf8';
-
- CREATE TABLE IF NOT EXISTS `roles_users` (
- `role_id` INT(11) NOT NULL,
- `user_id` INT(11) NOT NULL,
- KEY `role_id` (`role_id`,`user_id`)
- ) ENGINE='MyISAM' DEFAULT CHARSET='utf8';
-
- CREATE TABLE IF NOT EXISTS `groups` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `name` VARCHAR(24) NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE='MyISAM' DEFAULT CHARSET='utf8';
-
- CREATE TABLE IF NOT EXISTS `groups_roles` (
- `group_id` INT(11) NOT NULL,
- `role_id` INT(11) NOT NULL,
- KEY `group_id` (`group_id`,`role_id`)
- ) ENGINE='MyISAM' DEFAULT CHARSET='utf8';
And with some sample data:
- INSERT INTO `users` VALUES (1,NOW(),NOW(),'reader@example.com','5f5a3325bce31f27472ececf3f9aee9a',1),
- (2,NOW(),NOW(),'writer@example.com','5f5a3325bce31f27472ececf3f9aee9a',1),
- (3,NOW(),NOW(),'moderator@example.com','5f5a3325bce31f27472ececf3f9aee9a',1);
- INSERT INTO `roles` VALUES (1, 'Root'), (2, 'CanAddPosts'), (3, 'CanModeratePosts'), (4, 'CanEditOwnPosts'), (5, 'CanEditOtherPeoplesPosts');
- INSERT INTO `groups` VALUES (1, 'Reader'), (2, 'Writer'), (3, 'Moderator');
- -- Now the clever bit:
- INSERT INTO `groups_roles` VALUES (2, 2), (2, 4), (3, 2), (3, 3), (3, 4), (3, 5);
Which creates a mapping of roles to groups. We can then create a function which applies the given set of roles to the user. I put mine in GroupsController for lack of a better place, but I am not sure it should stay there. It goes like this:
- function _applyGroup($user_id,$group_id){
- $data['User']['id'] = $user_id;
- $data['Role']['Role'] = array_keys($this->Group->GroupsRole->find('list', array('conditions'=>array('group_id'=>$group_id), 'fields'=>'GroupsRole.role_id,GroupsRole.group_id')));
- if($this->User->exists($user_id)){
- if($this->User->save($data)){
- //Success!
- return true;
- }else{
- //failure :(
- return false;
- }
- }else{
- //failure, no user found...
- return false;
- }
This function will then allow you to align your users' access to fit all the roles you have associated with the group.
This brings a question, should I links my groups with users directly? and read their security roles from the group. Or do I simply use the groups to define set of roles to Apply to users as I want?
I don't know.
The first sounds better, but then we couldn't do any bespoke customisations (i.e. one-off adding of roles to particular users). The second is what I currently use, but if you update a group the use's dont' automatically update.
I guess there's an answer in there that you update all users' permission's that match the previous role set of a group to the new role set whenever you change a group. Confused? hopefully not too much...
Bill said at 00:28, 7th July 2008:
theChrisWalker said at 17:36, 7th July 2008:
Theo said at 21:30, 9th July 2008:
Theo said at 21:44, 9th July 2008:
theChrisWalker said at 09:17, 10th July 2008:
itsnotvalid said at 13:02, 11th July 2008:
Theo said at 12:59, 12th July 2008:
blablacio said at 15:15, 15th July 2008:
itsnotvalid said at 12:08, 20th July 2008:
theChrisWalker said at 20:48, 20th July 2008:
theChrisWalker said at 20:54, 20th July 2008:
Lukas said at 16:11, 29th July 2008:
Lukas said at 16:22, 29th July 2008:
Darren said at 08:39, 5th August 2008: