Middleware dan Guard
Panel adalah Laravel route group, sehingga middleware stack-nya merupakan stack Laravel biasa. Panel mendeklarasikan base stack dan authentication stack; route registrar kemudian menambahkan middleware resolution milik framework setelah keduanya. Halaman ini menjelaskan middleware apa yang diterapkan, urutannya, dan lokasi yang tepat untuk middleware milik aplikasi.
Mewajibkan user login
use PandaPanel\Core\Panel;
use PandaPanel\Core\PanelProvider;
final class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->path('admin')
->auth(); // 'auth' and 'verified', appended after 'web'
}
}2
3
4
5
6
7
8
9
10
11
12
panel('admin')->getMiddleware(); // ['web', 'auth', 'verified']
panel('admin')->getBaseMiddleware(); // ['web']
panel('admin')->getAuthMiddleware(); // ['auth', 'verified']2
3
Dua stack
| Method | Signature | Default | Perilaku |
|---|---|---|---|
middleware | middleware(array $middleware): self | ['web'] | Mengganti base stack. |
authMiddleware | authMiddleware(array $middleware): self | ['auth'] | Mengganti auth stack. Gunakan [] hanya untuk panel yang sengaja dibuat publik. |
auth | auth(bool $verified = true): self | — | Menggabungkan auth (dan verified) ke auth stack. |
middleware() mengganti isi stack, bukan menambahkan. Jadi panel yang memanggilnya harus menyertakan web sendiri — tanpa session dan CSRF token, page panel tidak dapat melakukan submit apa pun:
$panel->middleware(['web', 'throttle:panel']);auth() melakukan merge, sehingga dapat dipakai bersama auth stack eksplisit tanpa membuang konfigurasi sebelumnya. Default sebenarnya sudah berisi auth; pemanggilan auth() terutama menambahkan verified:
$panel->authMiddleware(['auth:staff'])->auth(verified: false);
// getAuthMiddleware() === ['auth:staff', 'auth']2
Lewati pemeriksaan email verified untuk panel yang tidak membutuhkannya:
$panel->auth(verified: false); // ['web', 'auth']Jadikan panel publik hanya dengan mengosongkan auth stack:
$panel->authMiddleware([]); // ['web']getMiddleware() mengembalikan base + auth, dideduplikasi sesuai urutan tersebut, dan hasil inilah yang diberikan kepada route group.
Middleware yang ditambahkan registrar
Setelah stack milik panel, setiap route group panel menerima middleware berikut secara berurutan:
| Middleware | Parameter | Peran |
|---|---|---|
PandaPanel\Http\Middleware\ResolvePanel | panel id | Mengikat current panel, menerapkan isAccessibleTo(), menjalankan boot(). |
PandaPanel\Http\Middleware\RequireTwoFactor | panel id | Redirect ke security page ketika panel mewajibkan second factor. |
PandaPanel\Http\Middleware\RequireEmailCode | panel id | Menahan page sampai session menjawab emailed code untuk account yang mengaktifkannya. |
PandaPanel\Http\Middleware\ResolveTenant | panel id | Hanya untuk panel yang memanggil tenant(). Mengidentifikasi dan mengikat tenant. |
ResolvePanel berjalan setelah auth, sehingga $request->user() sudah tersedia ketika canAccess() dievaluasi. Middleware menerima panel id sebagai parameter daripada mencoba menebaknya dari URL, sehingga dua panel yang berbagi prefix tidak menjadi ambigu.
User yang sudah login tetapi gagal access check menerima 403. Guest tidak pernah mencapai ResolvePanel pada authenticated panel karena middleware auth melakukan redirect lebih dulu.
Full stack pada route tipikal:
Route::getRoutes()->getByName('panel.admin.dashboard')->gatherMiddleware();
// ['web', 'auth', 'verified', 'PandaPanel\Http\Middleware\ResolvePanel:admin', ...]2
Middleware pada satu page
Standalone page dapat menambahkan middleware ke route-nya sendiri:
use Illuminate\Auth\Middleware\RequirePassword;
use PandaPanel\Pages\Page;
final class BillingSettings extends Page
{
/** @var list<string> */
protected static array $middleware = [RequirePassword::class];
}2
3
4
5
6
7
8
Page::middleware(): array adalah reader-nya. Registrar membaca method tersebut dan memasang hasilnya hanya pada route page itu ketika array tidak kosong.
Gunakan ini untuk concern yang harus diterapkan route sebelum page dibuat — seperti password confirmation atau signed URL — yang tidak dapat diekspresikan oleh canAccess() karena canAccess() hanya menjawab yes/no dan tidak dapat melakukan redirect. Built-in SecuritySettings menggunakan pola yang sama.
Resource page tidak memiliki mekanisme setara: resource page dilindungi panel stack dan policy resource. Letakkan route-level concern resource pada panel, atau ekspresikan melalui policy.
Alias middleware
Service provider mendaftarkan empat alias sehingga aplikasi dapat menggunakan class yang sama pada route miliknya sendiri:
| Alias | Class |
|---|---|
panel | ResolvePanel |
panel.two-factor | RequireTwoFactor |
panel.email-code | RequireEmailCode |
panel.parent | ResolveParentRecord |
Route::get('/reports/export', ExportController::class)->middleware('panel:admin');Registrar menyebut class secara langsung dan tidak bergantung pada alias, sehingga menghapus alias tidak akan merusak routing panel.
Group web
Empat middleware berikut berada pada seluruh group web, bukan pada panel tertentu, dan package menambahkannya sendiri:
| Middleware | Mengapa bukan di panel group |
|---|---|
ResetPanelContext | Harus berjalan pada request yang sama sekali tidak masuk panel agar state tidak bocor antar-request di Octane atau antar-request pada satu test. |
RedirectPanelHome | Menangani /dashboard, yang merupakan route aplikasi, bukan route panel. |
ShareFlashToast | Harus berjalan pada redirect yang keluar kembali dari panel. |
SharePanelData | Membagikan panel, navigation, panels, broadcasting, search, notifications, dan tenancy. Setiap value berupa closure sehingga request non-panel tidak membayar biaya pembentukannya. |
Middleware ditambahkan melalui HTTP kernel setelah kernel di-resolve karena bootstrap/app.php mengonfigurasi group dalam afterResolving hook yang sebaliknya dapat menimpa middleware yang sebelumnya ditambahkan ke router. Matikan automatic registration jika ingin menempatkannya sendiri:
// config/panda-panel.php
'register_web_middleware' => false,2
3
// bootstrap/app.php
use PandaPanel\Http\Middleware\ResetPanelContext;
use PandaPanel\Http\Middleware\ShareFlashToast;
use PandaPanel\Http\Middleware\SharePanelData;
->withMiddleware(function (Middleware $middleware): void {
$middleware->web(append: [
ResetPanelContext::class,
ShareFlashToast::class,
SharePanelData::class,
]);
})2
3
4
5
6
7
8
9
10
11
12
13
Tujuan redirect guest
Dengan register_guest_redirect aktif — default — package mengarahkan guest redirect Laravel ke PandaPanel\Support\PanelLoginRedirect. Perilakunya merupakan superset default Laravel: panel yang memiliki login sendiri mengirim guest ke login panel tersebut, sedangkan route lain tetap mengarah ke route('login').
// config/panda-panel.php
'register_guest_redirect' => true,2
3
Untuk mempertahankan rule Anda sendiri sekaligus mendukung login panel, matikan flag tersebut lalu panggil helper-nya:
use PandaPanel\Support\PanelLoginRedirect;
->withMiddleware(function (Middleware $middleware): void {
$middleware->redirectGuestsTo(
fn ($request) => PanelLoginRedirect::for($request) ?? route('welcome'),
);
})2
3
4
5
6
7
Auth page milik panel didaftarkan di luar auth stack panel — hanya menggunakan base middleware dan ResolvePanel — karena menaruh login page di balik auth akan mengirim user yang belum dapat login ke page yang justru mengharuskan mereka sudah login.
Mewajibkan second factor
$panel->requireTwoFactor(); // requireTwoFactor(bool $required = true): self
panel('admin')->requiresTwoFactor(); // bool2
RequireTwoFactor mengarahkan seluruh page panel ke security settings sampai account memiliki second factor. Authenticator app yang sudah dikonfirmasi, emailed code yang aktif, atau passkey terdaftar semuanya dianggap memenuhi syarat — panel yang memaksa TOTP kepada user yang sudah memakai hardware key justru akan meminta downgrade keamanan. Security page dan account page lainnya dikecualikan. Jika panel menonaktifkan security page melalui settings(false), middleware membiarkan semua request lewat daripada mengunci semua user.
Catatan
middleware()mengganti stack. Memanggilnya tanpawebmenghasilkan route tanpa session, dan gejalanya tampak seperti semua form selalu 419.- Middleware berjalan sebelum
canAccess(), sehingga rate limiter atau IP allowlist yang dipasang pada panel berlaku untuk guest juga. - Seluruh route panel menunjuk ke controller, bukan closure, sehingga
php artisan route:cachetetap bekerja. Middleware parameter menggunakan string karena alasan yang sama. - Menambahkan middleware ke panel setelah boot tidak memengaruhi route yang sudah didaftarkan.
ResolvePaneltanpa parameter id fallback keresolveFromRequest(), yang membuat aliaspaneldapat digunakan di luar panel group.