Pull to refresh

Минималистичная система разделения прав по группам за 5 минут

Reading time 4 min
Views 3.6K
Original author: Rasmus
Замучались с ACL? Есть пожалуй самое простое решение для разделения прав по группам. Никаких ACL таблиц, никакого дерева прав. Но если вам требуется задавать права персонально для каждого пользователя, то это решение точно не для вас.

У нас есть всего 5 минут, поэтому давайте сразу начнем.

Создаем или изменяем таблицы базы данных с пользователями и группами, что бы они выглядели вот так:

users
    id - primary
    username - unique
    password
    group_id
groups
    id - primary
    name - unique


Потом создаем несколько групп и пользователей. Не забудьте создать группу «Администраторы»

Далее создаем классы моделей пользователей и групп

<?php
class User extends AppModel {
    var $name = 'User';
    var $displayField = 'username';
    var $belongsTo = array(
        'Group' => array(
            'className' => 'Group',
            'foreignKey' => 'group_id'
        )
    );
}
?>


<?php
class Group extends AppModel {
    var $name = 'Group';
    var $displayField = 'name';

    var $hasMany = array(
        'User' => array(
            'className' => 'User',
            'foreignKey' => 'group_id',
            'dependent' => false
        )
    );

}
?>


И добавляем в app_controller.php следующий код:

<?php
class AppController extends Controller {

    var $components = array('Auth');
    var $permissions = array();
   
    function beforeFilter() {
        $this->Auth->fields  = array(
            'username'=>'username', // Поле в базе с логином пользователя
            'password' =>'password' // Поле с паролем
        );
        $this->Auth->authorize = 'controller';
        $this->Auth->autoRedirect = false;
        $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
        $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
        $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'welcome');

    }
   
    function isAuthorized(){
        if($this->Auth->user('group') == 'Администраторы') return true; // Если не хотите давать доступ для группы "Администраторы" ко всему по умолчанию, закомментируйте эту строчку
        if(!empty($this->permissions[$this->action])){
            if($this->permissions[$this->action] == '*') return true;
            if(in_array($this->Auth->user('group'), $this->permissions[$this->action])) return true;
        }
        return false;
       
    }

}
?>


Добавляем в users_controller.php такие строки:

<?php
class UsersController extends AppController {

    var $name = 'Users';
    var $helpers = array('Html', 'Form');
    var $permissions = array(
        'logout' => '*',
        'welcome' => '*'
    );
   
    function welcome(){
    }

    function login(){
        if($this->Auth->user()){
            $this->Session->write('Auth.User.group', $this->User->Group->field('name',array('id' => $this->Auth->user('group_id'))));
            $this->redirect($this->Auth->redirect());
        }
    }
   
    function logout(){
        $this->redirect($this->Auth->logout());
    }

    // Ну и прочие необходимые вам методы, например add, edit, delete
?>


Ну вообщем-то все. Теперь что бы указать права доступа необходимо добавить $permissions для любого контроллера как мы сделали это в users_controller

Как это работает:

Когда пользователь заходит мы добавляем название его группы в Auth сессию. После когда мы обращаемся к методу контроллера, компонент Auth вызывает нашу функцию isAuthorized и если она возвращает true, то пользователь получает доступ, а если она возвращает false, то запрещает его. Если пользователь находится в группе «Администраторы», то он всегда получает доступ. Функция isAuthorized проверяет массив $permissions указанные в каждом контроллере используя в качестве ключа название текущего action и если группа пользователя есть в массиве по этому ключу (ну или вместо массива там стоит '*' — то есть всем) то пользователю разрешается доступ.
Примечание: Подразумевается, что вы все равно авторизовались, даже если уровень доступа '*'. Можно разрешить заходить неавторизованным пользователям воспользовавшись методом Auth->allow
Примечание: Мы не определяли доступ к users/login, потому что Auth по умолчанию разрешает к нему доступ.

Пример:

Допустим мы хотим разрешить группе «Модераторы» удалять пользователей. Добавим следующий код в users_controller.php:

var $permissions = array(
        'logout' => '*',
        'welcome' => '*'
        'delete' => array('Модераторы')
    );


Но ведь пользователи который не авторизовались не смогут зарегистрироваться. Добавим в users_controller.php:

function beforeFilter(){
    $this->Auth->allow('signup');
    parent::beforeFilter();
}


Надеюсь это решение вам помогло. Это исключительно простое решение для разделения прав по группам, ну конечно у него есть свои недостатки. Например нельзя разрешить пользователю изменять статью только в том случае если он ее создал. Ну по крайней мере без изменений приведенного кода. Но я оставлю это для вас.
Tags:
Hubs:
+3
Comments 19
Comments Comments 19

Articles