3

I'm using spatie/laravel-permission to add permissions for my routes.

One of the routes I have can be accessed by two permissions (earnings, financial_fund). The user doesn't need to have both permissions to access the controller. He can access the controller by having one of the permissions or both of them.

I've tried to write something like this.

Route::group(['middleware' => ['can:earnings']], function () {
    Route::get('/payment', [PaymentsController::class, 'getAll']);
    Route::post('/payment/cash', [PaymentsController::class, 'addCashPayment']);
});
Route::group(['middleware' => ['can:financial_fund']], function () {
    Route::get('/payment', [PaymentsController::class, 'getAll']);
    Route::post('/payment/cash', [PaymentsController::class, 'addCashPayment']);
});

But the above code allows only users with can:earnings permission to access the routes, it doesn't allow users with can:financial_fund permission.

I've also tried to write something like this

Route::group(['middleware' => ['can:earnings,financial_fund']], function () {
    Route::get('/payment', [PaymentsController::class, 'getAll']);
    Route::post('/payment/cash', [PaymentsController::class, 'addCashPayment']);
});

But this requires both of permissions to exist with the current user.

How can I tell that I want only one of the permissions at least to exist?

I have found that Laravel has introduced the canAny for use in blade templates. Is there a way I can use it in my api.php file while defining the Routes?

Abozanona
  • 2,261
  • 1
  • 24
  • 60
  • Just use OR operator.```['can:earnings|financial_fund']```.Routes are always executed from top to bottom . So once it receive the relevant route it will not execute further. – Nipun Tharuksha Aug 15 '21 at 09:59

1 Answers1

2

I fixed it by creating a new middleware

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AuthorizeCanAny
{
    public function handle(Request $request, Closure $next, ...$permissions)
    {
        if (!$request->user()) {
            abort(403);
        }

        $userPermissions = array_map(function ($e) {
            return $e['name'];
        }, $request->user()->permissions->toArray());

        $userPermissionsIntersect = array_intersect($userPermissions, $permissions);

        if (!sizeof($userPermissionsIntersect)) {
            abort(403);
        }

        return $next($request);
    }
}

Adding the middleware to kernal.php file

protected $routeMiddleware = [
    ...,
    'canAny' => AuthorizeCanAny::class,
];

Then use it in the router

Route::group(['middleware' => ['canAny:earnings,financial_fund']], function () {
    Route::get('/payment', [PaymentsController::class, 'getAll']);
    Route::post('/payment/cash', [PaymentsController::class, 'addCashPayment']);
});
Abozanona
  • 2,261
  • 1
  • 24
  • 60