<sect1 id="zend.acl.refining">

    <title>Настройка управления доступом</title>

    <sect2 id="zend.acl.refining.precise">

        <title>Точное управление доступом</title>

        <para>
            Базовый ACL, как было описано в
            <link linkend="zend.acl.introduction">предыдущем разделе</link>,
            демонстрирует, как
            различные привилегии могут быть разрешены в ACL (ко всем ресурсам).
            Но на практике средства управления доступом
            имеют тенденцию к тому, чтобы иметь исключения из правил и различную
            степень сложности. Zend_Acl позволяет производить
            детализацию просто и гибко.
        </para>

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

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

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

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

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

        <programlisting role="php"><![CDATA[
// Создаем ресурсы для этих ролей

// подписка
$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');
]]>
        </programlisting>

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

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

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

// Всем, включая администраторов, не разрешается удалять объявления
$acl->deny(null, 'announcement', 'archive');
]]>
        </programlisting>

        <para>
            Теперь мы можем производить запросы к ACL с учетом последних
            изменений:
        </para>

        <programlisting role="php"><![CDATA[
echo $acl->isAllowed('staff', 'newsletter', 'publish') ?
     "разрешен" : "запрещен";
// запрещен

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

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

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

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

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

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

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

    </sect2>

    <sect2 id="zend.acl.refining.removing">

        <title>Удаление правил доступа</title>

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

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

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

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

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

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

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

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

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

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

echo $acl->isAllowed('marketing', 'latest', 'anything') ?
     "разрешен" : "запрещен";
// разрешен
]]>
        </programlisting>

    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
