false: the app renders its own * screens (R1/R2) and Fortify keeps only the POST actions. */ #[Layout('layouts.portal')] class VerifyEmail extends Component { /** * Six a minute is generous for a person and useless for anything else. * Without it this is a button that makes the server send mail to an * arbitrary address as fast as it can be clicked. */ private const PER_MINUTE = 6; /** * Somebody already through has no step left, and telling them they do is * how a confirmed account goes looking for a mail it does not need. The * `verified` middleware only guards the other direction — it keeps the * unconfirmed out of the portal and has nothing to say about this page. */ public function mount() { if (Auth::user()?->hasVerifiedEmail()) { return $this->redirectRoute('dashboard', navigate: false); } return null; } public function resend(): void { $user = Auth::user(); // Already through — a stale tab, or the link opened in another window. // Sending another confirmation for an address that no longer needs one // is how somebody ends up chasing a mail they do not need. if ($user === null || $user->hasVerifiedEmail()) { $this->redirectRoute('dashboard', navigate: true); return; } $key = 'verify-resend:'.$user->getKey(); if (RateLimiter::tooManyAttempts($key, self::PER_MINUTE)) { $this->dispatch('notify', message: __('verify_email.notice_hint')); return; } RateLimiter::hit($key, 60); $user->sendEmailVerificationNotification(); $this->dispatch('notify', message: __('verify_email.notice_sent')); } public function signOut() { Auth::guard('web')->logout(); session()->invalidate(); session()->regenerateToken(); return $this->redirectRoute('login', navigate: false); } public function render() { return view('livewire.auth.verify-email', [ 'email' => Auth::user()?->getEmailForVerification() ?? '', ]); } }