I've been working on putting a new app up against Zend. In my admin section, I want the nav links to only show if the user has rights to see the page. So I set up some Acls. But this doesn't seem like the right way to do things. What's the "right" way to do this stuff?
Bootstrap.php
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected $_aclAdapter;
protected function _initDoctype() {
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
}
protected function _initPlugins() {
// First, set up the Cache
$frontendOptions = array(
'automatic_serialization' => true
);
if (! is_dir("/tmp/cache")) mkdir("/tmp/cache");
$backendOptions = array(
'cache_dir' => '/tmp/cache'
);
$cache = Zend_Cache::factory('Core',
'File',
$frontendOptions,
$backendOptions);
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
$this->_aclAdapter = new My_Plugin_Acl();
}
protected function _initRoute() {
/*
$this->bootstrap('FrontController');
$front = $this->getResource('FrontController');
$router = $front->getRouter();
$restRoute = new Zend_Rest_Route($front, array(), array('rest'));
$router->addRoute('rest', $restRoute);
return $router;
*/
}
protected function _initAutoloadModuleAdmin() {
$autoloader = new Zend_Application_Module_Autoloader(
array(
'namespace' => 'Admin',
'basePath' => APPLICATION_PATH . '/modules',
)
);
return $autoloader;
}
protected function _initDatabase() {
$database = Zend_Db_Table::getDefaultAdapter();
return $database;
}
protected function _initAuthChecker() {
$this->bootstrap('view');
$view = $this->getResource('view');
/**
* @todo Determine how to pass Acl information to the view
* so that links can be determined properly
*/
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$view->isLoggedIn = true;
$aclAdapter = $this->_aclAdapter;
$container = new Zend_Navigation();
$pages = array(
new Zend_Navigation_Page_Mvc(array('module' => 'admin', 'action' => 'index', 'controller' => 'make', 'label' => 'Makes')),
new Zend_Navigation_Page_Mvc(array('module' => 'admin', 'action' => 'index', 'controller' => 'model', 'label' => 'Models')),
new Zend_Navigation_Page_Mvc(array('module' => 'admin', 'action' => 'index', 'controller' => 'year', 'label' => 'Years')),
new Zend_Navigation_Page_Mvc(array('module' => 'admin', 'action' => 'index', 'controller' => 'user', 'label' => 'Users')),
);
foreach ($pages as $page) {
$resources = $aclAdapter->getCurrentResources($page);
$allowedToViewResource = true;
foreach ($resources as $resource) {
// access to the module
if(!$aclAdapter->isAllowed($aclAdapter->getRolesForIdentity($auth->getIdentity()->nickname), $resource, 'view')) {
$allowedToViewResource = false;
}
}
if ($allowedToViewResource) {
$container->addPage($page);
}
$view->navigation = $container;
}
} else {
$view->isLoggedIn = false;
}
}
}
My/Plugin/Acl.php
<?php
/**
* Acl functionality
*
* @category My
* @package My_Plugin
* @author Glen Solsberry <glens@dp.cx>
*/
class My_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
/**
* @var Zend_Acl
*/
protected $_acl = null;
public function __construct() {
$args = func_get_args();
if (count($args) > 0) {
$this->_acl = $args[0];
} else {
$this->_acl = new Zend_Acl();
}
$this->_acl = $this->setupRoles($this->_acl);
$this->_acl = $this->setupResources($this->_acl);
$this->_acl = $this->setupAllowances($this->_acl);
}
public function isAllowed($role, $resource, $function) {
return $this->_acl->isAllowed($role, $resource, $function);
}
/**
* preDispatch
*
* @param Zend_Controller_Request_Abstract $request
* @return none
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
if (Zend_Auth::getInstance()->hasIdentity()) {
$identity = Zend_Auth::getInstance()->getIdentity();
$role = $this->getRolesForIdentity($identity->nickname);
} else {
$role = 'guest';
}
$resources = $this->getCurrentResources($request);
$allowedToViewResource = true;
foreach ($resources as $resource) {
// access to the module
if(!$this->_acl->isAllowed($role, $resource, 'view')) {
$allowedToViewResource = false;
}
}
if ($allowedToViewResource === false) {
//If the user has no access we send him elsewhere by changing the request
// print sprintf("I'm sorry, but your role '%s' doesn't have access to the resource named '%s'<br>", $role, $resource);
$request->setModuleName('')->setControllerName('auth')->setActionName('login');
return false;
}
return true;
}
public function getCurrentResources($request) {
if ($request instanceOf Zend_Controller_Request_Http) {
$resources = array(
$request->getModuleName(),
implode("-", array($request->getModuleName(), $request->getControllerName())),
implode("-", array($request->getModuleName(), $request->getControllerName(), $request->getActionName())),
);
} else if ($request instanceOf Zend_Navigation_Page_Mvc) {
$resources = array(
$request->getModule(),
implode("-", array($request->getModule(), $request->getController())),
implode("-", array($request->getModule(), $request->getController(), $request->getAction())),
);
} else {
throw new Zend_Exception('Unsupported request type');
}
return $resources;
}
/**
* Gets available roles for an identity, by nickname
* @param string $nickname
*/
public function getRolesForIdentity($nickname) {
if ($nickname === "") {
return 'guest';
}
return 'admin';
}
private function setupRoles(Zend_Acl $acl) {
$acl->addRole(new Zend_Acl_Role('guest'));
// make-admin has all rights that guest has
$acl->addRole(new Zend_Acl_Role('make-admin'), 'guest');
$acl->addRole(new Zend_Acl_Role('model-admin'), 'guest');
$acl->addRole(new Zend_Acl_Role('year-admin'), 'guest');
$acl->addRole(new Zend_Acl_Role('user-admin'), 'guest');
// admin has all rights that year-admin, make-admin, user-admin and model-admin have
$acl->addRole(new Zend_Acl_Role('admin'), array('year-admin', 'make-admin', 'model-admin', 'user-admin'));
return $acl;
}
private function setupResources(Zend_Acl $acl) {
// setup admin resources
$this->setupResourcesFromArrays(
$acl,
array('admin'),
array('index','make','year','model','user'),
array('index','update','delete')
);
$this->setupResourcesFromArrays(
$acl,
array('default'),
array('auth','index','error'),
array('index')
);
$this->setupResourcesFromArrays(
$acl,
array('default'),
array('auth'),
array('logout')
);
$this->setupResourcesFromArrays(
$acl,
array('default'),
array('favicon.ico'),
null
);
return $acl;
}
private function setupResourcesFromArrays($acl, $modules, $controllers, $actions) {
foreach ($modules as $module) {
$resource_name = $module;
$this->addResource($acl, $resource_name);
foreach ($controllers as $controller) {
$resource_name = sprintf('%s-%s', $module, $controller);
$this->addResource($acl, $resource_name);
if (is_array($actions)) {
foreach ($actions as $action) {
$resource_name = sprintf('%s-%s-%s', $module, $controller, $action);
$this->addResource($acl, $resource_name);
}
}
}
}
}
private function addResource($acl, $resource_name) {
if (! $acl->has($resource_name)) {
$acl->addResource(new Zend_Acl_Resource($resource_name));
}
}
private function setupAllowances(Zend_Acl $acl) {
// role, resource, privilege
$acl->allow('admin', 'admin', 'view');
$acl->allow('admin', 'admin-index', 'view');
$acl->allow('admin', 'admin-index-index', 'view');
/**
SNIP
*/
$acl->allow('guest', 'default', 'view');
$acl->allow('guest', 'default-index', 'view');
$acl->allow('guest', 'default-index-index', 'view');
$acl->allow('guest', 'default-auth', 'view');
$acl->allow('guest', 'default-auth-index', 'view');
return $acl;
}
}