How to return to intended page in this case - laravel-5

I have the typical scenario of an online newspaper where you have the article and below a form to comment, but where you need to login to comment. So on clicking it takes you to the log page and it should return you to that page once you have authenticated.
So, because the form is part of a page that the user can see without being logged in, I cannot write the middleware for that page created by a PostController, (get route).
The CommentController only has one method, which is the store one for the Form. so, of course, if I placed a middleware for that controller, it would fail because although it would indeed take you to the login page on clicking the submit button, the Intended URL saved would be that Post for the form, so on returning after authenticating, it would take you to a non existent URL page under the name of the Post route for that Form.
I have read about Auth::guards and the like but could not come clear with it,
This
Laravel 5 - After login redirect back to previous page
asks exactly the same question that I do, it is the same scenario, but I dont see how his answer works, because defining a protected variable (and I have that already) like protected $redirectTo in the Auth controller only tells where to go after authenticating, and it is only a fixed route, in my case it takes you to the dashboard. But I dont want to be taken to the dashboard, it has to return to the page where the article and the comment form are.

I found the solution at Laracasts. I must say I really dont understand it, but it works. It adds two functions to the AuthController.
https://laracasts.com/discuss/channels/laravel/redirect-to-page-where-login-button-was-clicked
public function showLoginForm()
{
if(!session()->has('from')){
session()->put('from', url()->previous());
}
return view('auth.login');
}
public function authenticated($request,$user)
{
return redirect(session()->pull('from',$this->redirectTo));
}

It's been a while since i've done this, but this should work normally.
You could add a GET param in your link from the comment section to login page.
http://....com/login?intended=http://yourredirectlink.com/#form
Put the intended url in in the session variable url.intended and after login you redirect like so
Redirect::intended('/');
This will redirect back to the the url '/' if the session variable is not available.

Related

Laravel 5.7 Passing a value to a route in a controller

My controller posts a form to create a new page. After posting the form I need to redirect the user to the new page that will have the contents for that page that were entered in the previous form. If I simply do return view('mynewpageview', compact('mycontent')); where my mycontent is the object used to execute the $mycontent->save(); command, I carry the risk for someone refreshing the url thus posting the same content twice by creating a new page.
Instead I would like to redirect the user to the actual page url.
My route is
Route::get('/newpage/{id}', 'PageController#pagebyid'); and if I use return redirect()->route('/newpage/$pageid'); where $pageid = $mycontent->id; I get Route not defined error.
What would be the solution either to stop someone from resubmitting the content or a correct syntax for passing the parameter?
The correct answer that works for me is -
Give your route a name in the routes file
Then pass the parameters with an array as shown below in the controller.
return redirect()->route('newpageid', ['id' => $pageid]);
With basic (unnamed) routes, the correct syntax was return redirect('/newpage/'.$pageid);
You have already found out you can alternatively use named routes.
Last but not least, thanks for having considered the "double submit" issue! You have actually implemented the PRG pattern :)

Redirect in controller using RedirectToAction malfunction

Normally google is my best friend but this problem I can't figure out or even understand.
I have an action in my controller that I use for selecting which follow up action in my controller to use, based on user input (see image)
This redirect work like a charm, it's when the action I'm redirected to is finished as the problem arises. In my action I fetch some much needed data for the web site. When tha data is fetched the action are supposed to redirect to a generic action, that in turn will present my view. The "middleware" action redirect correctly and it also send the parameters but the "recieving action" don't handle or recieve the parameters.
I'm totally clueless here, is it not possible to redirect to an action that in turn redirect to another action or what is the problem?
The route specification looks a bit odd.
I think it should be possibly:
[HttpGet("Customer/Device/{id}")]
public IActionResult Device(string id, bool like)
{
}
Now the URL it tried to redirect you to should work. Id from URL, and the like parameter from query.
If you want both in URL:
[HttpGet("Customer/Device/{id}/{like}")]
public IActionResult Device(string id, bool like)
{
}

Magento - Passing a session variable to a page called via _redirect()

