I am developing a RESTful API with Laravel 5. I have some resource in my routes.php
file and everything works properly.
But now I had added auth.basic
middleware and I want introduce the user roles and I got confused.
In my Controller I have a constructor to call 2 middleware, auth.basic and roles middleware, but cannot continue because of lack of knowledge.
What do I need? Well, I need to set the user roles who can access every controller, but cant achieve this. Im the Controller I would like to access the user to check his role and compare it with the role stablished on the Controller, but I don't know how to access the user, can you help me?
EDIT:
I put this on the constructor of the Controller
public function __construct(Request $request)
{
$actions = $request->route()->setAction( ['roles' => ['admin', 'seller', 'buyer']]);
$this->middleware('auth.basic');
$this->middleware('roles');
}
Basically I inject the request in the controller constructor and then I set an action called roles. Then I call middleware auth.basic to set the user. And last call middleware roles which checks the user role against the roles array in the request, if it has the role or if he is root, then result is true, else I return error:
return response([
'error' => [
'code' => 'INSUFFICIENT_ROLE',
'description' => 'You are not authorized to access this resource.'
]
], 401);
Now I have the error that always get:
{"error":{"code":"INSUFFICIENT_ROLE","description":"You are not authorized to access this resource."}}
Thats because User model dont returns a Role. See my class:
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['username', 'email', 'password', 'role_id'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
//Comprobacion del rol del usuario
public function hasRole($roles)
{
$this->have_role = $this->getUserRole();
// Check if the user is a root account
if($this->have_role->name == 'root') {
return true;
}
if(is_array($roles)){
foreach($roles as $need_role){
if($this->checkIfUserHasRole($need_role)) {
return true;
}
}
} else{
return $this->checkIfUserHasRole($roles);
}
return false;
}
private function getUserRole()
{
return $this->role()->getResults();
}
private function checkIfUserHasRole($need_role)
{
return (strtolower($need_role)==strtolower($this->have_role->name)) ? true : false;
}
//User relation with role
public function role(){
return $this->belongsTo('App\Role');
}
}
Whats wrong?
Found the solution!!!!! Thanks Phorce for guiding me, you gave me the idea basics. I post it here for everyone who needs. How to get Role Authentication for a RESTful API with Laravel 5.
Explanation. In the controller of the route I call a constructor for the middleware, first add the attribute roles (sets which roles can access this route) with an injected $request object. Then I call middleware auth.basic for requesting user, and then another middleware to check roles. Ando thats it! All working.
Middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
//return $next($request);
// Get the required roles from the route
$roles = $this->getRequiredRoleForRoute($request->route());
// Check if a role is required for the route, and
// if so, ensure that the user has that role.
//print "HasRole:".$request->user()->hasRole($roles).".";
if($request->user()->hasRole($roles) || !$roles)
{
return $next($request);
}
return response([
'error' => [
'code' => 'INSUFFICIENT_ROLE',
'description' => 'You are not authorized to access this resource.'
]
], 401);
}
private function getRequiredRoleForRoute($route)
{
$actions = $route->getAction();
//print "actinos:".print_r($actions);
return isset($actions['roles']) ? $actions['roles'] : null;
}
}
User Model
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['username', 'email', 'password', 'role_id'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
protected $have_role;
protected $profile;
//Comprobacion del rol del usuario
public function hasRole($roles)
{
$this->have_role = $this->getUserRole();
//$this->have_role = $this->role()->getResults();
// Check if the user is a root account
if($this->have_role->nombre == 'root') {
return true;
}
if(is_array($roles)){
foreach($roles as $need_role){
if($this->checkIfUserHasRole($need_role)) {
return true;
}
}
} else{
return $this->checkIfUserHasRole($roles);
}
return false;
}
private function getUserRole()
{
return $this->role()->getResults();
}
private function checkIfUserHasRole($need_role)
{
if($need_role === $this->have_role->nombre){
return true;
}else{
return false;
}
//return (strtolower($need_role)==strtolower($this->have_role->name)) ? true : false;
}
//Relaciones de user
public function role(){
return $this->belongsTo('App\Role');
}
}
Routes:
Route::resource('perfiles','PerfilesUsuariocontroller',[ 'only'=>['index','show'] ]);
Controller Constructor method
public function __construct(Request $request)
{
$actions = $request->route()->setAction( ['roles' => ['root', 'admin', 'seller']]);
$this->middleware('auth.basic');
$this->middleware('roles');
}