13
votes

I am trying to come up with an efficient and flexible RBAC solution for my app. I have done a little research and think I have created the following.

In my User model I have:

...
public function role() {
        return $this->belongsToMany('App\Models\Role', 'user_roles');
    }

    public function hasRole($role) {
        if($this->role->where('name', $role)->first())
            return true;
    }
...

And an example of usage:

Route::group(['middleware' => 'auth'], function () {

    Route::get('/dashboard', function () {
        if (Auth::user()->hasRole('Sales')) {
            return view('dashboards/sales');
        } else {
            return 'Don\'t know where to send you :(';
        }
    });

});

Permissions are assigned to roles, but permissions are not checked in the example above. Roles are then assigned to users and a user can have many roles.

Is the way I have done things scaleable and an effective RBAC solution?

3
5.1.11 introduced authorization using capabilities and policies. Could they fit your requirements?. laravel.com/docs/5.1/authorization .. you could try ENTRUST though github.com/Zizaco/entrust - e4rthdog
Thanks, the only thing it doesn't tell you how to do is how to assign abilities to certain users using a database. - imperium2335
Its rather that you check the ability via user model...laravel.com/docs/5.1/authorization#defining-abilities - e4rthdog
Just to deliver an alternative to the L5 out of the box solution: Another good Package is the Entrust package - that is very well documented and does exactly what you want to do. github.com/Zizaco/entrust - Gummibeer

3 Answers

3
votes

I've made some RBAC apps, and it depends on kind of challange are you facing, e.g.

User have a role but you want a that a specific user have access to some area, like Posts, now user can edit posts like a Moderator. The permissions approach in this case suits better than just a role approach.

Define access by a slug, the other fields can be used as a reference to Super Admin, or ironically for a Editor Role, starting now, a Editor Role plus Permission to a new "area".

public function up()
{
    Schema::create('permissions', function (Blueprint $table) {
        $table->increments('id')->unsigned();
        $table->string('name');
        $table->string('slug')->unique();
        $table->string('description')->nullable();
        $table->string('model')->nullable();
    });
}

As example of content data,

$createUsersPermission = Permission::create([
    'name' => 'Create permissions',
    'slug' => 'create.permissions',
    ...
]); 

And a example of usage:

if ($user->can('create.permissions') { // you can pass an id or slug
    //
}

Personally preference, and never used Zizaco Entrust as suggested by the other folks, but it works in the same way. Also you have levels approach too.

3
votes

I did a little different, I made hasRole in UserRole , not is User(does not impact too much but as per code it should be). So Here is my route :

Route::group(['middleware' => 'auth'], function () {
Route::get('/myProfile', function () {
    if (App\UserRole::hasRole('ROLE_CUSTOMER',Auth::user())) {
        return view('views/customer');
    } else {
        return 'Don\'t know where to send you :(';
    }
}); });

Next Thing is, the method in my UserRole. I tried to keep it simple:

public static function hasRole($authority,$user) {
        $role = Role::where('authority',$authority)->first();
        $userRole = UserRole::where('role_id',$role->id)
                    ->where('user_id',$user->id)->first();
        if($userRole){
            return true;
        }
    }

We look for the authority(ROLE_USER, ROLE_CUSTOMER etc) and $user is User Object retrieved from DB . Everything else runs as per your question/ Hope it helps! Cheers!

0
votes

As there is not out of box solution available for Role based authentication in laravel. You can create a custom Role table that defines the all possible roles your application can have, and role_user table which contains association of user and roles.

You can create methods under your User model to check if user belong to a particular role. Make use of that method to register a new middleware. Middleware can be attache to routes or controllers.

Detailed demo is given in this link https://www.5balloons.info/user-role-based-authentication-and-access-control-in-laravel/