I have the need to pass a URL to Magento, where it should redirect the User after completing the logout. To store it, I do the following:
$BackTo = Mage::app()->getRequest()->getParam('backto');
if(!empty($BackTo)) {
Mage::getSingleton('core/session')->setBackTo($BackTo);
}
When needed, I retrieve the URL using Mage::getSingleton('core/session')->getBackTo(). The issue is that, while this works well on login, it doesn't work on logout (where it's most needed). I can store the session variable, I can also immediately retrieve it, but, when I am in logout.phtml, where the redirect JavaScript is located, such variable is set to null.
I suspect that the redirect performed by Magento upon logout has something to do with this "disappearing" session variable, but I can't say for sure.
For completeness, here is the relevant code (there's more code than this, but they are mainly auxiliary functions, which don't get called on logout).
Account Controller
class MyPackage_Redirectplugin_AccountController extends Mage_Customer_AccountController {
/**
* #see AccountController:logoutAction()
*/
public function logoutAction() {
$this->_getSession()
->logout()
->setBeforeAuthUrl(Mage::getUrl());
// Store the "back to" URL in a session variable
$this->StoreBackToURL();
$this->_redirect('*/*/logoutSuccess');
}
protected function StoreBackToURL() {
// Store the value of the "backto" argument, if it was passed
$BackTo = Mage::app()->getRequest()->getParam('backto');
if(!empty($BackTo)) {
Mage::getSingleton('core/session')->setBackTo($BackTo);
// At this point I can see the correct value stored in the session variable
}
}
}
Logout.phtml
// The following command returns null
$redirectURL = Mage::getSingleton('core/session')->getBackTo();
Thanks in advance for the help.
Update 12/09/25 - Found a workaround
Since I couldn't find a way to pass a session variable to the logout page opened by redirect, I chose an alternative way: I'm passing it via the URL. Specifically, I implemented a logoutAction() which calls $this->_redirect('*/*/logoutSuccess', array('myvar' => $MyValue));.
In the template, where I have to do the redirect, I simply read such parameter using Mage::helper('core')->urlDecode(Mage::app()->getRequest()->getParam('myvar'));.
I'm aware that there might have been better ways to implement the whole thing, but I needed a bug fix solution and this does the job. Thanks to all people who answered.
The cleanest option which I see (no controller rewrite necessary!) is to observe the dynamically-dispatched controller_action_postdispatch_customer_account_logout event - see the relevant line fromMage_Core_Controller_Varien_Action::postDispatch(). The postDispatch() method is called after the controller action completes.
Example observer method:
public function logoutRedirect($obs)
{
$redirectUrl = Mage::getUrl(/* url args */);
$obs->getControllerAction()->getResponse()->setRedirect($redirectUrl);
}
Doing this will redirect the user to the desired URL directly upon logout meaning that the logoutSuccess page with the JS redirect will not be accessed.
If the desire is to have the logoutSuccess page render as normal, but redirect to a different URL, this can be achieved a couple of ways:
1. By creating a custom template
2. By creating a custom template block class, overriding the getUrl() method to retrieve the URL of your choice, and assigning that as block to render in the content area (by removing or displacing the customer_logout block) in a custom layout XML update file.
just observe this event customer_logout, and when event call method you save the session key on database.
Learn more: http://www.magentocommerce.com/wiki/5_-_modules_and_development/reference/events
http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method
GL.
Update 12/09/25 - Found a workaround
This workaround has also been posted in the question itself.
Since I couldn't find a way to pass a session variable to the logout page opened by redirect, I chose an alternative way: I'm passing it via the URL. Specifically, I implemented a logoutAction() which calls $this->_redirect('*/*/logoutSuccess', array('myvar' => $MyValue));.
In the template, where I have to do the redirect, I simply read such parameter using Mage::helper('core')->urlDecode(Mage::app()->getRequest()->getParam('myvar'));.
I'm aware that there might have been better ways to implement the whole thing, but I needed a bug fix solution and this does the job. Thanks to all people who answered.

MVC 3 Page navigation security rules

