Предисловие
Доброе время суток хабравчане.
Для начала представлюсь. Меня зовут Роман, и я занимаюсь разработкой сайтов (в основном на php-фреймворке «yii», но проскакивают и другие php\python фреймворки\цмс\велосипеды\быдлокоды). В своих проектах на yii всеы нам часто приходится реализовывать тривиальные функции регистрации, авторизации и тд. Плюс ко всему прибавьте к этому ещё и распределние прав доступа для различных пользователей. Готов поспорить, что у каждого толкового разработчика есть хотя бы одна заготовка реализации этого функционали, либо он использует сторонее расширение. Вот и я каждый раз использовал одну и туже реализацию, от пректа к проекту допиливал её, интегрировал с другими частями системы. Но недавно я всё же решил порыть в сторону готовых решений, которые удовлетворяли бы мои потребности и таковые нашлись довольно быстро. 2 самых популярных расширения для yii из оффициального репозитория – «yii-user» и «rights».
Интеграция
Оба расширения оформлены в виде модулей. Так что могут быть легко интегрированны в уже существующий проект (если в вашем проекте уже есть модули «user» и «rights» сделайте бекапы), но я для чистоты буду их соединять в новом приложении. Для начала его нужно создать, как это делать отлично описано в документации. Скачиваеим дополнения и распаковываем в папку /protected/modules (её может не быть, создайте вручную). Теперь в нашем проекте появились 2 новых модуля – «user» и «rights». Включим их в конфиге (/protected/config/main.php).
'import'=>array(
#...
'application.modules.user.*',
'application.modules.user.models.*',
'application.modules.user.components.*',
'application.modules.rights.*',
'application.modules.rights.models.*',
'application.modules.rights.components.*',
#...
),
'modules'=>array(
#...
'user' => array(
// названия таблиц взяты по умолчанию, их можно изменить
'tableUsers' => 'tbl_users',
'tableProfiles' => 'tbl_profiles',
'tableProfileFields' => 'tbl_profiles_fields',
),
'rights',
#...
),
'components'=>array(
#...
'user'=>array(
'class' => 'RWebUser',
'allowAutoLogin'=>true,
),
'authManager'=>array(
'class'=>'RDbAuthManager',
'defaultRoles' => array('Guest') // дефолтная роль
),
#...
),
Далее создаем таблицы в базе данных mysql из файлов /protected/modules/user/data/schema.mysql.sql и /protected/modules/user/data/schema.sq.
Ура! Мы успешно установили модули. Проверяем. Заходим по ссылке yiitest/?r=user и видим —
По умолчанию при установке модуля создаются 2 пользователя — admin и demo с паролями admin и demo соответственно. Вы можете авторизоваться под admin:admin и посмотреть все прелести данного модуля. Вкраце о них:
- Готовая реализация регистрации, авторизации, восстановления пароля, активации аккаунта;
- Есть механизм дополнительных полей профиля. То есть к профилю пользователя можно безболезненно прикрутить дополнительные поля, например дату рождения, город, телефон и тд. Можно настроить название поля, тип, код, дефолтное значение, регулярное выражение для валидации, навесить свой виджет вместо стандартного инпута и ещё много всякого разного и вкусного;
- Готовый интерфейс администрирования всего модуля (в стиле CRUD).
INSERT INTO `AuthItem` (`name`, `type`, `description`, `bizrule`, `data`) VALUES
('Admin', 2, 'Администратор', NULL, 'N;'),
('Authenticated', 2, 'Зарегистрированный пользователь', NULL, 'N;'),
('Guest', 2, 'Гость', NULL, 'N;');
INSERT INTO `AuthAssignment` (`itemname`, `userid`, `bizrule`, `data`) VALUES
('Admin', '1', NULL, 'N;'), -- цифру 1 нужно заменить на ID администратора (в нашем примере это первый пользователь)
('Authenticated', '2', NULL, 'N;');
Обновляем страницу yiitest/?r=rights, если снова просит авторизоваться под superuser, авторизуемся под пользователем с ID=1 (в нашем примере это admin:admin). И, как говорят в одной замечательной стране, вуаля! Сразу видим интерфейс администрирования. Вкраце о возможностях:
- Можно привязать несколько ролей к одному пользователю;
- Операции группируются;
- Роли могут наследовать разрешения;
- Многое другое.
public function filters(){
return array(
#...,
'rights'
);
}
На сладкое
Это все конечно очень здорово, но во всей этой схеме закрался небольшой багнебаг (разработчики не предусмотрели, либо я чего-то ещё не изучил). А именно после регистрации вручную придется выставлять пользователю роль «Authenticated». Для этого я написал небольшой костыль. В модуль «user» в папке components создаем файл OnAfterRegistrationBehavior.php со следующим содержимым:
class OnAfterRegistrationBehavior extends CActiveRecordBehavior{
function afterSave($event){
// получаем таблицу в БД
$assignmentTable = Yii::app()->getAuthManager()->assignmentTable;
// получаем параметры нового пользователя
$attr = $event->sender->getAttributes();
// вытаскиваем название роли по умолчанию из настроек модуля rights
$defRole = Yii::app()->getModule('rights')->authenticatedName;
// добавляем привязку
Yii::app()->db->createCommand(
"INSERT INTO {$assignmentTable}
(`itemname`,`userid`,`bizrule`,`data`)
VALUES
('{$defRole}','{$attr['id']}',NULL,'N;')")->execute();
}
}
После чего к модели «RegistrationForm» добавляем поведение «OnAfterRegistrationBehavior»
public function behaviors(){
return array(
'OnAfterRegistrationBehavior' => array(
'class' => 'application.modules.user.components.OnAfterRegistrationBehavior'
)
);
}
Только после обновления модуля user не забудьте восстановить поведение. Будем надеяться, что разработчики прикрутят events к своим контроллерам, что бы в будущем не пришлось прибегать к таким костылям.Если кто-то знает более изящное решения, буду рад услышать.
Спасибо за внимание.