1

I am working on Laravel passport api in which i am using spatie package for user role's and permission's. I have to perform certain operation ('store','view','update','delete') based on user permission's. For this purpose i have created a trait and used in controller but it is not working correctly. On every api request it throw's an exception "This action is unauthorized" either the user has permission or not.

Authorize Trait :

<?php

namespace App;
/*
 * A trait to handle authorization based on users permissions for given controller
 */

trait Authorizable
{
    /**
     * Abilities
     *
     * @var array
     */
    private $abilities = [
        'index' => 'view',
        'edit' => 'edit',
        'show' => 'view',
        'update' => 'edit',
        'create' => 'add',
        'store' => 'add',
        'destroy' => 'delete'
    ];

    /**
     * Override of callAction to perform the authorization before it calls the action
     *
     * @param $method
     * @param $parameters
     * @return mixed
     */
    public function callAction($method, $parameters)
    {
        if( $ability = $this->getAbility($method) ) {
            $this->authorize($ability);
        }

        return parent::callAction($method, $parameters);
    }

    /**
     * Get ability
     *
     * @param $method
     * @return null|string
     */
    public function getAbility($method)
    {
        $routeName = explode('.', \Request::route()->getName());
        $action = array_get($this->getAbilities(), $method);

        return $action ? $action . '_' . $routeName[0] : null;
    }

    /**
     * @return array
     */
    private function getAbilities()
    {
        return $this->abilities;
    }

    /**
     * @param array $abilities
     */
    public function setAbilities($abilities)
    {
        $this->abilities = $abilities;
    }
}

Routes:

Route::middleware('auth:api')->group(function () {
        Route::post('user', 'ApiController@user');
        Route::post('view_department', 'DepartmentController@index');
        Route::post('add_department', 'DepartmentController@store');
        Route::post('edit_department', 'DepartmentController@update');
        Route::post('delete_department', 'DepartmentController@destroy');

        Route::post('/logout', 'ApiController@logout');
    }); // auth middleware ends

Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use App\User;
use App\Authorizable;
use Illuminate\Support\Facades\Validator;
use App\Department;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class DepartmentController extends Controller
{
     use Authorizable;

        //
    public function index(Request $request) {

        // return response
        return response()->json([
            'success' => 'You have the permission to view departments!']);
    }

    //
    public function store(Request $request) {
        // validate the posted data
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|unique:departments',
        ]);
        // return errors
        if ($validator->fails())
        {
            return response(['errors'=>$validator->errors()->all()]);
        }

        $department = new Department;
        $department->name = $request->name;
        $department->save();

        // return response
        return response()->json([
            'success' => 'Successfully created department!']);
    }
}

I am badly stack at it, don't know where i am going wrong. I would highly appreciate if anyone guide me through this. Thanks,

apokryfos
  • 38,771
  • 9
  • 70
  • 114
Amir Khan
  • 183
  • 2
  • 16
  • Did you fixed this? – beingjungshahi Dec 06 '19 at 06:22
  • I have solved this problem using a middle ware which checks for specific permission and allow user to access only assigned routes. – Amir Khan Dec 06 '19 at 06:42
  • Did you created permissions and roles on your database with api guard? – beingjungshahi Dec 07 '19 at 15:02
  • Yes I assigned the permissions and roles to user on database end with spatie methods, and then through middleware i managed these permissions on runtime. – Amir Khan Dec 08 '19 at 17:13
  • You can assign permissions to user and then in middleware just check for $user->can('edit articles'). If user has the permission to access the route he will be allowed to visit the url otherwise you can redirect to 404 page or some message to user. – Amir Khan Dec 08 '19 at 17:19
  • if you had used api as guard_name that is the problem with passport and spatie. change it to web and the above trait will work. – beingjungshahi Dec 13 '19 at 19:17

0 Answers0