CodeIgniter Forums
Which is best for ACL? - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forum-20.html)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forum-22.html)
+--- Thread: Which is best for ACL? (/thread-3066.html)



Which is best for ACL? - El Forum - 09-07-2007

[eluser]Kemik[/eluser]
Hello,

I'm creating a fairly complicated user system. A user can be one of the following, with each group given different permissions.

Admin Groups
Site Admin (root)
General Admin
News Admin
Competition Admin
Referee
Site User

Users and admins can also be a member of a clan (aka team)

Clan Permissions
Clan Leader (all clan permissions)
Clan Member
Manage Applications
Manage Fixtures
User awaiting member approval

E.g. Bill is clan leader and has access to all clan actions. Bob is a clan member with the ability to manage applications. Fred is a clan member with both manage applications and manage fixtures.

As you can see, it's sort of a two tier permission system. A user can only be one of the "Admin Groups" but can also (optionally) be one of the "Clan Permissions".

Which library do you feel would be best to manage this kind of system? I don't need the frontend area for users/admins to edit details as I've already created that. Just need something that manages the database side of things and I can do to check if the user has the permission to do the action.

Thanks for your help.


Which is best for ACL? - El Forum - 09-07-2007

[eluser]alpar[/eluser]
i don't think that you can find such a library out of the box, and for such relations i think your better off yourself. Feel free to post you questions here, and i (we) am glad to help. I think that most important is how you store the access levels.


Which is best for ACL? - El Forum - 09-07-2007

[eluser]Kemik[/eluser]
Well thats the thing. I don't have a clue how to lay this out. It's not as easy as giving a user a role_id (user, admin or news editor) as they can be one of them, PLUS a rank in a clan.

I could add the role to the clan_members entry for the user, but it's even more to add to the session, and without forcing the user to logout and log back in, I'm not sure how to force the session to refresh.

This is pretty complicated Sad


Which is best for ACL? - El Forum - 09-07-2007

[eluser]Rick Jolly[/eluser]
Check out the Zend Framework ACL. Even if you don't use it, you might get some ideas. Although, it is easy to integrate into CI.

It looks to me that you have roles (admin roles and clan roles) and resources (application, fixtures). The Zend ACL covers roles and allows you to easily assign resources to those roles. You'll find that the Zend ACL's use of inheritance greatly simplifies authorization.


Which is best for ACL? - El Forum - 09-07-2007

[eluser]Kemik[/eluser]
The ability to assign users to multiple groups is interesting, and common sense. I'm not sure why I didn't think of that.

I'm not sure, because it's a whole other framework and because permission checks on are on every page, it would be viable to implement Zend Framework to my application. If it is possible with minimal overhead then please let me know, because I'd hate to have to code it myself and have wasted time.


Which is best for ACL? - El Forum - 09-07-2007

[eluser]Rick Jolly[/eluser]
There isn't much to integrating the Zend Framework components. You might find other bits of it useful as well. You can integrate other "packaged" classes like PEAR in the same way.

1) download the Zend Framework
2) put it somewhere within your CI application naming it "Zend". I put it in a folder called "Zend" within my libraries folder.
3) set your include path to the folder in which you dropped "Zend". I did this in config.php since that is always loaded:
Code:
ini_set('include_path',ini_get('include_path'). PATH_SEPARATOR . APPPATH . '/libraries/');

4) Require/include the classes you need and use it. Here is working example similar to that in the zend acl documentation:
Code:
require_once(APPPATH . '/libraries/Zend/Acl.php');
require_once(APPPATH . '/libraries/Zend/Acl/Role.php');
require_once(APPPATH . '/libraries/Zend/Acl/Resource.php');

class SomeController extends Controller
{
    function index()
    {
    $acl = new Zend_Acl();
        
    $acl->addRole(new Zend_Acl_Role('guest'));
    $acl->addRole(new Zend_Acl_Role('member'));
    $acl->addRole(new Zend_Acl_Role('admin'));
        
    $parents = array('guest', 'member', 'admin');
        
    $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
        
    $acl->add(new Zend_Acl_Resource('someResource'));
    $acl->deny('guest', 'someResource');
    $acl->allow('member', 'someResource');
        
    echo ($acl->isAllowed('guest', 'someResource') ? 'allowed' : 'denied');
    }
}



Which is best for ACL? - El Forum - 09-08-2007

[eluser]esra[/eluser]
The phpGACL library by Mike Benoit is a another solution but it is dependent on the ADODB database abstraction layer. Earlier someone was attempting to port this over to CI by adapting the ADODB calls to CI database calls. CI syntax and ADODB syntax are similar. phpGACL uses nested sets, so understanding their code requires some knowledge of the nested sets model. phpGACL supports AXO objects which should allow you to support just about any kind of authorization, including access to various kinds of content.

There is a RBAC solution with code posted on the web at sqlrecipes.com that appears to be extremely versatile. I started to port this over some time ago, but the project fell to the wayside because of other priorities. Aside from supporting role and permissions objects, this project also supports domain objects which are somewhat compatible to phpGACL AXO objects (in a RBAC way of thinking).

Rick's solution also looks interesting. You might note that Zend also had a proposed phpGACL solution sitting in hibernation for a while and it was abandoned because of Zend ACL. However, you might be able to find some information there about it hidden in the bowels of the Zend wiki or in mailing list threads.


Which is best for ACL? - El Forum - 09-08-2007

[eluser]Kemik[/eluser]
I had a look at the Zend ACL last night but the documentation isn't the best in the world. How would you store the roles? You coulpdn't have them being added every time a user visits page.

There's no mention of how you'd store them in the database and then pull them. No mention of linking them to a user.

In the documentation they query the roles, but use the role names. Why would you want to do this? I'd want to query with the username to see if they have access. Why did I have to choose such a complicated application Sad


Which is best for ACL? - El Forum - 09-08-2007

[eluser]esra[/eluser]
I have not taken a close look at the Zend ACL code, but you should be able to adapt it to use database tables. Rather than creating roles and permissions in the controller, you would have to handle this in your database schema. You might be able to find some Zend mailing list threads where this is discussed.

To minimize controller code (better code reuse and better performance), you might think about using a factory (based on the factory design pattern) composed of get/set methods (&getSession;, &getUser;, &getRoles;, &getPermissions;, etc.). A factory class delegates resposibilities to other libraries without loading them until they are called. You could load the factory as a single library in your application controller (base controller) without loading the delegated libraries directly. The factory Get methods create an instance of the library objects, calling the delegated libraries only when necessary. Set methods called by the Get methods in the factory could handle your database queries.


Which is best for ACL? - El Forum - 09-08-2007

[eluser]Rick Jolly[/eluser]
[quote author="Kemik" date="1189273173"]I had a look at the Zend ACL last night but the documentation isn't the best in the world.
[/quote]
Yep, they miss some important pieces. IMO they document the ACL well, but they don't show complete examples using the session and database user/roles. However, for simple sites all you'd need is the username of the authenticated user from the session. See this line from the previous example:
Code:
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);
'someUser' is assigned an array of roles in $parents.

Quote:How would you store the roles? You coulpdn't have them being added every time a user visits page.
Well using the simplest setup, you'd have the roles/resources defined in one script (probably within a library) and added whenever a user is visits a page that requires authorization. So you could add your custom ACL wrapper library to the constructor of every controller that requires authorization. Then in each controller, you'd only have to do your tests like:
Code:
if ($this->acl->isAllowed($_SESSION['username'], 'someResource'))
{
   // do something
}

Quote:There's no mention of how you'd store them in the database and then pull them. No mention of linking them to a user.
This is where the documentation doesn't go far enough. If you have roles stored in the database you'd want something more than the example above provides.

In my database I'd have a user table and a user_role table. Of course the user table has username and password and that is used for authentication. Once the user is authenticated, I'd load that user's role(s) from the user_role table into the session. Then you'd check the ACL using the user's role from the session. Now, if a user has an array of roles in the session, of course you'd have to iterate over them. This could be automated in a method of your custom ACL library.

If you want to take it a step further and totally build your ACL from the database, there are some examples out there.
Quote:In the documentation they query the roles, but use the role names. Why would you want to do this? I'd want to query with the username to see if they have access. Why did I have to choose such a complicated application Sad
See the example above where a username is treated like a role and it is assigned roles.