Layout redirect in zend Framework 2 - authentication

Is it possible to redirect to a route in Layout.phtml in ZF2. I want to redirect to login page if the user is not logged in from layout.phtml
So far i have tried:
<?php $auth = new AuthenticationService();
if ($auth->hasIdentity()) {?>
<li class="active"><a href="<?php echo $this->url('home') ?>">
<?php echo $this->translate('Home') ?></a></li>
<li class="active"><?php echo $this->translate('Logout') ?></li>
<?php
}
else
{
$this->_forward('login/process');
} ?>
its giving me error "get was unable to fetch or create an instance for _forward"
BOOTSTRAP CODE:
public function onBootstrap(MvcEvent $e)
{
$e->getApplication()->getServiceManager()->get('translator');
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$eventManager = $e->getApplication()->getEventManager();
//nothing's available for non logged user, so redirect him to login page
$eventManager->attach("dispatch", function($e) {
$match = $e->getRouteMatch();
$list = $this->whitelist;
// Route is whitelisted
$name = $match->getMatchedRouteName();
if (in_array($name, $list)) {
return;
}
$sm = $e->getApplication()->getServiceManager();
$controller = $e->getTarget();
$auth = $sm->get('AuthService');
if (!$auth->hasIdentity() && $e->getRouteMatch()->getMatchedRouteName() !== 'login/process') {
$application = $e->getTarget();
$e->stopPropagation();
$response = $e->getResponse();
$response->setStatusCode(302);
$response->getHeaders()->addHeaderLine('Location', $e->getRouter()->assemble(array(), array('name' => 'login/process')));
//returning response will cause zf2 to stop further dispatch loop
return $response;
}
}, 100);
}

This is not something that you wanna be doing inside your layout.phtml. Typically you want to hook in to an event that happens before the rendering. In ZF2, the earliest event to hook into that kind of stuff, where it makes sense to hook into, would be the route event. A good diagram of the process that's used in the Authorization-Module BjyAuthorize explains it quite well:
If you don't want to use the Module, you can minify what's happening there, too, like this:
//class Module
public function onBootstrap(MvcEvent $mvcEvent)
{
$eventManager = $mvcEvent->getApplication()->getEventManager();
$eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), -1000);
}
public function onRoute(MvcEvent $event)
{
$serviceLocator = $mvcEvent->getApplication()->getServiceLocator();
// From this point onwards you have access to the ServiceLocator and can check
// for an authenticated user and if the user is not logged in, you return a
// Response object with the appropriate ResponseCode redirected and that's it :)
}

Related

Dynamic domain in reset password link Laravel 8

I'm aware that password reset link can be customized by adding the below function in AuthServiceProvider.php
ResetPassword::createUrlUsing(function ($user, string $token) {
return 'https://example.com/reset-password?token='.$token;
});
This is my sendResetPassword function
public function sendResetPassword(Request $request) {
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
if ($status === Password::RESET_LINK_SENT) {
return response()->json(['message' => __($status)], 200);
} else {
return response()->json(['message' => __($status)], 500);
}
}
Now I'm wondering if there is a way to pass a domain from the sendResetPassword $request to the createUrlUsing function.
The main purpose of this is to avoid hardcoding the frontend URL in my API. I just want that the forgot password form in my frontend sends the email and also the domain.
Not sure if this is the best approach, but as soon I posted the question I found that this is a working solution:
ResetPassword::createUrlUsing(function ($user, string $token) {
return $this->app->request->headers->get('origin').'/reset-password?token='.$token;
});

Laravel /broadcasting/auth Always forbidden with 403 Error

I tried many solutions but no one works for me
I've installed Laravel echo and pusher js and Pusher/Pusher
#bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
});
#.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=my_id
PUSHER_APP_KEY=my_key
PUSHER_APP_SECRET=my_secret
PUSHER_APP_CLUSTER=eu
my event file NewMessage
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('messages.'. $this->message->to);
}
public function broadcastWith()
{
return ["message" => $this->message];
}
}
channel.php
Broadcast::channel('messages.{id}', function ($user, $id) {
return $user->id === (int) $id;
});
Vue App JS code
mounted(){
Echo.private(`messages${this.user.id}`)
.listen('NewMessage', (e) => {
this.handleIncoming(e.message)
});
},
methods:{
saveNewMessage(msg){
this.messages.push(msg);
},
handleIncoming(message){
if(this.selectedContact && message.from == this.selectedContact.id ){
this.saveNewMessage(message);
return;
}
alert(message.text);
}
}
Api.php
Route::post('/conversation/send', 'Api\ContactController#sendNewMessage');
Contact Controller
public function sendNewMessage(Request $request)
{
$message = Message::create([
'from' => $request->sender_id,
'to' => $request->receiver_id,
'text' => $request->text
]);
broadcast(new NewMessage($message));
return response()->json($message);
}
I also read the official documentation everything is going good but I didn't figure out why, it's a throwing error. Have any idea?
I figure out why it is every time shows auth forbidden or doesn't display auth
Solution:
you need to double-check your PUSHER_APP_KEY because if it is not set correctly, it will through error because our stream not connected with pusher
PUSHER_APP_KEY="PUT KEY HERE"
If you are very sure that your app key is correct then go to the Network tab and click on your pusher app key which like e70ewesdsdssew0
If it is displaying the result like this
{"event":"pusher:connection_established","data":"{\"socket_id\":\"131139.31305364\",\"activity_timeout\":120}"}
your API key is good
if it not correct it will display an error like this
{"event":"pusher:error","data":{"code":4001,"message":"App key 3fdsfdfsdfsd not in this cluster. Did you forget to specify the cluster?"}}
Also, don't forget to put the cluster key
PUSHER_APP_CLUSTER=eu

