views:

255

answers:

3

Hi folks, it's my first post, so be gentle!

I'm familiar with a whole bunch of ways to authenticate users for the web-based administration application we're developing, and even various techniques to keep tabs on authorisation...

However, my question to you is, how would you recommend I implement a fine-grained access control mechanism that offers the following:

  1. Users belong to 'roles' or 'groups' such as 'salesperson', 'planning', etc.
  2. The admin menu system shows only 'pages' which have functions relevant to the users role(s)
  3. Specfic functions within those pages have constraints - for example, on the 'new booking' page, 'salesperson' users can issue a booking 'only in the future', and on the 'edit bookings' page can edit bookings 'one week from now'. However, 'planning' users might be allowed to retrospectively book 'up to one week ago' and edit bookings made by themselves for 'any time period', but bookings made by others only 'up until tomorrow'...

I know I can implement a basic role-based system to satisfy no.1... I have a feeling I should split the entire application into code chunks, each with their own objectID-permissionID relationship so that I can scan the database of permissions to see which objects are available - that would help me with no.2.

Any ideas how I might build the form control for example, which for 'sales' users only displays a date in the future (but displays dates up to 'one week ago' for planning users), then somehow pairing that with a line in the POST parser that checks to see if the date is in fact within the expected range?

I've played around with the idea I should save each code chunk to the database, then have an object table which dynamically builds the code according to the permissions table, so that the only 'file' on the server is the db connection file!

Any ideas welcome... (even if your background isn't php/MySQL)

+2  A: 

Warning, a lot of Zend Framework ahead!

You can easily handle 1. and 2. with Zend_Acl and Zend_Navigation .

For number 3 you will have to query the ACL object in your model and do a lot of stuff by hand. You could utilize Zend Framework for the forms as well and include specific form element validators depending on the users role permission.

EDIT:

If you do not feel like going the ZF route you can at least take a look at how the ACL is handled in ZF.

Goran Jurić
Hi Goran, thanks for the suggestion about Zend ACL - I've already ploughed through a lot of the Zend documentation! However, since we'll need to implement our own 'native' approach, I've tried to find examples of how Zend ACL has been integrated within other applications so that we might borrow some ideas... See below for another thought!
boatingcow
A: 

In a bid to implememt a 'native' approach, rather than piggy-backing a framework, I've been playing around with the following. Would anyone rate this approach? Do you foresee any pitfalls?

// Check database for existence of this $user against this $object.
function get_permission($user, $object){
    // Query goes here...
    if( ... ){
     return $permission;
    } else {
     return FALSE;
    }
}

The above function would query the database and output something like this:

// Result of role-object query.  
role_ID      object_ID          permission  
-------      ---------          ----------
salesperson  new_booking_date   'min' => 'now', 'max' => '+1 year'  
planning     new_booking_date   'min' => '-1 week', 'max' => '+1 year'  
salesperson  edit_booking_date  'this_user_min' => 'now', 'this_user_max' => '+1 week', 'other_user_min' => 'now', 'other_user_max' => '+1 week'  
planning     edit_booking_date  'this_user_min' => '-1 week', 'this_user_max' => '+1 year', 'other_user_min' => '-1 week', 'other_user_max' => '+1 week'

The following code in the page containing the form input:

// Draw form control with javascript date validation...
$this_permission = get_permission($this_user, 'new_booking_date');
if($this_permission){
    $html->datepicker('min' => $this_permission['min'], 'max' => $this_permission['max']);
}

After the booking has been made, another page allows us to edit that field:

// Verify POST data...
$this_permission = get_permission($this_user, 'edit_booking_date');
if($this_permission){
    if($this_user == $author_user && $_POST['date'] >= strtotime($this_permission['this_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['this_user_max'], $date_ref)){
     // Update database...
    } elseif($_POST['date'] >= strtotime($this_permission['other_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['other_user_max'], $date_ref)){
     // Update database...
    }
}

Am I on the rigt track?

boatingcow
This seems very much like the ZF acl component with the addition of the permission specification and except that you merge the action and the resource. This way you won't be able to add inheritance to the resources but you don't seem to need that and at the moment I think resource-inheritance is a bad idea anyway.The permissions seem interesting but static. E.i. they are tied to the specific rule.
koen
Something I'm not a fan of is $this_user == $author_user. If I understand your example correctly this is actually a hardcoded rule: access is allowed if the user is the author. Checks like these belong in the acl.
koen
Thanks Koen. As I understand it, I can still add inheritance (since that is a feature I'd be keen to implement) but the sticking point is the 'hardcoded' rule as you mention - normally, I wouldn't mind sticking user flow-control in the code (as it's not strictly authorisation; it's more like authentication...) but I'm keen to know if you had any ideas how I might seperate a rule like this into an ACL? Ta for your input!
boatingcow
A: 

If you want to build real fine-grained access control (FGAC), just check my article on this subject for MySQL :

MySQL 5.0 Fine-Grained Access Control (FGAC)

Basically, you don't want your business code be dependent on the FGAC implementation, you don't want to mix FGAC code in where clause of the select statements of your business rules. This article shows solutions to avoid cluttering of SQL statements.

Jérôme Radix