перевод | Кирилл Павлюков
Сен 04

Это перевод второй части статьи с DevZone об использовании Zend_Acl MVC Zend Framework.

В первой части мы говорили о том, как настроить экземпляр Zend_Acl, и как присоединить его к окружению MVC (с использованием плагина фронт-контроллера). Но как насчет установки другого действия для обработки запрета доступа, или как сделать, чтобы статью мог редактировать только ее владелец? Это и кое-то другое вы найдете в приведенных ниже примерах.

Как я упоминал в первой части, эта статья основана на Предложениях Zend Framework (ссылка), которая в настоящее время находится в лаборатории (Лаборатория – часть кода и концепции Zend Framework, которая внесена в проект, но дожидается утверждения для внесения в основной релиз, – прим. переводчика).

1. Использование модулей

Давайте поговорим об использовании модулей. Мы использовали в качестве примера для данной статьи сайт аналогичный devzone. Как насчет того, чтобы создать административный модуль, для утверждения (одобрения) статей и некоторых других задач (например, измениения быстрых ссылок или разделов)? Для этого нам потребуется изменить модель ресурсов нашего ACL:

Модуль по-умолчанию:

  • Контроллер user.
  • Контроллер article.

Административный модуль:

  • Контроллер article.
  • Контроллер quick-link.
  • Контроллер category.

Основываясь на данной модели ресурсов, создадим экземпляр Zend_Acl, отображающий это.

ВАЖНО
Помните, этот код и создание объекта Zend_Acl должны быть выполнены до вызова метода диспетчеризации фронт-контроллера (в файле bootstrap).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/** Создание Ролей */
require_once 'Zend/Acl/Role.php';
$myAcl->addRole(new Zend_Acl_Role('guest'))
      ->addRole(new Zend_Acl_Role('writer'), 'guest')
      ->addRole(new Zend_Acl_Role('admin'), 'writer');

/** Создание Ресурсов */
require_once 'Zend/Acl/Resource.php';
/** Модуль по-умолчанию */
$myAcl->add(new Zend_Acl_Resource('user'))
      ->add(new Zend_Acl_Resource('article'));

/** Административный модуль */
$myAcl->add(new Zend_Acl_Resource('admin'))
      ->add(new Zend_Acl_Resource('admin:article', 'admin'))
      ->add(new Zend_Acl_Resource('admin:quick-link', 'admin'))
      ->add(new Zend_Acl_Resource('admin:category', 'admin'));

/** Создание привелегий */
$myAcl->allow('guest', 'user')
      ->deny('guest', 'article')
      ->allow('guest', 'article', 'view')
      ->allow(array('writer', 'admin'), 'article', array('add', 'edit'))
      ->allow('admin', 'admin');

/** Установка фронт-контроллера */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory(array('default' => 'path/to/default/controllers',
                                     'admin' => 'path/to/admin/controllers'));

/** Регистрация объекта плагина */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, 'guest'));

/** Запуск диспетчеризации */
$front->dispatch();

Заметьте, мы создали ресурс для каждого контроллера модуля по-умолчанию, а для административного модуля – ресурс для самого модуля и по одному для каждого контроллера внутри модуля (в формате ‘модуль:контроллер’), которые являются дочерними по отношению к ресурсу модуля администрирования. Кроме того мы указали, что только пользователи с административной ролью имеют доступ к административному модулю.

2. Использование ролей

Войдя в приложение, пользователь должен получить одну из ролей (в нашем примере роль может быть ‘guest, ‘writer’ или ‘admin’). Так как же мы можем определить роль в наших приложениях? Для начала необходимо сохранить роль в переменной, которая хранится в сессии. Поэтому, после авторизации пользователя, нужно сохранить его роль в хранилище сессии, а при последующих запросах, извлечь ее из сессии, чтобы передать плагину фронт-контроллера в bootstrap-файле.

Контроллер User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
user controller class UserController extends Zend_Controller_Action
{
    protected $_application;

    public function init()
    {
        require_once 'Zend/Session/Namespace.php';
        $this->_application = new Zend_Session_Namespace('myApplication');
    }

    public function loginAction()
    {
        ... Код проверки авторизации
        if ($valid) {
            /** Сохранение роли в сессии */
            $this->_application->currentRole = $user->role;
            $this->_application->loggedUser = $user->username;
        }
    }

    public function logoutAction()
    {
        $this->_application->currentRole = 'guest';
        $this->_application->loggedUser = null;
    }
}

