Skip to content

2. Roles

Warrick Bayman edited this page Mar 8, 2020 · 1 revision

Deadbolt doesn't have support for roles in the traditional sense. It does provide something called Permission Groups, which was our attempt a making roles simple, but they're not really the same as roles. If you want to use proper roles with Deadbolt, then you'll need to implement them yourself. However, doing so is actually easier than you might think.

There are two Deadbolt features that make this possible:

  • you can manipulate and test the permissions on a collection of users at the same time,
  • Deadbolt doesn't care what model you give it, as long as there is a permissions array available.

For this to work, you need to be using at least Deadbolt v0.3.

Here's a simple example of how this could be done:

The Role model

Create a Role model along with a migration table:

php ./artisan make:model Role -m

Update the create_roles_table migration so that it includes a permissions column. You'll assign permissions to the roles in your application instead of directly to your users.

Schema::create('roles', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('name');
    $table->string('description')->nullable();
    $table->string('permissions')->nullable();
    $table->timestamps();
});

You won't need a permissions column on your users table as we'll be assigning permissions to the roles we create. Users will then have roles instead of permissions.

you'll also need to create a pivot table:

Schema::create('role_user', function (Blueprint $table) {
    $table->unsignedBigInteger('role_id');
    $table->unsignedBigInteger('user_id');

    $table->foreign('role_id')->references('id')->on('roles');
    $table->foreign('user_id')->references('id')->on('users');
});

Now update your Role model and add the users relationship method:

class Role
{
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
}

Do the same on the User model, adding the roles relationship method:

class User
{
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

Now when you need to add permissions to a role, Deadbolt can be used in the same way. Instead of passing in an instance of your User model, you'll passing in a Role instance. For example, lets create a Writer role:

$role = Role::create([
    'name' => 'writer',
    'description' => 'Writer',
]);

Deadbolt::user($role)->give('articles.create', 'articles.create', 'articles.delete')->save();

Now you have a role named writer that has three permissions. You can easily assign this role to your users:

$user->roles()->attach($role->id);

You really shouldn't test your users abilities by testing for roles. Rather, users should still have permissions. But in this example, your users don't actually have permissions directly. However, since Deadbolt doesn't require a user, and can manage permissions on any model, we can pass the roles collection from one of our users to the Deadbolt::users() method (note that it's users and not user).

So In your policy class you can test if a user has a permission by first passing the roles collection from the user instead of the user itself, and then using the anyHave method to check if any of the roles have the specified permission. Like this:

public function create(User $user)
{
    return Deadbolt::users($user->roles)->anyHave('articles.create');
}

Deadbolt itself does not manage your roles, only the permissions on the roles. To give users abilities, you would need to assign roles to users yourself.

Clone this wiki locally