Verifikasi Email dengan Mailtrap
This commit is contained in:
parent
3d4a23ddcd
commit
6000103c21
|
@ -6,6 +6,7 @@
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class LoginController extends Controller
|
class LoginController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -40,6 +41,40 @@ public function __construct()
|
||||||
$this->middleware('auth')->only('logout');
|
$this->middleware('auth')->only('logout');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has been authenticated.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param mixed $user
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function authenticated(Request $request, $user)
|
||||||
|
{
|
||||||
|
// Cek jika email belum terverifikasi
|
||||||
|
if (!$user->hasVerifiedEmail()) {
|
||||||
|
Auth::logout();
|
||||||
|
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'email' => [__('Akun Anda belum diverifikasi. Silakan periksa email Anda untuk link verifikasi.')],
|
||||||
|
])->redirectTo(route('verification.notice'));
|
||||||
|
}
|
||||||
|
|
||||||
|
session()->flash('success', 'Login berhasil!');
|
||||||
|
if ($user->role === 'admin') {
|
||||||
|
return redirect('/admin');
|
||||||
|
}
|
||||||
|
return redirect()->intended($this->redirectTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the user out of the application.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
public function logout(Request $request)
|
public function logout(Request $request)
|
||||||
{
|
{
|
||||||
Auth::logout();
|
Auth::logout();
|
||||||
|
@ -50,14 +85,4 @@ public function logout(Request $request)
|
||||||
session()->flash('error', 'Berhasil logout!');
|
session()->flash('error', 'Berhasil logout!');
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function authenticated(Request $request, $user)
|
|
||||||
{
|
|
||||||
session()->flash('success', 'Login berhasil!');
|
|
||||||
if ($user->role === 'admin') {
|
|
||||||
return redirect('/admin');
|
|
||||||
}
|
|
||||||
return redirect()->intended($this->redirectTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Auth\Events\Registered;
|
||||||
|
|
||||||
class RegisterController extends Controller
|
class RegisterController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -69,4 +71,25 @@ protected function create(array $data)
|
||||||
'password' => Hash::make($data['password']),
|
'password' => Hash::make($data['password']),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the registration method to prevent auto-login after registration
|
||||||
|
* and show a verification email message.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function register(Request $request)
|
||||||
|
{
|
||||||
|
$this->validator($request->all())->validate();
|
||||||
|
|
||||||
|
event(new Registered($user = $this->create($request->all())));
|
||||||
|
|
||||||
|
// Don't automatically login the user
|
||||||
|
// $this->guard()->login($user);
|
||||||
|
|
||||||
|
return $this->registered($request, $user)
|
||||||
|
?: redirect($this->redirectPath())
|
||||||
|
->with('success', 'Pendaftaran berhasil! Silahkan periksa email Anda untuk verifikasi akun.');
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
use App\Providers\RouteServiceProvider;
|
use App\Providers\RouteServiceProvider;
|
||||||
use Illuminate\Foundation\Auth\VerifiesEmails;
|
use Illuminate\Foundation\Auth\VerifiesEmails;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Auth\Events\Verified;
|
||||||
|
|
||||||
class VerificationController extends Controller
|
class VerificationController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -36,59 +37,52 @@ class VerificationController extends Controller
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth')->except(['verify']);
|
||||||
$this->middleware('signed')->only('verify');
|
$this->middleware('signed')->only('verify');
|
||||||
$this->middleware('throttle:6,1')->only('verify', 'resend');
|
$this->middleware('throttle:6,1')->only('verify', 'resend');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the email verification notice.
|
* Mark the authenticated user's email address as verified.
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function show(Request $request)
|
|
||||||
{
|
|
||||||
// Jika user sudah terverifikasi, redirect ke halaman utama
|
|
||||||
if ($request->user()->hasVerifiedEmail()) {
|
|
||||||
return redirect($this->redirectPath())
|
|
||||||
->with('success', 'Email anda sudah terverifikasi.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jika user belum terverifikasi dan baru register (email_verified_at adalah null),
|
|
||||||
// tampilkan halaman verifikasi
|
|
||||||
return view('auth.verify');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has been verified.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
protected function verified(Request $request)
|
|
||||||
{
|
|
||||||
session()->flash('success', 'Email berhasil diverifikasi! Selamat datang di Ayo Venue.');
|
|
||||||
return redirect($this->redirectPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resend the email verification notification.
|
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function resend(Request $request)
|
public function verify(Request $request)
|
||||||
{
|
{
|
||||||
// Jika user sudah terverifikasi, tidak perlu kirim ulang
|
$user = \App\Models\User::find($request->route('id'));
|
||||||
if ($request->user()->hasVerifiedEmail()) {
|
|
||||||
return redirect($this->redirectPath())
|
if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
|
||||||
->with('success', 'Email anda sudah terverifikasi.');
|
return redirect()->route('verification.notice')
|
||||||
|
->with('error', 'Link verifikasi tidak valid.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kirim email verifikasi baru
|
if ($user->hasVerifiedEmail()) {
|
||||||
$request->user()->sendEmailVerificationNotification();
|
return redirect()->route('login')
|
||||||
|
->with('verified', true)
|
||||||
|
->with('success', 'Email sudah terverifikasi sebelumnya. Silakan login.');
|
||||||
|
}
|
||||||
|
|
||||||
return back()->with('success', 'Link verifikasi baru telah dikirim ke email anda.');
|
if ($user->markEmailAsVerified()) {
|
||||||
|
event(new Verified($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->user()) {
|
||||||
|
auth()->logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('login')
|
||||||
|
->with('verified', true)
|
||||||
|
->with('success', 'Email berhasil diverifikasi. Silakan login.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the verification success page.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function verified()
|
||||||
|
{
|
||||||
|
return view('auth.verified');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto px-4 py-8">
|
||||||
|
<div class="max-w-md mx-auto bg-white shadow-lg rounded-lg overflow-hidden">
|
||||||
|
<div class="bg-green-600 px-6 py-4">
|
||||||
|
<h2 class="text-xl font-bold text-white">{{ __('Email Berhasil Diverifikasi!') }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="text-center mb-6">
|
||||||
|
<div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-green-100 mb-4">
|
||||||
|
<i class="fas fa-check text-green-500 text-3xl"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-semibold text-gray-800">{{ __('Verifikasi Berhasil') }}</h3>
|
||||||
|
<p class="text-gray-600 mt-2">
|
||||||
|
{{ __('Selamat! Email Anda telah berhasil diverifikasi.') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-gray-50 p-4 rounded-lg mb-6">
|
||||||
|
<p class="text-gray-600 text-sm">
|
||||||
|
<i class="fas fa-info-circle text-green-500 mr-2"></i>
|
||||||
|
{{ __('Anda sekarang memiliki akses penuh ke semua fitur Ayo Venue.') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<a href="{{ route('index') }}"
|
||||||
|
class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition duration-200 inline-block">
|
||||||
|
{{ __('Login Sekarang') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -14,21 +14,29 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if (session('verified'))
|
||||||
|
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-4" role="alert">
|
||||||
|
<p>{{ __('Akun Anda telah berhasil diverifikasi. Sekarang Anda dapat login.') }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<div class="flex items-center mb-4">
|
<div class="flex items-center mb-4">
|
||||||
<i class="fas fa-envelope-open-text text-blue-500 text-3xl mr-4"></i>
|
<i class="fas fa-envelope-open-text text-blue-500 text-3xl mr-4"></i>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-gray-700">
|
<p class="text-gray-700">
|
||||||
{{ __('Sebelum melanjutkan, silakan periksa email Anda untuk link verifikasi.') }}</p>
|
{{ __('Sebelum melanjutkan, silakan periksa email Anda untuk link verifikasi.') }}
|
||||||
|
</p>
|
||||||
<p class="text-sm text-gray-500 mt-1">
|
<p class="text-sm text-gray-500 mt-1">
|
||||||
{{ __('Email verifikasi biasanya dikirim dalam beberapa menit.') }}</p>
|
{{ __('Email verifikasi biasanya dikirim dalam beberapa menit.') }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-gray-50 p-4 rounded-lg mb-4">
|
<div class="bg-gray-50 p-4 rounded-lg mb-4">
|
||||||
<p class="text-gray-600 text-sm">
|
<p class="text-gray-600 text-sm">
|
||||||
<i class="fas fa-info-circle text-blue-500 mr-2"></i>
|
<i class="fas fa-info-circle text-blue-500 mr-2"></i>
|
||||||
{{ __('Tidak perlu khawatir. Anda sudah dapat login dan menggunakan fitur dasar Ayo Venue. Verifikasi email ini hanya diperlukan untuk fitur tertentu dan keamanan akun Anda.') }}
|
{{ __('Verifikasi email diperlukan untuk menggunakan fitur aplikasi Ayo Venue. Pastikan Anda memverifikasi email Anda untuk akses penuh ke platform kami.') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -138,6 +138,18 @@ class="absolute top-3 right-4 text-gray-500 hover:text-gray-700 text-xl">
|
||||||
<template x-if="modalType === 'login'">
|
<template x-if="modalType === 'login'">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-xl font-semibold mb-4">Masuk</h2>
|
<h2 class="text-xl font-semibold mb-4">Masuk</h2>
|
||||||
|
|
||||||
|
<!-- Error message for validation errors -->
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4" role="alert">
|
||||||
|
<ul>
|
||||||
|
@foreach($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<form method="POST" action="{{ route('login') }}" class="space-y-4">
|
<form method="POST" action="{{ route('login') }}" class="space-y-4">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="email" name="email" placeholder="Email" class="w-full border px-4 py-2 rounded"
|
<input type="email" name="email" placeholder="Email" class="w-full border px-4 py-2 rounded"
|
||||||
|
@ -170,6 +182,18 @@ class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Masuk</butt
|
||||||
<template x-if="modalType === 'register'">
|
<template x-if="modalType === 'register'">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-xl font-semibold mb-4">Daftar</h2>
|
<h2 class="text-xl font-semibold mb-4">Daftar</h2>
|
||||||
|
|
||||||
|
<!-- Error message for validation errors -->
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4" role="alert">
|
||||||
|
<ul>
|
||||||
|
@foreach($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<form method="POST" action="{{ route('register') }}" class="space-y-4">
|
<form method="POST" action="{{ route('register') }}" class="space-y-4">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="text" name="name" placeholder="Nama Lengkap"
|
<input type="text" name="name" placeholder="Nama Lengkap"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@if($bookings->isEmpty())
|
@if($bookings->isEmpty())
|
||||||
<div class="bg-white rounded-lg shadow-md p-6 text-center">
|
<div class="bg-white rounded-lg shadow-md p-6 text-center">
|
||||||
<p class="text-gray-500">Anda belum memiliki riwayat booking.</p>
|
<p class="text-gray-500">Anda belum memiliki riwayat booking.</p>
|
||||||
<a href="{{ route('venues.index') }}" class="mt-4 inline-block bg-blue-500 text-white px-4 py-2 rounded-lg">Cari
|
<a href="{{ url('/') }}" class="mt-4 inline-block bg-blue-500 text-white px-4 py-2 rounded-lg">Cari
|
||||||
Venue</a>
|
Venue</a>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
|
|
|
@ -8,12 +8,16 @@
|
||||||
use App\Http\Controllers\admin\BookingsController;
|
use App\Http\Controllers\admin\BookingsController;
|
||||||
use App\Http\Controllers\admin\TableController;
|
use App\Http\Controllers\admin\TableController;
|
||||||
use App\Http\Controllers\admin\AdminController;
|
use App\Http\Controllers\admin\AdminController;
|
||||||
|
use App\Http\Controllers\Auth\VerificationController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
// Authentication Routes (dengan verifikasi email aktif)
|
// Authentication Routes (dengan verifikasi email aktif)
|
||||||
Auth::routes(['verify' => true]);
|
Auth::routes(['verify' => true]);
|
||||||
|
|
||||||
|
// Rute custom untuk verifikasi email
|
||||||
|
Route::get('/email/verified', [VerificationController::class, 'verified'])->name('verification.verified');
|
||||||
|
|
||||||
Route::get('/', [HomeController::class, "index"])->name('index');
|
Route::get('/', [HomeController::class, "index"])->name('index');
|
||||||
Route::get('/venue/{venueName}', [VenueController::class, "venue"])->name('venue');
|
Route::get('/venue/{venueName}', [VenueController::class, "venue"])->name('venue');
|
||||||
|
|
||||||
|
@ -23,8 +27,22 @@
|
||||||
Route::get('/booking/schedules', [BookingController::class, 'getBookedSchedules'])->name('booking.schedules');
|
Route::get('/booking/schedules', [BookingController::class, 'getBookedSchedules'])->name('booking.schedules');
|
||||||
Route::post('/payment/notification', [BookingController::class, 'handleNotification'])->name('payment.notification');
|
Route::post('/payment/notification', [BookingController::class, 'handleNotification'])->name('payment.notification');
|
||||||
|
|
||||||
// Booking history routes (authenticated only, tidak perlu verified)
|
// Routes that require authentication but not email verification
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth'])->group(function () {
|
||||||
|
// Route untuk melihat halaman verifikasi email dan kirim ulang email verifikasi
|
||||||
|
// sudah ditangani oleh Auth::routes(['verify' => true])
|
||||||
|
|
||||||
|
// Profile route access without verification
|
||||||
|
Route::get('/profile', [AccountController::class, 'settings'])->name('profile');
|
||||||
|
|
||||||
|
// Account settings routes - moved from password confirmation middleware
|
||||||
|
Route::get('/account/settings', [AccountController::class, 'settings'])->name('account.settings');
|
||||||
|
Route::put('/account/update', [AccountController::class, 'update'])->name('account.update');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Routes that require both authentication and email verification
|
||||||
|
Route::middleware(['auth', 'verified'])->group(function () {
|
||||||
|
// Booking history routes
|
||||||
Route::get('/booking/history', [BookingHistoryController::class, 'index'])->name('booking.history');
|
Route::get('/booking/history', [BookingHistoryController::class, 'index'])->name('booking.history');
|
||||||
|
|
||||||
// Pending bookings routes
|
// Pending bookings routes
|
||||||
|
@ -32,20 +50,14 @@
|
||||||
Route::get('/booking/pending/{id}/resume', [BookingController::class, 'resumeBooking'])->name('booking.resume');
|
Route::get('/booking/pending/{id}/resume', [BookingController::class, 'resumeBooking'])->name('booking.resume');
|
||||||
Route::delete('/booking/pending/{id}', [BookingController::class, 'deletePendingBooking'])->name('booking.pending.delete');
|
Route::delete('/booking/pending/{id}', [BookingController::class, 'deletePendingBooking'])->name('booking.pending.delete');
|
||||||
|
|
||||||
// Profile route definition - use the existing account settings as the profile page
|
// Routes that require password confirmation - moved account settings out of this group
|
||||||
Route::get('/profile', [AccountController::class, 'settings'])->name('profile');
|
|
||||||
|
|
||||||
// Routes that require password confirmation
|
|
||||||
Route::middleware(['password.confirm'])->group(function () {
|
Route::middleware(['password.confirm'])->group(function () {
|
||||||
// Add routes that require password confirmation here
|
// Any sensitive operations that should still require password confirmation can go here
|
||||||
// For example, account settings, deleting accounts, etc.
|
|
||||||
Route::get('/account/settings', [AccountController::class, 'settings'])->name('account.settings');
|
|
||||||
Route::put('/account/update', [AccountController::class, 'update'])->name('account.update');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Admin routes (admin tetap perlu verified untuk keamanan)
|
// Admin routes (admin tetap perlu verified untuk keamanan)
|
||||||
Route::middleware(['auth', 'is_admin'])->prefix('admin')->group(function () {
|
Route::middleware(['auth', 'verified', 'is_admin'])->prefix('admin')->group(function () {
|
||||||
Route::get('/', [AdminController::class, 'index'])->name('admin.dashboard');
|
Route::get('/', [AdminController::class, 'index'])->name('admin.dashboard');
|
||||||
Route::get('/bookings', [BookingsController::class, 'index'])->name('admin.bookings.index');
|
Route::get('/bookings', [BookingsController::class, 'index'])->name('admin.bookings.index');
|
||||||
Route::get('/bookings/export', [BookingsController::class, 'export'])->name('admin.bookings.export');
|
Route::get('/bookings/export', [BookingsController::class, 'export'])->name('admin.bookings.export');
|
||||||
|
|
Loading…
Reference in New Issue