View Source

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFDEV:Zend Proposal Zone Template}

{zone-data:component-name}
Zend_Acl & MVC Integration
{zone-data}

{zone-data:proposer-list}
[Aldemar Bernal|mailto:aldemar.bernal@gmail.com]
[Matthew Weier O'Phinney (Zend Liaison)|~matthew]
{zone-data}

{zone-data:liaison}
[Darby Felton|mailto:darby@zend.com]
{zone-data}

{zone-data:revision}
1.0 - 14 November 2007: Proposal created.
1.1 - 15 November 2007: Use cases created.
1.2 - 17 November 2007: First working prototype implemented.
1.3 - 12 January 2008: Changes made for ready for review state.
{zone-data}

{zone-data:overview}
Zend_Acl - MVC Integration is a combination of a front controller plug in and a action helper that allows to grant or deny access to certain actions in MVC structured applications, this component helps the developer to allow users the access only to the pages they are meant to access in a easy way by just defining once which parts of the application can be accessed, this can be configured either in the bootstrap where you can define the guest privileges, or, at login time loading from your db users table the correct privileges.
{zone-data}

{zone-data:references}
* [Zend_Acl documentation|http://framework.zend.com/manual/en/zend.acl.html]
* [Zend_Controller Plugin documentation|http://framework.zend.com/manual/en/zend.controller.plugins.html]
* [My own implementation|http://www.nabble.com/MVC-and-Zend_Acl-integration-tf4776448s16154.html]
{zone-data}

{zone-data:requirements}
* This component *will* allow developers to stop validating if an user has access to certain page by just setting up the component in the bootstrap or when a user login.
* This component *will* help applications to be more secure.
* This component *will* work with both module/controller/action and controller/action configurations.
* This component *will* be available via an action helper.
{zone-data}

{zone-data:dependencies}
* Zend_Acl
* Zend_Config
* Zend_Controller_Front
* Zend_Acl_Exception

{zone-data}

{zone-data:operation}
This component can be instantiated using an ACL object, it must have a role (which name can be set up on the plugin) and the allowed/denied operations (module/controller/action combination). After created, it must be registered as a Front Controller Plugin, optionally, if you want to access ACL inside the controller you will have to register the Action Helper.
{zone-data}

{zone-data:milestones}
* Milestone 1: \[DONE\]Create ZF Wiki info.
* Milestone 2: \[DONE\]Working prototype and some examples. *UCs implemented click [here|http://framework.zend.com/wiki/download/attachments/39025/ZionFramework.zip] to download.*
* Milestone 3: Working prototype checked into the incubator supporting use cases.
* Milestone 4: Unit tests exist, work, and are checked into SVN.
* Milestone 5: Initial documentation exists.
{zone-data}

{zone-data:class-list}
* Zend_Controller_Plugin_Acl
* Zend_Controller_Action_Helper_Acl
{zone-data}

{zone-data:use-cases}
{composition-setup}
{deck:id=Usecases}
{card:label=UC-01: Initial setup}
index.php
{code}
<?php
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$acl = new Zend_Acl();

/** Creating the Role object */
require_once 'Zend/Acl/Role.php';
$acl->addRole(new Zend_Acl_Role('defaultRole'));

/**
* Creating resources:
* - News Controller
* Creating privileges:
* - Allow defaultRole to access news controller
* - Deny defaultRole to access add action of news controller
*/
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news')
->deny('defaultRole', 'news', 'add');

/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Registering the Plugin object */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl));

/** Dispatching the front controller */
$front->dispatch();
{code}

* Trying to access http://mysite/myapp/news
** Expected result: the view is rendered.
* Trying to access http://mysite/myapp/news/add
** Expected result: the site will forward to http://mysite/myapp/error/denied
{card}
{card:label=UC-02: Using modules}
index.php
{code}
<?php
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$acl = new Zend_Acl();

/** Creating Roles */
require_once 'Zend/Acl/Role.php';
$acl->addRole(new Zend_Acl_Role('defaultRole'))
->addRole(new Zend_Acl_Role('adminRole', 'defaultRole'));

/**
* Creating resources:
* - News Controller
* - Admin Module
* - Admin Module, Blog Controller
* Creating privileges:
* - Allow defaultRole to access news controller
* - Allow adminRole to access admin module
*/
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->add(new Zend_Acl_Resource('admin'))
->add(new Zend_Acl_Resource('admin:blog', 'admin'))
->allow('defaultRole', 'news')
->allow('adminRole', 'admin');

/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory(array('default' => 'path/to/default/controllers',
'admin' => 'path/to/admin/controllers'));

/** Registering the Plugin object */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl));

/** Dispatching the front controller */
$front->dispatch();
{code}

* Trying to access http://mysite/myapp/news
** Expected result: the view is rendered.
* Trying to access http://mysite/myapp/admin/blog/
** Expected result: the site will forward to http://mysite/myapp/error/denied
{card}
{card:label=UC-03: Using roles}
index.php
{code}
<?php
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$acl = new Zend_Acl();

/** Creating Roles */
require_once 'Zend/Acl/Role.php';
$acl->addRole(new Zend_Acl_Role('defaultRole'))
->addRole(new Zend_Acl_Role('adminRole'), 'defaultRole');

/**
* Creating resources:
* - News Controller
* Creating privileges:
* - Allow defaultRole to access news controller
* - Deny defaultRole to access add action of news controller
* - Allow adminRole to access add action of news controller
*/
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news')
->deny('defaultRole', 'news', 'add')
->allow('adminRole', 'news', 'add');

/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Registering the Plugin object using adminRole */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl, 'adminRole'));

/** Dispatching the front controller */
$front->dispatch();
{code}

