AngryGantz

Заметки о Web-стройках

JCFYii 4 Управление пользователями и правами.

| Comments

Что нужно практически в любом web-приложении? Что бы мы не делали, практически всегда необходима система управления пользователями и их правами. Только совсем простейшие проекты обходятся без этого. Поэтому до перехода ко всему остальному надо прикрутить что-то такое к проекту.

В Yii реализована схема управления правами RBAC, есть готовые менеджеры авторизации пользователей (для БД и файла). Чудненько. Но мы ещё упростим себе жизнь и не будем отписывать реализацию, а воспользуемся чем нибудь готовым. Как сказано в одном хорошем кино «всё уже покрадено до нас». Написано как правило тоже. Так что вперед, на офф сайт за нужными плюшками.

В разделе дополнений на офф сайте полно всякого разного по управлению пользователями и правами. Смотреть их все ни желания ни времени. Положимся на мнение общественности, рекомендующей Yii-User и Rights.

Yii-User

Страничка на оффсайте Yii

Домашняя страничка

По описанию делает всё, что надо и не делает лишнего. Возможно не зря хвалили. Качаю, создаю папку /protected/modules , Папку User из архива кидаю туда.

Далее всё включаем по мануалу в главном конфиге:

В секцию import добавлено:

'application.models.*',
'application.components.*',
'application.modules.user.models.*',
'application.modules.user.components.*',
  • В секцию modules после gii добавлено user,
  • В секции components уже прописан компонент user. Это демо-компонент, сгенерированный приложением. Меняю на то, что в мануале по модулю:
1
2
3
4
5
6
7
<?php
'user'=>array(
  // enable cookie-based authentication
  'allowAutoLogin'=>true,
  'loginUrl' => array('/user/login'),
),
?>

Заодно надо почистить хвостики от старого. Удаляем компонент UserIdentity.php, из контроллера SiteController.php удаляем действия actionLogin() и actionLogout(), ибо использоваться будет модуль. Так же удаляется полностью модель LoginForm.php и вьюшка site/login.php. Вроде всё. Идём дальше.

  • Создание таблиц БД. Смотрим modules/user/data/schema.mysql.sql Там создание трёх таблиц и занесение пары аккаунтов - admin и demo. Вот только префиксы… Ну не люблю я эти «tbl_». Буду делать префиксы помодульно. Будет более менее осмысленно, когда (и если) проект разрастется. Меняю «tbl_» на «user_» и выполняю скрипт в MySQL. Но ведь очевидно, где-то была привязка к этим «tbl_». Начнем с файла модуля modules/user/UserModule.php. Нахожу вот такие строки:
1
2
3
4
5
6
<?php
  public $tableUsers = '{ {users} }';
  public $tableProfiles = '{ {profiles} }';
  public $tableProfileFields = '{ {profiles_fields} }';

?>

Это даже не привязка к «tbl_». Даже не знаю, как понимать. Может это связано с настройкой модуля из консоли через миграции? Что-такое читал. Ну да бог с ним. В любом случае это паблик свойства и их можно переопределить прямо в глобальном конфиге приложения, в секции модуля user. Топаем в config/main.php и меняем сиротливую строку user, на секцию

1
2
3
4
5
6
7
8
<?php
'user'=>array(
  'tableUsers'=>'user_users',
  'tableProfiles'=>'user_profiles',
  'tableProfileFields'=>'user_profiles_fields',
),

?>
  • Ну и последнее. Прописать эти все радости в меню. Меню нарисовано в view/layouts/main.php Выбрасываю оттуда неактуальные Login и Logout и особо не всматриваясь копипастом из мануала загоняю туда блок
1
2
3
4
5
6
7
8
9
10
11
<?php
array('url'=>Yii::app()->getModule('user')->loginUrl,
  'label'=>Yii::app()->getModule('user')->t("Login"), 'visible'=>Yii::app()->user->isGuest),
array('url'=>Yii::app()->getModule('user')->registrationUrl,
  'label'=>Yii::app()->getModule('user')->t("Register"), 'visible'=>Yii::app()->user->isGuest),
array('url'=>Yii::app()->getModule('user')->profileUrl,
  'label'=>Yii::app()->getModule('user')->t("Profile"), 'visible'=>!Yii::app()->user->isGuest),
array('url'=>Yii::app()->getModule('user')->logoutUrl,
  'label'=>Yii::app()->getModule('user')->t("Logout").' ('.Yii::app()->user->name.')',
'visible'=>!Yii::app()->user->isGuest),
?>

Проверяем модуль. Ссылки меню, регистрация, логин-логаут, всё работает. Приятно. Да, всё конечно англицкое, придется с этим всем повозиться потом. Причём чует моё сердце писсимиста, что если делать интернационализацию “по фен-шую” то повозиться придется долго. В идеале даже во вьюшках текста прямого быть не должно, только вызовы мессаджей. Но боюсь, что на этот мазохизм меня всё таки не хватит. Хотя… Пишу же эти простыни, кто знает… :-)

Но главное, модуль работает, логика своё отрабатывает, а внешний вид и языки потом. Сначала строим логику.

Модуль RIGHTS

Страничка на оффсайте Это модуль управления правами пользователей. Зачем он мне нужен? Ну как минимум у меня предполагается Гость, Админ, Клиент (дилер) и Менеджер. В дальнейшем возможно ещё розничные клиенты, какой нибудь старший менеджер и так далее и тому подобное. В Yii реализована система управления правами RBAC. Подробности тут. Rights вроде как предоставляет полный инструментарий для управления и использования этой системы. То, что бегло прочитал, понравилось. Вопрос на сколько это удобно и как этот модуль “сработается” с предыдущим установленным - Yii-User. Начнем.