I have a MVC3 application which follows PRG pattern, I am looking for a best way to define navigation rules to my application. For example I have application with pages A, B, C and D. Lets say A is a logon page. After user logon successfully, user will be redirected to page B. Now I do not want let the user to type url of page C in the address bar and get access to page C (Page C should be accessible only after POST ing page B or from Page D back button) I have to setup similar rules for all other pages as well (lets say when user is in page D, should not allow them to get into Page B)
currently I have one option where I can check the #Request.UrlRefferer property to get the source of the every request and decide which page to redirect to. I am not sure this is a best solution.
Appreciate your feedbacks!!
Do not base your security on this. Use the [Authorize] attribute to define security. The UrlReferrer can easily be forged as well.
Why are you trying to limit this? If you have a business reason the user most go through a particular flow, then consider either a cookie, session, or database entry to note their current 'completion' status - IE some somewhat persistent method to determine this. You could also form a token based on say - a session id - that gets passed into each page. If the token exists and matches the user's current session , then load the page for them. Of course this could be forged if the user understands this - but if you are simply trying to ensure the proper flow then this is a way as well. The user would not get a link with the current session id in it until they hit the prior step.
If you don't want a particular page to be accessible via the URL, one option available is to make sure there's no way to access the page via a URL. To access the page, make a POST action that will return a view rather than a redirect. This would mean the view your POST action returns will be shown on a page with the URL of the previous page. For exameple:
Page A URL is /login and after logging in, the user is redirected to Page B. The URL is now /home. Page B sends a POST request and the contents of the page becomes Page C but the URL still remains as /home. The only way to view the contents of Page C would be to visit Page B and send a POST request.
This breaks the PRG pattern but that's one option.
There is one more alternative, store the current permissions of the user indicating which page they're allowed to enter and check if the user is authorized to view a page before executing the action. You could place the code in an ActionAttribute which you can apply to your action methods or entire controllers. If you'd like a more detailed explanation of this technique, leave me a comment and I'll write up another answer describing this technique in more detail.
Here's a quick proof-of-concept of the technique described above:
public class PermissionsNeeded : ActionFilterAttribute
{
string expectedPermission;
public PermissionsNeeded(string permission)
{
expectedPermission = permission;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var currentPermissions = filterContext.HttpContext.Session["CurrentPermissions"] as IEnumerable<string> ?? new List<string>();
// If user does NOT have permission to access the action method
if(!currentPermissions.Contains(expectedPermission)
{
throw new HttpException(403, "User is not authorized to view this page");
}
}
}
class YourController : Controller
{
[HttpPost]
public ActionResult PageB()
{
var currentPermissions = Session["CurrentPermissions"] ?? new List<string>();
currentPermissions.Add("PostedFromPageB");
Session["CurrentPermissions"] = currentPermissions;
return RedirectToAction("PageC");
}
[PermissionsNeeded("PostedFromPageB")
public ActionResult PageC()
{
return View();
}
}
Currently, the custom attribute will only accept one permission at a time which is a simply limitation to rectify. You'd be responsible for removing the permissions stored in the Session when you feel the user shouldn't have certain permissions anymore. I threw an HttpException that return a 403 status code (unauthorized access) but if you'd instead like to return an ActionResult such as a RedirectToRoute or a View, you could set a value to the filterContext.Result property.
I end up doing this task as below:
On successful completion of every page, save the page Name in database
When user request for a new page, simply check the page they have completed last from database and decide what to do.
I chooses this approach simply because it will definitely help during Problem Solving/Troubleshooting once application is in Production, which is huge for me.
Thanks everyone for your responses!

Redirect CI problem

I'm kind of new with CodeIgniter and I'm still learning (a lot).
So I have a view and when I submit a form I 'call' the controller by surfing to the right URL dynamically e.g. site/delete
class Site extends Controller {
function index(){$this->load->view('...')}
function delete() {
$this->site_model->delete_row();
$this->index();
}
}
Now when that action is done (deleted the row) I'm calling $this->index(); to redirect to my initial page (which is good) but my url stays: site/delete . I want my URL to be ../site/index (or without the /index)
Any help would be appreciated :-) .
So far I found something to solve this:
instead of:
$this->index();
I'm using:
redirect('site');
Does anyone know this is a good practice?
Redirect is what you should use.
In the user guide:
http://codeigniter.com/user_guide/helpers/url_helper.html
they use it after checking if a user is logged in. Depending on if they are or not, they redirect to a different place.
Also, note that any code after the redirect won't run. Make sure and redirect after you've done everything you need to.
My preferred method is to have actions like that handled by the same method that will be seen by the user afterwards.
What if you go to /site/delete afterwards, as a user? It will either have to detect and throw a error (show a message) or redirect to an appropriate page. /site/delete has no meaning.
For example, if a user would normally see an overview after deleting, then my form will be posted to /site/index; with index quickly checking for the condition and calling _delete() in the same controller, before doing its normal work.
That way, if the user refreshes the page, or presses 'back', things should look consistent to them.
Another example would be that /settings/edit would post to itself - this means that it can act on the post and show any output (e.g. validation errors). It means there's no /settings/do_edit location on my site, and also means that the user can go back to /settings/edit safely, and see a form for editing their settings.
I suppose this is a subjective take on a perhaps objective question, and I would encourage feedback on my view, but it's my way of avoiding the problem you have asked about.
$this->index();
Call of function in a function simply execute the functionality within that function.
And url never changed.
for changing the url you should use.
redirect ( base_url().'site');
but you should load url helper in constructor.

Resources