Middleware
bwp.permission
Registered automatically as Route::middleware('bwp.permission'). It resolves access for the current route, then checks bits against it.
Route::middleware('bwp.permission')->group(function () {
Route::get('/leads', [LeadController::class, 'index'])->name('leads.index');
});
Route::middleware('bwp.permission:create')->group(function () {
Route::post('/leads', [LeadController::class, 'store'])->name('leads.store');
});
Route::middleware('bwp.permission:delete')->group(function () {
Route::delete('/leads/{lead}', [LeadController::class, 'destroy'])->name('leads.destroy');
});
What happens on every request
- If the user isn't authenticated, redirect to
login. - If the current route has no name, the request passes through untouched — the package can only resolve access for named routes.
- If the user
isSuperAdmin(), access is set to the sum of every positive bit in config and the request proceeds — no query. - Otherwise,
$user->resolveAccess($routeName)looks up the matching wildcard permission and returns the access integer, which is cached on the user viasetAccess()for the rest of the request (available in controllers and views). - The
viewbit is checked first, unconditionally. If it isn't present, the request is denied — this happens even if a middleware parameter likecreatewas satisfied. - If a bit parameter was passed (e.g.
create), that bit is checked too.
The view prerequisite rule
This is the one rule to remember: no bit works without view. A user with create + update but without view is still denied, because view represents "is allowed to be here at all," and everything else is scoped inside that.
// bits: view=1, create=4 → access = 4 (create only, no view)
$access & 1 === 1 // false — denied, regardless of the create bit
This mirrors how the config is meant to be used: always include view in every permission that should be reachable at all.
Denied requests
if ($request->expectsJson()) {
return response()->json(['message' => 'Unauthorized.'], 403);
}
abort(403);
bwp-ui gate middleware
Protects every route under /bwp/* — the bundled admin UI. It evaluates the bwp-ui gate, which you define in the gate config key (see Configuration):
'gate' => function ($user) {
return $user->hasRole('super_admin');
},
Unauthenticated users are redirected to login; authenticated users who fail the gate get a 403.
Combining with other middleware
The permission middleware only checks authorization — pair it with auth (or your guard of choice) as usual:
Route::middleware(['auth', 'bwp.permission:update'])->group(function () {
Route::put('/leads/{lead}', [LeadController::class, 'update'])->name('leads.update');
});