Make an ajax request from a Prestashop module

I am making a module and I need to make an ajax request, with JSON response if possible, how can i do this ?
I don't understand really well the structure of Prestashop 1.7 on this.
Thanks !
This is pretty simple, you just have to make the controller with Prestashop's standards then link it to your frontend Javascript.
Name a php file like this : ./modules/modulename/controllers/front/ajax.php
Then put inside :
<?php
// Edit name and class according to your files, keep camelcase for class name.
require_once _PS_MODULE_DIR_.'modulename/modulename.php';
class ModuleNameAjaxModuleFrontController extends ModuleFrontController
{
public function initContent()
{
$module = new ModuleName;
// You may should do some security work here, like checking an hash from your module
if (Tools::isSubmit('action')) {
// Usefull vars derivated from getContext
$context = Context::getContext();
$cart = $context->cart;
$cookie = $context->cookie;
$customer = $context->customer;
$id_lang = $cookie->id_lang;
// Default response with translation from the module
$response = array('status' => false, "message" => $module->l('Nothing here.'));
switch (Tools::getValue('action')) {
case 'action_name':
// Edit default response and do some work here
$response = array('status' => true, "message" => $module->l('It works !'));
break;
default:
break;
}
}
// Classic json response
$json = Tools::jsonEncode($response);
echo $json;
die;
// For displaying like any other use this method to assign and display your template placed in modules/modulename/views/template/front/...
// Just put some vars in your template
// $this->context->smarty->assign(array('var1'=>'value1'));
// $this->setTemplate('template.tpl');
// For sending a template in ajax use this method
// $this->context->smarty->fetch('template.tpl');
}
}
?>
In your Module Hooks, you need to bring access to the route in JS, so we basicaly make a variable :
// In your module PHP
public function hookFooter($params)
{
// Create a link with the good path
$link = new Link;
$parameters = array("action" => "action_name");
$ajax_link = $link->getModuleLink('modulename','controller', $parameters);
Media::addJsDef(array(
"ajax_link" => $ajax_link
));
}
On the frontend side, you just call it like this in a JS file (with jQuery here) :
// ajax_link has been set in hookfooter, this is the best way to do it
$(document).ready(function(){
$.getJSON(ajax_link, {parameter1 : "value"}, function(data) {
if(typeof data.status !== "undefined") {
// Use your new datas here
console.log(data);
}
});
});
And voila, you have your ajax ready to use controller

Facing difficulties to activate user registration by email in Yii

