Аутентификация с использованием Jelly и Jelly-Auth -- часть 2
Четверг, 22 апреля 2010 г.Рубрика: Web frameworks
Метки: Kohana | обучение
Просмотров: 3058
Подписаться на комментарии по RSS
Briefly in English
Next part of tutorial on using Kohana 3 Jelly and Jelly-Auth (autologin, built-in role system application). Will be translated soon.
1. вместо
$this->auth = Jelly_Auth::instance();
лучше
$this->auth = Auth::instance();
Thanks SpadXIII
2. модуль ORM здесь действительно не нужен и его можно спокойно отключить (спасибо Sezarin).
3. Для удобства можно ввести свойство Controller_admin::$user и определять его в before():
$this->user = $this->auth->get_user();
3. В описании поля email модели стоит только проверка на уникальность, но нет проверки на пустое поле. Поэтому если кто-то не указал электронную почту, а потом это же делает другой, то выбрасывается Database Exception на неуникальность полей под индексом UNIQUE (которое не ловится, поскольку стоит catch на Validation_Exception). Я не нашел лучшего способа исправить ситуацию, кроме как наследовать User, переопределив метод initialize() таким образом (если нет желания переписать в нем все поля полностью):
public static function initialize(Jelly_Meta $meta)
{
$meta->fields = array(
'email' => new Field_Email(array(
'unique' => TRUE,
'rules' => array(
'not_empty' => array(TRUE),
)
)),
);
parent::initialize($meta);
}Кроме того, был малость исправлен и дополнен вывод сообщений об ошибках при валидации.
Сделаем автологин.
Для этого нужно
а) изменить форму, добавив чекбокс
б) добавить на страницу логина обработку чекбокса, переписав проверку $_POST таким образом
// try to login
if ($_POST)
{
$username = $_POST['username'];
$password = $_POST['password'];
$remember = isset($_POST['remember']) ? TRUE : FALSE;
if ($this->auth->login($username, $password, $remember))
{
Request::instance()->redirect('admin/index');
} else {
$errors = array('Login or password incorrect');
}
}в) переписать защищенные методы с учетом включенного автологина. В моем случае пришлось проверять право на просмотр страницы с помощью $this->auth->logged_in('login'), что автоматически пытается заавтологинить юзера.
Для реализации простейшей ролевой системы вполне пригоден имеющийся в модуле Jelly-Auth функционал -- метод has_role($role). Например, разрешим добавлять пользователя только администратору. Однако для этого нужно предоставить возможность назначать роли пользователям.
Надо
а) в методе контроллера action_users() в ветке 'edit' добавить переменные, содержащие коллекцию ролей системы и массив активных ролей пользователя:
$roles = Jelly::select('roles')
->execute();
...
if ($is_saved)
{
$this->template->content = 'User profile was updated';
} else {
// output user profile form
$this->template->content = $content
->set('id', $user->id)
->set('username', $user->username)
->set('email', $user->email)
->set('user_roles', $user->roles->as_array())
->set('roles', $roles);
}б) соответственно, в форме ('views/admin/edit_user') нужно вставить массив чекбоксов типа
<SPAN>Assigned roles</SPAN>
<UL style="list-style-type: none;">
<?php
$role_ids = array();
foreach ($user_roles as $ur)
{
$role_ids[] = $ur['id'];
}
foreach ($roles as $role)
{
?>
<LI>
<?php echo Form::checkbox('roles[]', $role['id'], in_array($role['id'], $role_ids), array('id' => 'roles_'.$role['id'])).' '
.Form::label('roles_'.$role['id'], $role['name'].'<BR>'.$role['description']);
?></LI>
<?
}
?></UL>Первый foreach выглядит не очень красиво, но я в силу неопытности не нашел лучшего способа извлечь массив role IDs из ассоциативного массива.
в) Остается обработать приходящий в POST массив номеров ролей:
$user->roles = isset($_POST['roles']) ? $_POST['roles'] : array();
Далее можем, например, разрешить добавление нового пользователя только админу
if ($this->user->has_role('admin'))
...Увы, хранение данных пользователя в сессии приводит к тому, что внесенные изменения вступают в силу после перелогина.
Разумеется, такая простая ролевая система может помочь только в несложных случаях. Поэтому буду думать над продолжением.
Скачать / Download 161 (zipped ~11 KiB)
Комментариев: 6
Неплохой пример реализации сложных вещей просто...
Я думаю, у Jelly - большое будущее.
Кстати, со вчера на Github (http://github.com/jonathangeiger/kohana-jelly) появилась версия с документацией на русском.
Спасибо Сергею Гладковскому! (http://github.com/smgladkovskiy)
да, Jelly мне кажется достаточно удобным инструментом, хотя тут не имею большого опыта. А на русском языке вообще приятно читать
1.
if ($_POST) { $username = $_POST['username']; $password = $_POST['password']; ...Добавьте проверку на наличие этих ключей. Arr::get() я уже на автопилоте подставляю в любом месте, где работаю с массивами
2. А зачем пункт "в" в реализации автологина? Для этого обычно используется метод Auth::instance()->auto_login(), который пробует залогиниться на основании кук (вернет TRUE, если получилось). Пихаем его в before(), если не прокатило, то уже тогда предлагаем залогиниться.
пункт в) нужен из-за того, что я изначально отказался от менеджмента доступа к страницам в before(), решив разбираться в каждом методе отдельно
а так конечно -- вы абсолютно правы
Александр спасибо Вам за столь интересные статьи.
Я немного поправил код в вашем примере. Надеюсь в лучшую сторону )
1. Контроллер action_users(), ветка 'edit'
... if ($is_saved) { $this->template->content = 'User profile was updated'; } else { // output user profile form $this->template->content = $content ->set('id', $user->id) ->set('username', $user->username) ->set('email', $user->email) ->set('user_roles', $user->roles->as_array('id')) // т.е. выводим ассоциативный массив ролей, где ключем // является поле ID ->set('roles', $roles); } ...2.Форма views/admin/edit_user
<SPAN>Assigned roles</SPAN> <UL style="list-style-type: none;"> <?php foreach ($roles as $role) { ?> <LI> <?php echo Form::checkbox('roles[]', $role['id'], array_key_exists($role['id'], $user_roles), array('id' => 'roles_'.$role['id'])) . ' ' . Form::label('roles_'.$role['id'], $role['name'].'<BR>'.$role['description']); ?> </LI> <? } ?> </UL>Т.е. я в форме убрал лишний цикл и изменил поиск ID в массиве ролей пользователей.
Anree, спасибо за отзыв и простите, что поздно отвечаю -- провайдер подорвал доверие :(
Спасибо за правки, самое то!