bootstrap-файл

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** Загрузка данных приложения из сессии */
require_once 'Zend/Session/Namespace.php';
$application = new Zend_Session_Namespace('myApplication');

if (!isset($application->currentRole)) {
    $application->currentRole = 'guest';
}

/** Установка фронт-контроллера */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Регистрация объекта плагина */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, $application->currentRole));

/** Запуск диспетчеризации */
$front->dispatch();

3. Установка действия, отображаемого в случае запрета доступа

Возможно, некоторым из вас (надеюсь, никому =D) просто не понравится идея хранения действия, отображаемого в случае запрета доступа, в контроллере ошибок (error controller), или просто захочется иметь какой-то обходной путь. В этом случае вам поможет метод setErrorPage плагина фронт-контроллера.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** Установка фронт-контроллера */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');
 
/** Установка действия, отображаемого в случае запрета доступа  */
require_once 'Zend/Controller/Plugin/Acl.php';
$aclPlugin = new Zend_Controller_Plugin_Acl($myAcl, 'guest');
$aclPlugin->setErrorPage('goaway', 'my-error-controller', 'my-module');

/** Регистрация объекта плагина */
$front->registerPlugin($aclPlugin);
 
/** Запуск диспетчеризации */
$front->dispatch();

К методу setErrorPage можно обратиться, указав только имя действия (в этом случае будут использованы имя контроллера и модуля по-умолчанию: ‘error’ и ‘default’ соответственно), но также можно передать методу действие и контроллер или все три параметра.

4. Использование помощника действий

В конце мы рассмотрим одну из наиболее важных частей этого предложения: как на примере devzone только авторам и администраторам разрешить редактировать статьи (Но, стоп: здесь есть упущенный момент. Если я – автор, и у меня есть доступ к article/edit/:id, в таком случае я смогу редактировать не только свои статьи, но и чужие. Это проблема, не так ли? Итак, что же нам теперь делать? Управлять с помощью помощника действий (Action Helper), который позволит обратиться к нашему ACL внутри любого контроллера, а не только во время запуска.
Итак, перво-наперво нам нужно зарегистрировать наш плагин фронт-контроллера и Controller Action Helper Broker.
Bootstrap-файл

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/** Загрузка данных приложения из сессии */
require_once 'Zend/Session/Namespace.php';
$application = new Zend_Session_Namespace('myApplication');

if (!isset($application->loggedUser)) {
    $application->loggedUser = null;
}

/** Установка фронт-контроллера */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Регистрация объекта плагина */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($myAcl, $application->currentRole));

/** Регистрация объекта Action Helper */
require_once 'Zend/Controller/Action/Helper/Acl.php';
require_once 'Zend/Controller/Action/HelperBroker.php';
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Acl());

/** Запуск диспетчеризации */
$front->dispatch();

После регистрации помощника, мы можем использовать его внутри любого имеющегося контроллера. Поэтому давайте теперь разрешим редактирование только владельцам или любому из администраторов.
Контроллер Article

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
article controller class ArticleController extends Zend_Controller_Action
{
    protected $_acl;
    protected $_application;
 
    public function init()
    {
        /** Получаем наш помощник действия (Action Helper) */
        $this->_acl = $this->_helper->getHelper('acl');

        require_once 'Zend/Session/Namespace.php';
        $this->_application = new Zend_Session_Namespace('myApplication');
    }

    ...
 
    public function editAction()
    {
        /** Получаем статью по id */
        $article = new Article($this->_request->id);

        /** Проверяем, является ли пользователь владельцем или администратором */
        if (($article->author != $this->_application->loggedUser) && ($this->_application->currentRole != 'admin')) {
            $this->_acl->denyAccess();
        }
 
        ...
    }
}

Заключение

И последняя рекомендация: придерживайтесь принципа Оставлять Все Простым (Keep It Simple). Если вам не нужны динамически подгружаемые ACL, написанные руками правила – это не грех, это только лишь лучший способ реализовать необходимый функционал.

Автор статьи: Альдемар Берналь

