It happened to me just now to write a dynamic system of roles and rights for an online store.
Since
I didn’t find anything on the Internet except for
this series of articles, I thought of writing everything myself.
So let's get started.
Base
Store information about roles, resources and access rights, we will be in the database. The base has approximately the following structure:
acl_resources - resources
acl_roles are user groups, they are roles
acl_cross - the intersection of matching roles and resources:
id / role_id / res_id
1 1 1
2 1 2
3 1 3
')
* Resources 1,2,3 are available for the role with id = 1
ACL
In the file with access control, we write the following code:
class Acl extends Zend_Acl
{
public function __construct ()
{
$ model = new User ();
/ **
* add resources
* /
// get resources
$ resources = $ model-> getResources ();
foreach ($ resources as $ mod)
{
// if such resource has not been added yet
if (false == $ this-> has ($ mod ['module'] .'_ '. $ mod [' controller ']))
{
// add
$ this-> add (new Zend_Acl_Resource ($ mod ['module'] .'_ '. $ mod [' controller ']));
}
}
/ **
* add user roles
* and immediately give permission to them
* /
// get the role
$ roles = $ model-> getRoles ();
// for each role
foreach ($ roles as $ role)
{
// make an addition
$ this-> addRole (new Zend_Acl_Role ($ role ['name']));
// get resources available for this role
$ permissions = $ model-> getRoleResources ($ role ['id']);
// set permissions for these resources
foreach ($ permissions as $ perm)
{
$ this-> allow ($ role ['name'],
$ perm ['module'] .'_ '. $ perm [' controller '],
$ perm ['action']);
}
}
}
}
Thus we process records from the database and create, in fact, ACL.
Plugin
Next we transfer control to the plugin. The plugin will handle permissions at the controller level. Well, this is, for example, if a regular user copied a moderator link to the action of deleting a product - so that it would not be allowed. Here is an example code:
class Lord_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
private $ _acl = null;
public function __construct (Zend_Acl $ acl)
{
$ this -> _ acl = $ acl;
}
public function preDispatch (Zend_Controller_Request_Abstract $ request)
{
// Get the Zend_Layout object
$ layout = Zend_Layout :: getMvcInstance ();
// Get the view object
$ view = $ layout-> getView ();
$ auth = Zend_Auth :: getInstance ();
// if there is any user in session storage
if ($ auth-> hasIdentity () == true)
{
// get this user data
$ user = $ auth-> getIdentity ();
$ userModel = new User ();
$ role = $ userModel-> getRole ($ user-> role);
$ user-> roleName = $ role-> name;
}
else
{
$ user-> roleName = 'anon';
}
// put in a view variable to display
$ view-> user = $ user;
/ * ------------------------------------------------ -------------- * /
$ request = $ this-> getRequest ();
$ controller = $ request-> getControllerName ();
$ module = $ request-> getModuleName ();
$ action = $ request-> getActionName ();
$ acl = new Acl ();
$ isAllow = $ acl-> isAllowed ($ user-> roleName, $ module .'_ '. $ controller, $ action);
if ($ isAllow == false)
{
$ request-> setModuleName ('user')
-> setControllerName ('login')
-> setActionName ('index');
}
$ view-> acl = $ acl;
/ * ------------------------------------------------ -------------- * /
}
}
Viewhelper
Now we need to hide and show controls at the level of the application view. To do this, we will write a helper, which would check the access rights and show or not show the control:
class Lord_View_Helper_Acl
{
public function Acl ($ module = 'default',
$ controller = 'index',
$ action = 'index')
{
// Get the Zend_Layout object
$ layout = Zend_Layout :: getMvcInstance ();
// Get the view object
$ view = $ layout-> getView ();
$ acl = new Acl ();
$ isAllow = $ acl-> isAllowed ($ view-> user-> roleName, $ module .'_ '. $ controller, $ action);
if ($ isAllow == false)
{
return false;
}
else
return true;
}
}
After writing the helper in the view script, we just need to write something like this to hide or show the control:
<? if ($ this-> acl ('store', 'categories', 'add') == true):?>
<img src = "<? = $ this-> imagesUrl?> icons / icon_add.png"
title = "<? = $ this-> translate ('store_category_primary_add');?>">
<? endif;?>
As a result, we have a system that from the web interface can distribute rights to any group on any module / controller / action.
Some download code:
-
Base-
Plugin-
ViewHelper-
ACL