🚚 How to migrate to Kirby Tips & tutorials
Skip to content

Permissions

User permissions help you to restrict access and capabilities for specific user roles – in the Panel as well as when using Kirby's PHP API or REST API.

Defining permissions

Permissions in Kirby can be defined in two places:

  1. In a user blueprint for each role
  2. In the page, file or the site blueprint for more detailed rules

Role based permissions in user blueprints

Each role can have its own blueprint with custom fields for users with that role and optional user permissions. User blueprints are stored in /site/blueprints/users and get the name of each role (e.g. /site/blueprints/users/editor.yml).

Permissions are only valid for custom roles. The admin role does not obey to those settings and can always do anything.

Here is an overview of all available permissions:

/site/blueprints/users/editor.yml
title: Editor
permissions:
  access:
    account: true
    panel: true
    site: true
    languages: true
    system: true
    users: true
  files:
    create: true
    changeName: true
    changeTemplate: true
    delete: true
    read: true
    replace: true
    update: true
  languages:
    create: true
    delete: true
  pages:
    access: true
    changeSlug: true
    changeStatus: true
    changeTemplate: true
    changeTitle: true
    create: true
    delete: true
    list: true
    move: true
    duplicate: true
    preview: true
    read: true
    sort: true
    update: true
  site:
    changeTitle: true
    preview: true
    update: true
  user:
    changeEmail: true
    changeLanguage: true
    changeName: true
    changePassword: true
    changeRole: true
    delete: true
    update: true
  users:
    changeEmail: true
    changeLanguage: true
    changeName: true
    changePassword: true
    changeRole: true
    create: true
    delete: true
    update: true

There are different types of permissions and permission categories:

  • The access.panel permission controls access to the Panel and the REST API in general. If it is disabled, the user will be a pure frontend user/visitor.
  • The remaining access permissions control access to individual Panel areas.
  • The other permission categories belong to different model types (e.g. page, file, user) and control access to the different actions one can perform with a model. There is a special case: The user permission category applies to the current user (access of a user to themselves), while the users permission category applies to other users.

You don't have to set all possible permissions for each role. Each permission is set to true by default, if not specified otherwise.

You can also enable or disable entire permission categories by passing true or false instead of an array of definitions for each action. A more simple permission setup for an editor, who should not be allowed to edit other users, could look like this:

/site/blueprints/users/editor.yml
title: Editor
permissions:
  site:
    update: false
  pages:
    delete: false
  users: false
  user:
    changeRole: false

This would prevent the editor from editing other users (users: false), from changing their own role, from deleting pages and from updating the site settings.

The category permission only controls the permissions you can find in the full list above. Setting a category to true or false is the same as setting all available permissions of that category manually.

The * wildcard

For permission types with many actions with the same setting, you can use the * wildcard as first argument. Afterwards you can still override specific actions, for example to allowlist some actions but disable the others:

user:
  *: false
  changeName: true

The * wildcard only controls the permissions you can find in the full list above. It is the same as setting all available permissions (except those that are overridden explicitly by another rule) manually.

Visitors without Panel access

Frontend users can also be managed through the Panel, but you most likely don't want them to be able to access the Panel at all. In order to achieve this, set Panel access to false.

title: Visitor
permissions:
  access:
    panel: false

With this permission setup, the Panel and REST API are no longer available to users of that role.

However the model-based permissions are independent of this. If you use any of Kirby's PHP APIs in the site frontend to modify pages, files, the site, languages or users, you should set the permissions like above to control what a visitor can do in your frontend. You can also have multiple frontend user roles without access to the Panel but with different access rights to the PHP APIs.

Specific permissions in page, file, user or site options

You can keep all permissions in the role files, but you can also overwrite them individually per page, file, user or the site in the corresponding blueprints. Those specific permission settings will always override the role settings.

Page options

/site/blueprints/pages/project.yml
title: Project

options:
  changeTemplate: false
  changeTitle: false
  update: true
  delete: false

You can control each option for pages, files and users in blueprints with fine-grained permissions based on user role:

options:
  delete:
    admin: true
    editor: false

You can also use a wildcard to change the default for all roles and then assign exceptions to individual roles:

options:
  update:
    *: false
    editor: true

Controlling permissions with hooks

If the blueprint-based permission settings are too limiting for your project, you can get more flexibility by creating your own permission checks with before hooks for various actions.

/site/config/config.php
return [
  'hooks' => [
    'page.delete:before' => function (Page $page) {
      if ($this->user()->email() !== 'overlord@ourcompany.com') {
        throw new Exception('Only our overlord and savior can delete pages');
      }
    }
  ]
];

Of course this can be more complex and sophisticated than that, but it's a good first start.

Authenticate or impersonate

To obtain the required permissions for certain actions, you can authenticate as a user by logging in. If you want to run actions programmatically without logging in, you can also impersonate a user.

Authentication

Users can log in through the Panel login page or a custom login form. To learn more about how to log in a user programmatically, read the reference for $user->login().

Impersonate

One way to go without authentication is to impersonate an existing user or the special kirby super user, which has full permissions:

<?php

$kirby = kirby();
$kirby->impersonate('kirby');

page('notes/a-great-article')->update([
  'author' => 'Homer Simpson'
]);

The impersonation will be active for all code that runs in the current request after the call to $kirby->impersonate(). If you want to limit the impact to a single operation, call the method with a callback (see below).

Impersonate with callback

If you only want a single operation to run with different privileges, use a callback:

<?php

$kirby = kirby();
$result = $kirby->impersonate('kirby', function () {
  page('notes/a-great-article')->update([
    'author' => 'Homer Simpson'
  ]);

  return 'this will be returned to $result above';
});

The impersonation automatically gets reset to the previous value after the callback returns.

Disable all permissions

It is also possible to disable all permissions, even if a user is currently logged in. This is useful for operations where you want to ensure that no changes are made to the site (read-only access):

<?php

$kirby = kirby();
$kirby->impersonate('nobody');

// later in the code: an unwanted update, which will now fail
page('notes/a-great-article')->update([
  'author' => 'Homer Simpson'
]);