Jump to content
ren

Redirect admin pages disables logout

Recommended Posts

Hi all,

I'm creating a website for a magazine publisher. This will include a supplier section with press releases attached to company profiles. The idea is that companies can register and manage their profile and press releases (CRUD) via a dashboard.

The dashboard is a Process module. Ben Byford's RedirectAdminPages module is being used to lock out the rest of the backend, with a few modifications.

The following code should redirect every admin page to the dashboard page but still allowing logging out. However logging out just redirects to the dashboard page:

    // do not redirect if page matches:
    if($this->page->template != "admin" // any non-admin page 
	|| $this->page->is($this->redirectPage) // the dashboard page (prevent infinite loop)
	|| $this->page->parent->is('/admin/login/') // various attempts to allow logging out
	|| $this->wire("process") == 'ProcessLogin'
	|| strpos($this->page->url, $this->wire('config')->urls->admin . 'login/logout') !== false
	) {
      return;
    }

    // find roles set in module configuration and create array
    $roles = explode(',', $this->userRoles);

    // for each user in module config check to see if current user
    foreach ($roles as $key => $val) {

      // get a role from the roles array
      $roles[$key] = trim($roles[$key]);

      // if current user found with role then redirect
      if($this->user->hasRole($roles[$key])){

        // redirect session to page stored in config
        $this->session->redirect($this->redirectPage);

        // code should never get here but this is a simple fallback
        break;
      }
    }
  }
}

I'm surprised that this URL matching doesn't work:

|| strpos($this->page->url, $this->wire('config')->urls->admin . 'login/logout') !== false

Because this does work for allowing page edit:

|| strpos($this->page->url, $this->wire('config')->urls->admin . 'page/edit') !== false

Any ideas?

That issue aside, as a learning process I'm going to re-implement the dashboard as front-end pages. I guess that the advantage of using the ProcessWire back-end is most of the functionality is already there, you don't need to create forms and handle the processing, create / import css etc. So it'll be interesting to see how much of a difference this makes, and how much control each approach provides. I'd love to have some thoughts and feedback from those of you who've tried both methods?

PS this will be my third website created with ProcessWire and it's already been a lot of fun, and as a CMS it 'just feels right', so a big thanks to Ryan and everyone who has contributed.

Thanks :)

  • Like 1

Share this post


Link to post
Share on other sites

Hi and welcome @ren!

I recommend you install the Tracy Debugger module as you'll find this an essential tool when developing.

Then you can dump the $page object above your if() conditional and explore what its properties are (parent, url, etc). It should be obvious then why $page will or will not match those conditions you have set.

// do not redirect if page matches:
bd($this->page, 'page');
if($this->page->template != "admin" // any non-admin page 
    || $this->page->is($this->redirectPage) // the dashboard page (prevent infinite loop)
    || $this->page->parent->is('/admin/login/') // various attempts to allow logging out
    || $this->wire("process") == 'ProcessLogin'
    || strpos($this->page->url, $this->wire('config')->urls->admin . 'login/logout') !== false
) {
  return;
}

 

  • Like 3

Share this post


Link to post
Share on other sites

Hi @Robin S,

Thanks, Tracy Debugger is looovely. I did as you said, and put db calls to log both cases (redirect and no redirect):

// do not redirect if page matches:
if($this->page->template != "admin" // any non-admin page 
    || $this->page->is($this->redirectPage) // the dashboard page (prevent infinite loop)
    || $this->page->parent->is('/admin/login/') // various attempts to allow logging out
    || $this->wire("process") == 'ProcessLogin'
    || strpos($this->page->url, $this->wire('config')->urls->admin . 'login/logout') !== false
) {
	bd($this->page, 'no redirect page');
	return;
}

bd($this->page, 'redirect page');

When I tried to logout it logged both cases, with 'redirect page' first:

data protected => array (3) title => "Login" (5) process => "ProcessLogin" (12) urlSegment => "logout" (6)

... for some reason 'ProcessLogin' is sailing through the conditional.

Followed by 'no redirect page':

data protected => array (2) title => "Dashboard" (9) process => "ProcessDashboard" (16)
The first log gave me the idea to match the urlSegment, which works a charm!

So if it's of any use to anyone, the working code is:

    if($this->page->template != "admin" || $this->page->is($this->redirectPage) || $this->input->urlSegment1 == 'logout') {
      return;
    }

    // find roles set in module configuration and create array
    $roles = explode(',', $this->userRoles);

    // for each user in module config check to see if current user
    foreach ($roles as $key => $val) {

      // get a role from the roles array
      $roles[$key] = trim($roles[$key]);

      // if current user found with role then redirect
      if($this->user->hasRole($roles[$key])){

        // redirect session to page stored in config
        $this->session->redirect($this->redirectPage);

        // code should never get here but this is a simple fallback
        break;
      }
    }

Thanks Robin, you've been a great help, and I'm sure to be using Tracy Debugger again :)

  • Like 1

Share this post


Link to post
Share on other sites
14 minutes ago, ren said:

