From 3d4a23ddcdadca414c50668b529e7c713a40b530 Mon Sep 17 00:00:00 2001 From: Stephen Gesityan Date: Fri, 9 May 2025 17:53:18 +0700 Subject: [PATCH] Halaman Account Settings --- app/Http/Controllers/AccountController.php | 98 ++++++ .../Auth/ConfirmPasswordController.php | 66 ++++- .../Auth/ForgotPasswordController.php | 73 ++++- .../Auth/ResetPasswordController.php | 44 ++- .../Auth/VerificationController.php | 57 +++- app/Http/Kernel.php | 4 +- app/Http/Middleware/IsAdmin.php | 23 +- app/Models/User.php | 16 +- resources/views/account/settings.blade.php | 245 +++++++++++++++ .../views/auth/passwords/confirm.blade.php | 69 ++--- .../views/auth/passwords/email.blade.php | 74 ++--- .../views/auth/passwords/reset.blade.php | 94 +++--- resources/views/auth/verify.blade.php | 53 +++- resources/views/layouts/app.blade.php | 279 +++++++++++++++++- resources/views/layouts/main.blade.php | 68 +++-- routes/web.php | 20 +- 16 files changed, 1097 insertions(+), 186 deletions(-) create mode 100644 app/Http/Controllers/AccountController.php create mode 100644 resources/views/account/settings.blade.php diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php new file mode 100644 index 0000000..9597f07 --- /dev/null +++ b/app/Http/Controllers/AccountController.php @@ -0,0 +1,98 @@ +middleware(['auth']); + } + + /** + * Show the account settings page. + * + * @return \Illuminate\View\View + */ + public function settings() + { + $user = Auth::user(); + return view('account.settings', compact('user')); + } + + /** + * Update the user's account information. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function update(Request $request) + { + $user = Auth::user(); + + $validated = $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => [ + 'required', + 'string', + 'email', + 'max:255', + Rule::unique('users')->ignore($user->id), + ], + 'current_password' => ['nullable', 'required_with:password', 'string'], + 'password' => ['nullable', 'string', 'min:8', 'confirmed'], + ]); + + // Check if current password is provided and is correct + if ($request->filled('current_password')) { + if (!Hash::check($request->current_password, $user->password)) { + return back()->withErrors(['current_password' => 'Password saat ini tidak valid.']); + } + } + + // Update user information + $user->name = $validated['name']; + + // Check if email is changed + $emailChanged = $user->email !== $validated['email']; + if ($emailChanged) { + $user->email = $validated['email']; + + // Set email_verified_at ke null hanya jika sebelumnya sudah terverifikasi + // Ini untuk memastikan user harus verifikasi email baru + if ($user->hasVerifiedEmail()) { + $user->email_verified_at = null; + $emailNeedsVerification = true; + } + } + + // Update password if provided + if ($request->filled('password')) { + $user->password = Hash::make($validated['password']); + } + + $user->save(); + + // Jika email diubah dan sebelumnya sudah terverifikasi, kirim email verifikasi baru + if ($emailChanged && isset($emailNeedsVerification)) { + $user->sendEmailVerificationNotification(); + session()->flash('success', 'Profil berhasil diperbarui. Silakan verifikasi alamat email baru Anda.'); + } else { + session()->flash('success', 'Profil berhasil diperbarui.'); + } + + return back(); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/ConfirmPasswordController.php b/app/Http/Controllers/Auth/ConfirmPasswordController.php index 3559954..5bac553 100644 --- a/app/Http/Controllers/Auth/ConfirmPasswordController.php +++ b/app/Http/Controllers/Auth/ConfirmPasswordController.php @@ -3,7 +3,9 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\ConfirmsPasswords; +use Illuminate\Http\Request; class ConfirmPasswordController extends Controller { @@ -14,7 +16,7 @@ class ConfirmPasswordController extends Controller | | This controller is responsible for handling password confirmations and | uses a simple trait to include the behavior. You're free to explore - | this trait and override any functions that require customization. + | this trait and override any methods you wish to tweak. | */ @@ -25,7 +27,7 @@ class ConfirmPasswordController extends Controller * * @var string */ - protected $redirectTo = '/home'; + protected $redirectTo = '/'; /** * Create a new controller instance. @@ -36,4 +38,62 @@ public function __construct() { $this->middleware('auth'); } -} + + /** + * Display the password confirmation view. + * + * @return \Illuminate\View\View + */ + public function showConfirmForm() + { + return view('auth.passwords.confirm'); + } + + /** + * Confirm the given user's password. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + public function confirm(Request $request) + { + $request->validate($this->rules(), $this->validationErrorMessages()); + + $this->resetPasswordConfirmationTimeout($request); + + return redirect()->intended($this->redirectPath()); + } + + /** + * Reset the password confirmation timeout. + * + * @param \Illuminate\Http\Request $request + * @return void + */ + protected function resetPasswordConfirmationTimeout(Request $request) + { + $request->session()->put('auth.password_confirmed_at', time()); + } + + /** + * Get the password confirmation validation rules. + * + * @return array + */ + protected function rules() + { + return [ + 'password' => 'required|password', + ]; + } + + /** + * Get the password confirmation validation error messages. + * + * @return array + */ + protected function validationErrorMessages() + { + return []; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 465c39c..cf415db 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -4,6 +4,8 @@ use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; class ForgotPasswordController extends Controller { @@ -19,4 +21,73 @@ class ForgotPasswordController extends Controller */ use SendsPasswordResetEmails; -} + + /** + * Create a new controller instance. + * + * @return void + */ + public function __construct() + { + $this->middleware('guest'); + } + + /** + * Display the form to request a password reset link. + * + * @return \Illuminate\View\View + */ + public function showLinkRequestForm() + { + return view('auth.passwords.email'); + } + + /** + * Send a reset link to the given user. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + public function sendResetLinkEmail(Request $request) + { + $this->validateEmail($request); + + // 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. + $response = $this->broker()->sendResetLink( + $request->only('email') + ); + + return $response == Password::RESET_LINK_SENT + ? $this->sendResetLinkResponse($request, $response) + : $this->sendResetLinkFailedResponse($request, $response); + } + + /** + * Get the response for a successful password reset link. + * + * @param \Illuminate\Http\Request $request + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetLinkResponse(Request $request, $response) + { + session()->flash('success', trans($response)); + return back(); + } + + /** + * Get the response for a failed password reset link. + * + * @param \Illuminate\Http\Request $request + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetLinkFailedResponse(Request $request, $response) + { + session()->flash('error', trans($response)); + return back() + ->withInput($request->only('email')); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index fe965b2..0053598 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -3,7 +3,9 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\ResetsPasswords; +use Illuminate\Http\Request; class ResetPasswordController extends Controller { @@ -25,5 +27,43 @@ class ResetPasswordController extends Controller * * @var string */ - protected $redirectTo = '/home'; -} + protected $redirectTo = '/'; + + /** + * Create a new controller instance. + * + * @return void + */ + public function __construct() + { + $this->middleware('guest'); + } + + /** + * Get the response for a successful password reset. + * + * @param \Illuminate\Http\Request $request + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetResponse(Request $request, $response) + { + session()->flash('success', trans($response)); + return redirect($this->redirectPath()); + } + + /** + * Get the response for a failed password reset. + * + * @param \Illuminate\Http\Request $request + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetFailedResponse(Request $request, $response) + { + session()->flash('error', trans($response)); + return redirect()->back() + ->withInput($request->only('email')) + ->withErrors(['email' => trans($response)]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/VerificationController.php b/app/Http/Controllers/Auth/VerificationController.php index 23a43a8..4b23c59 100644 --- a/app/Http/Controllers/Auth/VerificationController.php +++ b/app/Http/Controllers/Auth/VerificationController.php @@ -3,7 +3,9 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\VerifiesEmails; +use Illuminate\Http\Request; class VerificationController extends Controller { @@ -25,7 +27,7 @@ class VerificationController extends Controller * * @var string */ - protected $redirectTo = '/home'; + protected $redirectTo = '/'; /** * Create a new controller instance. @@ -38,4 +40,55 @@ public function __construct() $this->middleware('signed')->only('verify'); $this->middleware('throttle:6,1')->only('verify', 'resend'); } -} + + /** + * Show the email verification notice. + * + * @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 + * @return \Illuminate\Http\RedirectResponse + */ + public function resend(Request $request) + { + // Jika user sudah terverifikasi, tidak perlu kirim ulang + if ($request->user()->hasVerifiedEmail()) { + return redirect($this->redirectPath()) + ->with('success', 'Email anda sudah terverifikasi.'); + } + + // Kirim email verifikasi baru + $request->user()->sendEmailVerificationNotification(); + + return back()->with('success', 'Link verifikasi baru telah dikirim ke email anda.'); + } +} \ No newline at end of file diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 08e5e8c..c2660c2 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -61,9 +61,9 @@ class Kernel extends HttpKernel 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, - 'signed' => \App\Http\Middleware\ValidateSignature::class, + 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'is_admin' => \App\Http\Middleware\IsAdmin::class, ]; -} +} \ No newline at end of file diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php index 04deab6..d11d39a 100644 --- a/app/Http/Middleware/IsAdmin.php +++ b/app/Http/Middleware/IsAdmin.php @@ -1,8 +1,10 @@ check() && auth()->user()->role === 'admin') { - return $next($request); - } + public function handle(Request $request, Closure $next): Response + { + if (Auth::check() && Auth::user()->role === 'admin') { + return $next($request); + } - abort(403); // atau redirect('/login') -} -} + session()->flash('error', 'Anda tidak memiliki akses ke halaman tersebut!'); + return redirect('/'); + } +} \ No newline at end of file diff --git a/app/Models/User.php b/app/Models/User.php index 4d7f70f..5ef0a20 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,13 +2,13 @@ namespace App\Models; -// use Illuminate\Contracts\Auth\MustVerifyEmail; +use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; -class User extends Authenticatable +class User extends Authenticatable implements MustVerifyEmail { use HasApiTokens, HasFactory, Notifiable; @@ -42,4 +42,14 @@ class User extends Authenticatable 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; -} + + /** + * Check if the user is an admin. + * + * @return bool + */ + public function isAdmin() + { + return $this->role === 'admin'; + } +} \ No newline at end of file diff --git a/resources/views/account/settings.blade.php b/resources/views/account/settings.blade.php new file mode 100644 index 0000000..61a4d5d --- /dev/null +++ b/resources/views/account/settings.blade.php @@ -0,0 +1,245 @@ +@extends('layouts.app') + +@section('content') +
+
+
+
+
+
+

+ {{ __('Account Settings') }} +

+
+
+ + @if (session('message')) + + @endif + + @if (session('success')) + + @endif + +
+ @csrf + @method('PUT') + + +
+ +
+ + + + +
+ @error('name') +
{{ $message }}
+ @enderror +
+ + +
+ +
+ + + + +
+ @error('email') +
{{ $message }}
+ @enderror + @if ($user->email) +
+ @if ($user->hasVerifiedEmail()) + + {{ __('Email verified') }} + + @else + + {{ __('Not Verified') }} + + + {{ __('Resend verification email') }} + + @endif +
+ @endif +
+ +
+
+

+ {{ __('Change Password') }} +

+
+
+ +
+ +
+ + + + + +
+ @error('current_password') +
{{ $message }}
+ @enderror +
+ + +
+ +
+ + + + + +
+ @error('password') +
{{ $message }}
+ @enderror +
+ + +
+ +
+ + + + + +
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ + + + +@endsection \ No newline at end of file diff --git a/resources/views/auth/passwords/confirm.blade.php b/resources/views/auth/passwords/confirm.blade.php index f8c8e61..829d79c 100644 --- a/resources/views/auth/passwords/confirm.blade.php +++ b/resources/views/auth/passwords/confirm.blade.php @@ -1,49 +1,52 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Confirm Password') }}
+
+
+
+
+
{{ __('Confirm Password') }}
-
- {{ __('Please confirm your password before continuing.') }} +
+

{{ __('Please confirm your password before continuing.') }}

-
- @csrf + + @csrf -
- +
+ -
- +
+ - @error('password') - - {{ $message }} - - @enderror + @error('password') + + {{ $message }} + + @enderror +
-
-
-
- +
+
+ - @if (Route::has('password.request')) - - {{ __('Forgot Your Password?') }} - - @endif + @if (Route::has('password.request')) + + {{ __('Forgot Your Password?') }} + + @endif +
-
- + +
-
-@endsection +@endsection \ No newline at end of file diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index d1ac783..5a7fa47 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -1,47 +1,49 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Reset Password') }}
+
+
+
+
+
{{ __('Reset Password') }}
-
- @if (session('status')) - - @endif - -
- @csrf - -
- - -
- - - @error('email') - - {{ $message }} - - @enderror +
+ @if (session('status')) + -
+ @endif -
-
- + + @csrf + +
+ + +
+ + + @error('email') + + {{ $message }} + + @enderror +
-
- + +
+
+ +
+
+ +
-
-@endsection +@endsection \ No newline at end of file diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index dccf6c6..5991d38 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -1,65 +1,73 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Reset Password') }}
+
+
+
+
+
{{ __('Reset Password') }}
-
-
- @csrf +
+ + @csrf - + -
- +
+ -
- +
+ - @error('email') - - {{ $message }} - - @enderror + @error('email') + + {{ $message }} + + @enderror +
-
-
- +
+ -
- +
+ - @error('password') - - {{ $message }} - - @enderror + @error('password') + + {{ $message }} + + @enderror +
-
-
- +
+ -
- +
+ +
-
-
-
- +
+
+ +
-
- + +
-
-@endsection +@endsection \ No newline at end of file diff --git a/resources/views/auth/verify.blade.php b/resources/views/auth/verify.blade.php index 9f8c1bc..d336085 100644 --- a/resources/views/auth/verify.blade.php +++ b/resources/views/auth/verify.blade.php @@ -1,28 +1,49 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Verify Your Email Address') }}
+
+
+
+

{{ __('Verifikasi Email Anda') }}

+
-
- @if (session('resent')) -
-
-@endsection +@endsection \ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 8e3f802..44ecbb4 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -4,27 +4,220 @@ - - {{ config('app.name', 'Laravel') }} - - + + + + + + @vite(['resources/sass/app.scss', 'resources/js/app.js']) + +
-