View Single Post
Old 09-02-2009, 02:16 PM   #2 (permalink)
ioan1k
The Contributor
 
ioan1k's Avatar
 
Join Date: Mar 2009
Location: US
Posts: 76
Thanks: 0
ioan1k is on a distinguished road
Default

ACL lists can be quite simple to use for a basis such as this,

Here is a breakdown of how it works

All pages, widgets, features etc etc .. that you want to limit access would be considered resources

Each usergroup would be considered as roles

It would then be written in a manner such as
Code:
if (role A) can access (resource B)
    grant access
else
    deny access
Here it is in PHP ,

php Code:
class Acl {
   
    /**
     * List of roles
     */

    protected $_roles = array();
   
    /**
     * List of resources
     */

    protected $_resources = array();
   
    /**
     * List of resources with mapping for allowed roles
     */

    protected $_resourceAllow = array();
   
   
    /**
     * Instance sel of resources with mapping for allowed roles
     */

    private static $_instance = null;
   
    const ADMIN = 3;
   
    const USER = 2;
   
    const GUEST = 1;
   
    /*
     * Constructor
     *
     * Add list of roles and resources
     *
     * @param  array  roles            Array of roles
     * @param  array  resources        Array of resources
     * @param  array  resourcesAllow  Array of key => value for resource ID -> role ID allowed maps
     *
     * @return  this
     */

    private function __construct($roles, $resources, $resourceAllow)
    {
       
        if (null == $roles && null == $this->_roles) {
            throw new Exception('You must define the role, resource and allow list for first ACL call');
        }
       
        $this->_roles = $roles;
       
        $this->_resources = $resources;
       
        $this->_resourceAllow = $resourceAllow;
       
        return $this;
    }
   
    /*
     * Returns Instance of ACL
     *
     * First Call must include list of roles, resources and resourcesAllow therafter it is no longer required
     *
     * @param  array  roles            Array of roles
     * @param  array  resources        Array of resources
     * @param  array  resourcesAllow  Array of key => value for resource ID -> role ID allowed maps
     *
     * @return  this
     */

   
    public function getInstance($roles = null, $resources = null, $resourceAllow = null)
    {
        if (self::$_instance == null) {
            self::$_instance = new self();
        }
       
        return self::$_instance;
    }
   
    /*
     * Checks if role has access to resource
     *
     * @param  array  roleID      Name of role
     * @param  array  resource    Name of resource
     *
     * @return boolean
     */

    public function isAllowed($role, $resource)
    {
        // ERROR CHECKING
        if (is_string($role)) {
            $role = array_search($role, $this->_roles);
        }
       
        if (is_string($resource)) {
            $resource = array_search($resource, $this->_resources);
        }
       
        if (!is_int($role)) {
            throw new Exception('isAllowed Role expected integer for role '.gettype($role).' given');
        }
       
        if (!is_int($resource)) {
            throw new Exception('isAllowed Resource expected integer for resource '.gettype($role).' given');
        }
       
        if (!array_key_exists($role, $this->_roles)) {
            throw new Exception('Unknown RoleID given : '.$role);
        }
       
        if (!array_key_exists($resource, $this->_resources)) {
            throw new Exception('Unknown ResourceID given : '.$role);
        }
       
        // NOW FOR PERMISSION CHECKS
        if (!array_key_exists($resource, $this->_resourceAllow))
        {
            // THIS IS WHERE WE COULD SET A DEFAULT ON TO ALLOW OR DENY BASED
            // ON THIS ROLE HAVING NO ACCESS LEVELS DEFINED
           
            return true;
           
        } else {
           
            // HERE WE WILL USE A DESCENDING LEVEL FOR EXAMPLE
            // USERGROUP ROLES ARE ID
            // GUEST 1
            // USER  2
            // ADMIN 3
           
            if (!array_key_exists($role, $this->_resourceAllow[$resource])) {
                // ALLWAYS GRANT ADMIN PERMISSION THIS CAN BE REMOVED
                if ($role == self::ADMIN) {
                    return true;
                } else {
                    // deny
                    return false;
                }
            } else {
               
                // ADMINS HAVE ACCESS TO ALL
                if ($role == self::ADMIN) {
                    return true;
                }
               
                // HERE WE USE A DESCENDING CHECK
                // EVERYONE HAS ACCESS TO GUEST RESOURCES
               
                if (in_array($role, $this->_resourceAllow[$resource]) || ($role >= self::GUEST && count($this->_resourceAllow[$resource]) == 1 && $this->_resourceAllow[$resource][0] == self::GUEST) {
                    return true;
                }
               
                return true;
            }
        }
    }
}

To use this you would do the following

Have a 3 mysql tables that contain the following, assuming you already have the usergroup table you would need the following two

resources
----------------------------------------
resourceId name

resourcesAllow
----------------------------------------
resourceId roleId

Map the role that are allowed to view each resource

Example for roles

roles
------------------------------------------
roleId name


For the first call to the ACL you would do the following

php Code:
// GET ROLES
$sql = mysql_query('SELECT roleId, name FROM roles');
$roles = array();
while ($v = mysql_fetch_assoc($roles)) {
    $roles[$v['roleId']] = $v;
}
$sql = null;

// GET RESOURCES
$sql = mysql_query('SELECT resourceId, name FROM resource');
$resource = array();
while ($v = mysql_fetch_assoc($roles)) {
    $roles[$v['resourceId']] = $v;
}
$sql = null;

// GET LIST OF PERMISSIONs

$perm = array();
$sql = mysql_query('SELECT * FROM resourcesAllow');
while ($v = mysql_fetch_assoc($roles)) {
    if (array_key_exists($v['resourceId'])) {
        $perm[$v['resourceId']][] = $v['roleId'];
    } else {
        $perm[$v['resourceId']] = array();
    }
}

// INIT
$acl = Acl::getInstance($roles, $resource, $perm);

// CHECK EPRMISSION
if ($acl->isAllowed($user->groupId, 'contact_me_page')) {
    // do stuff
} else {
    // no access
}

There after it would only be
php Code:
$acl = Acl::getInstance();

// CHECK EPRMISSION
if ($acl->isAllowed($user->groupId, 'contact_me_page')) {
    // do stuff
} else {
    // no access
}

This is a very basic ACL ....

Adding a removing resources, permissions would be quite simple through the administration and users could even create their own :)

Hope this get u on a good start
__________________
My Portfolio - Work - Need freelance Work?
I've been developing 5 years now, and I learn something new everyday
ioan1k is offline  
Reply With Quote
The Following 2 Users Say Thank You to ioan1k For This Useful Post:
gamer13 (09-02-2009), Tanax (09-02-2009)