В Кохане встроен модуль авторизации пользователей. В базе уже есть таблица с ролями. Но пошарив по пространствам интернета я так и не нашел как же удобно сделать разграничение прав доступа. Поэтому предлагаю Вам свое решение этой задачи.
Начнем
Все контроллеры я наследую от одного общего Common.php В нем прописываю базовые настройки проекта: подключение css, js, заголовков, контента, загрузка всех конфигов, и т.д. В зависимости что нужно от проекта.
Для начала объявляем все то, что нам пригодится в других контроллерах.
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Common extends Controller_Template {
public $sys_mes, $auth, $session, $user, $class_id;
public $user_roles = array();
public $security = array();
public $template = 'v_common';
public $layout = 'v_column_12';
public $css = array('bootstrap.min', 'style');
public $js = array('jquery-2.0.0.min', 'bootstrap.min');
public $configs = array('order_control', 'payment_method');
}
Далее пишем функцию которая срабатывает до загрузки контролера любой страницы. Ниже описаны только те настройки, которые нам понадобятся. Список ролей можно записать в сессию.
Функция которая делает разграничение — _check_permission()
public function before()
{ parent::before();
# Установка
$this->auth = Auth::instance();
$this->session = Session::instance();
$this->class_id = Get_class($this);
# Проверка на авторизованность
if($this->auth->logged_in())
{
# Индификационные данные
$this->user = $this->auth->get_user();
# Получаем список ролей пользователя
$this->user_roles = Model::factory('User')->user_roles($this->user->id);
}
# Проверка прав доступа
$this->_check_permission();
# Загрузка конфигов
foreach($this->configs as $config)
{
$this->template->set_global($config, Kohana::$config->load($config)->as_array());
}
}
Модель для получения списка ролей. Тут все просто понятно.
class Model_User extends Model_Auth_User {
public function user_roles($user_id)
{
$result = array();
$db = DB::select(array('roles.name', 'name'));
# SELECT -> ROLES_USERS
$db->from('roles_users');
$db->where('roles_users.user_id', '=', $user_id);
# SELECT -> ROLES
$db->join('roles');
$db->on('roles.id', '=', 'roles_users.role_id');
$roles = $db->execute()->as_array();
foreach($roles as $role)
{
array_push($result, $role['name']);
}
}
Сама функция, которая разграничивает доступ. Не зависимо от директории контроллера, она все равно отработает как надо.
private function _check_permission()
{
$check_permission = FALSE;
$config_security = Kohana::$config->load('security')->as_array();
$action = Request::current()->action();
if(isset($config_security[$this->class_id][$action]))
{
foreach($config_security[$this->class_id][$action] as $users_role)
if(in_array($users_role, $this->user_roles) || in_array($users_role, array('public')))
$check_permission = TRUE;
}
if(isset($config_security[$this->class_id]['all_actions']))
{
foreach($config_security[$this->class_id]['all_actions'] as $users_role)
if(in_array($users_role, $this->user_roles))
$check_permission = TRUE;
}
if($check_permission != TRUE)
exit('Access deny - 403 ');
}
Конфиг лежит здесь application/config/security.php
В нем мы пишем разрешение на доступ к экшену, иначе получай 403.
<?php defined('SYSPATH') or die('No direct script access.');
return array(
# Order
'Controller_Orders' => array(
'index' => array('root', 'manager', 'admin'),
'by_organization' => array('root'),
'add' => array('admin', 'manager'),
'edit' => array('admin', 'manager'),
# Auth
'Controller_Auth' => array(
'all_actions' => array('login'),
'login' => array('public'),
),
# Organization
'Controller_Organization' => array(
'all_actions' => array('root'),
),
);
Controller_Orders — название контроллера.
index — экшен который отрабатывает (если нужно открыть доступ для всех то пишем 'all_actions')
array('admin', 'manager') — список ролей, которым разрешен доступ.
Интересно узнать Ваше мнение об этом методе решения проблемы.