Page 2 of 4

Re: ACL and Reflection

Posted: Fri Oct 10, 2008 6:08 pm
by Luke
What I would do is define those two groups as roles:

Code: Select all

$myAcl = new Zend_Acl();
 
$myAcl->addRole(new Zend_Acl_Role('standard')) // standard access
      ->addRole(new Zend_Acl_Role('pro'), 'standard'); // pro inherits standard

Code: Select all

<?php
class PostsController extends BaseController {
 
    public function indexAction() {
 
        switch($this->_user->role) {
            case 'pro':
                $posts = $posts->select()->where('1')->order('post_date', 'asc');
                break;
            default:
                $posts = $posts->select()->where('pro <> 1')->order('post_date', 'asc');
                break;
        }
        $this->view->posts = $posts;
 
    }
 
}

Re: ACL and Reflection

Posted: Fri Oct 10, 2008 6:19 pm
by VladSun
VladSun wrote:... I don't think a Controller, or a Model or a View should have any knowledge of what the current user is permitted to do or not. It's simply out of their scope...
... That's why I think I need the Reflection and a MVC provider class...
RANDOM THOUGHTS ;)

So, I imagine that like having a top level ACL object, which owns ModelProvider, ControllerProvider and ViewProvider objects. Every M-V-C class is instantiated by using these providers, so ACL rules are applied even before creation of M-V-C objects.

A Model should consist of one or more objects (i.e. objUser, objProfile). These objects has some "editable" properties. These properties are ACL-protected by having them in a ProtectedPropertyObject. A ProtectedPropertyObject should deny/allow write/read access to the "real" property according to the ACL.

A View should be a hierarchy of Subview objects created by the ACL ViewProvider. If a subview shouldn't be displayed it's simply not created by the ViewProvider (hm... we need a ViewLayoutManager?).

I think it's needed a user-role-group-everybody schema for defining ACL.

Re: ACL and Reflection

Posted: Fri Oct 10, 2008 6:45 pm
by VladSun
Linux sudo command with its configuration file is much closer to what I'm looking for than the Zend ACL approach.
In sudo config file one can define permission to a specific user(s) to run a command, while keeping control over the arguments passed to this command. The command itself, doesn't know about sudo :)
Also, the setuid() and setgid() functions are in interest for defining temporary role to a user according to some specific data.

The final result, I want to get, is to have M-V-C classes free of "ACL related IFs/SWITCHs" and the whole ACL should be managed only by using the storage layer, without even a single touch to the application layer.

Re: ACL and Reflection

Posted: Fri Oct 10, 2008 7:55 pm
by Luke
I agree that that would be very nice. I just haven't ever been able to accomplish it. I tried pulling out all the ACL and putting it into a plugin, but I failed. This was a compromise I was willing to make.

Re: ACL and Reflection

Posted: Sat Oct 11, 2008 6:56 pm
by josh
http://framework.zend.com/wiki/pages/vi ... geId=39025
may be of interest, I've tried it out and it seems to do everything you mentioned.

Another article on doing more with ACL, http://www.xaprb.com/blog/2006/08/16/ho ... ol-in-sql/

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 9:54 am
by webaddict
VladSun wrote:The final result, I want to get, is to have M-V-C classes free of "ACL related IFs/SWITCHs" and the whole ACL should be managed only by using the storage layer, without even a single touch to the application layer.
That would be great, except that it can not be done. ACL is a cross-cutting concern, which has to interfere in each layer of your application. When saying it's cross-cutting, it means that you'd have to be able to show or hide certain buttons (View), you should block access to certain actions (Controller), and you should not include some results in the resultset (Model).

It's noble to try, but impossible from my point of view.

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 1:40 pm
by inghamn
I'd be interested in seeing a way to ACL with per-field permissions. So far, I'm having to hard code Roles into my controllers and views. Otherwise, asking permitsEditing() on each and every field of a form gets quite tedious.

Here's the code I'm using for a Page Controller for Updating Users

Code: Select all

 
verifyUser(array('Administrator','Clerk'));
 
$user = new User($_REQUEST['user_id']);
 
if (isset($_POST['user']))
{
    # Both clerk and admin can edit these fields
    $fields = array('gender','firstname','lastname','email','address','city',
                    'zipcode','about','race_id','birthdate','phoneNumbers');
 
    # Only the Administrator can edit these fields
    if (userHasRole('Administrator'))
    {
        $fields[] = 'authenticationMethod';
        $fields[] = 'username';
        $fields[] = 'password';
        $fields[] = 'roles';
    }
 
    # Set all the fields they're allowed to edit
    foreach($fields as $field)
    {
        if (isset($_POST['user'][$field]))
        {
            $set = 'set'.ucfirst($field);
            $user->$set($_POST['user'][$field]);
        }
    }
 
    try
    {
        $user->save();
        Header('Location: home.php');
        exit();
    }
    catch (Exception $e) { $_SESSION['errorMessages'][] = $e; }
}
 
$template = new Template();
 
$form = new Block('users/updateUserForm.inc');
$form->user = $user;
$form->return_url = $_REQUEST['return_url'];
$template->blocks[] = $form;
 
echo $template->render();
 
And the top level view:

Code: Select all

 
<h1>Edit <?php echo $this->user->getUsername(); ?></h1>
<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
 
