TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Release(s): A1 - Authentication, ACL - ACL for Kohana, A2 - Object-Level Authorization
  • http://github.com/Wouterrr/ (edit 16 Oct 09 - Link updated)

    - A1: Authentication -

    Similar to Kohana's AUTH and Fred Wu's AUTHLITE (http://forum.kohanaphp.com/comments.php?DiscussionID=1909&page=1). I wrote this when I was working on the other libraries and I needed an AUTH lib without roles. Not too much new here :).


    - ACL : ACL for Kohana -

    I rewrote the Zend_ACL lib for Kohana (if you just want a port of Zend_ACL, keep on reading too :)), with the following changes:
    1) The ACL definition is stored using the string IDs of the roles/resources. Not the role/resource objects themselves. Adding a role is as simple as $acl->add_role('user') (and NOT $acl->add(new Zend_Acl_Role('user')).
    2) When using assertions, the assert objects will have access to the objects you pass in the ->allowed method call. If you define $acl->allow('user','blog','read',new User_Blog_Assert) and run $acl->is_allowed($user,$blog,'read'), the assert method of User_Blog_Assert will have access to the $user object and the $blog object. This was essential for me to develop object-level authorization (see A2, this wasn't the case with Zend_ACL).
    3) I did not port all methods yet (let me know if you need any), and I underscored the methods instead of Zend's camelCasing.
    4) It's way smaller than Zend_ACL, but very similar to anyone familiar with Zend_ACL
    $acl = new ACL;
    $acl->add_role('guest')
    $acl->add_role('user','guest');
    $acl->add_resource('blog');
    $acl->allow('guest','blog','read');
    $acl->allow('user','blog','add');
    $acl->allow('user','blog','edit',new User_Blog_Assert); //User_Blog_Assert verifies if the user is the owner of the blog-article

    $blog = ORM::factory('blog',23);

    // can a guest read the blog
    $acl->is_allowed('guest','blog','read');
    $acl->is_allowed('guest',$blog,'read'); //same result

    // can the user edit a certain blog article - this is made easier with the A2 library (see below)
    if($user = Auth::instance()->get_user())
    {
    if($acl->is_allowed($user,$blog,'edit'))
    {
    // edit blog


    - A2: Object-Level Authorization -
    The A2 library offers authorization on object level. You can allow and deny access not only to 'areas' of your website (like a membersarea), but also to objects (eg members can only edit articles they wrote, and members of a certain project can only view articles of that certain project. Project-administrators can add and remove members to their projects, but not to others etc). A2 is useful in large applications where you're dealing with multiple accounts with several users per account. You can define the full ACL in a single config file, and with a proper specified ACL each user will only have access to the areas AND objects they're supposed to.

    A2 library is compatible with any Authentication lib that supports a get_user method as long as the user returned implements Acl_Role_Interface.

    The usage is very easy, in your controller/model/library (depending on the context)
    if( ! A2::instance()->allowed($blog,'delete'))
    die('not allowed to delete this blog')


    You do not have to pass a $user object, nor do you have to check if a user is logged in. This is done within A2.

    - Demos -
    I don't have access to a host, but I wrote a demo for just the ACL lib (it's offered together with a Kohana port of the Zend_ACL lib, so you can see AND try for yourself if the functionality is exactly the same), and I wrote a demo for the A2 lib (which uses A1 and ACL).

    I tried to set up a repository at Github. I'm new to this, so hopefully I won't make any mistakes in the future, but it's available here:
    http://github.com/Wouterrr/

    Please let me know what you think of it!! All suggestions are welcome!

    Note: I'm using the Kohana 2.4/3.0 (??) directory structure, if you're still in the current directory structure, you might have to move some files around and rename some files.
  • Nice work Wouter! I'm going to check 'em out. :)
  • The ACL implementation looks great. I hope to see this integrated into Kohana Auth in some way. Thanks for sharing!

  • At first inspection this seems to be much better than Zend_Acl for Kohana users and should come in handy down the road. Thanks for sharing your work!

  • @Wouter this is tremendous work and hopefully will be the basis of the recommendations I am putting forward for Kohana 2.4. I will be in touch shortly to discuss this further.

    Excellent work.
  • Your OLA is a wonderful addition and a great starting point for people wishing to use Kohana for more complex multi user requirements. For myself this will be a chance to compare my recent authorization module work to that of someone more versed with Kohana. Thank you very much for taking the time to release this to the community.
  • Thanks guys, it's great to read all your positive comments. Suggestions are always welcome, so let me know if you see room for improvement.
  • Thanks for this Wouter. Is there any official name for these plugins all working together? Like Wouter ACL 3?
  • Well, A1 and A2 are shorthands for Authentication (A1) and Authorization (A2) (Something I found on wikipedia :)). The latter is called A2 because you can only authorize people if you know who they are (so authentication is first, and only then authorization).

    A1 is for authentication, and ACL is for access control. They come together in A2 - object level authorization. So I guess A2 is the name for the libraries working together, although I like any name with my name in it better of course :).
  • great work Wouter, thanks a lot for this!
  • Hi.
    Could someone please help me installing A1 && A2. Sorry for not being able to do this myself.

    Regards,
    Dmitry.
  • Did you look at the demo files in the repository?!

    For A1, you should build your own User_Model (an a users table in the DB) and indicate the name of the model, and the name of a some columns of the model, in the config file of A1.

    Besides, what version of Kohana are you using?! The files currently in the repository are suitable for the proposed directory structure of Kohana. Using them in the old directory structure requires some renaming.
  • really nice work Wouter.

    So this should work with the pre_3.0 version right?
  • Yup, that's the one. I'm not sure when the next version of Kohana is launched, but that should make implementation of my libraries a bit easier for the average user not aware of pre_3.0 etc.
  • Is it possible for you to create a 2.x version? The vast majority of users are going to be on this, not an unstable 3.0.

  • @zombor I'm already create a port based on Wouters work and an interpretation of the Zend ACL library (as Wouter did). This is my submission for Auth for 2.4
  • @samsoir, are your files hosted somewhere?
  • New Auth library in 2.4! This is getting very interesting :)
  • New Auth library in 2.4!

    I think he means compatible with 2.4. We plan on moving all non-core functionality to the modules site, and marking some modules with a "Kohana Approved" tag or something.

  • @zombor: I like the idea showing "Kohana Approved" for certain actively maintained modules. That is similar to what that the Drupal community is trying to do now with the massive number of contributed modules (and is something that Acquia is doing as well in their role as a semi-official paid support provider). Having and promoting modules which are actively supported by the community allows us to remove them from core (allowing there to exist multiple Auth modules, or multiple Form handling modules, etc) while still providing new-comers to the community with the peace of mind that these types of modules are available and are being actively maintained.

    Again, great work to you and those involved in getting up the new projects site.
  • Waiting for 2.x version :(
    I dont know what to do with ACL classes (assert/resource/role) - where they should be classified in 2.3.1
  • @Wouter not yet, will be putting my work into Kohana Projects. Not going to yet though as I'm am evaluating how different the 2.3.x approach is going to be to your 3.0 approach.
  • @biakaveron: try this

    1) create a folder 'acl' in your modules folder and add the acl module in your application's config.php
    2) create a folder libraries in acl
    3) add all files to this folder (no subdirectories!)
    4) look at all filenames and name the files appropriately:
    Class Acl --> Acl.php (no change)
    Interface Acl_Assert_Interface -> Acl_Assert_Interface.php (was Acl/Assert/Interface.php)
    etc

    I think this should work.

    Good luck
  • @Wouter
    Thank you! Demo works.

    PS. In demo controller Zend classes also must be included, so i copied them to the libraries too.
  • Please note that the Zend classes are ONLY used in the demo to show compare my ACL to Zend_ACL (both should return the same results, which they do in the test cases in the demo controller). There's no need to retain the Zend_ACL classes for anything else if you want to use my ACL implementation.
  • @Wouter
    Yes, of course! :)

    Also, in 2.3.1 there is no Validation rule named 'equals' and 'matches' means another function... By the way i think it will be better to add role 'user' by default at registration (roles must be managed in some kind of admin panel).
    And in create() method must be input->post() checking (because anyway system tries to validate $_POST variable).

    PS. I understand that it is only a demo, but...
    PPS. My english is very bad, i know ;)
  • My variant for 2.x.

    Changes:

    1. Directory structure and class names allow 2.x rules
    2. Zend library and acldemo were excluded.
    3. Some changes in a2demo at registration ('user' role assigns automatically, additional post checking added).
    4. Correcting rules in User_Model->validate(), because Validation rules v2.3 and 3.0 are different.
  • Please note the A1 lib allows you to create your own user model. Just specify the name of the model and the names of some columns (the ones used for username, password etc) in the a1 config file and you can use whatever user model your app needs. (a nice feature I learned about when I was looking at Fred Wu's Authlite).

    So the demo user model is just one possibility.
  • @Wouter
    Yes, customizable model name and column names thats cool
  • I've updated biakaveron's 2.x version:

    1. Included acldemo and required Zend files.
    2. a2demo no longer assigns role - you can choose just like Wouter's version. Links have been lowercased - 404 otherwise/
    3. User_Model->validate() now checks role again using in_array.
  • Hi, I was trying to download the update to biakaveron's 2.x variant of Wouter's ACL for Kohana and I can't get the link to work, it just redirects to the filedropper homepage. I was wondering if it's available anywhere else?
  • @Bockit I didn't realise that filedropper would remove it after a while. It's on my desktop which is packed up at the moment but I should be able to re-upload sometime this weekend.
  • Thanks :)
  • Wouter any chance you could add a 2.3.x compatible version to the projects page? I don't think very many people use Kohana pre_3.0 and saying "Compatible Kohana Version: 2.3.x" (when it's only pre_3.0 compatible) leads to a lot of confusion.

    Thanks!
  • Link 1
    Link 2

    Works with Kohana 2.3.x
  • @Isaiah:

    Done @ http://github.com/Wouterrr/kohanamodules2.3.2/tree/master (I updated the projects page too)

    I haven't made a single change to the source code itself, I only moved the files of the pre_3.0 version around and renamed them so the became compatible with Kohana 2.3.2.
  • Error in 2.3.2 version, file a1/libraries/A1.php, lines 128—136:

    if(isset($this->config['last_login']))
    {
    $user->{$this->config['last_login']} = time();
    }

    if(isset($this->config['logins']))
    {
    $user->{$this->config['logins']}++;
    }

    must be replaced with folow:

    if(isset($this->columns['last_login']))
    {
    $user->{$this->columns['last_login']} = time();
    }

    if(isset($this->columns['logins']))
    {
    $user->{$this->columns['logins']}++;
    }
  • You're right! Thanks I'll update it right now.
  • Also, in acl.php

    line 160:
    $role = $role->get_resource_id();


    should be:
    $role = $role->get_role_id();
  • Thanks, it's fixed now.
  • @ Wouter
    I think the links in the a2demo controller need to be lowercase otherwise you get a 404. Can you fix this in your 2.3.2 version?
    Is your a2-acl-demo folder meant to be a module or should you copy the files to the right places in the application folder?
  • Thanks for letting me know, I'm working/testing under Windows and I didn't get the 404s. Anyway, it should be fixed now! :-)

    a2-acl-demo is a separate module because I wanted to separate the libraries (= production code) from the demo (non production) code. It keeps the A1/A2/ACL directories nice & clean. Just a personal preference :-). (a2-acl-demo works perfectly as a module, so no need to move files around)

    It's the same with the libraries. Each lib is stored in its own module. Just for flexibility. Someone might only want to use A1 for Authorization, someone else might only want to use ACL, and someone might want to use A2 with Kohana's AUTH module. Of course, you can always move files around if it somehow suits your configuration better :-).
  • Thanks Wouter.
    Now this is really weird....

    I have to name the class A2demo_Controller (not A2Demo_Controller) otherwise I get a recoverable error message:

    /nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/acl/libraries/Acl.php [109]:

    Argument 4 passed to Acl::allow() must be an instance of Acl_Assert_Interface, instance of __PHP_Incomplete_Class given, called in /nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/a2/libraries/A2.php on line 106 and defined


    All the files are there and correct - it only works when I change the class name. Weird?

    Edit: I don't think it's the class name as it's happening when it's named A2demo_Controller as well now...
  • Hmm I'm gonna check it out and make it work, give me a minute :).

    I never actually tried to demo controller when I ported it back from the pre_v3.0 directory structure to the kohana 2.3.2 directory structure, I tried to run it just now and it doesn't work :-)

    Edit: There were some errors in the 2.3.2 version running under a clean Kohana install. I updated it and it now works fine (under windows). Please let me know if you run into errors (and then please copy the full error in this thread).

  • Recoverable Error
    An error was detected which prevented the loading of this page. If this problem persists, please contact the website administrator.

    >/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/acl/libraries/Acl.php [109]:

    Argument 4 passed to Acl::allow() must be an instance of Acl_Assert_Interface, instance of __PHP_Incomplete_Class given, called in /nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/a2/libraries/A2.php on line 106 and defined
    Stack Trace
    >/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/a2/libraries/A2.php [106]:
    Acl->allow( user, blog, edit, __PHP_Incomplete_Class Object
    (
    [__PHP_Incomplete_Class_Name] => Acl_Assert_Argument
    [arguments:protected] => Array
    (
    [primary_key_value] => user_id
    )

    )
    )>/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/a2/libraries/A2.php [56]:
    A2->__construct( a2 )>/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/modules/a2-acl-demo/controllers/a2demo.php [9]:
    A2::instance( )A2demo_Controller->__construct( )>/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/system/core/Kohana.php [235]:
    ReflectionClass->newInstance( )Kohana::instance( )>/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/system/core/Event.php [209]:
    call_user_func( Array
    (
    [0] => Kohana
    [1] => instance
    )
    )>/nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/system/core/Bootstrap.php [55]:
    Event::run( system.execute )>index.php [106]:
    require( /nfs/c04/h02/mnt/63866/domains/mydomain.com/kohana2_3_2/system/core/Bootstrap.php )Loaded in 0.0190 seconds, using 1.37MB of memory. Generated by Kohana v2.3.2.


    I'm still getting the errors with a new download from GitHub. It's running on Linux at mediatemple. From what I gather __PHP_Incomplete_Class is caused by unserialize?
  • I'm sorry but I can't replicate the error. I tried the demo on an Ubuntu box without any errors.

    Honestly, I don't even understand the error. I looked online, and the __PHP_Incomplete_Class error is thrown when a serialized object is unserialized and the class of the object cannot be found, but in a2demo, first of all, no (un)serialization takes place and secondly, the required class (Acl_Assert_Interface) can be found by Kohana's Autoloader...

    If you feel like diving into the code, the error you're getting is caused by a Assert object that is specified in the a2/config/config.php (line 51) (if you remove the assertion part, everybody can edit all blogs (instead of just their own) but you can at least see if it runs without the Assert).
  • I think I've worked it out. Basically it's to do with config file caching - turned it off and it magically worked! That maybe worth noting somewhere for people who use it in future.

    Nick
  • Hmm you're right, good catch!

    I suspect Kohana's Autoloader isn't available when the cached configuration is unserialized. I will have to rethink the way assertions are defined.

    Edit: Ok, I changed the config files so they never contain any objects. I also moved some config data around (some demo data wasn't located in the demo folder).

    No more incomplete_class errors, thanks for your help. :-)
  • Hello, Wouter!
    I have a problem with your great A2 library.
    config:

    $config['roles'] = array
    (
    'user' => 'guest',
    'admin' => 'user'
    );

    $config['guest_role'] = 'guest';

    $config['resources'] = array
    (
    'text' => NULL,
    'category' => NULL,
    'post' => 'text',
    'comment' => 'text',
    );

    $config['rules'] = array
    (
    'allow' => array
    (
    array('guest', null, 'read'),
    array('user','text','create'),
    array('admin',null,null),
    array('user', 'post', 'update', array('Acl_Assert_Argument', array('primary_key_value'=>'author_id'))),
    ),
    'deny' => array
    (
    // no deny rules in this example
    )
    );

    When I try A2::instance()->is_allowed('guest', 'post', 'create'), the warning shows:
    Illegal offset type in isset or empty in Acl.php at line 288.
    As I can see, isset($attach['byRoleId'][$role]) returns TRUE, but there is no 'guest' key in $attach array...
    Thanks for support.

    Update. I caught the same warnings with 'user' role. I understand that this is due to the inheritance of resources (post & comment) from the basic (text). When I define them as free resources (w/o parents) all of resources and actions seems work for guest correctly, but for its inherited roles warnings still showing.
  • After updating module with your last commit there is only one error, when I check rules with assert (in my example its a 'user+post+update' combination). As I understand, Acl_Assert_Argument->assert(Acl $acl, $role = null, $resource = null, $privilege = null) method is waiting for $role and $resource as objects, not as strings. So when I call $a2->is_allowed('user', 'post', 'update') I caught an error in Acl_Assert_Argument.php [line 28].
  • Hmm, I did reply to your previous post, but my reply is gone now, good thing you found out I fixed the error, but strange thing that my reply is gone..

    Anyway if you use assertions, you need to supply the actual role object (usually the user) and the resource object, because the assertion does nothing else than checking if the primary key value of the role object is the same as the author_ID of the resource object.

    Please note that although it is completely OK to use the is_allowed($role,$resource,$privilege) method, A2 also provides an allowed($resource,$privilege) method, this method automatically fetches the user from the Authetication library (A1/AUTH/whatever you've specified in your a2 config file). Your code could look like this:
    class Post_controller {
    (....)
    public fuction update($post_id)
    {
    $post = ORM::factory($post,$post_id);
    if(!A2::instance()->allowed($post,'update'))
    die('you are not allowed to update this blog');

    if($post->validate($_POST,true))
    {
    // post updated
    }
    else
    {
    // post not updated
    }
    }
    (...)


    Remember that your Post_Model should implemet ACL_Resource_Interface, for example (if you use ORM) it could look something like this:
    class Post_Model extends ORM implements ACL_Resource_Interface {

    //protected $has_one etc

    public function get_resource_id()
    {
    return 'post';
    }

    }

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion