2.2. Усовершенствования Управления Доступом

2.2.1. Точное Управление Доступом

Базовый, ACL как было описано в предыдущем разделе, демонстрирует, как различные привилегии могут быть разрешены в ACL (ко всем ресурсам). Но на практике средства управления доступом имеют тенденцию к тому, чтобы иметь исключения из правил и различную степень сложности. Zend_Acl позволяет производить детализацию простым и гибким способом.

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

В дополнение, необходимо чтобы группе 'сотрудник' было позволено просматривать новости, но запрещено редактировать их. И наконец, должно быть запрещено всем (в том числе и администраторам) удалять любые 'объявления' если их время существования составляет только 1-2 дня.

В первую очередь мы внесем изменение в регистр Роли для отражения этих именений. Мы определили, что группа 'маркетинг' имеет те же базовые права, что и 'сотрудник', поэтому мы определим 'маркетинг' таким образом, чтобы она наследовала права группы 'сотрудник':

<?php
// Новая группа 'маркетинг' наследует права от группы 'сотрудник'
$acl->addRole(new Zend_Acl_Role('marketing'), 'staff');

Далее, заметьте, что указанные выше права доступа имеют отношение к особым Ресурсам (например, "подписка", "последние новости"). Теперь мы добавим эти Ресурсы:

<?php
// Создаем Ресурсы для этих ролей
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('newsletter'));           // подписка
$acl->add(new Zend_Acl_Resource('news'));                 // новости
$acl->add(new Zend_Acl_Resource('latest'), 'news');       // последние новости
$acl->add(new Zend_Acl_Resource('announcement'), 'news'); // объявления

Затем просто определяются более точные правила для целевых областей ACL.

<?php
// Маркетинг должен иметь возможность публиковать и удалять подписку и последние новости	
$acl->allow('marketing', array('newsletter', 'latest'), array('publish', 'archive'));

// Пользователю (и маркетингу, через наследование), запрещено редактировать последние новости
$acl->deny('staff', 'latest', 'revise');

// Каждому (включая администраторов) запрещено удалять объявления
$acl->deny(null, 'announcement', 'archive');

Теперь мы можем делать запрос ACL с учетом последних изменений:

<?php
echo $acl->isAllowed('staff', 'newsletter', 'publish') ?
     "allowed" : "denied"; // denied (запрещен)

echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
     "allowed" : "denied"; // allowed (разрешен)

echo $acl->isAllowed('staff', 'latest', 'publish') ?
     "allowed" : "denied"; // denied (запрещен)

echo $acl->isAllowed('marketing', 'latest', 'publish') ?
     "allowed" : "denied"; // allowed (разрешен)

echo $acl->isAllowed('marketing', 'latest', 'archive') ?
     "allowed" : "denied"; // allowed (разрешен)

echo $acl->isAllowed('marketing', 'latest', 'revise') ?
     "allowed" : "denied"; // denied (запрещен)

echo $acl->isAllowed('editor', 'announcement', 'archive') ?
     "allowed" : "denied"; // denied (запрещен)

echo $acl->isAllowed('administrator', 'announcement', 'archive') ?
     "allowed" : "denied"; // denied (запрещен)

2.2.2. Удаление Контроля Доступа

Для того, чтобы удалить одно или несколько правил из ACL, просто используйте методы removeAllow() или removeDeny(). Как и с allow() и deny(), вы можете передавать null как параметр, чтобы применить метод ко всем Правилам, Ресурсам, и/или привилегиям:

<?php
// Удаляем запрет на редактирование последних новостей для 'пользователя' (и маркетинга, через наследование)
$acl->removeDeny('staff', 'latest', 'revise');

echo $acl->isAllowed('marketing', 'latest', 'revise') ?
     "allowed" : "denied"; // allowed (разрешен)

// Удаляем разрешение на публикацию и удаление подписки для маркетинга
$acl->removeAllow('marketing', 'newsletter', array('publish', 'archive'));

echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
     "allowed" : "denied"; // denied (запрещен)

echo $acl->isAllowed('marketing', 'newsletter', 'archive') ?
     "allowed" : "denied"; // denied (запрещен)

Привилегии могут модифицироваться в порядке возрастания, как показано выше, но параметр null для привилегий перекрывает такой порядок изменений:

<?php
// Разрешить маркетингу все для действий над последними новостями
$acl->allow('marketing', 'latest');

echo $acl->isAllowed('marketing', 'latest', 'publish') ?
     "allowed" : "denied"; // allowed (разрешен)

echo $acl->isAllowed('marketing', 'latest', 'archive') ?
     "allowed" : "denied"; // allowed (разрешен)

echo $acl->isAllowed('marketing', 'latest', 'anything') ?
     "allowed" : "denied"; // allowed (разрешен)