User permissions per page

Hi,

i created a few small projects with great success. Now I have a new project with a set of features I am not sure how to handle in kirby.
Besides some basic pages, forms etc. the page should allow users to administrate/modify one single page within the web project. Think of it like a small business directory page. Each business gets a kirby user account and can then edit one single page. The structure of this page is identical for all users. In addition for one such page there should exist a collection of events, also manageable by this user (subpages?), and the project has a dedicated site where all events from all users should be listet.
I am thinking on how to structure the content and how to handle the permissions.
As far as I know, there exist no per-page permissions in Kirby. Also the other sites need to be hidden in the panel.
I attempted to use groups for this, nut then I have as many groups as users.
Can I use some specific naming scheme to build this functionality. Like storing a field “user” within a page, and only if they match, the user can edit the page or create new subpages?

Any plugins for this? I would like to quickly hack a working demo together in order to estimate
the effort or if I have to switch cms for this project.

regards, durpex

Kirby’s permissions allow you to control access via user roles rather than single users. However, you could use route hooks to prevent individual users from actually accessing a page (although that would not hide those pages from the panel).

If you use custom pages sections like the Pagesdisplay Section plugin, you could however, filter the pages a user gets to see by user, assuming that you store which user can access a page in a field in the page.

And welcome to the Kirby forum!

If you combine the above with site.yml files on a per role basis (you can do that in a plugin), you can achieve what you need.

Hi,

thank you for your fast reply. I tried to implement your suggestions within a fresh kirby installation including the demo data. The notes have a user field already, so my idea was to assign a few users to different notes and try to filter them.
I tried different versions of the query, but all result in the same error:

    Der Bereich "notes" konnte nicht geladen werden: Argument 1 passed to Kirby\Toolkit\Collection::filterBy() must be of the type string, null given, called in /Users/durpex/tmp/kirby/kirby/src/Toolkit/Query.php on line 98

this is my corresponding site.yml section

notes: #sections/notes
        headline: Notes
        type: pagesdisplay
        query: site.pages.filterBy(Author, *=, test)

There is no documentation for the pagesdisplay-section plugin except the two examples.

I think you are getting the wrong pages here:

notes:
  headline: Notes
  type: pagesdisplay
  query: page.children.filterBy("author", "test@email.de", "-")

The user field stores an email address, or did you enter something manually? This works if you hardcode the value.

However, we want to use the current user, but there is a problem with getting the current user, so in my test I used a workaround as described here: https://github.com/getkirby/kirby/issues/1941#issuecomment-538677774

 query: page.getUserPages()

With this page method defined in a plugin. Alternatively, if you only need it for a specific page type, you can define the method in a page model instead.

Kirby::plugin('my/plugin', [
    'pageMethods' => [
        'getUserPages' => function() {
            return $this->children()->filterBy('author', kirby()->user()->email(), '-');
        }
    ]
]);

Hi,

thank you again for pointing me in the right direction.

Hardcoding values works fine now, but using the plugin I get the following error:

Der Bereich “notes” konnte nicht geladen werden: Invalid query result - Result must be of type Kirby\Cms\Pages, Kirby\Cms\Field given.

I used your example from above.

Just to be sure: all filter queries documented here should work theoretically? So I could use a function to diplay all notes for the admin user group and only specific ones for others.

Another idea that could come in handy: Is it possible, using the ‘user.create:after’ Hook to create a page if a user within a specific user group is created and setting this new user for the page? Reading the documentation it seems that ‘$page->createChild’ should work.

Yes, that is definitely possible.

If you use the method in site.yml, you have to adapt the query:

query: site.find("notes").getUserPages()

page refers to the current page, so might be the wrong reference.

This results in the same error message.
This is the section in site.yml:

sections:
      # The `notes` section reuses the pages section defined in `/site/blueprints/sections/notes.yml`
      notes: #sections/notes
        headline: Notes
        type: pagesdisplay
        query: site.find("notes").getUserPages()

And the plugin code is in my models/album.php:

class AlbumPage extends Page
{
    public function cover()
    {
        return $this->content()->get('cover')->toFile() ?? $this->image();
    }
}

Kirby::plugin('my/plugin', [
    'pageMethods' => [
        'getUserPages' => function() {
            return $this->children()->filterBy('author', kirby()->user()->email(), '-');
        }
    ]
]);

That doesn’t make sense.

The plugin code has to be in the plugins folder, e.g. in /site/page-methods/index.php.

Alternatively, you could create a model for the notes page, in /site/models/notes.php

class NotesPage extends Page
{
    public function getUserPages()
    {
        return $this->children()->filterBy('author', kirby()->user()->email(), '-');
    }
}

Then this method will only apply to the notes page.

Page methods apply to all pages, methods in page models only to pages of the given type.