Phalcon forward to different module - phalcon

Trying to work my way through setting up a phalcon mvc application.
I have 2 modules current set up for testing. "Frontend" and "Admin".
I have different views set up so I can confirm I am getting through to each of the modules. When I change the defaultnamespace and defaultmodule I can indeed see that both modules are being accessed fine and loading ok. I can see that the admin controllers are being accessed correctly and the frontend controllers are being accessed when I change this.
The problem I am currently having is when I try to authenticate a user and start the session I want to forward the request over from "Frontend" to "Admin":
return $this->dispatcher->forward(array(
'namespace' => 'Qcm\Admin\Controllers',
'action' => 'index',
'controller' => 'index'
));
Again I have confirmed these namespaces work fine. The problem is when I now forward onto the new namespace it can no longer find the admin index controller?
"Qcm\Admin\Controllers\IndexController handler class cannot be loaded"
However I have already confirmed that I can switch between the modules by changing the defaultnamespace/defaultmodule. Is this a limitation within the dispatcher that I can not forward to a different module?
Just to clarify I am also using the same url's so for example after login I want it to go back to '/' (root) but because it has forwarded to the admin module this should work fine correct?

The phalcon dispatcher can only forward to actions within the same module. It cannot forward you outside the current module. This restriction comes because the dispatcher is only aware of the module in which it is declared.
In order to forward to another module, you must instead return a redirect response from a controller action. In my case, I wanted to forward the user to a login screen or a 404 error page based on their ACL permissions in the beforeDispatch() method of a plugin. The dispatcher is native to this method, but cannot forward the user outside of the current module. Instead, I have the dispatcher forward the user to a controller in the same module that has a custom action that in turn performs the redirect.
// hack to redirect across modules
$dispatcher->forward(
array(
'controller' => 'security',
'action' => 'redirect',
'params' => array(
'redirect' => '/home/index/login'
),
)
);
return false; // stop progress and forward to redirect action
This means that each module needs to have a copy of this custom redirect action in one of its controllers. I accomplished this by putting the action in the base controller that all of my controllers extend from.
/**
* the phalcon dispatcher cannot forward across modules
* instead, forward to this shared action which can then redirect across modules
* */
public function redirectAction(){
$this->view->disable();
$params = $this->dispatcher->getParams();
$redirect = '/';
if( ! empty( $params['redirect'] ) ){
$redirect = $params['redirect'];
}
return $this->response->redirect( $redirect );
}

Because phalcon didn't add all modules to global loader, so the namespace is not registered. you need to register another module in current module bootstrap file, modify your Module.php as
class Module
{
public function registerAutoloaders()
{
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
//Your current module namespaces here
....
//Another module namespaces here
'Qcm\Admin\Controllers' => 'controller path',
));
$loader->register();
}
}

The main reason it shows IndexController class not loaded is because you might not have added Dispatcher in that module or in the bootstrap file(depending on your approach)
Add
$debug = new \Phalcon\Debug();
$debug->listen();
to your code before
$application->handle()->getcontent();
to view erros.

Before the replacement line:
echo $application->handle()->getContent();
code:
$router = $this->getDi()->get("router");
$params = $router->getParams();
$modName = $router->getModuleName();
$url = null;
if ($modName == "admin" && isset($params[0])) {
$module = "/" . $params[0];
$controller = isset($params[1]) ? "/" . $params[1] . "/" : null;
$action = isset($params[2]) ? $params[2] . "/" : null;
$params = sizeof($params) > 3 ? implode("/", array_slice($params, 3)) . "/" : null;
$url = $module . $controller . $action . $params;
}
echo $application->handle($url)->getContent();

Related

Laminas Authentication adapter is being overwritten

I'm running into an issue where Laminas's Authentication Service's adapter is being overwritten from another module. How I have it set up is that under the Application module it sets the adapter, which is fine, but when I have it set the Adapter under another module, it overwrites the adapter in Application, or so I think that this is the issue, because when I prevent the other module from being initialized, it works just fine.
Here is the code I have in place for Module.php in the Application Module:
AuthenticationService::class => function($container) {
$db_adapter = $container->get(Adapter::class);
$auth_adapter = new DbTableAuthAdapter($db_adapter, 'users', 'username', 'password');
$auth_service = new AuthenticationService();
$auth_service->setAdapter($auth_adapter);
$auth_service->setStorage($container->get(LoginAuthStorage::class));
return $auth_service;
},
And here is the code in the other module
AuthenticationService::class => function($container) {
$db_adapter = $container->get(Adapter::class);
$auth_adapter = new DbTableAuthAdapter($db_adapter, 'admins', 'username', 'password');
$auth_service = new AuthenticationService();
$auth_service->setAdapter($auth_adapter);
$auth_service->setStorage($container->get(AdminLoginAuthStorage::class));
return $auth_service;
},
For further clarification, here is the list of module namespaces being loaded:
/**
* List of enabled modules for this application.
*
* This should be an array of module namespaces used in the application.
*/
return [
'Laminas\Navigation',
'Laminas\Mail',
'Laminas\Di',
'Laminas\Log',
'Laminas\Db',
'Laminas\Mvc\Plugin\FilePrg',
'Laminas\Mvc\Plugin\FlashMessenger',
'Laminas\Mvc\Plugin\Identity',
'Laminas\Mvc\Plugin\Prg',
'Laminas\Session',
'Laminas\Mvc\I18n',
'Laminas\Form',
'Laminas\Hydrator',
'Laminas\InputFilter',
'Laminas\Filter',
'Laminas\I18n',
'Laminas\Router',
'Laminas\Validator',
'Laminas\Diactoros',
'Application',
'Admin',
];
If I comment out 'Admin', it works fine but if not, it tries to fetch the adapter I defined for the admin module under application.
I apologize in advance if my question is unclear, I am uncertain how to phrase it to be honest. What I am basically am trying to do is to have one authentication service for users under the application module and an authentication service for admins under the admin module.
Thanks!

