Hey guys, I was originally using an ACL Class that was posted on net tuts. After scouring the internet for an ACL plugin that was similar to the net tuts one I opted to just adapt the net tuts one since I couldn’t find one similar. I tried out the Zend ACL library but it didnt (that i saw) have the same functionality
- User by user permissions
- Multiple Roles
- Database configured
- Etc.
Here is the net.tutsplus.com walk through if anyone needs it.
http://net.tutsplus.com/tutorials/php/a-better-login-system/
Database
- Same as the net tuts, just renamed the tables for my own preference.
- USER_DATA can be basically anything you want, just needs to have “id
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -- -- Table structure for table `perm_data` -- CREATE TABLE `perm_data` ( `ID` bigint(20) unsigned NOT NULL auto_increment, `permKey` varchar(30) NOT NULL, `permName` varchar(30) NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY `permKey` (`permKey`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=39 ; -- -------------------------------------------------------- -- -- Table structure for table `role_data` -- CREATE TABLE `role_data` ( `ID` bigint(20) unsigned NOT NULL auto_increment, `roleName` varchar(20) NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY `roleName` (`roleName`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; -- -------------------------------------------------------- -- -- Table structure for table `role_perms` -- CREATE TABLE `role_perms` ( `ID` bigint(20) unsigned NOT NULL auto_increment, `roleID` bigint(20) NOT NULL, `permID` bigint(20) NOT NULL, `value` tinyint(1) NOT NULL default '0', `addDate` datetime NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY `roleID_2` (`roleID`,`permID`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; -- -------------------------------------------------------- -- -- Table structure for table `user_data` -- CREATE TABLE `user_data` ( `ID` int(10) unsigned NOT NULL auto_increment, `username` varchar(20) NOT NULL, `password` text NOT NULL, `name` tinytext NOT NULL, `address` tinytext, `address2` tinytext, `city` tinytext, `state` tinytext, `zip` tinytext, `cellphone` tinytext, `telephone` tinytext, `email` tinytext, `aim` tinytext, `yahoo` tinytext, `icq` tinytext, `other` tinytext, `dateAdded` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`ID`), KEY `Username` (`username`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; -- -------------------------------------------------------- -- -- Table structure for table `user_perms` -- CREATE TABLE `user_perms` ( `ID` bigint(20) unsigned NOT NULL auto_increment, `userID` bigint(20) NOT NULL, `permID` bigint(20) NOT NULL, `value` tinyint(1) NOT NULL default '0', `addDate` datetime NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY `userID` (`userID`,`permID`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; -- -------------------------------------------------------- -- -- Table structure for table `user_roles` -- CREATE TABLE `user_roles` ( `userID` bigint(20) NOT NULL, `roleID` bigint(20) NOT NULL, `addDate` datetime NOT NULL, UNIQUE KEY `userID` (`userID`,`roleID`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The Class File
- Just a converted version of the net tuts class.
class acl
{
var $perms = array(); //Array : Stores the permissions for the user
var $userID; //Integer : Stores the ID of the current user
var $userRoles = array(); //Array : Stores the roles of the current user
var $ci;
function __construct($config=array()) {
$this->ci = &get_instance();
$this->userID = floatval($config['userID']);
$this->userRoles = $this->getUserRoles();
$this->buildACL();
}
function buildACL() {
//first, get the rules for the user's role
if (count($this->userRoles) > 0)
{
$this->perms = array_merge($this->perms,$this->getRolePerms($this->userRoles));
}
//then, get the individual user permissions
$this->perms = array_merge($this->perms,$this->getUserPerms($this->userID));
}
function getPermKeyFromID($permID) {
//$strSQL = "SELECT `permKey` FROM `".DB_PREFIX."permissions` WHERE `ID` = " . floatval($permID) . " LIMIT 1";
$this->ci->db->select('permKey');
$this->ci->db->where('id',floatval($permID));
$sql = $this->ci->db->get('perm_data',1);
$data = $sql->result();
return $data[0]->permKey;
}
function getPermNameFromID($permID) {
//$strSQL = "SELECT `permName` FROM `".DB_PREFIX."permissions` WHERE `ID` = " . floatval($permID) . " LIMIT 1";
$this->ci->db->select('permName');
$this->ci->db->where('id',floatval($permID));
$sql = $this->ci->db->get('perm_data',1);
$data = $sql->result();
return $data[0]->permName;
}
function getRoleNameFromID($roleID) {
//$strSQL = "SELECT `roleName` FROM `".DB_PREFIX."roles` WHERE `ID` = " . floatval($roleID) . " LIMIT 1";
$this->ci->db->select('roleName');
$this->ci->db->where('id',floatval($roleID),1);
$sql = $this->ci->db->get('role_data');
$data = $sql->result();
return $data[0]->roleName;
}
function getUserRoles() {
//$strSQL = "SELECT * FROM `".DB_PREFIX."user_roles` WHERE `userID` = " . floatval($this->userID) . " ORDER BY `addDate` ASC";
$this->ci->db->where(array('userID'=>floatval($this->userID)));
$this->ci->db->order_by('addDate','asc');
$sql = $this->ci->db->get('user_roles');
$data = $sql->result();
$resp = array();
foreach( $data as $row )
{
$resp[] = $row->roleID;
}
return $resp;
}
function getAllRoles($format='ids') {
$format = strtolower($format);
//$strSQL = "SELECT * FROM `".DB_PREFIX."roles` ORDER BY `roleName` ASC";
$this->ci->db->order_by('roleName','asc');
$sql = $this->ci->db->get('role_data');
$data = $sql->result();
$resp = array();
foreach( $data as $row )
{
if ($format == 'full')
{
$resp[] = array("id" => $row->ID,"name" => $row->roleName);
} else {
$resp[] = $row->ID;
}
}
return $resp;
}
function getAllPerms($format='ids') {
$format = strtolower($format);
//$strSQL = "SELECT * FROM `".DB_PREFIX."permissions` ORDER BY `permKey` ASC";
$this->ci->db->order_by('permKey','asc');
$sql = $this->ci->db->get('perm_data');
$data = $sql->result();
$resp = array();
foreach( $data as $row )
{
if ($format == 'full')
{
$resp[$row->permKey] = array('id' => $row->ID, 'name' => $row->permName, 'key' => $row->permKey);
} else {
$resp[] = $row->ID;
}
}
return $resp;
}
function getRolePerms($role) {
if (is_array($role))
{
//$roleSQL = "SELECT * FROM `".DB_PREFIX."role_perms` WHERE `roleID` IN (" . implode(",",$role) . ") ORDER BY `ID` ASC";
$this->ci->db->where_in('roleID',$role);
} else {
//$roleSQL = "SELECT * FROM `".DB_PREFIX."role_perms` WHERE `roleID` = " . floatval($role) . " ORDER BY `ID` ASC";
$this->ci->db->where(array('roleID'=>floatval($role)));
}
$this->ci->db->order_by('id','asc');
$sql = $this->ci->db->get('role_perms'); //$this->db->select($roleSQL);
$data = $sql->result();
$perms = array();
foreach( $data as $row )
{
$pK = strtolower($this->getPermKeyFromID($row->permID));
if ($pK == '') { continue; }
if ($row->value === '1') {
$hP = true;
} else {
$hP = false;
}
$perms[$pK] = array('perm' => $pK,'inheritted' => true,'value' => $hP,'name' => $this->getPermNameFromID($row->permID),'id' => $row->permID);
}
return $perms;
}
function getUserPerms($userID) {
//$strSQL = "SELECT * FROM `".DB_PREFIX."user_perms` WHERE `userID` = " . floatval($userID) . " ORDER BY `addDate` ASC";
$this->ci->db->where('userID',floatval($userID));
$this->ci->db->order_by('addDate','asc');
$sql = $this->ci->db->get('user_perms');
$data = $sql->result();
$perms = array();
foreach( $data as $row )
{
$pK = strtolower($this->getPermKeyFromID($row->permID));
if ($pK == '') { continue; }
if ($row->value == '1') {
$hP = true;
} else {
$hP = false;
}
$perms[$pK] = array('perm' => $pK,'inheritted' => false,'value' => $hP,'name' => $this->getPermNameFromID($row->permID),'id' => $row->permID);
}
return $perms;
}
function hasRole($roleID) {
foreach($this->userRoles as $k => $v)
{
if (floatval($v) === floatval($roleID))
{
return true;
}
}
return false;
}
function hasPermission($permKey) {
$permKey = strtolower($permKey);
if (array_key_exists($permKey,$this->perms))
{
if ($this->perms[$permKey]['value'] === '1' || $this->perms[$permKey]['value'] === true)
{
return true;
} else {
return false;
}
} else {
return false;
}
}
}
Example Usage
// Use whatever user script you would like, just make sure it has an ID field to tie into the ACL with
$this->load->library('user',array('username'=>'admin','password'=>'abc123') );
// Get the user's ID and add it to the config array
$config = array('userID'=>$this->user->getUserID());
// Load the ACL library and pas it the config array
$this->load->library('acl',$config);
// Get the perm key
// I'm using the URI to keep this pretty simple ( http://www.example.com/test/this ) would be 'test_this'
$acl_test = $this->uri->segment(1).'_';
$acl_test .= ($this->uri->segment(2)!="")?$this->uri->segment(2):'view';
// If the user does not have permission either in 'user_perms' or 'role_perms' redirect to login, or restricted, etc
if ( !$this->acl->hasPermission($acl_test) ) {
redirect('/login/');
}
Boy george
23 queries?!
Nov 10, 2009 @ 6:23 pm
admin
I’m not sure how you came to 23, but its only 8 queries, and on an average check there should only be 2 queries, one for the Role Permissions, and another for the separate User Permissions
Nov 11, 2009 @ 9:24 am
Piotr Polak
You might consider using cache for efficiency. You could store user rights in a session variable that is refreshed every 5 minutes or store serialized result sets on filesystem.
Jun 08, 2010 @ 1:43 pm
Sergio
This note is to thank you for sharing your port to CI. I just downloaded it and made some minor adjustments. You saved me quite a bit of work.
Seeing the code work put a smile on my face.
Aug 20, 2010 @ 10:43 pm
admin
Agreed, I may adapt the file cache script I recently posted to do just this. Thanks for the tip.
Aug 23, 2010 @ 7:38 am
admin
Your welcome, I figured someone could use some of the stuff I’ve been coding up.
Aug 27, 2010 @ 7:30 pm