Verifikasi dihalaman yang sama

This commit is contained in:
Stephen Gesityan 2025-05-17 19:30:21 +07:00
parent 68ade5ce60
commit 7c7c6f9238
3 changed files with 128 additions and 33 deletions

View File

@ -41,6 +41,62 @@ public function __construct()
$this->middleware('auth')->only('logout'); $this->middleware('auth')->only('logout');
} }
/**
* Handle a login request to the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Get the failed login response instance.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
// Cek apakah email ada di database tapi belum diverifikasi
$user = \App\Models\User::where('email', $request->email)->first();
if ($user && !$user->hasVerifiedEmail()) {
return redirect()->route('home')
->with('login_error', 'Email belum diverifikasi. Silakan periksa email Anda untuk link verifikasi atau klik resend untuk mengirim ulang.')
->withInput($request->only('email'));
}
return redirect()->route('home')
->with('login_error', 'Kredensial yang Anda masukkan tidak valid.')
->withInput($request->only('email'));
}
/** /**
* The user has been authenticated. * The user has been authenticated.
* *
@ -57,9 +113,9 @@ protected function authenticated(Request $request, $user)
$request->session()->invalidate(); $request->session()->invalidate();
$request->session()->regenerateToken(); $request->session()->regenerateToken();
throw ValidationException::withMessages([ return redirect()->route('home')
'email' => [__('Akun Anda belum diverifikasi. Silakan periksa email Anda untuk link verifikasi.')], ->with('login_error', 'Akun Anda belum diverifikasi. Silakan periksa email Anda untuk link verifikasi.')
])->redirectTo(route('verification.notice')); ->withInput($request->only('email'));
} }
session()->flash('success', 'Login berhasil!'); session()->flash('success', 'Login berhasil!');

View File

@ -53,14 +53,13 @@ public function verify(Request $request)
$user = \App\Models\User::find($request->route('id')); $user = \App\Models\User::find($request->route('id'));
if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) { if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
return redirect()->route('verification.notice') return redirect()->route('home')
->with('error', 'Link verifikasi tidak valid.'); ->with('error', 'Link verifikasi tidak valid.');
} }
if ($user->hasVerifiedEmail()) { if ($user->hasVerifiedEmail()) {
return redirect()->route('login') return redirect()->route('home')
->with('verified', true) ->with('verified', 'Email sudah terverifikasi sebelumnya. Silakan login.');
->with('success', 'Email sudah terverifikasi sebelumnya. Silakan login.');
} }
if ($user->markEmailAsVerified()) { if ($user->markEmailAsVerified()) {
@ -71,18 +70,44 @@ public function verify(Request $request)
auth()->logout(); auth()->logout();
} }
return redirect()->route('login') return redirect()->route('home')
->with('verified', true) ->with('verified', 'Email berhasil diverifikasi. Silakan login.');
->with('success', 'Email berhasil diverifikasi. Silakan login.');
} }
/** /**
* Show the verification success page. * Resend the email verification notification.
* *
* @return \Illuminate\Contracts\View\View * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/ */
public function verified() public function resend(Request $request)
{ {
return view('auth.verified'); if ($request->user()->hasVerifiedEmail()) {
return redirect()->route('home');
}
$request->user()->sendEmailVerificationNotification();
return back()->with('resent', true)
->with('success', 'Link verifikasi telah dikirim ulang ke alamat email Anda.');
}
/**
* Show the email verification notice.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function show(Request $request)
{
if ($request->user()->hasVerifiedEmail()) {
return redirect($this->redirectPath());
}
// Redirect to homepage with message instead of showing verification.notice view
return redirect()->route('home')
->with('error', 'Silakan verifikasi email Anda terlebih dahulu.
Link verifikasi telah dikirim ke alamat email Anda.')
->with('resend_link', true);
} }
} }

View File

@ -22,8 +22,8 @@
<body class="font-poppins"> <body class="font-poppins">
<header class="fixed top-0 w-full bg-white shadow-sm z-50" x-data="{ <header class="fixed top-0 w-full bg-white shadow-sm z-50" x-data="{
showModal: {{ $errors->any() || session('login_error') || session('register_error') ? 'true' : 'false' }}, showModal: {{ $errors->any() || session('login_error') || session('register_error') || session('verified') ? 'true' : 'false' }},
modalType: '{{ session('login_error') ? 'login' : (session('register_error') ? 'register' : ($errors->any() ? (old('email') && !old('name') ? 'login' : 'register') : '')) }}' modalType: '{{ session('login_error') || session('verified') ? 'login' : (session('register_error') ? 'register' : ($errors->any() ? (old('email') && !old('name') ? 'login' : 'register') : '')) }}'
}"> }">
<nav x-data="{ isMobileMenuOpen: false }" class="relative py-4 px-4 lg:px-44 flex items-center justify-between"> <nav x-data="{ isMobileMenuOpen: false }" class="relative py-4 px-4 lg:px-44 flex items-center justify-between">
<a href="/"> <a href="/">
@ -143,6 +143,11 @@ class="absolute top-3 right-4 text-gray-500 hover:text-gray-700 text-xl">
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4" role="alert"> <div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4" role="alert">
@if(session('login_error')) @if(session('login_error'))
<p>{{ session('login_error') }}</p> <p>{{ session('login_error') }}</p>
@if(str_contains(session('login_error'), 'belum diverifikasi'))
<form method="POST" action="{{ route('verification.resend') }}" class="mt-2">
@csrf
</form>
@endif
@else @else
<ul> <ul>
@foreach($errors->all() as $error) @foreach($errors->all() as $error)
@ -221,14 +226,14 @@ class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Daftar</but
</header> </header>
<main class="pt-20"> <main class="pt-20">
@if (session('success') || session('error')) @if (session('success') || session('error') || session('verified'))
<div id="floating-alert" style=" <div id="floating-alert" style="
position: fixed; position: fixed;
top: 30px; top: 30px;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
background-color: {{ session('success') ? '#d1e7dd' : '#f8d7da' }}; background-color: {{ session('success') || session('verified') ? '#d1e7dd' : '#f8d7da' }};
color: {{ session('success') ? '#0f5132' : '#842029' }}; color: {{ session('success') || session('verified') ? '#0f5132' : '#842029' }};
padding: 10px 20px; padding: 10px 20px;
border-radius: 6px; border-radius: 6px;
font-size: 14px; font-size: 14px;
@ -238,7 +243,7 @@ class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Daftar</but
max-width: 300px; max-width: 300px;
text-align: center; text-align: center;
"> ">
{{ session('success') ?? session('error') }} {{ session('success') ?? session('error') ?? session('verified') }}
</div> </div>
<script> <script>
@ -250,6 +255,15 @@ class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Daftar</but
setTimeout(() => alert.remove(), 500); setTimeout(() => alert.remove(), 500);
} }
}, 3000); }, 3000);
// Jika ada pesan verified, buka modal login
@if(session('verified'))
document.addEventListener('DOMContentLoaded', function () {
const alpineData = document.querySelector('header').__x.$data;
alpineData.showModal = true;
alpineData.modalType = 'login';
});
@endif
</script> </script>
@endif @endif