I am facing problem to activate an user by click on activation link that sent by email.
After click on activation link i.e. http://www.example.com/devtest/index.php?r=user/check&activationcode=bc74873d0e3f684d3e6b99a36169a793ee688406 then it redirect to login page without updating database.
I think my following controller code not working for view file check.php which located on user directory.
Here is my code-
UserController.php:
public function actionCheck(){$activationcode = Yii::app()->request->getQuery('activationcode');
if(isset($activationcode))
{
$model = User::model()->findByAttributes(array('activationcode'=>$activationcode));
if($model !== null)
{
$model->status=1;
$model->save();Yii::app()->user->setFlash('check','Thank you for register with us');
$this->refresh();
}
}
$this->render('check',array('model'=>$model));
}
View file check.php:
<?php if(Yii::app()->user->hasFlash('check')): ?>
<div class="flash-success">
<?php echo Yii::app()->user->getFlash('check'); ?>
</div>
<?php endif; ?>
I am not sure how I can handle GET URL action in UserController. Also, I already tested by adding word 'check' in accessRules but then browser show me Page not redirect properly.
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','create','view','captcha'),
'users'=>array('*'),
),);}
Any idea? Please give me a solution about my issue.
With Thanks,
MRS
I think that your model is null, so you can't update database.
Also I think that your action should be like this
public function actionCheck(){$activationcode = null){
if(!is_null($activationcode))
{
$model = User::model()->findByAttributes(array('activationcode'=>$activationcode));
if($model){
$model->status=1;
if($model->save())
Yii::app()->user->setFlash('check','Thank you for register with us');
$this->refresh();
}else{
Yii::app()->user->setFlash('check','Something is wrong!');
}
}
$this->render('check',array('model'=>$model));
}
I think you haven't added Check action to your accessControl and allowed all users to it.
Could you please paste your accessRules array code here?
public function filters() {
return array(
'accessControl',
);
}
public function accessRules() {
return array(
array('allow', // allow all users to perform
'actions'=>array('check'),
'users'=>array('*'),
),

Elliot Haughin API verify credentials error

I am currently building an Twitter client application for campus project using Codeigniter and Elliot Haughin Twitter library. It's just a standard application like tweetdeck. After login, user will be directed to the profile page containing timline. I am using Jquery to refresh the timeline every 20 second. At the beginning, everything run smoothly until i found the following error at the random time :
![the error][1]
A PHP Error was encountered
Severity: Notice
Message: Undefined property: stdClass::$request
Filename: libraries/tweet.php
Line Number: 205
I already search the web about this error but can't find satisfied explanation. So I tried to find it myself and found that the error comes out because credentials validation error. I tried to var_dump the line $user = $this->tweet->call('get', 'account/verify_credentials'); and resulting an empty array. My question is how come this error showed up when user already login and even after updated some tweets? is there any logical error in my script or is it something wrong with the library? Could anyone explain whats happening to me? please help me...
Here's my codes:
The Constructor Login.php
<?php
class Login extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('tweet');
$this->load->model('login_model');
}
function index()
{
$this->tweet->enable_debug(TRUE); //activate debug
if(! $this->tweet->logged_in())
{
$this->tweet->set_callback(site_url('login/auth'));
$this->tweet->login();
}
else
{
redirect('profile');
}
}
//authentication function
function auth()
{
$tokens = $this->tweet->get_tokens();
$user = $this->tweet->call('get', 'account/verify_credentials');
$data = array(
'user_id' => $user->id_str,
'username' => $user->screen_name,
'oauth_token' => $tokens['oauth_token'],
'oauth_token_secret' => $tokens['oauth_token_secret'],
'level' => 2,
'join_date' => date("Y-m-d H:i:s")
);
//jika user sudah autentikasi, bikinkan session
if($this->login_model->auth($data) == TRUE)
{
$session_data = array(
'user_id' => $data['user_id'],
'username' => $data['username'],
'is_logged_in' => TRUE
);
$this->session->set_userdata($session_data);
redirect('profile');
}
}
}
profile.php (Constructor)
<?php
class Profile extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('tweet');
$this->load->model('user_model');
}
function index()
{
if($this->session->userdata('is_logged_in') == TRUE)
{
//jika user telah login tampilkan halaman profile
//load data dari table user
$data['biography'] = $this->user_model->get_user_by_id($this->session->userdata('user_id'));
//load data user dari twitter
$data['user'] = $this->tweet->call('get', 'users/show', array('id' => $this->session->userdata('user_id')));
$data['main_content'] = 'private_profile_view';
$this->load->view('includes/template', $data);
}
else
{
//jika belum redirect ke halaman welcome
redirect('welcome');
}
}
function get_home_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/home_timeline');
echo json_encode($timeline);
}
function get_user_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/user_timeline', array('screen_name' => $this->session->userdata('username')));
echo json_encode($timeline);
}
function get_mentions_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/mentions');
echo json_encode($timeline);
}
function logout()
{
$this->session->sess_destroy();
redirect('welcome');
}
}
/** end of profile **/
Default.js (The javascript for updating timeline)
$(document).ready(function(){
//bikin tampilan timeline jadi tab
$(function() {
$( "#timeline" ).tabs();
});
//home diupdate setiap 20 detik
update_timeline('profile/get_home_timeline', '#home_timeline ul');
var updateInterval = setInterval(function() {
update_timeline('profile/get_home_timeline', '#home_timeline ul');
},20*1000);
//user timeline diupdate pada saat new status di submit
update_timeline('profile/get_user_timeline', '#user_timeline ul');
//mention diupdate setiap 1 menit
update_timeline('profile/get_mentions_timeline', '#mentions_timeline ul');
var updateInterval = setInterval(function() {
update_timeline('profile/get_mentions_timeline', '#mentions_timeline ul');
},60*1000);
});
function update_timeline(method_url, target)
{
//get home timeline
$.ajax({
type: 'GET',
url: method_url,
dataType: 'json',
cache: false,
success: function(result) {
$(target).empty();
for(i=0;i<10;i++){
$(target).append('<li><article><img src="'+ result[i]['user']['profile_image_url'] +'">'+ result[i]['user']['screen_name'] + ''+ linkify(result[i]['text']) +'</li></article>');
}
}
});
}
function linkify(data)
{
var param = data.replace(/(^|\s)#(\w+)/g, '$1#$2');
var param2 = param.replace(/(^|\s)#(\w+)/g, '$1#$2');
return param2;
}
That's the codes. Please help me. After all, I really appreciate all comments and explanation from you guys. Thanks
NB: sorry if i had bad English grammar :-)
You are making a call to statuses/home_timeline which is an unauthenticated call. The rate limit for unauthenticated calls is 150 requests per hour.
Unauthenticated calls are permitted 150 requests per hour.
Unauthenticated calls are measured against the public facing IP of the
server or device making the request.
This would explain why you see the problem at the peak of your testing.
With the way you have it setup you would expire your rate limit after 50 minutes or less.
I suggest changing the interval to a higher number, 30 seconds would do. That way you'll be making 120 requests per hour and under the rate limit.