Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 role based access control

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?

like image 686
imperium2335 Avatar asked Sep 12 '15 20:09

imperium2335


2 Answers

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.

like image 179
Andre Avatar answered Nov 20 '22 10:11

Andre


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!

like image 3
89n3ur0n Avatar answered Nov 20 '22 12:11

89n3ur0n