Verifikasi Email
PandaBear dapat menyediakan halaman "periksa inbox Anda" di path milik Panel, menggunakan branding Panel, lengkap dengan tombol resend yang mengirim request ke Fortify.
Fitur ini cocok untuk Panel yang memungkinkan user melakukan self-registration, sehingga user baru tetap berada di shell dan branding Panel saat diminta memverifikasi email.
Perlu dibedakan:
PandaBear menyediakan halaman notice.
Sedangkan:
Verification link tetap milik Laravel/Fortify.
PandaBear tidak mengubah URL verification link secara otomatis.
Contoh Minimal
<?php
declare(strict_types=1);
namespace App\Panels\Portal;
use PandaPanel\Core\Panel;
use PandaPanel\Core\PanelProvider;
final class PortalPanelProvider
extends PanelProvider
{
public function panel(
Panel $panel
): Panel {
return $panel
->path('portal')
->auth()
->login()
->registration()
->emailVerification();
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Periksa route:
php artisan route:list --name=panel.portal.auth.verificationGET portal/verify-email panel.portal.auth.verification.noticeAPI
public function emailVerification(
bool $emailVerification = true
): self;
public function hasEmailVerification():
bool;2
3
4
5
6
Contoh:
use PandaPanel\Core\PanelManager;
$panel =
app(PanelManager::class)
->get('portal');
$panel->hasEmailVerification();
// true
$panel->routeName(
'auth.verification.notice'
);
// 'panel.portal.auth.verification.notice'
route(
$panel->routeName(
'auth.verification.notice'
)
);
// '…/portal/verify-email'2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Dua bagian membaca flag tersebut:
| Pembaca | Jika false |
|---|---|
PanelRouteRegistrar::registerAuth() | Route tidak diregistrasikan, URL menjadi 404 |
PanelAuthController::verifyEmail() | abort_unless(..., 404) |
Seperti front-door Page lainnya, Email Verification membutuhkan:
login()Jika:
hasLogin() === falseregisterAuth() berhenti sebelum mendaftarkan Page ini.
Hubungan dengan Fortify Feature
Page ini berbeda dari dua link pada Login Page.
Page hanya memeriksa:
Panel::hasEmailVerification()dan tidak memeriksa:
Laravel\Fortify\Features::emailVerification()Akibatnya Anda dapat membuat:
GET /portal/verify-emailtetap tersedia ketika Fortify email verification feature dimatikan.
Tetapi tombol resend kemudian menuju endpoint yang tidak tersedia.
Karena itu aktifkan keduanya atau matikan keduanya.
Page
public function verifyEmail(
Request $request
): Response {
abort_unless(
$this
->panel()
->hasEmailVerification(),
404
);
return Inertia::render(
'panel/auth/VerifyEmail',
[
'panel' =>
$this
->panel()
->toSharedArray(),
'status' =>
$request
->session()
->get('status'),
]
);
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Props:
| Prop | Type | Sumber |
|---|---|---|
panel | PanelDefinition | Panel::toSharedArray() |
status | string|null | Session flash status; 'verification-link-sent' setelah resend |
Frontend:
resources/js/pages/panel/auth/VerifyEmail.vuedi dalam:
PanelAuthLayoutContoh:
<script setup lang="ts">
import {
Form,
Link,
} from '@inertiajs/vue3';
import {
logout,
} from '@/routes';
import {
send,
} from '@/routes/verification';
</script>
<template>
<Form
v-slot="{ processing }"
v-bind="send.form()"
>
<Button
type="submit"
:disabled="processing"
>
Resend the link
</Button>
<Link
:href="logout()"
as="button"
>
Log out
</Link>
</Form>
</template>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Target:
| Control | Target | Route |
|---|---|---|
| Resend | POST /email/verification-notification | verification.send |
| Logout | POST /logout | logout |
Kedua route berasal dari application/Fortify melalui Wayfinder.
PandaBear tidak mendaftarkan duplicate resend endpoint per Panel.
Jika duplicate dibuat, Anda juga harus menjaga throttle-nya tetap konsisten dengan Fortify.
Route Middleware
Page menggunakan guest stack:
Panel base middleware
+
ResolvePanel2
3
bukan full authenticated Panel group.
Tetapi tombol di dalamnya hanya bermakna bagi signed-in user.
Route Tujuan verified Middleware
Bagian ini penting.
Default:
$panel->auth();menambahkan:
auth
verified2
Sedangkan:
$panel->auth(
verified: false
);2
3
hanya menambahkan:
authLaravel EnsureEmailIsVerified secara default mengarahkan ke route:
verification.noticemilik application, bukan:
panel.{id}.auth.verification.noticeJadi konfigurasi:
$panel
->auth()
->emailVerification();2
3
tidak otomatis membuat unverified user dialihkan ke:
/portal/verify-emailSecara default mereka tetap diarahkan ke application route seperti:
/email/verifyMengarahkan Middleware ke Verification Page Milik Panel
Gunakan:
use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
$panel
->auth(
verified: false
)
->authMiddleware([
'auth',
EnsureEmailIsVerified::redirectTo(
'panel.portal.auth.verification.notice'
),
]);2
3
4
5
6
7
8
9
10
11
12
13
Helper menghasilkan middleware string:
EnsureEmailIsVerified::redirectTo(
'panel.portal.auth.verification.notice'
);
// Illuminate\Auth\Middleware\EnsureEmailIsVerified:
// panel.portal.auth.verification.notice2
3
4
5
6
Perhatikan:
authMiddleware()mengganti auth stack.
Jadi 'auth' harus ditulis kembali.
Jangan memahami keduanya sebagai hal yang sama:
auth()
→ merge
authMiddleware()
→ replace2
3
4
5
Verification sebagai Panel Access Rule
Anda juga dapat menolak unverified account melalui PanelUser:
use PandaPanel\Contracts\PanelUser;
use PandaPanel\Core\Panel;
final class User
extends Authenticatable
implements
MustVerifyEmail,
PanelUser
{
public function canAccessPanel(
Panel $panel
): bool {
return $this
->hasVerifiedEmail();
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Tetapi behavior-nya berbeda:
| Mekanisme | Hasil untuk unverified user |
|---|---|
verified middleware | 302 redirect ke verification notice |
canAccessPanel() false | 403 |
ResolvePanel sengaja abort, bukan redirect.
Jangan Campur Keduanya secara Sembarangan
ResolvePanel juga berjalan pada auth/guest Page milik Panel.
Artinya signed-in unverified user yang:
canAccessPanel() === falsejuga mendapatkan:
403ketika mencoba membuka:
/portal/verify-emailPadahal Page tersebut seharusnya membantu mereka menyelesaikan verification.
Jadi pilih satu pendekatan:
Gunakan verified middleware jika Anda ingin user diarahkan ke verification Page.
Gunakan PanelUser::canAccessPanel() jika Anda memang ingin unverified account ditolak penuh dengan 403.
Apa yang Dimiliki Fortify
| Concern | Owner |
|---|---|
GET /email/verify | Fortify |
GET /email/verify/{id}/{hash} | Fortify |
POST /email/verification-notification | Fortify |
| Throttle | fortify.limiters.verification |
| Verification Email | Laravel VerifyEmail |
| Redirect setelah link diklik | Fortify |
Verification link tetap menggunakan:
verification.verifymilik application.
PandaBear tidak membuat per-Panel verification link.
Jika setelah verification user harus kembali ke Portal:
// config/fortify.php
'redirects' => [
'email-verification'
=> '/portal',
],2
3
4
5
6
redirect()->intended() masih memiliki prioritas jika intended URL tersedia.
Notice pada Profile Page
Profile Settings juga menyediakan resend button.
Props:
'mustVerifyEmail' =>
Auth::user()
instanceof MustVerifyEmail,
'status' =>
session('status'),2
3
4
5
6
Notice tampil hanya jika:
mustVerifyEmail = true
dan
email_verified_at = null2
3
Confirmation tampil ketika:
status === 'verification-link-sent'Account dari Console
panel:user langsung mengisi:
$user->forceFill([
'name' =>
$attributes['name'],
'email' =>
$attributes['email'],
'password' =>
Hash::make(
$attributes['password']
),
'email_verified_at' =>
now(),
])->save();2
3
4
5
6
7
8
9
10
11
12
13
14
15
Account yang dibuat operator melalui console dianggap sudah diverifikasi oleh operator tersebut.
Jika email_verified_at dibiarkan null, first admin dapat langsung terjebak pada verification wall.
Testing
use Inertia\Testing\AssertableInertia;
it(
'serves the panel own verification notice',
function (): void {
$this
->get(
'/portal/verify-email'
)
->assertOk()
->assertInertia(
fn (
AssertableInertia $page
) =>
$page
->component(
'panel/auth/VerifyEmail'
)
->where(
'panel.id',
'portal'
)
);
}
);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Panel tanpa fitur:
$this
->get(
'/admin/verify-email'
)
->assertNotFound();2
3
4
5
Route registration:
expect(
Route::has(
'panel.door.auth.verification.notice'
)
)
->toBeTrue()
->and(
Route::has(
'panel.admin.auth.login'
)
)
->toBeFalse();2
3
4
5
6
7
8
9
10
11
12
Untuk middleware Laravel:
$this
->actingAs(
User::factory()
->unverified()
->create()
)
->get('/portal')
->assertRedirect(
route(
'verification.notice'
)
);2
3
4
5
6
7
8
9
10
11
12
Hal yang Perlu Diperhatikan
- Panel verification Page bukan otomatis tujuan
verifiedmiddleware. authMiddleware()replace;auth()merge.canAccessPanel()yang mensyaratkan verified email juga dapat memblokir verification Page milik Panel.- Resend button membutuhkan Fortify email-verification feature aktif.
- Feedback menggunakan
status === 'verification-link-sent'. - Logout tetap milik application.
- Registration menghasilkan unverified account secara default.