Home > Zend_Acl > Implementing Access Control using Zend_Acl(DB version)

Implementing Access Control using Zend_Acl(DB version)

intro
This article shows code of access control using Zend_Acl especially with DB.
You can see the screens from the demonstration site.

1.Create Tables
In this article, the following tables are used.

CREATE TABLE members
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    role_id        integer        NOT NULL,
    nick_name      varchar(100)   NOT NULL,
    email          varchar(200)   NOT NULL
);
 
CREATE TABLE roles
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    role_name      varchar(20)    NOT NULL,
    privileges    varchar(10)    NOT NULL
);
 
CREATE TABLE messages
(
    id             integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    member_id      integer        NOT NULL,
    message        text           NOT NULL
);
2.Create Controller
Create the file application/constorllers/MessageController.php with the following content.

<?php
require_once 'My/Controller/Simple.php';
require_once APP_BASE . '/models/Roles.php';
require_once APP_BASE . '/models/Members.php';
require_once APP_BASE . '/models/Messages.php';
require_once APP_BASE . '/models/forms/MessageForm.php';
require_once APP_BASE . '/models/acls/MessageAcl.php';
 
class MessageController extends My_Controller_Simple
{
    protected $_session_name = "Message";
    protected $_table_class = "Messages";
    protected $_form_class = "MessageForm";
 
    protected $_acl = null;
 
    protected function _getOutputFilter($data = null)
    {
        $messages = new Messages();
        return $messages->getOutputFilter($data);
    }
 
    public function getForm()
    {
        $form = parent::getForm();
        $form->getElement('member_id')->setValue($this->getSession()->member_id);
        return $form;
    }
 
    public function getLoginForm()
    {
        $members = new Members();
        $member_options = $members->getOptions();
 
        $form = new Zend_Form(array(
            'method'   => 'post',
            'action'   => $this->_helper->url->url(array('action'=>'index')),
            'elements' => array(
                'member' => array('select', array(
                    'required' => true,
                    'label' => 'member',
                    'multiOptions' => $member_options,
                    'validators' => array(
                        array('inArray', true, array(array_keys($member_options)))
                    ),
                )),
                'submit' => array('submit', array(
                    'label' => 'Login',
                    'decorators' => array(
                        'ViewHelper',
                        array('HtmlTag', array('tag' => 'dt', 'class' => 'submit'))
                    )
                ))
            ),
        ));
 
        return $form;
    }
 
    public function init()
    {
        parent::init();
        $this->_acl = new MessageAcl();
    }
 
    public function preDispatch()
    {
        parent::preDispatch();
        $action = $this->getRequest()->getActionName();
        $session = $this->getSession();
        if ($action != 'index' && $action != 'deny')
        {
            if (!isset($session->role))
            {
                $this->_helper->redirector('index');
            }
            else
            {
                $id = isset($session->current_id) ? $session->current_id : null;
                $id = isset($_GET['id']) ? $_GET['id'] : $id;
                $resource = $this->_acl->getResource($id, $session->member_id);
                if (!$this->_acl->isAllowed($session->role, $resource, $action))
                {
                    $this->_helper->redirector('deny');
                }
            }
        }
        $this->view->name = "message";
        $this->view->of = $this->_getOutputFilter();
    }
 
    public function indexAction()
    {
        // Select project and member
        $this->view->action = $this->getRequest()->getActionName();
        $form = $this->getLoginForm();
        $session = $this->getSession();
        if ($this->getRequest()->isPost())
        {
            if ($form->isValid($_POST))
            {
                $values = $form->getValues();
                $members = new Members();
                $member = $members->find($values['member'])->current();
                if ($member)
                {
                    $role = $member->findParentRoles();
                    if ($role)
                    {
                        $session->member_id = $values['member'];
                        $session->role = $role->role_name;
                        $this->_helper->redirector('list');
                    }
                }
            }
        }
        $this->view->form = $form;
        return $this->render('form');
    }
 
    public function denyAction()
    {
    }
}

This controller checks the access privileges including the resource in the function preDispatch.

                $id = isset($session->current_id) ? $session->current_id : null;
                $id = isset($_GET['id']) ? $_GET['id'] : $id;
                $resource = $this->_acl->getResource($id, $session->member_id);
                if (!$this->_acl->isAllowed($session->role, $resource, $action))
3.Create Models
Create the file application/models/acls/MessageAcl.php with the following content.

<?php
require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';
require_once 'Zend/Acl/Resource.php';
require_once APP_BASE . '/models/Messages.php';
 
class MessageAcl extends Zend_Acl
{
    public function __construct()
    {
        $admin = new Zend_Acl_Role('admin');
        $user = new Zend_Acl_Role('user');
        $guest = new Zend_Acl_Role('guest');
 
        $this->addRole($admin);
        $this->addRole($guest);
        $this->addRole($user, $guest);
 
        $this->allow($admin);
 
        $this->allow($guest, null, array('list', 'detail'));
 
        // user is allowed list and view also
        $this->allow($user, null, array('add'));
 
        $messages = new Messages();
        $rowset = $messages->fetchAll();
        foreach($rowset as $row)
        {
            $resource = $this->getResource($row->id, $row->member_id, false);
            $this->add($resource);
            $this->allow($user, $resource, array('update', 'delete'));
        }
    }
 
    public function getResource($message_id, $member_id, $check = true)
    {
        if ($message_id == null || $member_id == null)
        {
            return null;
        }
        $resource_name = 'message_' . $message_id . '_' . $member_id;
        $resource = new Zend_Acl_Resource($resource_name);
        if (!$check || $this->has($resource))
        {
            return $resource;
        }
        return null;
    }
}

This class sets the acl including resources in the constructor.
The other models are same as the previous article.

4.Create Views
The views are same as the previous article.

5.Check
Access the web server and check that some members can't edit messages.
History
Date Content
2008/5/10 Published

Comments:1

Jonathan 08-09-11 (Thu) 3:25

Wow. This is the first time I’ve seen someone not blabber on for years and produce 10 lines of code I could figure out myself. I haven’t even begun to read through you’re articles, but I’m very excited. You’re personality fits me well.

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.oplabo.com/article/45/trackback
Listed below are links to weblogs that reference
Implementing Access Control using Zend_Acl(DB version) from Open Programming Laboratory

Home > Zend_Acl > Implementing Access Control using Zend_Acl(DB version)

Japanese
Search
Feeds

Return to page top