validate([ 'email' => 'required|email|exists:users,email', ], [ 'email.exists' => 'Email tidak terdaftar dalam sistem.' ]); $user = User::where('email', $request->email)->first(); // Generate OTP 6 digit $otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); // Simpan OTP ke database (expired 5 menit) PasswordReset::updateOrCreate( ['email' => $request->email], [ 'token' => $otp, 'created_at' => Carbon::now(), ] ); // Kirim email menggunakan Laravel Mail try { Mail::send([], [], function ($message) use ($user, $otp) { $message->to($user->email, $user->name) ->subject('Kode OTP Reset Password - LearnMood') ->html($this->getEmailTemplate($user->name, $otp, $user->email)); }); return redirect()->route('password.verify.form', ['email' => $request->email]) ->with('success', 'Kode OTP telah dikirim ke email Anda. Cek inbox/spam folder.'); } catch (\Exception $e) { // Log error \Log::error('Email error: ' . $e->getMessage()); // Untuk development, tampilkan OTP di session return redirect()->route('password.verify.form', ['email' => $request->email]) ->with('dev_otp', $otp) ->with('success', '🔧 Mode Development - Gagal kirim email. Gunakan kode OTP berikut:'); } } /** * Tampilkan form verifikasi OTP */ public function showVerifyForm(Request $request) { return view('auth.verify-code', ['email' => $request->email]); } /** * Verifikasi OTP */ public function verifyOtp(Request $request) { $request->validate([ 'email' => 'required|email', 'otp' => 'required|string|size:6', ]); $reset = PasswordReset::where('email', $request->email) ->where('token', $request->otp) ->first(); if (!$reset) { return back()->with('error', 'Kode OTP tidak valid.'); } // Cek apakah OTP sudah expired (lebih dari 5 menit) if (Carbon::parse($reset->created_at)->addMinutes(5)->isPast()) { $reset->delete(); return back()->with('error', 'Kode OTP sudah kadaluarsa. Silakan minta kode baru.'); } // OTP valid, arahkan ke form reset password return redirect()->route('password.reset.form', [ 'email' => $request->email, 'token' => $request->otp ])->with('success', 'Kode valid. Silakan buat password baru.'); } /** * Tampilkan form reset password */ public function showResetForm(Request $request) { return view('auth.reset-password', [ 'email' => $request->email, 'token' => $request->token ]); } /** * Reset password dengan OTP */ public function resetPassword(Request $request) { $request->validate([ 'email' => 'required|email', 'token' => 'required|string|size:6', 'password' => 'required|string|min:8|confirmed', ]); // Verifikasi OTP sekali lagi $reset = PasswordReset::where('email', $request->email) ->where('token', $request->token) ->first(); if (!$reset || Carbon::parse($reset->created_at)->addMinutes(5)->isPast()) { return back()->with('error', 'Kode OTP tidak valid atau sudah kadaluarsa.'); } // Update password user $user = User::where('email', $request->email)->first(); $user->password = Hash::make($request->password); $user->save(); // Hapus data reset $reset->delete(); return redirect()->route('login') ->with('success', 'Password berhasil direset. Silakan login dengan password baru.'); } /** * Template email HTML */ private function getEmailTemplate($toName, $otp, $toEmail) { return "
Halo {$toName},
Kami menerima permintaan reset password untuk akun Anda. Gunakan kode OTP berikut untuk melanjutkan:
Kode Verifikasi
⏰ Berlaku selama: 5 menit
📧 Email: {$toEmail}
Jika Anda tidak meminta reset password, abaikan email ini.
© " . date('Y') . " LearnMood. All rights reserved.