* Trying to access http://mysite/myapp/news
** Expected result: the view is rendered.
* Trying to access http://mysite/myapp/news/add
** Expected result: the view is rendered.
{card}
{card:label=UC-04: Setting denied error action}
index.php
{code}
<?php
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$acl = new Zend_Acl();

/** Creating the Role object */
require_once 'Zend/Acl/Role.php';
$acl->addRole(new Zend_Acl_Role('defaultRole'));

/**
* Creating resources:
* - News Controller
* Creating privileges:
* - Allow defaultRole to access news controller
* - Deny defaultRole to access add action of news controller
*/
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news')
->deny('defaultRole', 'news', 'add');

/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Setting default access denied action */
require_once 'Zend/Controller/Plugin/Acl.php';
$aclPlugin = new Zend_Controller_Plugin_Acl($acl);
$aclPlugin->setErrorPage('goaway');

/** Registering the Plugin object */
$front->registerPlugin($aclPlugin);

/** Dispatching the front controller */
$front->dispatch();
{code}

* Trying to access http://mysite/myapp/news
** Expected result: the view is rendered.
* Trying to access http://mysite/myapp/news/add
** Expected result: the site will forward to http://mysite/myapp/error/goaway
{card}
{card:label=UC-05: Using the action helper}
index.php
{code}
<?php
/** Creating the ACL object */
require_once 'Zend/Acl.php';
$acl = new Zend_Acl();

/** Creating the Role object */
require_once 'Zend/Acl/Role.php';
$acl->addRole(new Zend_Acl_Role('defaultRole'));

/**
* Creating resources:
* - News Controller
* Creating privileges:
* - Allow defaultRole to access news controller
*/
require_once 'Zend/Acl/Resource.php';
$acl->add(new Zend_Acl_Resource('news'))
->allow('defaultRole', 'news');

/** Setting up the front controller */
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('path/to/controllers');

/** Registering the Plugin object */
require_once 'Zend/Controller/Plugin/Acl.php';
$front->registerPlugin(new Zend_Controller_Plugin_Acl($acl));

/** Registering the Action Helper object */
require_once 'Zend/Controller/Action/Helper/Acl.php';
require_once 'Zend/Controller/Action/HelperBroker.php';
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Acl());

/** Setting the user logged */
require_once 'Zend/Session/Namespace.php';
$myApp = new Zend_Session_Namespace('myApplication');
$myApp->loggedUser = 'aldemar';

/** Dispatching the front controller */
$front->dispatch();
{code}
NewsController.php
{code}
<?php
require_once 'Zend/Controller/Action.php';

class NewsController extends Zend_Controller_Action
{
protected $_acl;

public function init()
{
$this->_acl = $this->_helper->getHelper('acl');
}

public function indexAction()
{
}

public function editAction()
{
$id = $this->_request->getParam('id');

/** Load news by id */
require_once 'News.php';
$news = new News($id);

/** Loading the user logged */
require_once 'Zend/Session/Namespace.php';
$myApp = new Zend_Session_Namespace('myApplication');

if ($news->author != $myApp->loggedUser) {
$this->_acl->denyAccess();
}

$this->view->id = $id;
}
}
{code}
* Trying to access http://mysite/myapp/news/edit/id/15 (loggedUser as the author of news 15)
** Expected result: the view is rendered.
* Trying to access http://mysite/myapp/news/edit/id/31 (loggedUser as not the author of news 31)
** Expected result: the site will forward to http://mysite/myapp/error/denied
{card}
{deck}
{zone-data}

{zone-data:skeletons}
{composition-setup}
{deck:id=Usecases}
{card:label=Zend_Controller_Plugin_Acl}
{code}
class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
/**
* @var Zend_Acl
**/
protected $_acl;

/**
* @var string
**/
protected $_roleName;

/**
* @var array
**/
protected $_errorPage;

/**
* Constructor
*
* @param mixed $aclData
* @param $roleName
* @return void
**/
public function __construct(Zend_Acl $aclData, $roleName = 'defaultRole')
{}

/**
* Sets the ACL object
*
* @param mixed $aclData
* @return void
**/
public function setAcl(Zend_Acl $aclData)
{}

/**
* Returns the ACL object
*
* @return Zend_Acl
**/
public function getAcl()
{}

/**
* Sets the ACL role to use
*
* @param string $roleName
* @return void
**/
public function setRoleName($roleName)
{}

/**
* Returns the ACL role used
*
* @return string
* @author
**/
public function getRoleName()
{}

/**
* Sets the error page
*
* @param string $action
* @param string $controller
* @param string $module
* @return void
**/
public function setErrorPage($action, $controller = 'error', $module = null)
{}

/**
* Returns the error page
*
* @return array
**/
public function getErrorPage()
{}

/**
* Predispatch
* Checks if the current user identified by roleName has rights to the requested url (module/controller/action)
* If not, it will call denyAccess to be redirected to errorPage
*
* @return void
**/
public function preDispatch(Zend_Controller_Request_Abstract $request)
{}

/**
* Deny Access Function
* Redirects to errorPage, this can be called from an action using the action helper
*
* @return void
**/
public function denyAccess()
{}
}
{code}
{card}
{card:label=Zend_Controller_Action_Helper_Acl}
{code}
class Zend_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract
{
/**
* @var Zend_Controller_Plugin_Acl
**/
protected $_aclPlugin;

/**
* Constructor
*
* @return void
**/
function __construct()
{}

/**
* Returns the Acl Plugin object
*
* @return Zend_Controller_Plugin_Acl
**/
public function getAclPlugin()
{}

/**
* Call the denyAccess function of the Acl Plugin object
*
* @return void
**/
public function denyAccess()
{}
}
{code}
{card}
{deck}
{zone-data}

{zone-template-instance}]]></ac:plain-text-body></ac:macro>