Jump to content

Users to have access to specific pages (not templates)


a-ok
 Share

Recommended Posts

I am creating a site which I want users to have access to specific pages. For example... this is my site structure:

Properties
  - Property 1
    - Gallery
    - Contact
    - Etc
  - Property 2
  - Property 3

Each property uses the same template, which has an include file at the top to check if the user is logged in or not and if not show a login form (taken from https://processwire.com/talk/topic/107-custom-login/) which seems to work well. What I now want to do is add users (which will send off an email) and give that user access to a specific property (and its child pages). That same user could have access to more than one property or simply one property. If they try to access another property they don't have access to it will return them to the homepage, for example... or 404 error more probably.

What do we think? Is it possible to have users have access to parent pages only rather than templates (as I'm using the same templates for each property).

Ideally I'd like to use SendGrid to send off emails once a user is added so perhaps I could write some sort of hook when a user is added? Is it possible to add a hook when a user is added?

I'm also going to use the Login Scheduler module (https://modules.processwire.com/modules/login-scheduler/) to set start/end times for user access.

Any other advice would be appreciated.

Link to comment
Share on other sites

I think one of my problems may be that when a user is created it is auto assigned as 'guest' and you cannot remove 'guest' as a role of a user nor can you remove the 'view pages' capability of that role so regardless... the user will be able to access all pages. Hmm.

Link to comment
Share on other sites

An approach you can use is to create a Page field referencing pages with that template.

Add this field to the User template. Thus, if you add property X to the user "Mary", you can check that in your code when Mary requests page X. 

 

  • Like 3
Link to comment
Share on other sites

9 minutes ago, oma said:

nor can you remove the 'view pages' capability of that role so regardless... the user will be able to access all pages. Hmm.

No need to remove "view" rights, just do a check at the top of your template file (or in an included file if you need this across your site) which checks the user and determines if they should be able to view the page. If not, then you could redirect them elsewhere. Does that make sense?

  • Like 2
Link to comment
Share on other sites

11 minutes ago, adrian said:

No need to remove "view" rights, just do a check at the top of your template file (or in an included file if you need this across your site) which checks the user and determines if they should be able to view the page. If not, then you could redirect them elsewhere. Does that make sense?

I think so! So just create my roles as normal with view rights only then at the top of my template, for example...

if page or page parent == and $user->hasRole("property-1") else 404?

 

 

 

Link to comment
Share on other sites

5 minutes ago, oma said:

I think so! So just create my roles as normal with view rights only then at the top of my template, for example...

if page or page parent == and $user->hasRole("property-1") else 404?

Yeah, that is the gist of it. I would consider carefully the 404 though - you might want to show a login form instead.

  • Like 1
Link to comment
Share on other sites

Wouldn't it just send them in a loop though? I have my login check at the top of each template (if user is logged in then show (and I can set my permissions here as you said) otherwise show login form) but if the user logs in but then doesn't have access it would then show the form again and then endless loop?

  • Like 1
Link to comment
Share on other sites

Just now, oma said:

Wouldn't it just send them in a loop though? I have my login check at the top of each template (if user is logged in then show (and I can set my permissions here as you said) otherwise show login form) but if the user logs in but then doesn't have access it would then show the form again and then endless loop?

My apologies - yes, that's not what you want :)

You still may choose to go with a "you don't have access" message, rather than a 404 - I guess it depends on your use case. Either way, sorry for the confusion :)

  • Like 1
Link to comment
Share on other sites

Thanks, @adrian.

One problem... if my pages are using the same template... when I run my check (if ($user->hasRole("property-1")), for example, if the user has that role won't they be able to see all the other properties too as the role isn't defining what pages a user can access?

Link to comment
Share on other sites

@oma - you will need to somehow define what users/roles have access to which parent pages (and their children - I think that is what you want). You could do as @Sérgio Jardim suggested, or come up with some other approach - perhaps the role's name could include a reference to the allowed parent page - you could even name the roles: property-1, property-2 etc and make that role name to the parent page name to determine if the user is allowed to view the page or not.

Link to comment
Share on other sites

4 minutes ago, oma said:

Thanks, @adrian.

One problem... if my pages are using the same template... when I run my check (if ($user->hasRole("property-1")), for example, if the user has that role won't they be able to see all the other properties too as the role isn't defining what pages a user can access?

I guess per template I could include the following...

if ( (($page->id == 1030 || $page->parentID == 1030) && $user->hasRole("property-1")) || (($page->id == 1031 || $page->parentID == 1031) && $user->hasRole("property-2")) )

But I'd need to do this for every user role... but not the end of the world if it's the best option.

Link to comment
Share on other sites

If you name the roles to match the page names, then it's much simpler:

if($user->hasRole($page->parent->name) {
     //allow access
}
else {
      //404
}

At least I think that's what you need?

  • Like 1
Link to comment
Share on other sites

2 minutes ago, adrian said:

If you name the roles to match the page names, then it's much simpler:


if($user->hasRole($page->parent->name) {
     //allow access
}
else {
      //404
}

At least I think that's what you need?

I wonder if IDs may be better as page names can sometimes change...

I think either this or @Sérgio Jardim's suggestion could work...

Link to comment
Share on other sites

I think @Sérgio Jardim's suggest may be the best solution... create a PageReference field 'property_permission' then add it to the user template so when a user is added the admin can set which pages they have access to...

if ($user->property_permission->has("id=$page->id") || $user->property_permission->has("id=$page->parentID"))

Thoughts? Also while anyone is here... can you hook into a new user creation? Preferably a hookAfter?

  • Like 3
Link to comment
Share on other sites

That approach sounds good to me - very flexible.

The only dedicated user hook is:

Users::saveReady

so you might need to add some logic if you don't want existing users altered when their details are changed.

Regarding finding appropriate hooks, take a look at the Captain Hook panel in Tracy: https://processwire.com/blog/posts/introducing-tracy-debugger/#captain-hook-panel

It makes it easy to search through classes and methods for things you might need and if you have the editor link protocol set up properly, it will open the file to the class/method you click on.

  • Like 4
Link to comment
Share on other sites

22 minutes ago, adrian said:

The only dedicated user hook is:

Users::saveReady

Users are pages so you have all the hookable methods in the Pages class too ('added', 'publishReady', etc). So you make the code in the hook conditional on the page template being 'user'.

  • Like 3
Link to comment
Share on other sites

2 minutes ago, Robin S said:

Users are pages so you have all the hookable methods in the Pages class too ('added', 'publishReady', etc). So you make the code in the hook conditional on the page template being 'user'.

Ohhhh interesting! But I guess I would need $page and not $pages if I wanted it to send off an email once a user has been added?

Link to comment
Share on other sites

3 minutes ago, Robin S said:

Users are pages so you have all the hookable methods in the Pages class too ('added', 'publishReady', etc). So you make the code in the hook conditional on the page template being 'user'.

Yeah, I was thinking about that, but thought Users::saveReady might be a tiny bit more efficient because it's only called when a user is saved, but it probably doesn't make any different, so perhaps Pages::added with a check for the admin template like you suggested would be better.

Link to comment
Share on other sites

6 minutes ago, oma said:

But I guess I would need $page and not $pages if I wanted it to send off an email once a user has been added?

Most of the hookable methods in the Pages class have $page as their first argument. So you get $page in your hook like so:

$page = $event->arguments(0);

 

  • Like 1
Link to comment
Share on other sites

1 minute ago, Robin S said:

Most of the hookable methods in the Pages class have $page as their first argument. So you get $page in your hook like so:


$page = $event->arguments(0);

 

@oma - you can see what @Robin S means here (Tracy Captain Hook panel) - see how $page is the first argument?

598a46a267ed8_ScreenShot2017-08-08at4_16_59PM.png.827355f09e5c68a49bf9bc9829efa2a3.png

Link to comment
Share on other sites

2 minutes ago, Robin S said:

Most of the hookable methods in the Pages class have $page as their first argument. So you get $page in your hook like so:


$page = $event->arguments(0);

 

Sorry what I meant is that I can only hook an 'added' method on Pages class and not on a Page class.

Just now, adrian said:

@oma - you can see what @Robin S means here (Tracy Captain Hook panel) - see how $page is the first argument?

598a46a267ed8_ScreenShot2017-08-08at4_16_59PM.png.827355f09e5c68a49bf9bc9829efa2a3.png

Ah got you!

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...