Panel Login to any children

I am wondering if there’s a predefined function/setting where i could instantly jump to a sub-page after using the panel login form.

E.g. I am linking towards an url like:

domain.ext/panel/some/sub/page/edit

when not being logged in, i’ll get redirected to the login screen, after typing in the correct login information, i’ll end at the default domain.ext/panel screen

so is there anything that i’ll end at the desired page?

i can only think of having a route setup which also provides a login form and after submission will forward using go()…

but that’s kinda inventing the wheel a second time.

Edit:

I have a working route with login form which already does the job… just thinking if that’s really necessary?

No, there is no Kirby setting that would redirect you to a particular page.

// adjust pattern to your need  obviously
array(
    'pattern' => '(:all)/login',
    'action' => function ($uid){
      
      $site = site();
      $page = page();
      $output = null;
      if($site->user()){
        go(u('panel').'/pages/'.$uid.'/edit');
      } else {
        if($site->user()) go(u('panel').'/pages/'.$uid.'/edit');

        // handle the form submission
        if(r::is('post') and get('login')) {
      
          // fetch the user by username and run the
          // login method with the password
          if($user = $site->user(get('username')) and $user->login(get('password'))) {
            // redirect to the homepage
            // if the login was successful
            go(u('panel').'/pages/'.$uid.'/edit');
          } else {
            // make sure the alert is being
            // displayed in the template
            $error = true;
          }
      
        } else {
          // nothing has been submitted
          // nothing has gone wrong
          $error = false;
        }
        $output .= '<!DOCTYPE html><html><head><title>Login</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="'.u().'/node_modules/css.css"></head><body>';
        $output .= '<form method="post">
                    <div>
                      <label for="username">'.$page->username()->html().'</label>
                      <input type="text" id="username" name="username">
                    </div>
                    <div>
                      <label for="password">'.$page->password()->html().'</label>
                      <input type="password" id="password" name="password">
                    </div>
                    <div>
                      <input type="submit" name="login" value="Login">
                    </div>
                  </form>
                  <div class="'.$error.'"></div>';
        
        $output .='</body></html>';
        return new Response($output);
      }
    },
    'method' => 'POST'
  )

for someone who is looking for a solution… might want to adjust some though… thats basically right from the docs…

1 Like

Probably a bit hacky, but possible:

Use JavaScript to save the value of the page to local storage if the link is clicked. Then add a widget to your dashboard that reads the value on window load and redirects to the page.

1 Like

Another approach can be to use a panel hook. The hook can in the Panel save the latest page id to a file and that way keep the latest page in memory (file).

The one of your solutions above can be used to read the page id from the file. Maybe the form can be on http://example.com/login an it will redirect to the page id of the file.

Hm, yes, but that does not help if you have links to a particular page on the frontend and want to link directly to a page in the backend, which works perfectly if you are logged in but not otherwise. Then keeping the last page on track doesn’t make much sense.

@carstengrimm Why do you check twice if the user is logged in?

if($site->user()){
        go(u('panel').'/pages/'.$uid.'/edit');
      } else {
        if($site->user()) go(u('panel').'/pages/'.$uid.'/edit');

so far it was just the hacky way to see if it works or not, so the code after else was a direct copy and paste from the docs with editing the $uid part so…

i am not a javascript person …

my use case would be: a QR code is scanned which has either the panel-subpage or page-url/login (as above) to quickly being able to access and change a few values on that page, a login is inevitable, so since since the panel always redirects towards main/parent i am looking for options…

e.g. a delivery / invoice has the QR Code, some operator/package handler/whoever scans the package, and can proceed to mark it as “shippment has arrived” status.

Ok, this is another use case, then listening for a click on a link doesn’t make sense.

Yes, my approach was different and even my case. Personally, when I edit a page, save a few times and suddenly get thrown out, I want to login where I was, not on the panel root. For that my solution would work, but yes it’s a bit different.

@carstengrimm I like the idea of your approach with the route, but it can be a bit weird for routed pages.

Without routing

projects/project-a
projects/project-a/login

With routing

articles/cases/project-a // Routed from projects/project-a
articles/cases/project-a/login // FAILS - Page id can't be found

projects/project-a/login // WORKS - The real page id + login

so articles/cases/project-a/login would not work here. We can’t just “hang on” login in this case.

But not all people are using routed urls. I use them a lot because I often have a parent folder as content “wrapper”.

1 Like

for my case i could also just include the tinyurl function so there should always be only one available page per hash i assume.

obviously if there were multiple routes and each other would break themselves i’d have to go for another way…

'action' => function ($hash){
        $site = site();
        $output = null;
        if($page = $site->index()->findBy('hash', $hash)){

To prevent route collisions, maybe you could do something like this?

'login/(:all)'

Cases:

login/projects/project-a
login/tinyurl-8iknasdash7y