Permissions

Permissions are the abilities that can be assigned to Roles.

Out of the box, Statamic has its own set of permissions that you can choose from to configure your roles. However, you are free to add your own that can be used throughout your project, or included with addons.

Basic permissions

You can register a basic permission in a service provider by specifying the string.

use Statamic\Facades\Permission;

public function boot()
{
    $this->app->booted(function () {
        Permission::register('manage stuff')
                  ->label('Manage Custom Stuff');
    });
}

This will add an option to the permissions list when editing a role in the Control Panel.

If selected, this will add the permission string to the role:

permissions:
  - manage stuff

Nested permissions

It could be useful to only allow some permissions if others have already been granted. For example, you want a tree like this:

view blog entries
`-- edit blog entries
    |-- create blog entries
    `-- delete blog entries

Initially, only the view option will be selectable. When you check it, then the edit option becomes selectable. Check that, and the create and delete options become selectable.

This can be achieved by passing an array of permissions to the children method on the parent permission:

Permission::register('view blog entries', function ($permission) {
    $permission->children([
        Permission::make('edit blog entries')->children([
            Permission::make('create blog entries'),
            Permission::make('delete blog entries')
        ])
    ]);
});

The second argument of the register method accepts a closure that allows you to modify the permission.

Policy based permissions

When dealing with a permission that could apply to a variable number of items, it makes more sense to use a Policy.

You may combine your policy with a wildcard permission. A new permission will be created for each item you require.

For example, Statamic creates a view {collection} entries permission for each collection that exists.

It does this by using a replacements method to return a list of items to determines the replacements. It should return an array of arrays where value is the string to be inserted into the permission, and a label to be inserted into the label.

Permission::register('view {collection} entries', function ($permission) {
    $permission
        ->label('View :collection entries')
        ->replacements('collection', function () {
            return Collection::all()->map(function ($collection) {
                return [
                    'value' => $collection->handle(),
                    'label' => $collection->title()
                ];
            });
    });
});

To use your policy permissions, you should write the authorization checks from within a Policy class. For example:

class EntryPolicy
{
    public function edit($user, $entry)
    {
        return $user->hasPermission("view {$entry->collectionName()} entries");
    }
}

Finally, you may combine policy wildcard permissions with nested permissions.

Permission::register('view {collection} entries', function ($permission) {
    $permission
        ->label('View :collection entries')
        ->replacements('collection', function () { /* ... */ });
        ->children([
            Permission::make('edit {collection} entries')->children([
                Permission::make('create {collection} entries')
                Permission::make('delete {collection} entries')
            ])
        ])
});

When using replacements, ensure your label string contains a placeholder prefixed with a colon.

Groups

You can put your permissions in your own group. Give it a name, a label, and then any permissions created inside the callback will be added to that group.

Permission::group('myaddon', 'My Addon', function () {
    Permission::make(...);
});

If you want to add permissions to an existing group (eg. the core ones like collections, taxonomies, etc.) you can just leave out the label argument:

Permission::group('collections', function () {
    Permission::make(...);
});

Adding to the core permissions

It’s possible to add to the built-in permission tree if you need to.

For example, maybe you want to add a permission to send tweets once an entry is published. You might want to jam that in every collection’s permission tree under its ‘edit’ permission.

You can use the addChild method on an existing permission to inject it at that position.

$this->app->booted(function () {
    Permission::get('edit {collection} entries')->addChild(
        Permission::make('tweet {collection} entries')
    );
});
Betterify this page on Github!