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?
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']);
});