i was following the tutorial by Jesse Boyer, but I am stuck on the ACL part of teh tutorial, which seems not to be working for some reason, when adding more public areas like 'posts', 'forum' etc. instead of just 'index' and 'signin'.
Background info:
I am running Windows 7 64-bit and WAMP SERVER 2.4 (32-bit) with PHP 5.4.16 and Apache is 2.4.4, if it helps. It's a strange combination, but the 64-bit versions of WAMP didn't work on my 64-bit machine for some reason.
Phalcon Windows dll version is 1.3.2 x86 TS ( the same problem occurs with 1.3.1. version as well )
I have this in my Permission.php file located in config/Permission.php
<?php
use \Phalcon\Mvc\Dispatcher,
\Phalcon\Events\Event,
\Phalcon\Acl;
/**
* Permission
*
* Prevents User Types from accessing areas they are not allowed in.
*/
class Permission extends \Phalcon\Mvc\User\Plugin {
/**
* Constants to prevent a typo
*/
const GUEST = 'guest';
const USER = 'user';
const ADMIN = 'admin';
/**
* Accessible to everyone
* @var array
*/
protected $_publicResources = [
'index' => ['*'],
'signin' => ['*'],
'posts' => ['*'],
];
/**
* Accessible to Users (and Admins)
* @var array
*/
protected $_userResources = [
'dashboard' => ['*']
];
/**
* Accessible to Admins
* @var array
*/
protected $_adminResources = [
'admin' => ['*']
];
// ------------------------------------------------------------------------
/**
* Triggers before a route is successfully executed
*
* @param Event $event
* @param Dispatcher $dispatcher
*
* @return boolean|void
*/
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
{
// Debug
// $this->session->destroy();
// Get the current role
$role = $this->session->get('role');
if (!$role) {
$role = self::GUEST;
}
// Get the current Controller/Action from the dispatcher
$controller = $dispatcher->getControllerName();
$action = $dispatcher->getActionName();
// Get the ACL Rule List
$acl = $this->_getAcl();
// See if they have permission
$allowed = $acl->isAllowed($role, $controller, $action);
if ($allowed != Acl::ALLOW)
{
$this->flash->error('You do not have permission to access this area');
$this->response->redirect('');
// Stop the dispatcher at the current operation
$this->view->disable();
return false;
}
}
// ------------------------------------------------------------------------
/**
* Build the Session ACL list one time if it's not set
*
* @return object
*/
protected function _getACL()
{
if (!isset($this->persistent->acl))
{
$acl = new Acl\Adapter\Memory();
$acl->setDefaultAction(Acl::DENY);
$roles = [
self::GUEST => new Acl\Role(self::GUEST),
self::USER => new Acl\Role(self::USER),
self::ADMIN => new Acl\Role(self::ADMIN),
];
// Place all the roles inside the ACL Object
foreach ($roles as $role) {
$acl->addRole($role);
}
// Public Resources
foreach ($this->_publicResources as $resource => $action) {
$acl->addResource(new Acl\Resource($resource), $action);
}
// User Resources
foreach ($this->_userResources as $resource => $action) {
$acl->addResource(new Acl\Resource($resource), $action);
}
// Admin Resources
foreach ($this->_adminResources as $resource => $action) {
$acl->addResource(new Acl\Resource($resource), $action);
}
// Allow ALL Roles to access the Public Resources
foreach ($roles as $role) {
foreach($this->_publicResources as $resource => $action) {
$acl->allow($role->getName(), $resource, '*');
}
}
// Allow User & Admin to access the User Resources
foreach ($this->_userResources as $resource => $actions) {
foreach ($actions as $action) {
$acl->allow(self::USER, $resource, $action);
$acl->allow(self::ADMIN, $resource, $action);
}
}
// Allow Admin to access the Admin Resources
foreach ($this->_adminResources as $resource => $actions) {
foreach ($actions as $action) {
$acl->allow(self::ADMIN, $resource, $action);
}
}
$this->persistent->acl = $acl;
}
return $this->persistent->acl;
}
// ------------------------------------------------------------------------
}
then I got this in my PostsController.php:
<?php
use \Phalcon\Tag;
class PostsController extends BaseController {
public function onConstruct()
{
parent::initialize();
}
public function indexAction()
{
Tag::setTitle('Posts');
}
}
and this in my index.php in the public root (bootstrap file):
<?php
require '../app/config/Config.php';
try {
//Register an autoloader
$loader = new \Phalcon\Loader();
$loader->registerDirs([
'../app/controllers/',
'../app/models/',
'../app/config/'
]);
$loader->registerClasses([
'Component\User' => '../app/components/User.php',
'Component\Helper' => '../app/components/Helper.php',
'Component\Security' => '../app/components/Security.php',
]);
$loader->register();
// Create a DI
$di = new Phalcon\DI\FactoryDefault();
// Return general config
$di->setShared('config', function() use ($config) {
return $config;
});
// Return API config
$di->setShared('api', function() use ($api) {
return $api;
});
// Return custom components
$di->setShared('component', function() {
$obj = new stdClass();
$obj->helper = new \Component\Helper;
$obj->user = new \Component\User;
return $obj;
});
// Database
$di->set('db', function() use ($di) {
$dbConfig = $di->get('config')->get('db')->toArray();
$db = new \Phalcon\Db\Adapter\Pdo\Mysql($dbConfig);
return $db;
});
// View
// Register Volt as a service
$di->set('voltService', function($view, $di) {
$volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
$volt->setOptions(array(
"compiledPath" => "../app/compiled-templates/",
"compiledExtension" => ".compiled",
"compileAlways" => true
));
return $volt;
});
// Register Volt as template engine
$di->set('view', function() {
$view = new \Phalcon\Mvc\View();
$view->setViewsDir('../app/views/');
$view->registerEngines(array(
".volt" => 'voltService'
));
return $view;
});
// Router
$di->set('router', function() {
$router = new \Phalcon\Mvc\Router();
$router->mount(new Routes());
return $router;
});
// Session
$di->setShared('session', function() {
$session = new \Phalcon\Session\Adapter\Files();
$session->start();
return $session;
});
// Flash Data (Temporary Data)
$di->set('flash', function() {
$flash = new \Phalcon\Flash\Session([
'error' => 'alert alert-danger',
'success' => 'alert alert-success',
'notice' => 'alert alert-info',
'warning' => 'alert alert-warning',
]);
return $flash;
});
// Base URI
$di->set('url', function(){
$url = new \Phalcon\Mvc\Url();
$url->setBaseUri('/test/');
return $url;
});
// Custom dispatcher including ACL (Overrides the default)
$di->set('dispatcher', function() use ($di) {
$eventsManager = $di->getShared('eventsManager');
// Custom ACL Class
$permission = new Permission();
// Listen for events from the permission class
$eventsManager->attach('dispatch', $permission);
$dispatcher = new \Phalcon\Mvc\Dispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
});
// Security - temporary b/c security->hash bug in 1.3.2
$di->set('security', function(){
$security = new \Component\Security();
//Set the password hashing factor to 12 rounds
$security->setWorkFactor(12);
return $security;
}, true);
// Deploy the App
$application = new \Phalcon\Mvc\Application($di);
echo $application->handle()->getContent();
} catch(\Phalcon\Exception $e) {
// !!! comment in production !!!
echo "PhalconException: ", $e->getMessage();
}
And I can only access: https://localhost/test/index
and https://localhost/test/signin
but I am NOT able to access https://localhost/test/posts
. When I hit https://localhost/test/posts
I am automaticallty redirected to the homepage and the message You do not have permission to access this area
pops out.
So, I think the problem is probably in the Permission.php file. Any idea what is wrong there?
Another thing that I don't understand is that even if I comment out the signin from the resources like:
/**
* Accessible to everyone
* @var array
*/
protected $_publicResources = [
'index' => ['*'],
// 'signin' => ['*'],
// 'posts' => ['*'],
];
I can still access https://localhost/test/signin
. How is it possible?
Could this part:
// Allow ALL Roles to access the Public Resources
foreach ($roles as $role) {
foreach($this->_publicResources as $resource => $action) {
$acl->allow($role->getName(), $resource, '*');
}
}
be causing the problem?