feat(auth):forgot-password page
This commit is contained in:
parent
4bfb472dbe
commit
968a9598fb
|
@ -3,9 +3,13 @@
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\PasswordResetToken;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Password;
|
use Illuminate\Support\Facades\Password;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
|
||||||
class PasswordResetLinkController extends Controller
|
class PasswordResetLinkController extends Controller
|
||||||
|
@ -23,22 +27,48 @@ public function create(): View
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
*/
|
*/
|
||||||
public function store(Request $request): RedirectResponse
|
|
||||||
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$customMessages = [
|
||||||
'email' => ['required', 'email'],
|
'email.required' => 'Email tidak boleh kosong',
|
||||||
|
'email.email' => 'Email tidak valid',
|
||||||
|
'email.exists' => 'Email tidak terdaftar',
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'email' => ['required', 'email', 'exists:users,email'],
|
||||||
|
], $customMessages);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
toast($validator->messages()->all()[0], 'error')->position('top')->autoclose(3000);
|
||||||
|
return redirect()->back()->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('password_reset_tokens')->updateOrInsert(['email' => $request->email], [
|
||||||
|
'token' => Hash::make($request->_token),
|
||||||
|
'created_at' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// We will send the password reset link to this user. Once we have attempted
|
alert()->success('Berhasil', 'Silahkan cek email anda untuk mereset password');
|
||||||
// to send the link, we will examine the response then see the message we
|
return redirect()->back();
|
||||||
// need to show to the user. Finally, we'll send out a proper response.
|
|
||||||
$status = Password::sendResetLink(
|
|
||||||
$request->only('email')
|
|
||||||
);
|
|
||||||
|
|
||||||
return $status == Password::RESET_LINK_SENT
|
|
||||||
? back()->with('status', __($status))
|
|
||||||
: back()->withInput($request->only('email'))
|
|
||||||
->withErrors(['email' => __($status)]);
|
|
||||||
}
|
}
|
||||||
|
// public function store(Request $request): RedirectResponse
|
||||||
|
// {
|
||||||
|
// $request->validate([
|
||||||
|
// 'email' => ['required', 'email'],
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// // We will send the password reset link to this user. Once we have attempted
|
||||||
|
// // to send the link, we will examine the response then see the message we
|
||||||
|
// // need to show to the user. Finally, we'll send out a proper response.
|
||||||
|
// $status = Password::sendResetLink(
|
||||||
|
// $request->only('email')
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return $status == Password::RESET_LINK_SENT
|
||||||
|
// ? back()->with('status', __($status))
|
||||||
|
// : back()->withInput($request->only('email'))
|
||||||
|
// ->withErrors(['email' => __($status)]);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ResetPasswordMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*/
|
||||||
|
public function envelope(): Envelope
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: 'Reset Password Mail',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*/
|
||||||
|
public function content(): Content
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'auth.mail-reset-password',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attachments for the message.
|
||||||
|
*
|
||||||
|
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||||
|
*/
|
||||||
|
public function attachments(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,154 @@
|
||||||
<x-guest-layout>
|
<!doctype html>
|
||||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
|
||||||
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
|
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Reset Password | CornQuest</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta content="Premium Multipurpose Admin & Dashboard Template" name="description" />
|
||||||
|
<meta content="Themesbrand" name="author" />
|
||||||
|
<!-- App favicon -->
|
||||||
|
<link rel="shortcut icon" href="assets/images/favicon.ico">
|
||||||
|
|
||||||
|
<!-- Layout config Js -->
|
||||||
|
<script src="assets/js/layout.js"></script>
|
||||||
|
<!-- Bootstrap Css -->
|
||||||
|
<link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Icons Css -->
|
||||||
|
<link href="assets/css/icons.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- App Css-->
|
||||||
|
<link href="assets/css/app.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- custom Css-->
|
||||||
|
<link href="assets/css/custom.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="auth-page-wrapper pt-5">
|
||||||
|
<!-- auth page bg -->
|
||||||
|
<div class="auth-one-bg-position auth-one-bg" id="auth-particles">
|
||||||
|
<div class="bg-overlay"></div>
|
||||||
|
|
||||||
|
<div class="shape">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 1440 120">
|
||||||
|
<path d="M 0,36 C 144,53.6 432,123.2 720,124 C 1008,124.8 1296,56.8 1440,40L1440 140L0 140z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- auth page content -->
|
||||||
|
<div class="auth-page-content">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="text-center mt-sm-5 mb-4 text-white-50">
|
||||||
|
<div>
|
||||||
|
<a href="index.html" class="d-inline-block auth-logo">
|
||||||
|
<img src="assets/images/logo-light.png" alt="" height="20">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end row -->
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6 col-xl-5">
|
||||||
|
<div class="card mt-4">
|
||||||
|
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="text-center mt-2">
|
||||||
|
<h5 class="text-primary">Lupa Password?</h5>
|
||||||
|
<p class="text-muted">Ingin melakukan reset password?</p>
|
||||||
|
|
||||||
|
<lord-icon src="https://cdn.lordicon.com/rhvddzym.json" trigger="loop"
|
||||||
|
colors="primary:#0ab39c" class="avatar-xl">
|
||||||
|
</lord-icon>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-borderless alert-warning text-center mb-2 mx-2" role="alert">
|
||||||
|
Masukan email anda dan instruksi akan dikirimkan kepada anda!
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<form action="{{ route('auth.reset_password') }}" class="needs-validation"
|
||||||
|
novalidate method="POST">
|
||||||
|
@csrf
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="form-label">Email</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email"
|
||||||
|
placeholder="Masukan Email" autofocus required>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Masukan email anda
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-4">
|
||||||
|
<button class="btn btn-success w-100" type="submit">Kirim Reset Password
|
||||||
|
Link!</button>
|
||||||
|
</div>
|
||||||
|
</form><!-- end form -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end card body -->
|
||||||
|
</div>
|
||||||
|
<!-- end card -->
|
||||||
|
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<p class="mb-0">Tunggu, saya ingat password saya... <a href="{{ route('auth.login') }}"
|
||||||
|
class="fw-semibold text-primary text-decoration-underline"> Login </a> </p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end row -->
|
||||||
|
</div>
|
||||||
|
<!-- end container -->
|
||||||
|
</div>
|
||||||
|
<!-- end auth page content -->
|
||||||
|
|
||||||
|
<!-- footer -->
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="text-center">
|
||||||
|
<p class="mb-0 text-muted">©
|
||||||
|
<script>
|
||||||
|
document.write(new Date().getFullYear())
|
||||||
|
</script> CornQuest. Crafted with <i
|
||||||
|
class="mdi mdi-heart text-danger"></i>
|
||||||
|
by LAB KSI Politeknik Negeri Jember
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<!-- end Footer -->
|
||||||
</div>
|
</div>
|
||||||
|
<!-- end auth-page-wrapper -->
|
||||||
|
@include('sweetalert::alert')
|
||||||
|
|
||||||
<!-- Session Status -->
|
<!-- JAVASCRIPT -->
|
||||||
<x-auth-session-status class="mb-4" :status="session('status')" />
|
<script src="assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/libs/simplebar/simplebar.min.js"></script>
|
||||||
|
<script src="assets/libs/node-waves/waves.min.js"></script>
|
||||||
|
<script src="assets/libs/feather-icons/feather.min.js"></script>
|
||||||
|
<script src="assets/js/pages/plugins/lord-icon-2.1.0.js"></script>
|
||||||
|
<script src="assets/js/plugins.js"></script>
|
||||||
|
|
||||||
<form method="POST" action="{{ route('password.email') }}">
|
<!-- particles js -->
|
||||||
@csrf
|
<script src="assets/libs/particles.js/particles.js"></script>
|
||||||
|
|
||||||
<!-- Email Address -->
|
<!-- particles app js -->
|
||||||
<div>
|
<script src="assets/js/pages/particles.app.js"></script>
|
||||||
<x-input-label for="email" :value="__('Email')" />
|
|
||||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
|
||||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-end mt-4">
|
<script src="assets/js/pages/form-validation.init.js"></script>
|
||||||
<x-primary-button>
|
</body>
|
||||||
{{ __('Email Password Reset Link') }}
|
|
||||||
</x-primary-button>
|
</html>
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</x-guest-layout>
|
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="float-end">
|
<div class="float-end">
|
||||||
<a href="auth-pass-reset-basic.html" class="text-muted">Lupa
|
<a href="{{ route('auth.forgot_password') }}" class="text-muted">Lupa
|
||||||
Password?</a>
|
Password?</a>
|
||||||
</div>
|
</div>
|
||||||
<label class="form-label" for="password-input">Password</label>
|
<label class="form-label" for="password-input">Password</label>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Halo,</p>
|
||||||
|
<p>Kami menerima permintaan untuk mereset password akun Anda.</p>
|
||||||
|
<p>Klik tautan di bawah ini untuk mereset password:</p>
|
||||||
|
<a href="{{ $resetLink }}">{{ $resetLink }}</a>
|
||||||
|
<p>Tautan ini akan kadaluarsa dalam waktu 60 menit.</p>
|
||||||
|
<p>Jika Anda tidak meminta reset password, abaikan email ini.</p>
|
||||||
|
<p>Terima kasih,</p>
|
||||||
|
<p>Tim {{ config('app.name') }}</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -1,39 +0,0 @@
|
||||||
<x-guest-layout>
|
|
||||||
<form method="POST" action="{{ route('password.store') }}">
|
|
||||||
@csrf
|
|
||||||
|
|
||||||
<!-- Password Reset Token -->
|
|
||||||
<input type="hidden" name="token" value="{{ $request->route('token') }}">
|
|
||||||
|
|
||||||
<!-- Email Address -->
|
|
||||||
<div>
|
|
||||||
<x-input-label for="email" :value="__('Email')" />
|
|
||||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus autocomplete="username" />
|
|
||||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Password -->
|
|
||||||
<div class="mt-4">
|
|
||||||
<x-input-label for="password" :value="__('Password')" />
|
|
||||||
<x-text-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
|
|
||||||
<x-input-error :messages="$errors->get('password')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Confirm Password -->
|
|
||||||
<div class="mt-4">
|
|
||||||
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
|
|
||||||
|
|
||||||
<x-text-input id="password_confirmation" class="block mt-1 w-full"
|
|
||||||
type="password"
|
|
||||||
name="password_confirmation" required autocomplete="new-password" />
|
|
||||||
|
|
||||||
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-end mt-4">
|
|
||||||
<x-primary-button>
|
|
||||||
{{ __('Reset Password') }}
|
|
||||||
</x-primary-button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</x-guest-layout>
|
|
|
@ -1,10 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\Auth\AuthenticatedSessionController;
|
use App\Http\Controllers\Auth\AuthenticatedSessionController;
|
||||||
|
use App\Http\Controllers\Auth\PasswordResetLinkController;
|
||||||
use App\Http\Controllers\DashboardController;
|
use App\Http\Controllers\DashboardController;
|
||||||
use App\Http\Controllers\ProfileController;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use SebastianBergmann\CodeCoverage\Report\Html\Dashboard;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -19,9 +18,20 @@
|
||||||
|
|
||||||
Route::middleware('guest')->group(function () {
|
Route::middleware('guest')->group(function () {
|
||||||
|
|
||||||
Route::controller(AuthenticatedSessionController::class)->name('auth.')->group(function () {
|
Route::name('auth.')->group(function () {
|
||||||
Route::get('/', 'create')->name('login');
|
|
||||||
Route::post('/', 'store')->name('login_post');
|
Route::controller(AuthenticatedSessionController::class)->group(function () {
|
||||||
|
Route::get('/', 'create')->name('login');
|
||||||
|
Route::post('/', 'store')->name('login_post');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::controller(PasswordResetLinkController::class)->group(function () {
|
||||||
|
Route::get('/forgot-password', 'create')->name('forgot_password');
|
||||||
|
Route::post('/reset-password', 'store')->name('reset_password');
|
||||||
|
|
||||||
|
Route::get('/validasi-lupa-password/{token}', 'validation')->name('validation_forgot_password');
|
||||||
|
Route::post('/validasi-lupa-password/{token}', 'update')->name('update_forgot_password');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue