A potential approach for more advanced and flexible permission system

Hey everyone,

I’ve already used Kirby in some projects, where everything worked like a charm and I’m really liking it so far.

However, for a current project I’m working on, more complex permissions that go beyond role-specific boolean definitions would be welcome (such as recursively checking pages for authorship).

Therefore I’m currently thinking about and building a plugin for more flexible permission definitions. A MVP is already running quite well thus far.

This should allow for example to define permissions like this: read: q{kirby.user.role.id} === 'admin' || q{page.checkAuthorship(kirby.user)} && q{page.template.name} === 'project'.

This is my approach:

  • automatically inject Page (AdvancedPage) and User (AdvancedUser) models for existing page types and user roles that override the standard kirby permissions() method. The overridden methods return instances of a AdvancedPagePermissions class or a AdvancedUserPermissions class respectively. These furthermore extend the Kirby PagePermissions and UserPermissions classes and override the default can() method by extending it with a custom flexible permission evaluator.

  • The custom permission evaluator is executed last, which only happens if a string is set as permission value instead of true or false.

  • At this point, the custom permission evaluator first executes all queries, which have to be marked with q{your_query} (all queries are fetched with a simple regex like /q{(.*?)}/) and then evaluates the resulting string, which should only contain boolean operations.

Current problems:

  • The custom permission evaluator internally uses the php eval() function, which poses potential security implications and should be avoided.

  • Project specific page models are overridden. A potential solution would be to check for existing page models and extend them dynamically instead of the Kirby Page class (if this can be realized with php).

  • Probably many more, not so obvious, that I haven’t yet encountered :smiley:

The following questions arose during ideation and development:

  • Is there a possible simpler solution for my issue?

  • Are there any problems that might emerge with this approach, or are there any stumbling blocks I need to be aware of?

  • Could the flexible permissions syntax collide with Kirby query definitions? (q{your_query})

  • What is the most sophisticated way to fetch all existing Page types to set corresponding models? (a $kirby->templates() function, which guarantees a correct resolution of file names (e.g. kebab- to camel-case conversion), doesn’t seem to exist)

  • One strange behavior I encountered was that Kirby apparently chose the correct test template for a page with a test.txt in a multilingual setup, but not the corresponding page model. After renaming test.txt to test.en.txt it worked again. I have to dig deeper to really understand and reproduce what’s happening, but can you give a short assessment of whether this is a bug or not?

Your help and assessment would be highly appreciated.
Please do not hesitate to criticize and make suggestions for improvement :slight_smile:

The language extension for text files is mandatory in multi-language installations.