When I tried to logout it logged both cases, with 'redirect page' first:


data protected => array (3) title => "Login" (5) process => "ProcessLogin" (12) urlSegment => "logout" (6)

... for some reason 'ProcessLogin' is sailing through the conditional.

Not sure but perhaps because you are not checking the process property of $this->page, i.e. instead of this...

|| $this->wire("process") == 'ProcessLogin'

...try...

|| $this->page->process == 'ProcessLogin'

 

  • Like 1

Share this post


Link to post
Share on other sites
10 hours ago, Robin S said:

Not sure but perhaps because you are not checking the process property of $this->page, i.e. instead of this...


|| $this->wire("process") == 'ProcessLogin'

...try...


|| $this->page->process == 'ProcessLogin'

 

Doh. Yes, that works :-) Prefer this to matching urlSegment I think.

Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By sambadave
      Hi there
      Short version of question
      Let's say I have a page in the admin that contains a field... Is it possible to output the content from that field on another page in the admin? Almost like a reference.
      Longer version of question (with example)
      A house builder with multiple (60+) developments. They want to be able to create notices/messages that can be added to one or many developments. Handy for things like regional covid lockdowns or temporary office closures due to bad weather.
      My approach for the admin editing options:
      Add each message to each development
      Pros: You edit the message on the development page in context
      Cons: Very time consuming and repetitive if the same message needs to be applied to 60+ developments
        Control all the messages from one admin page and say which development each message should be applied to
      Pros: Easier to add/remove messages to more than one development at a time. Control all messages from one place.
      Cons: Content is not added on development page, which is where typical admin users may expect to find it I went for option 2 due to flexibility, and created a page within the admin for global development notices. This contains a repeater with:
      Field for message to display Checkbox list of all developments. The user can select which ones to apply each message to It's working really well but the only thing is that if the user goes to a specific development in the admin, the relevant messages aren't displayed in context (as they aren't edited on that page and instead on the global development notices page)... which may cause confusion when a new staff member / content admin tries to edit the text but there is no field when they go to the development admin page where they expect to see it...
      Solution???
      I don't require the message(s) to also be editable on the development page, but I wondered if there was a nice way to show it/them somehow. I feel like I am missing something really simple as I'm sure ProcessWire will have a nice way of achieving this, or maybe there are field settings that allow this kind of thing to happen?
      Any ideas on approaches or similar experiences would be much appreciated, even if it is just a much simpler example with the content from one field being shown on another admin page to get the ball rolling.
      Thanks in advance for any advice :)
    • By jploch
      Hey folks,
      currently Iam working on a website for one of my clients and I need some advice on how to approach this in PW.
      The website is for a company, that offers holiday houses in two locations. 

      The client wants the homepage to show the first location. Normally I just have a home template for the first page, but here the URL should reflect that you are in Location 1. So when you visit the URL casamani.com it should redirect to casamani.com/location-1. Not sure if this makes sense at all.

      Whould it be bad for SEO and performance reasons to redirect home to the Location-1 page?
      Another approach would be to render the Location-1 template on the home template or do an include like discussed here.
      Here is how the tree looks:
      – Home
      – Location 1 (Homepage)
           – Creation
           – Adventure
           – Sustainability
      – Location 2 
           – Creation
           – Adventure
           – Sustainability

      Thanks for looking into this!
    • By humanafterall
      Hi,
      I would like to set an admin template to 'https only' as recommended in the Processwire security docs.
      However if I do this it forces this setting locally too, resulting in https://localhost requests which result in an error page.
      Is there a simple way round this? Setting https for templates in the config?
      Thanks!
    • By theoretic
      Hi guys and ladies! And thanks for Processwire!
      It appears i've got an interesting issue concerning the template-settings-based PW redirects dealing with access control. Any PW template has some access control options i.e. "Login redirect URL or page ID to render". If this option is used for a page having a template with this option filled, a redirect will occur if user is not logged in and/or has insufficient access rights.
      I like to hook PW events. In one of my current projects i decided to write an addHookBefore('Session::redirect', ...) which should store the page we are being redirected from. With "regular" redirects like $session->redirect('/somewhere/') this hook works like a charm. But it was strange to see that it doesn't work with the template-settings-based redirect.
      I'm too dumb to dive deep inside PW and to examine the whole PW session mechanism. But it could be rather logical if ANY redirect ( no matter template-settings-based or using $session->redirect() ) could be hooked in the same manner.
      Okay okay i can forget about template-settings-based redirect and write my own. Just a couple of lines of code, and it works. But it's less elegant than hooking the template-settings-based redirects.
      So am i missing something? It this behavior a bug, or is it intended by PW team? Thanks in advance for any comment!
    • By DanielKit
      Hi. I'm currently stuck at the login page in my project. Once I enter my admin username and my password and press login, nothing happens. The page just reloads. However, the URL changes from http://myipaddress/processwire to http://myipaddress/processwire/?login=1. I've checked all of my server settings, and to my knowledge, all seems to be fine there. I don't know where to go from here.. Thanks in advance!
×
×
  • Create New...