How do I access the oauth2 authenticated user in a Lumen controller?

I have followed this excellent tutorial Building a Web App with Lumen and OAuth2 for setting up OAuth2 and Lumen. Everything is working fine apart from now I want to access the currently authenticated user information/model.
My route correctly posts the supplied information after I have logged in and I can break with Netbeans inside the controller but I am not clear how to get the user from the underlying Auth framework. I have tried the three methods indicated here Authentication - Laravel but to no avail. The lumen logs shows:
==== routes.php ====
$app->group(['namespace' => 'App\Http\Controllers','prefix' => 'api', 'middleware' => 'oauth'], function($app)
{
$app->post('info', 'InfoController#send');
}
==== InfoController.php ====
namespace App\Http\Controllers;
// the controllers
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Authenticatable;
class InfoController extends Controller{
/* /api/info methods */
public function send(Request $request){
// can iterate over the entire users table but I just
// want the current user (must be some method through
// the authentication stack)
$users = \App\Auth\User::all();
foreach ($users as $user) {
$name = $user->name;
$key = $user->getAuthIdentifier();
$pwd = $user->getAuthPassword();
}
// CODE GETS HERE BUT how to get the current user?
// Authenticated OK (request supplies "Access-Token: Bearer ...")
}
}
This is probably not the cleanest solution and may not match your requirements exactly but it does retrieve the user.
I decided to make another DB query in the proxy to get the user with the same key (in my case, email address) that was requested by the client.
In my case I was sending the user id along with the standard oauth token.
You could use the same technique to set some value in the session.
// ../app/Auth/Proxy.php
namespace App\Auth;
use App\User; // ----- added this line
use GuzzleHttp\Client;
class Proxy {
...
private function proxy($grantType, array $data = [])
{
...
$response = json_decode($guzzleResponse->getBody());
if (property_exists($response, "access_token")) {
...
// added the following line to get the user
$user = User::where('email',$data['username'])->get()->first();
// untested, but you could add the user to your session here
$request = app()->make('request');
$request->session()->put('current_user', $user);
$response = [
'accessToken' => $response->access_token,
'accessTokenExpiration' => $response->expires_in,
'userId' => $user->id,
];
}
...

How to retrieve values from YII configuration and create custom parameters in configuration?

How to retrieve values from yii 2.0 configuration and create custom parameters in configuration? Is there any legal way?
http://www.yiiframework.com/doc-2.0/index.html gives no information, I could not find configuration class
Thanks
In your config file add:
$params = array_merge(
require(__DIR__ . '/params.php'),
......
//more here if needed
);
Then make file params.php here and add:
<?php
return [
'adminEmail' => 'admin#example.com',
];
To use params do:
Yii::$app->params['adminEmail']
Ofcourse with use Yii namespace.

Kohana 3.3 force SSL in controller

I have a few controllers. HTTPS is redirected by the webserver (ligttpd) itself, but as a extra security-check I want PHP to redirect specific controllers to https.
Does Kohana contain a function to check if the url is running on SSL and to redirect it if needed?
Found out my own answer :)
Make a class called URL:
class URL extends Kohana_URL
{
public static function SSL()
{
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "") {
$redirect = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("Location: $redirect");
}
}
}
Call it in your controller like this:
URL::ssl();
Please note: Using only above method is unsafe. You should redirect by server (Lighttpd/Nginx/Apache) too.

yii-user extension include(WebUser.php) No such file or directory

i'm trying to install the extension of yii-user following this official tutorial
http://www.yiiframework.com/extension/yii-user/#hh2
But i'm having some problems, specially when i'm adding this
user'=>array(
// enable cookie-based authentication
'class' => 'WebUser',
'allowAutoLogin'=>true,
'loginUrl' => array('/user/login'),
to the configuration main. When i add this code, i have this message error
include(WebUser.php) [function.include]: failed to open stream: No such file or directory
Any clue? I need to do something before?
Thanks in advance
I searched a little bit and i found the solution. But it wasn't in the documentation.
So, we should create the WebUser.php in protected/components like this :
<?php
// this file must be stored in:
// protected/components/WebUser.php
class WebUser extends CWebUser {
// Store model to not repeat query.
private $UserLogin;
// Return first name.
// access it by Yii::app()->user->first_name
function getFirst_Name(){
$user = $this->loadUserLogin(Yii::app()->user->user_id);
return $user->first_name;
}
// This is a function that checks the field 'role'
// in the User model to be equal to 1, that means it's admin
// access it by Yii::app()->user->isAdmin()
function isAdmin(){
$user = $this->loadUser(Yii::app()->user->user_id);
return intval($user->user_role_id) == 1;
}
// Load user model.
protected function loadUserLogin($id=null)
{
if($this->UserLogin===null)
{
if($id!==null)
$this->UserLogin=UserLogin::model()->findByPk($id);
}
return $this->UserLogin;
}
}?>
and should work.
Did you follow the instructions at http://www.yiiframework.com/extension/yii-user/#hh2?
You probably forgot to specify import paths to the user module in config.php
'import'=>array(
...
'application.modules.user.models.*',
'application.modules.user.components.*',
),
I had the same problem and found that it's the permission problem. Apache user (www-data in my case) couldn't access protected/modules/users/* files.