We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Access controller/action name from bootstrap

Hi all,

How do I access the controller and action name from the bootstrap file?

I've set up my app with the Security plugin like the Invo app tutorial displays. My authentication is done by a third-party library, and the Security plugin translates the integer access levels that library provides (ie: 1 = admin, 2 = employee, 3 = student), to role strings (ie: "Admin", etc). I would like to have that "role" accessible throughout the application, as well as other user properties provided by the third-party library. Long-story-short, I don't know the "role" of the user until after the beforeExecuteRoute() function is run. So, I'm considering reworking the Security class and just invoke it directly from the bootstrap file (since absolutely every controller/action in my app will require authentication).

However, to do that I need the controller and action names. In the Security-class-as-Plugin code, the beforeExecuteRoute() function gets passed the dispatcher. However, in my bootstrap, if I call $DI->get('dispatcher')->getControllerName(), I always get NULL.



98.9k

Hi, can you please post some code?, the code in your bootstrap for example?

edited Oct '14

Bootloader file

<?PHP
try{
    // Load config
    $Config = require '../app/config/config.php';

    // Register an autoloader
    $Loader = new \Phalcon\Loader();
    $Loader->registerDirs($Config->phalcon->loadDirs)->register();

    // Create a Dependency Injection container
    $DI = new \Phalcon\DI\FactoryDefault();

    // Set up the Dispatcher
    $DI->set('dispatcher',function() use ($DI){

        // Get the standard eventsManager
        $EM = $DI->getShared('eventsManager');

        // Instantiate the Security plugin
        $Security = new Security($DI);

        // Listen for events produced by the Dispatcher using the Security plugin
        $EM->attach('dispatch',$Security);

        // Set the dispatcher to the custom dispatcher with the newly modified Events Manager
        $Dispatcher = new Phalcon\Mvc\Dispatcher();
        $Dispatcher->setEventsManager($EM);

        return $Dispatcher;
    });

    // Set up the View component
    $DI->set('view',function() use ($Config){
        $View = new \Phalcon\Mvc\View();
        $View->setViewsDir($Config->app->appDir.'/views/');
        return $View;
    });

    #
    # User object is created in Security
    #

    # Initialize Session
    $Session = new Phalcon\Session\Adapter\Files();
    $Session->start();
    $Session->config = $Config;
    $DI->setShared('session',$Session);

    // Handle the requested URL
    $App = new \Phalcon\Mvc\Application($DI);

    // Echo the output
    echo $App->handle()->getContent();
}
catch(\Phalcon\Exception $e){
    echo 'Phalcon Exception: ',$e->getMessage();
}

Relevant parts of the Security plugin

<?PHP
#
#
# Relevant parts of the "Security" plugin
#
#
// "beforeExecuteRoute" is the name of the event for which we want this function to be called
public function beforeExecuteRoute($Event,$Dispatcher){

    $role       = $this->getRole();
    $controller = $Dispatcher->getControllerName();
    $action     = $Dispatcher->getActionName();
    $allowed    = $this->getAcl()->isAllowed($role,$controller,$action);

    if($allowed != Phalcon\Acl::ALLOW){
        $this->flash->error('You are not allowed to view this page.');
        $Dispatcher->forward(['controller'=>'index','action'=>'index']);

        // Returning false will tell the Dispatcher to stop the current operation
        return FALSE;
    }
    else
    {
        $User = new User(   [   'level' =>  RemoteAuth::$level,
                        'name'  =>  RemoteAuth::$name,
                        'ccid'  =>  RemoteAuth::$ccid,
                        'role'  =>  $role
                    ]
                );
        $DI = $Dispatcher->getDI();
        $DI->setShared('user',$User);
    }
}

###
# Get the role for the logged in user
###

private function getRole(){
    /* RemoteAuth is the library used by all organizational web apps for central authentication.
       Consequently, it doesn't tie in with Phalcon 100%.  Creating a new RemoteAuth object
       with no session, will cause the "You have no session" page to appear, rather than 
       proper routing via Phalcon
    */
    $RemoteAuth = new RemoteAuth('media',999);
    $level = RemoteAuth::$level;

    //need to convert access levels to "roles" for proper ACL integration
    $roles = $this->session->config->roles;
    $role = (isset($roles[$level])) ? $roles[$level] : FALSE;

    $this->session->role = $role;

    return $role;
}


98.9k

The code seems to be fine, however the Security plugin (for example in INVO) is intended to provide authorization rather than authentication, check the Auth component in Vokuro, perphaps that is you're needing: https://github.com/phalcon/vokuro/tree/master/app/library/Auth

Authorization (determining what privileges a logged in user has) is precisely what I want. Authentication (actually logging in the user) has already happened before this application and code is accessed. The Auth component you referenced seems pretty focused on logging in - Authentication.

The root of the problem is I don't like my "User" object being created in the Security plugin. But it seems attaching to the beforeExecuteRoute event is the only way to do authorization checking before page load. Is there a framework acceptable way to just put this logic in the bootstrap?



98.9k

But are you getting the current role service: new RemoteAuth('media',999)?

What I see is:

1) Perform the authentication getting the role and storing it in session (new RemoteAuth('media',999)) then validate it with the roles, also you don't to store the config in session. 2) In authorization, you use the role in session to check permissions

My apologies, I'm having a bit of trouble figuring out what you mean.

By the time this app is accessed, the user has already been authenticated, and their access level for this app has been determined. The system "RemoteAuth" interacts with assigns access levels (1-3), rather than roles. I need to convert the "level" into a "role

1) Config is stored in session near the bottom of the Bootstrap file 2) Is this an insight into how I'm currently doing authorization, or a comment on how Phalcon generally deals with authorization?

This discussion is perhaps a bit off track. Initially I was just wondering if there was any way to get the current controller & action name in the bootstrap file.