Reputation: 357
I have a function that check if the user has permission or not and it return Boolean.
Question is
How I check in each function user has permission or not. For example in users controller I have 2 functions:
index():
public function index () {
if(Auth::user() -> hasPermissionTo('show all users')) {
// continue for API
} else {
// response with error for API
}
}
I know that there is a better way to do that because I don't want to repeat this if statement in all my functions.
What I have tried to do:
I have tried to create a helper function that check if user has permission and return the response error if the user doesn't have permission. And call it in every function but it didn't work.
Helper function code:
if(!function_exists('userHasPermission')) {
function userHasPermission ($permission) {
$main_permission = 'do everything';
if (!Auth::user() -> hasPermissionTo($main_permission) || !Auth::user() -> hasPermissionTo($permission)) {
$res = trans('api_responses.authorization_failed');
return Response::json([
'message' => $res['message'],
'code' => $res['code']
], $res['code']);
}
}
}
index function call
public function index()
{
// PERMISSIONS CHECK
userHasPermission('users show active');
$getUsers = $this -> users -> getAllActive();
return Response::json($getUsers);
}
But it never returns the error response even if the user doesn't have permission and even it entered the if statement in my helper!
Upvotes: 5
Views: 40104
Reputation: 1725
With Laravel you can use a gate for this.
In you App\Providers\AuthServiceProvider
file do something like this:
public function boot()
{
$this->registerPolicies();
Gate::define('do-everything', function ($user) {
return $user->hasPermission('do-everything');
});
Gate::define('do-one-thing', function ($user) {
return $user->hasPermission('do-one-thing');
});
}
And then in your controller:
if (Auth::user()->can('do-everything')) {
// the user can do everything
}
if (Auth::user()->can('do-one-thing')) {
// the user can just do one thing
}
or
if (!Auth::user()->can('do-everything')) {
abort(403);
}
// user has permission to the everything from here on
or in your routes/web.php
you could do this:
Route::get('/things', 'ThingController@action')->middleware(['can:do-one-thing']);
or you can group the routes like this:
Route::middleware(['can:do-everything'])->group(function () {
Route::get('/things', 'ThingController@index');
Route::get('/other-things', 'OtherThingController@index');
...
}
You can also look at https://laravel.com/docs/5.7/authorization for more ideas.
Upvotes: 12
Reputation: 39
Another easy way checking permission inside controller
use Illuminate\Http\Request; //don't forget to include on top
public function index(Request $request)
{
if($request->user()->canDo('permission you need to check'))
userHasPermission('users show active');
$getUsers = $this -> users -> getAllActive();
return Response::json($getUsers);
}
return Response::json(['Unaurthrorized']);
}
Upvotes: 0
Reputation: 302
This way to check multi permissions to decide sho
@php
$patients_menu_item=0;
$users_menu_item=0;
$roles_menu_item=0;
if(Auth::user() -> hasPermissionTo('Patient Add')||Auth::user() -> hasPermissionTo('Patients List')) {
$patients_menu_item=1;
}
if(Auth::user() -> hasPermissionTo('User Add')||Auth::user() -> hasPermissionTo('Users List')) {
$users_menu_item=1;
}
if(Auth::user() -> hasPermissionTo('Role Add')||Auth::user() -> hasPermissionTo('Roles List')) {
$roles_menu_item=1;
}
@endphp
@if($patients_menu_item == 1)
<li class="has-sub">
<a>
<i class="ft-users"></i><span class="menu-title">Patients</span>
</a>
<ul class="menu-content">
@can('Patient Add')
<li>
<a href="{{url('patients/register')}}"
class="menu-item">Register Patient</a>
</li>
@endcan
@can('Patients List')
<li>
<a href="{{url('patients/index')}}"
class="menu-item">{{ trans('website.Show Patients') }}</a>
</li>
@endcan
</ul>
</li>
@endif
Upvotes: 0
Reputation: 1011
Your helper function returns a new response but it returns it to the controller not as HTTP response, so You can get the returned value like this:
public function index()
{
// PERMISSIONS CHECK
$response = userHasPermission('users show active');
$getUsers = $this -> users -> getAllActive();
return Response::json($getUsers);
}
So what you need is to check the response if it has a value but with this approach you are going to have the same problem as your first one.
To solve it: throw exception from the helper function instead of returning some response.
A better solution is to use FormRequest, check this link to do it, be sure to check "Authorizing Form Requests" section which states the authorize function.
EDIT:
what you have to do is the following:
create new class let's call it "IndexRequest" that inherits from "FormRequest" class, then implement authorize method.
so something like this:
class IndexRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::user() -> hasPermissionTo('show all users');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
];
}
}
then in your method:
public function index(IndexRequest $request)
{
$getUsers = $this -> users -> getAllActive();
return Response::json($getUsers);
}
you don't have to check it manually, Laravel will do it for you using "authorize" function of IndexRequest class.
Upvotes: 1