I need to redirect a user to an error page (view/error/403.phtml) from within the Module.php of a module called Admin when a user is not allowed to access the specific resource. I have been searching for a solution to this, but so far had no success. The best I found was this question, the accepted answer to which doesn't work for me (and I currently cannot add comments to the linked question because I don't have the required reputation level) - the page is displayed as if there is no redirect at all and the user is allowed to access it. I have tried to replace the redirecting code with a simple die; to test if the isAllowed() is working properly, and it correctly shows a blank page, so the problem lies in the redirection itself.
Relevant code in Module.php is:
public function onBootstrap(MvcEvent $e)
{
$this->initAcl($e);
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('route', array($this, 'checkAcl'));
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
public function checkAcl(MvcEvent $e)
{
// ...
if (!$this->acl->isAllowed($userRole, $controller, $privilege))
{
$response = $e->getResponse();
$response->setHeaders($response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseurl() . '/error/403'));
$response->setStatusCode(403);
$response->sendHeaders();
}
// ...
}
module.config.php
'view_manager' => array(
'display_exceptions' => true,
'exception_template' => 'error/403',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/admin_layout.phtml',
'error/403' => __DIR__ . '/../view/error/403.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
'Admin' => __DIR__ . '/../view',
),
'strategies' => array(
'ViewJsonStrategy',
),
),
If I add the line
throw new \Exception($translator->translate('Access denied'));
after the code for redirection, I do get redirected to URL http://[servername]/error/403, but the contents of the page is, instead of my custom 403.phtml, a styled (with layout) 404 error page, stating that "The requested URL could not be matched by routing."
A better way to achieve what you want is to trigger a dispatch.error event in your checkAcl function rather than trying to do a redirect. You can then handle this event and display the 403 page.
To trigger the event:
if (!$this->acl->isAllowed($userRole, $controller, $privilege))
{
$app = $e->getTarget();
$route = $e->getRouteMatch();
$e->setError('ACL_ACCESS_DENIED') // Pick your own value, would be better to use a const
->setParam('route', $route->getMatchedRouteName());
$app->getEventManager()->trigger('dispatch.error', $e);
}
Then in your onBootstrap add a listener for the dispatch.error event:
use Zend\Mvc\MvcEvent;
...
$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, <any callable>, -999);
In your callback for dispatch.error event you just attached to:
$error = $event->getError();
if (empty($error) || $error != "ACL_ACCESS_DENIED") {
return;
}
$result = $event->getResult();
if ($result instanceof StdResponse) {
return;
}
$baseModel = new ViewModel();
$baseModel->setTemplate('layout/layout');
$model = new ViewModel();
$model->setTemplate('error/403');
$baseModel->addChild($model);
$baseModel->setTerminal(true);
$event->setViewModel($baseModel);
$response = $event->getResponse();
$response->setStatusCode(403);
$event->setResponse($response);
$event->setResult($baseModel);
return false;
Related
I just updated a PrestaShop website from 1.7.8.3 to 1.7.8.4, everything worked fine, but I'm havine 404 errors on custom module routes.
On module install I register routes like:
$this->registerHook('ModuleRoutes')
And my routes are like:
public function hookModuleRoutes() {
$urls = array(
'module-mymodulename-posts' => array(
'controller' => 'posts',
'rule' => 'posts/list',
'keywords' => array(),
'params' => array(
'fc' => 'module',
'module' => 'mymodulename',
)
),
...
);
return $urls;
}
Now www.mywebsite.com/posts/list returns 404.
And www.mywebsite.com/modules/mymodulename/posts works but url is not looking as good.
It all was working fine until this morning update.
Any idea on how I could get this solved ?
I have nothing about routing in the release logs.
Apparently a PrestaShop bug:
https://github.com/PrestaShop/PrestaShop/issues/27854
that just got a fix:
https://github.com/PrestaShop/PrestaShop/pull/27874/files
Fix works fine on my side.
You have to change getHookStatusByName function in classes/Hook.php file :
public static function getHookStatusByName($hook_name): bool
{
$hook_names = [];
if (Cache::isStored('active_hooks')) {
$hook_names = Cache::retrieve('active_hooks');
} else {
$sql = new DbQuery();
$sql->select('lower(name) as name');
$sql->from('hook', 'h');
$sql->where('h.active = 1');
$active_hooks = Db::getInstance()->executeS($sql);
if (!empty($active_hooks)) {
$hook_names = array_column($active_hooks, 'name');
if (is_array($hook_names)) {
Cache::store('active_hooks', $hook_names);
}
}
}
return in_array(strtolower($hook_name), $hook_names);
}
I have been working through the getting started guide for Yii. After generating the CRUD code I receive an error when clicking on the "View/Edit/Delete" buttons. It appears that the generated links are incorrect in that they reference "id" rather than "code" (which is the primary key).
E.g the View link is
http://localhost/yii/demo/basic/web/index.php?r=country%2Fview&id=AU
which generates the error
Bad Request (#400)
Missing required parameters: code
when I manually change the link to
http://localhost/yii/demo/basic/web/index.php?r=country%2Fview&code=AU
it works correctly. Why is it referencing "id"?
I also had to modify the CountryController.php file, findModel function which was again referencing "id"
if (($model = Country::findOne($id)) !== null) {
when changed to "code" this worked.
protected function findModel($code)
{
if (($model = Country::findOne($code)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
Does anyone have any ideas, the db is MySQL and the Code column is defined as the Primary Key.
This is a bug in the current yii code.
It expects ID to be the primary key always
A way of fixing it would be to remove the action column from the gridview in index.php and add
[
'class' => 'yii\grid\ActionColumn',
'header' => 'Actions',
'headerOptions' => ['style' => 'color:#337ab7'],
'template' => '{view}{update}{delete}',
'urlCreator' => function ($action, $model, $key, $index) {
if ($action === 'view') {
$url ='index.php?r=country/view&code='.$model->code;
return $url;
}
if ($action === 'update') {
$url ='index.php?r=country/update&code='.$model->code;
return $url;
}
if ($action === 'delete') {
$url ='index.php?r=country/delete&code='.$model->code;
return $url;
}
}
],
Just got done going through old answers regarding how to change gridview to get to this.
I already seen some tuts and example about it and I have implemented it somehow.
Method in controller looks like this:
The logic used is just php and I would like to use more a lumen/laravel logic and not just simple vanilla php. Also I have tried and did not worked anhskohbo / no-captcha
public function create(Request $request)
{
try {
$this->validate($request, [
'reference' => 'required|string',
'first_name' => 'required|string|max:50',
'last_name' => 'required|string|max:50',
'birthdate' => 'required|before:today',
'gender' => 'required|string',
'email' => 'required|email|unique:candidates',
'g-recaptcha-response' => 'required',
]);
//Google recaptcha validation
if ($request->has('g-recaptcha-response')) {
$secretAPIkey = env("RECAPTCHA_KEY");
// reCAPTCHA response verification
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretAPIkey.'&response='.$request->input('captcha-response'));
$response = json_decode($verifyResponse);
if ($response->success) {
//Form submission
//Saving data from request in candidates
$candidate = Candidate::create($request->except('cv_path'));
$response = array(
"status" => "alert-success",
"message" => "Your mail have been sent."
);
} else {
$response = array(
"status" => "alert-danger",
"message" => "Robot verification failed, please try again."
);
}
}
} catch(Exception $e) {
return response()->json($e->getMessage());
}
return response()->json(['id' => $candidate->id, $response]);
}
Okey. Google has an package for this:reCAPTCHA PHP client library
just: composer require google/recaptcha "^1.2"
and in your method inside controller:
$recaptcha = new \ReCaptcha\ReCaptcha(config('app.captcha.secret_key'));
$response = $recaptcha->verify($request->input('g-recaptcha-response'), $_SERVER['REMOTE_ADDR']);
if ($response->isSuccess()) {
//Your logic goes here
} else {
$errors = $response->getErrorCodes();
}
config('app.captcha.site_key') means that I got the key from from config/app.php and there from .env file.
If you have not config folder, you should create it, also create app.php file same as in laravel.
my model code:
public $image;
return array(
array('filename', 'required'),
array('image', 'file', 'types'=>''),
array('filename', 'length', 'max'=>11),
array('id, filename', 'safe', 'on'=>'search'),
);
my view code:
<?php echo CHtml::activeFileField($model, 'image'); ?>
my controller code:
$model = new TblUpload;
$model->attributes=$_POST['TblUpload'];
$img = CUploadedFile::getInstance($model,'image');
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
{
$model->filename = $img;
$model->save(false);
}
}
$this->render('uploadfile',array('model'=>$model));
}
hi friends using this code i am able to upload all types of files like images and documents, but i am unable to upload videos.... i have changed my php.ini file max_upload_size also...
In your form view, have you set the enctype for the form?
$form = $this->beginWidget(
'CActiveForm', array(
'id' => 'my-form',
'htmlOptions' => array(
'enctype' => 'multipart/form-data'
),
)
);
It could also possibly be the path to the folder you are trying to upload to doesn't exists or is incorrect. Try using getcwd(), eg:
$model->my_image->saveAs(getcwd()."/uploads/myfile.jpg");
This is most likely the problem, your path in your code above is:
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
The basepath and followed by the ../ probably wrong unless you areally are trying to upload in the directory before your root?
Finally i sorted out how to upload images...
Here is my controller code.....
public function actionUploadfile()
{
$model = new TblUpload;
if(isset($_POST['TblUpload']))
{
$model->image=CUploadedFile::getInstance($model,'image');
if($model->save())
{
$model->image->saveAs('/wamp/www/fileupload/images/'.$fileName);
}*/
$model->attributes=$_POST['TblUpload'];
$img = CUploadedFile::getInstance($model,'image');
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
{
$model->filename = $img;
$model->save(false);
}
}
$this->render('uploadfile',array('model'=>$model));
}
this was the place i got mistaken... but now i am using uploadify extension to upload all kinds of files and edited it to be used for multiple upload at a time
I had some really complicated code, and now I've made it ridiculously simple, and it doesn't work.
Currently it simply takes me back to the page with the login URL echoed out.
Code is here:
<?php
require 'facebook.php';
// Create our application instance
// (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => 'sd',
'secret' => 'sda',
));
// Get User ID
$user = $facebook->getUser();
if($user) {
echo $user;
} else {
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=>'http://www.facebook.com/pages/CharlesTestPage/225802194155435?sk=app_252946408094785','scope'=>'email'));
echo $loginUrl;
}
exit;
?>
Please. I have spent a whole paid work day on this now, and am at the point of crying, not only for myself but for my boss.
Cry.
Edit: OK, the weird thing is, if I have the redirect_uri set to the facebook tab, if it's not authenticated itself, then it constantly redirects in an infinite loop. However, if I remove the redire
This is what's working for me using PHP SDK 3.1.1. Try it and let us know if this works:
include('facebook.php');
session_start();
//facebook application
$config['appid' ] = "YOUR_APP_ID";
$config['secret'] = "YOUR_APP_SECRET";
$config['baseurl'] = "http://example.com/facebookappdirectory";
$config['appbaseurl'] = "http://apps.facebook.com/your-app-name";
// Create our Application instance.
$facebook = new Facebook(array(
'appId' => $config['appid'],
'secret' => $config['secret'],
'cookie' => true,
));
$user = $facebook->getUser();
$loginUrl = $facebook->getLoginUrl(
array(
'scope' => 'email'
)
);
if ($user) {
try {
//get user basic description
$userInfo = $facebook->api("/$user");
$fb_access_token = $facebook->getAccessToken();
} catch (FacebookApiException $e) {
//you should use error_log($e); instead of printing the info on browser
error_log('APP ERROR: '.$e);
$user = null;
}
}
if (!$user) {
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
exit;
}
if (isset($_GET['code'])){
header("Location: " . $config['appbaseurl']);
exit;
}
Check for
if(isset($_GET['code'])){
$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();
}
Facebook return userID only after the login and that code.