Permissions

Permissions

Learn how to control permissions in the backend panel.

Permissions allow users to have specific privileges and functions in the backend panel. An example might be the ability to create or delete a record, or view the server logs. These permissions are based on the role assigned and can be granted on a per-user basis.

# Permission Codes

Permissions codes define a single permission and are string keys that use a "dot" notation, for example, some.area.permission_name. These permissions are granted to users by either direct assignment or by inheritance through their role.

When checking if a user has a specific permission, the permission for that user's role are inherited and then overridden by any permissions applied directly to that user. For example:

  • If user Bob has role called Genius; and
  • Role Genius has the eat_cake permission; but
  • Bob has the eat_cake permission specifically set to deny; then
  • Bob will not get to eat_cake.

However:

  • If Bob has the permission eat_vegetables assigned directly to him, but;
  • The Genius role does not, then;
  • Bob still gets to eat_vegetables.

# Nested Permissions

Permission codes support a nested structure to provide a cleaner interface when selecting permissions. To nest a permission code the "dot" value must be a direct descendant of its parent and unlimited nesting is supported.

In the following example, the manage_entries permission must be granted for the manage_entries.create and manage_entries.publish codes to become available. Visually it is represented like this:

├── manage_entries | ├── manage_entries.create | └── manage_entries.publish └── delete_entries

# Access Levels

Access to all parts of an October CMS instance is controlled by the permissions system. The BackendAuth::userHasAccess method is a quick way to check if the current user is logged in and has permission to a specific area.

// Returns true if the user has permission
$permissionGranted = BackendAuth::userHasAccess('utilities.logs');

# Super Users

Administrators can be granted a special flag called a "super user" that allows access to all areas. When granted, the permission system is bypassed with access to all areas. Super users are not visible to other regular administrators.

Any super user can create and remove other super users, so it should only be granted to the highest level administrator or owner of the application.

# Roles

Roles use the Backend\Models\UserRole model and are groupings of permissions with a name and description used to identify the role. An administrator can only have one role assigned to them at once.

October CMS ships with two default system roles called developer and publisher. Any number of custom roles with their own combinations of permissions can be created and applied to users.

System roles cannot change their permissions however they can be deleted if not required.

# Role Hierarchy

Each role is assigned a ranked position in the backend panel, represented as the sort_order column in the database. This allows a basic organisational structure to be established where users can only manage roles lower than their own role.

In the following example, the Senior Editor can manage all the users, outranking Staff Writer and Fact Checker roles. Whereas, the Fact Checker role cannot see users or manage permissions above them, in the Staff Writer and Senior Editor roles.

  • Senior Editor
  • Staff Writer
  • Fact Checker

If the Manage Admins → Manage Roles permission is granted, users can manage their own users, permissions and roles existing below their current role.

# Registering Permissions

Plugins can register backend user permissions by overriding the registerPermissions method inside the plugin registration file. The permissions are defined as an array with keys corresponding the permission keys and values corresponding the permission descriptions. The permission keys consist of the author name, the plugin name and the feature name. Here is an example code.

acme.blog.access_categories

The next example shows how to register backend permission items. Permissions are defined with a permission key and description. In the backend permission management user interface permissions are displayed as a checkbox list. Back-end controllers can use permissions defined by plugins for restricting the user access to pages or features.

public function registerPermissions()
{
    return [
        'acme.blog.access_posts' => [
            'label' => 'Manage the blog posts',
            'tab' => 'Blog',
            'order' => 200,
        ],
        // ...
    ];
}

You may also specify a roles option as an array with each value as a role API code. When a role is created with this code, it becomes a system role that always grants this permission to users with that role.

public function registerPermissions()
{
    return [
        'acme.blog.access_categories' => [
            'label' => 'Manage the blog categories',
            'tab' => 'Blog',
            'order' => 200,
            'roles' => ['developer']
        ]
        // ...
    ];
}

# Restricting Access to Backend Pages

In a backend controller class you can specify which permissions are required for access the pages provided by the controller. It's done with the $requiredPermissions controller's property. This property should contain an array of permission keys. If the user permissions match any permission from the list, the framework will let the user to see the controller pages.

namespace Acme\Blog\Controllers;

use Backend\Classes\BackendController;

class Posts extends BackendController
{
    public $requiredPermissions = ['acme.blog.access_posts'];
}

You can also use the asterisk symbol to indicate the "all permissions" condition. In the next example the controller pages are accessible for all users who has any permissions starting with the "acme.blog." string:

public $requiredPermissions = ['acme.blog.*'];

# Restricting Access to Features

The backend user model has methods that allow determining whether the user has specific permissions. You can use this feature in order to limit the functionality of the backend user interface. The permission methods supported by the backend user are userHasAccess and userHasPermission. Both methods take two parameters: the permission key string (or an array of key strings) and an optional parameter indicating that all permissions listed with the first parameters are required.

The userHasAccess method returns true for any permission if the user is a super user. The userHasPermission method is more strict, only returning true if the user actually has the specified permissions either in their account or through their role. Generally, userHasAccess is the preferred method to use as it respects the absolute power of the super user. The following example shows how to use the methods in the controller code.

if (BackendAuth::userHasAccess('acme.blog.*')) {
    // ...
}

if (BackendAuth::userHasPermission([
    'acme.blog.access_posts',
    'acme.blog.access_categories'
])) {
    // ...
}

You can also use the methods in the backend views for hiding user interface elements. The next example demonstrates how you can hide a button on a backend form.

<?php if (BackendAuth::userHasAccess('acme.blog.delete_categories')): ?>
    <button
        type="button"
        class="oc-icon-trash-o btn-icon danger"
        data-request="onDelete"
        data-load-indicator="Deleting Category..."
        data-request-confirm="Do you really want to delete this category?">
    </button>
<?php endif ?>