
Dynamic Roles and Rights
It happened to me a while ago to write a dynamic system of roles and rights for an online store.
Since I did not find anything on the Internet, except for this series of articles, I decided to write everything myself.
So let's get started.
We will store information about roles, resources and access rights in the database. The database has approximately the following structure:
acl_resources - resources
acl_roles - groups of usernames, they are also roles
acl_cross - the intersection of correspondence between roles and resources:
id / role_id / res_id
1 1 1
2 1 2
3 1 3
* For a role with id = 1, resources 1 are available , 2,3
We will write the following code in the access control file:
class Acl extends Zend_Acl
{
public function __construct ()
{
$ model = new User ();
/ **
* add resources
* /
// get resources
$ resources = $ model-> getResources ();
foreach ($ resources as $ mod)
{
// if no such resource has yet been added
if (false == $ this-> has ($ mod ['module'] .'_ '. $ mod [' controller ']))
{
// add
$ this-> add (new Zend_Acl_Resource ($ mod ['module'] .'_ '. $ mod [' controller ']));
// get the roles
$ roles = $ model-> getRoles ();
// for each role
foreach ($ roles as $ role)
{
// add
$ this-> addRole (new Zend_Acl_Role ($ role ['name']));
// get the resources available for this role
$ permissions = $ model-> getRoleResources ($ role ['id']);
// put permissions on 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 the ACL itself.
Next we transfer control to the plugin. The plugin will process access rights at the controller level. Well, this, 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 sample 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 an object of the form
$ view = $ layout-> getView ();
$ auth = Zend_Auth :: getInstance ();
// if there is any user in the session repository
if ($ auth-> hasIdentity () == true)
{
// get this user's 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->
$ acl = new Acl ();
$ isAllow = $ acl-> isAllowed ($ user-> roleName, $ module .'_ '. $ controller, $ action);
if ($ isAllow == false)
{
$ request-> setModuleName ('user')
-> setControllerName ('login')
-> setActionName ('index');
}
$ view-> acl = $ acl;
/ * ------------------------------------------------ -------------- * /
}
}
Now we need to hide and show controls at the application view level. To do this, we will write a helper that checks access rights and shows or does not show the control:
class Lord_View_Helper_Acl
{
public function Acl ($ module = 'default',
$ controller = 'index',
$ action = 'index')
{
// We
get the Zend_Layout object $ layout = Zend_Layout :: getMvcInstance ();
// Get an object of the form
$ 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 a helper in a view script, it’s enough for us to write something like this to hide or show the control:
acl ('store', 'categories',' add ') == true):?>
Title = " translate (' store_category_primary_add ');?> ">
As a result, we have a system that from the web interface can distribute rights to any group on any module / controller / action.
A bit of code to download:
- Base
- Plugin
- ViewHelper
- ACL
Since I did not find anything on the Internet, except for this series of articles, I decided to write everything myself.
So let's get started.
Base
We will store information about roles, resources and access rights in the database. The database has approximately the following structure:
acl_resources - resources
acl_roles - groups of usernames, they are also roles
acl_cross - the intersection of correspondence between roles and resources:
id / role_id / res_id
1 1 1
2 1 2
3 1 3
* For a role with id = 1, resources 1 are available , 2,3
ACL
We will write the following code in the access control file:
class Acl extends Zend_Acl
{
public function __construct ()
{
$ model = new User ();
/ **
* add resources
* /
// get resources
$ resources = $ model-> getResources ();
foreach ($ resources as $ mod)
{
// if no such resource has yet been added
if (false == $ this-> has ($ mod ['module'] .'_ '. $ mod [' controller ']))
{
// add
$ this-> add (new Zend_Acl_Resource ($ mod ['module'] .'_ '. $ mod [' controller ']));
// get the roles
$ roles = $ model-> getRoles ();
// for each role
foreach ($ roles as $ role)
{
// add
$ this-> addRole (new Zend_Acl_Role ($ role ['name']));
// get the resources available for this role
$ permissions = $ model-> getRoleResources ($ role ['id']);
// put permissions on 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 the ACL itself.
Plugin
Next we transfer control to the plugin. The plugin will process access rights at the controller level. Well, this, 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 sample 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 an object of the form
$ view = $ layout-> getView ();
$ auth = Zend_Auth :: getInstance ();
// if there is any user in the session repository
if ($ auth-> hasIdentity () == true)
{
// get this user's 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->
$ 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 application view level. To do this, we will write a helper that checks access rights and shows or does not show the control:
class Lord_View_Helper_Acl
{
public function Acl ($ module = 'default',
$ controller = 'index',
$ action = 'index')
{
// We
get the Zend_Layout object $ layout = Zend_Layout :: getMvcInstance ();
// Get an object of the form
$ 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 a helper in a view script, it’s enough for us to write something like this to hide or show the control:
acl ('store', 'categories',' add ') == true):?>
