Pull to refresh

Динамические роли и права

Reading time 3 min
Views 3.7K
Случилось мне давече писать динамическую систему ролей и прав для интернет-магазина.
Поскольку в интернете ничего нужного, кроме вот этой серии статей не нашел, придумал написать все сам.

Итак, приступим.

База


Хранить информацию о ролях, ресурсах и правах доступа мы будем в базе. База имеет примерно следующую структуру:
acl_resources — ресурсы
acl_roles — группы юзернеймов, они же — роли
acl_cross — перекресток соответствий ролей и ресурсов:

id / role_id / res_id
1 1 1
2 1 2
3 1 3

* Для роли с id=1 доступны ресурсы 1,2,3

ACL


В файле с контролем доступа напишем вот такой код:
class Acl extends Zend_Acl
{
public function __construct()
{
$model = new User();

/**
* добавляем ресурсы
*/
// получаем ресурсы
$resources = $model->getResources();

foreach($resources as $mod)
{
// если такой ресурс еще не добавлен
if(false == $this->has($mod['module'].'_'.$mod['controller']))
{
// добавляем
$this->add(new Zend_Acl_Resource($mod['module'].'_'.$mod['controller']));
}
}

/**
* добавляем роли пользователей
* и сразу проставляем им разрешения
*/
// достаем роли
$roles = $model->getRoles();
// для каждой роли
foreach($roles as $role)
{
// производим добавление
$this->addRole(new Zend_Acl_Role($role['name']));
// достаем доступные для этой роли ресурсы
$permissions = $model->getRoleResources($role['id']);
// проставляем разрешения на эти ресурсы
foreach($permissions as $perm)
{
$this->allow( $role['name'],
$perm['module'].'_'.$perm['controller'],
$perm['action']);
}
}
}
}
Таким образом мы обрабатываем записи из базы и создаем, собственно, ACL.

Плагин


Дальше мы передаем управление плагину. Плагин будет обрабатывать права доступа на уровне контроллера. Ну, это, напримиер, если обычный пользователь скопировал модераторскую ссылку на действие удаления товара — чтоб его не пустило. Вот примерный код:

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)
{
// Получаем объект Zend_Layout
$layout = Zend_Layout::getMvcInstance();

// Получаем объект вида
$view = $layout->getView();

$auth = Zend_Auth::getInstance();
// если есть какой-то пользователь в хранилище сессии
if ($auth->hasIdentity() == true)
{
// получаем данные этого пользователя
$user = $auth->getIdentity();
$userModel = new User();
$role = $userModel->getRole($user->role);
$user->roleName = $role->name;
}
else
{
$user->roleName = 'anon';
}
// кладем в переменную вида, для отображения
$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



Теперь нам нужно скрывать и показывать элементы управления на уровне вида приложения. Для этого мы напишем хэлпер, который проверял бы права доступа и показывал или не показывал элемент управления:

class Lord_View_Helper_Acl
{
public function Acl($module = 'default',
$controller = 'index',
$action = 'index')
{
// Получаем объект Zend_Layout
$layout = Zend_Layout::getMvcInstance();

// Получаем объект вида
$view = $layout->getView();

$acl = new Acl();
$isAllow = $acl->isAllowed($view->user->roleName, $module.'_'.$controller, $action);

if($isAllow == false)
{
return false;
}
else
return true;

}
}

После написания хэлпера в скрипте вида нам достаточно написать примерно такой вот код, чтоб скрыть или показать элемент управления:

<?if($this->acl('store', 'categories', 'add')==true):?>
<img src="<?=$this->imagesUrl?>icons/icon_add.png"
title = "<?=$this->translate('store_category_primary_add');?>">

<?endif;?>

В результате имеем систему, которая из вэбинтерфейса может раздавать права любой группе на любой модуль/контроллер/действие.

Немного кода для скачивания:
База
Плагин
ViewHelper
ACL
Tags:
Hubs:
+1
Comments 7
Comments Comments 7

Articles