Установка.

Скачиваю мануальчик и сам модуль. Папку rights из архива кидаем в модули и читаем мануальчик. Так. Первое. В требованиях наличие БД (ну это понятно) и наличие модели user с атрибутами id и name. В нашей табличке user_users поле id есть, а вот вместо поля name имеем username. Но пролистав документацию в разделе конфигурации вижу 'userNameColumn'=>'username', причём это по дефолту, даже менять ничего не надо. Возвращаюсь к инсталляции модуля. Первое стандартно - импорт.

1
2
3
4
5
6
<?php
'import'=>array(
  'application.modules.rights.*',
  'application.modules.rights.components.*', // Correct paths if necessary. 
),
?>

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

1
2
3
4
5
6
7
8
9
10
<?php
'components'=>array(
  'user'=>array(
      'class'=>'RWebUser', // Allows super users access implicitly. 
  ),
'authManager'=>array(
      'class'=>'RDbAuthManager', // Provides support authorization item sorting. 
  ),
),
?>

С менеджером аутентификации всё ясно - подключаем менеджера, работающего через БД. А вот user… Гложат меня смутные сомнения что не всё гладко будет… Надеюсь зря. Делаем и продолжаем. Просто добавляем в секцию user компонентов (и не путать с аналогичной секцией в модулях!) строку с определением класса. Пока до выяснения получится вот что:

1
2
3
4
5
6
7
8
<?php
'user'=>array(
      'class'=>'RWebUser',
      // enable cookie-based authentication
      'allowAutoLogin'=>true,
      'loginUrl' => array('/user/login'),
),
?>

В секции модулей рисуем как в мануале, только installer пока ставлю false, сначала надо разобраться чего это за зверь, мне ещё с табличками и префиксами разобраться надо, а то нарисует чего попало в базу…

1
2
3
4
5
<?php
'rights'=>array(
  'install'=>false, // Enables the installer. ), 
 ),
?>

Так, смотрим дальше. В конфиге по дефолту 'superuserName'=>'Admin',, а у нас юзер - admin. На всякий случай меняем. Секция в модулях теперь такая:

1
2
3
4
5
6
<?php
'rights'=>array(
  'install'=>false, // Enables the installer. 
  'superuserName'=>'admin',
 ),
?>

Остальные дефолты вроде устраивают. В файле modules/rights/data/schema.sql меняем названия таблиц соответственно на rights_auth_item, rights_auth_item_child, rights_auth_assignment, rights_rights не только добавив префикс модуля, но сменив тип нотации со стиля “CaMel” для единообразия в БД. Теперь смотрим где в модуле они привязаны. Собственно упоминания есть только в файле components/RInstaller.php. Но менять ничего не надо, поскольку судя по блоку, где они упоминаются, инсталлер сам корректирует названия в зависимости от схемы sql. Но. Тут есть одно большое Но. Провозился почти час, пока дошло. Дело в том, что к именам таблиц привязан и родной authManager CDbAuthManager И, соответственно, кроме того, что мы меняем имена таблиц в SQL файле, их надо ещё указать в компоненте authManager. И последний штрих - надо назначить роль по умолчанию для незалогиненых пользователей 'defaultRoles'=>array('Guest'), То есть секция этого компонента должна выглядеть вот так (таблица rights - это уже детище наследника из установленного модуля):

1
2
3
4
5
6
7
8
9
<?php
'authManager'=>array(
  'class'=>'RDbAuthManager',
  'assignmentTable'=>'rights_auth_assignment',
  'itemChildTable'=>'rights_auth_item_child',
  'itemTable'=>'rights_auth_item',
  'rightsTable'=>'rights_rights',
 ),
?>

А теперь собственно никто не мешает воспользоваться инсталлером модуля. В секции модулей у модуля rights возвращаем в true свойство install:

1
2
3
4
5
6
7
<?php
'rights'=>array(
  'install'=>true, // Enables the installer. 
  'superuserName'=>'admin',
  
 ),
?>

Теперь даем в браузере команду ../rights/ и наслаждаемся поздравлениями об успешной установке. Проверив таблицы в БД убеждаемся, что они созданы с нужными именами. Уффф… помучился.

Да, где-то по дороге вычитал ещё одну тонкость. Прежде чем устанавливать модуль Rights необходимо полностью установить Yii-User, авторизоваться под админом и только после этого ставить rights. Иначе возникнут дополнительные проблемы. У меня это “на автомате” получилось, а народ мучается…

Теперь в конфиге надо отключить инсталлер выставив false уже лениво писать где :-)

Но с окончательной установкой модуля ещё не всё. Во первых есть генератор разрешений для всех контроллеров (это по идеологии RBAC задачи, tasks ) и всех действий внутри контроллеров отдельно ( операции по RBAC) разрешение на которые можно присвоить любой роли или любому пользователю. Ну это постепенно буду соображать кому, что и зачем. А вот как поизящнее делать видимым элемент на вьюшке в зависимости от роли, надо будет решать уже скоро.

Для включения нового функционала - фильтров построенных на базе rights, осталось только унаследовать стандартный контроллер приложения не от CController, а от RController и в контроллерах можно использовать функции фильтров rights примерно так:

1
2
3
4
5
6
7
8
<?php
public function filters() {
    return array( 'rights', );
}
ublic function allowedActions() {
    return 'index, suggestedTags';
}
?>

allowedActions - перечисление действий, которые будут доступны всем и всегда вне зависимости от установленных прав.

Comments