Автор перевода: Кирилл Павлюков

Дополнительная информация:
Zend_Acl & MVC IntegrationА здесь вы найдете исходный код примеров к данной статье:
Исходный код
Оригинал статьи на DevZone:
http://devzone.zend.com/article/3510-Zend_Acl-and-MVC-Integration-Part-II-Advanced-Use

Share

Автор: Кирилл Павлюков \\ Метки: , , , ,

Авг 29

На сайте разработчиков Zend Framework еще в конце июня появилась статья об интеграции Zend_Acl и парадигмы MVC. Несмотря на полезность и актуальность информации, до сих пор я не встречал перевода этой статьи на русский язык. Ниже приведена моя попытка исправить это. Кроме того, я уже заканчиваю перевод продолжения этого материала, поэтому к понедельнику выложу и его.

Так что же не правильного в компоненте Zend_Acl и текущей реализации MVC в Zend Framework? Нет ничего неправильного, просто для разработчиков не вполне очевидно, как достичь оптимальной интеграции этих двух важнейших частей фреймворка.

Стоит отметить, что данная статья основана на текущих Предложениях к Zend Framework (ссылка), но в данный момент эти рекомендации находятся на утверждении. Окей! Как это работает? Для реализации этого в Предложениях существует два ключевых компонента:

  1. Плагин фронт-контроллера (Front Controller Plugin). Этот компонент проверяет, имеет ли текущий пользователь доступ к запрашиваемой странице.
  2. Помощник действий (Action Helper). Этот компонент позволяет делать проверку прав доступа пользователя внутри контроллера действий.

Давайте возьмем за основу эти два компонента, и попробуем воспользоваться ими на примере. В дальнейшем мы будем вести разговор о сайте на подобии DevZone. Нам будут необходимы один контроллер, который управляет администрированием пользователей, и второй – для управления статьями. Также нам нужны 3 типа пользователей (ролей): один для гостей, второй – для авторов, и еще один, с помощью которого мы будем утверждать статьи. Вот все что нам нужно:

Ресурсы:

  • Контроллер user.
  • Контроллер article.

Роли:

Share

Автор: Кирилл Павлюков \\ Метки: , , , , ,

Июн 04

Давно не писал в блог. Каюсь. Весь погрузился в бумажную работу и изучение новых для меня областей знаний.

Ну, да ладно. Возвращаюсь к теме. Душа потребовала заменить установленный на блоге редактор TinyMCE на что-нибудь более удобное. Выбор был сделан в пользу SPAW Editor. (К слову, я уже делал несколько постов по этой теме. Найти их можно здесь и здесь.)

Установка безумно проста и не требует никаких глубоких знаний.

Читать запись полностью »

Share

Автор: Кирилл Павлюков \\ Метки: , , , ,

Мар 06

Спорить о том, какой визуальный html-редактор лучше, а какой – хуже, можно очень долго. Равно как и о том, нужно ли их использовать вообще. В моих проектах визуальный редактор необходим, так как редакторский состав напрочь отказывается от использования в своей работе BB-кодов или чистого HTML.

Довольно долго я внедрял в свои проекты FCKEditor, затем переключился на TinyMCE. Но однажды (примерно летом 2007 года :-) ) произошло мое знакомство с наиболее, на мой взгляд, удобным редактором – SPAW Editor от компании Solmetra - http://www.spaweditor.com/. Этот редактор распространяется бесплатно, под GNU General Public License (GPL), но также можно приобрести и коммерческую лицензию.

Что мне больше всего в нем нравится? В отличие от тех же FCKEditor или TinyMCE – он не тормозит браузер. Это связано с тем, что редактор прорисовывается не из JavaScript, а непосредственно в HTML. Тут конечно дело вкуса, но мне и нашим редакторам нравится, что поле редактора не замирает при простой вставке текста из буфера.

Неоспоримое преимущество SPAW2 - встроенный файл-менеджер. Действительно мощный инструмент, и, опять-таки, бесплатный.

SPAW2 доступен для PHP и .NET, но так как с дотнетом я не дружу, все записи на этом блоге будут касаться именно PHP.

В этом посте я расскажу, как установить и начать использовать SPAW2. Читать запись полностью »

Share

Автор: Кирилл Павлюков \\ Метки: , , ,