Manage frontend permissions (per page) from panel

Hi all,

i created a “client” role for the frontend. When a user with the “client”-role is logged in, he has access to additional pages that other users don’t (surprise).

In the doc’s its mentioned that i can customize roles per page/file etc. from the page blueprint. But actually i want to edit which pages a client can see individually (different per client). Is there a solution to edit the pages a user (with the client role) has access to, from the panel?

Is it good practice to define additional fields for the user in the backend to manage such access?

thanks, best regards

I think if the easiest way would be select/multiselect or checkboxes field in each page that you can query in your templates where you assign either a role or individual users that can access a page from the frontend.

Hello @texnixe,

thanks for your answer. Maintaining permissions for each page is not feasible for the amount of pages I believe. I don’t want the editors to update 300pages for a new client.

Say I define the permissions (checkboxes for top level pages that have children) for each user of role client. Can i check role and permissions of the user in a hook so that I don’t have to constantly check permissions for each page in my templates when calling $page->children() for example or navigating to a page?

Yes, that doesn’t make sense, but you asked for per page permissions.

Maybe I’m missing something, but hooks are triggered if you do something in the Panel, so that doesn’t make sense. Instead of checking permissions in every template, you could do this with a catch all route, though.

Maybe I’m missing something, but hooks are triggered if you do something in the Panel,

Ah, i thought there are also some life cycle hooks available to add more functionality…
Actually, maybe let me try to rephrase the issue by giving an example.

I have set up a couple of user attributes that can be edited by admins in the backend. One of them is the checkbox “Backend” [boolean]. “Backend” is a page that shall be hidden for all visitors by default and should only be visible and accessable by my defined roles: clients, editors and admins.

Currently site->children()->listed()->not($site->homePage()) returns all visible pages on the top level, including “Backend”. I don’t want that “Backend” page to be part of the list for regular visitors. Furthermore the visitor shall not be able to access such restricted pages without logging in. On top of that, subpages of restricted pages shall also not be accessable nor visible for unauthorized users and should only be displayed for clients (cleints role + where user has permission), editors or admins.

Maybe that makes it a little bit clearer what i am trying to archive. What i am looking for is a way to programmatically solve this issue by evaluating a users attributes and serve pages accordingly… But i don’t know where kirby would resolve such rules.

I found this example for using hooks to blocking access to pages via route, but it will not hide pages from the being displayed in the front end without adjusting the templates…

// config.php
return [
  'hooks' => [
    'route:before' => function ($route, $path, $method) {
      if ($path === 'super/secret' && !kirby()->user()) {
        die('Nope');
      }
    }
  ]
]

I think if you want to loop through your collections, you would have to filter your pages by user permissions.

For displaying individual pages, you can use a catch all route or–if the number of parent pages that is protected–an array of parent pages and their children–and inside that route determine if the page can be shown or not.

Using a hook here doesn’t really make sense and wouldn’t provide any advantages over a normal route-

Hello Sonja,

thanks for taking your time to answer, i finally had some time to dig around in the documentation and think about alternative approaches.

Is it possible to overwrite the children() methods for $site and $pages as well as $page to check $kirby->user() for it’s role and permissions?

As you suggested the alternative is to add a siteMethod / pageMethod called permissions() with return $this->filterBy(‘id’, ‘not in’, $permissions) or similar…

There is no model for $site only page models.

page models are page specific, right - I can’t overwrite them globally?