<?php
    if (userHasRole('Administrator'))
    {
        include APPLICATION_HOME.'/blocks/html/users/authenticationFields.inc';
    }
    include APPLICATION_HOME.'/blocks/html/users/personalInfoFields.inc';
    include APPLICATION_HOME.'/blocks/html/users/phoneNumberFields.inc';
?>
 
<fieldset><legend>Submit</legend>
    <input name="user_id" type="hidden" value="<?php echo $this->user->getId(); ?>" />
    <input name="return_url" type="hidden" value="<?php echo View::escape($this->return_url); ?>" />
    <button type="submit" class="submit">Submit</button>
    <a class="cancel button" href="<?php echo View::escape($this->return_url); ?>">Cancel</a>
</fieldset>
</form>
 
Making sure the user can only change the specific fields they're allowed to is a bit tedious. And it seems to has to happen in both the controller and the view. I know this way is not ideal, I just haven't been able to adapt an ACL style approach without a ton more code.

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 8:38 pm
by josh
After reading some of the suggestions you guys posted the one I like best is having each property be accessed through an object that encapsulates field specific ACL rules, I'm going to toy around with the idea of doing something like this for my applications but implementing it as a generic 'data gateway' and having the field specific ACL checks register themselves as hooks to be run pre and post property access, that inverts control and also allows more access checks to be added later besides plain vanilla ACL (in case I think of something later). Not entirely necessary per se to solve the problem but it seems to be the right thing to do to me

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 9:24 pm
by Christopher
I have to admit that I don't really understand what specifically you guys are talking about! ;)
VladSun wrote:In sudo config file one can define permission to a specific user(s) to run a command, while keeping control over the arguments passed to this command. ...
The final result, I want to get, is to have M-V-C classes free of "ACL related IFs/SWITCHs" and the whole ACL should be managed only by using the storage layer, without even a single touch to the application layer.
Vlad starts using the term 'storage' and I am still not sure what he means from the previous discussion.
jshpro2 wrote:... the one I like best is having each property be accessed through an object that encapsulates field specific ACL rules ... implementing it as a generic 'data gateway' and having the field specific ACL checks register themselves as hooks to be run pre and post property access...
The gears in my mind are grinding between 'data gateway', 'field specific ACL checks' and 'hooks to be run pre and post'.

Can you explain these ideas with the standard RBAC terms like User/Subject, Role, Permissions, and Session? I am assuming that any system would be DataSource independent.

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 9:47 pm
by Luke
webaddict wrote:
VladSun wrote:The final result, I want to get, is to have M-V-C classes free of "ACL related IFs/SWITCHs" and the whole ACL should be managed only by using the storage layer, without even a single touch to the application layer.
That would be great, except that it can not be done. ACL is a cross-cutting concern, which has to interfere in each layer of your application. When saying it's cross-cutting, it means that you'd have to be able to show or hide certain buttons (View), you should block access to certain actions (Controller), and you should not include some results in the resultset (Model).

It's noble to try, but impossible from my point of view.
That's exactly the conclusion that I've come to. I have been able to extract most access control code into the controller, but even doing this requires that I make different views for different roles and select different data based on role. All this does happen in my controller though, or above it, in an action helper.

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 10:15 pm
by Christopher
The Ninja Space Goat wrote:I have been able to extract most access control code into the controller, but even doing this requires that I make different views for different roles and select different data based on role. All this does happen in my controller though, or above it, in an action helper.
If Access Control is truly a Cross Cutting Concern, then why don't the View and Model have the same access to the AC object as the Controller. Controllers use the AC info to determine program flow; Views use it to determine what to display; and Models use it to determine what to load and save.

The more I use MVC the more I find that the Model, View and Controller need to have and do most of the same things.

Re: ACL and Reflection

Posted: Mon Oct 13, 2008 11:07 pm
by Luke
I find that they have to do many of the same things, but I wouldn't say most of the same things. It is to be expected that since model, view and controller are where code is mainly separated, you'd notice these certain aspects that seem to be used by all three much more, wouldn't you think?

What specifically are you referring to? I can think of a few aspects of application development that spans all three:

* ACL
* Forms

What else is there?

Re: ACL and Reflection

Posted: Tue Oct 14, 2008 12:36 am
by Christopher
The Ninja Space Goat wrote:What else is there?
Well, in PHP is can be as simple as that they all need to load helper objects. They all can be part of a hierarchy. You mention Access Control -- at least they all need access to the same ACL object. Forms implies validation. You can pre-validate in the client -- so that's the View. You deep validate in the Model, but some people validate in the Controller. And the Controller might do some broad validation to see what kind of request is coming its way and if it is well formed. All might need to filter and escape (though in different ways). I am sure there are more...

Re: ACL and Reflection

Posted: Tue Oct 14, 2008 2:09 am
by webaddict
arborint wrote:
The Ninja Space Goat wrote:All might need to filter and escape (though in different ways). I am sure there are more...
Well, you can add logging to the list, since that is the most common example of cross cutting concerns. Just stating the obvious here: this obviously could be solved by Aspect Oriented Programming. Too bad there isn't a native PHP implementation though.

Re: ACL and Reflection

Posted: Tue Oct 14, 2008 4:51 am
by Christopher
Yes, AOP is one direction. But since we are talking about MVC which is usually off a Front Controller and in a Action Controller then DI is probably the easier way to go.