Disable or control the panel search button?

Hi,

I’m new here in the forum, although I’ve been reading passively for some time :wink:
I have been testing Kirby3 for a few weeks now and would like to use it in a larger project.

This project should have a customer area, where each customer is only allowed to see and edit his own data and pages. I would like to build this customer area with the panel.
I have already set up the following with the help of the documentation and various forum posts:

  • Role-specific general permissions
  • Role-specific blueprints
  • only display your own pages using a dynamic filter in the PageModel

The result: for a logged-in user only his data and his pages are visible.

BUT it is still possible for the logged-in user to access any other pages via a manually entered panel URL or via the panel search button in the upper right corner.

How can I prevent this?
My partial solutions: the user-specific pages are created with a alphanumeric 12-digit random slug. The manual url-input is theoretically still possible, but practically impossible to guess.
I have also hidden the search button using CSS - not really secure.

My questions:
Is there another way to disable the Panel Search button for a role? Or limit the search?
Or do I think in the wrong direction and there is another solution?

I am grateful for all tips :wink:

One way to disable access to prohibited pages is by using a route before hook. That way, the user should not be able to access a page even if they guess the URL:

Thanks @texnixe for the quick answer!
I have already tested route:before. Obviously route:before only works in the panel if I enter the URL directly in the browser or update the browser manually.
If I use the panel search, can I access any other pages despite route:before. Can I restrict the search somehow?

Have you used api your path?

For example:

   'hooks' => [
        'route:before' => function ($route, $path, $method) {
            if (Str::startsWith($path, 'api/pages/')) {
               
              throw new Exception('no no');
            }
          }
    ]

This should prevent access to any pages. From there, you have to define your logic…

As regards Panel search, it’s probably possible to disable it via the route as well.

    'hooks' => [
        'route:before' => function ($route, $path, $method) {
            if ($path === 'api/site/search') {
               
              throw new Exception('no no');
            }
          }
    ]

This still brings up the search but it doesn’t do anything. Together with hiding it, it should also do the job.

Thanks again @texnixe - that helps me one step further!
I had it so far tried with “panel/pages/…” instead of “api/pages/…”.

I implemented the second proposal right away - perfect!

But with your first suggestion I can’t get any further and have a “knot in my head” :wink:
My plan was: I add the user-id (e-mail-address) to each customer-page as a hidden field. With the route:before-hook only those pages will be read that have the email-address of the logged in user.

But how can I retrieve data in the route:before-hook from the page that should be called with the path?

Hm, quite hacky, but seems to work:

    'hooks' => [
        'route:before' => function ($route, $path, $method) {
            if (Str::startsWith($path, 'api/pages/')) {
                $pagePath = str_replace('+', '/', str_replace('pages/', '', $route->arguments()[0]));
                $page = page($pagePath);
                $user = kirby()->user();
                if ($page && $user) {
                    if ($page->email()->value() !== $user->email()) {
                        throw new Exception('You cannot access this page');
                    }
                }
                
            }
          }
    ]

Thank you very much @texnixe
I adjusted it a bit - it works perfect for me.
Great program and great support! :sunglasses: