Feat: history password#1096
Open
pandigresik wants to merge 4 commits into
Open
Conversation
|
🔄 AI PR Review sedang antri di server...
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request: Feature Password History (10 Riwayat Kata Sandi)
Description
Menerapkan mekanisme Password History yang menyimpan 10 riwayat kata sandi terakhir untuk setiap akun dan mencegah penggunaan kembali kata sandi yang pernah digunakan sebelumnya. Validasi diterapkan di seluruh mekanisme perubahan dan reset kata sandi melalui FormRequest dan penyimpanan riwayat dilakukan otomatis melalui UserObserver.
Changes made:
app/Observers/UserObserver.php— Observer pada model User yang otomatis menyimpan hash password lama ke tabelpassword_historiesdan melakukan pruning (hapus riwayat > 10) dalam transaksi databaseapp/Rules/StrongPassword.php— Menambah parameter$useruntuk pengecekan riwayat password pada konteks unauthenticated (reset password via email); defaulthistorySizeberubah jadi 10; tracking$failedRuleagarmessage()hanya mengembalikan 1 pesan relevan (bukan semua 6)app/Http/Requests/ChangePasswordRequest.php— OverridefailedValidation()untuk menampilkan flash error notification saat validasi gagalapp/Http/Requests/ResetPasswordRequest.php— Mencari user by email dan meneruskan keStrongPassword(user: $user)agar validasi riwayat tetap berjalan pada reset password via email; tambah flash error notification saat validasi gagalapp/Http/Controllers/Auth/ResetPasswordController.php— Menghapus manualPasswordHistory::create(), diganti dengan$user->passwordHistoryReasonyang diproses oleh observerapp/Http/Controllers/ForcePasswordResetController.php— Sama, menghapus manual history creation, diganti dengan observer patternapp/Models/User.php— Menambah properti$passwordHistoryReasondan$oldPasswordHash;setPasswordWithHistory()didelegasikan ke observerapp/Providers/AppServiceProvider.php— MendaftarkanUserObserverpada model Userconfig/password.php—history_countdari 5 menjadi 10tests/Feature/LoginControllerTest.php— Captcha test menggunakan user agent konsisten ('Symfony') danSetting::updateOrCreate()untuk mengaktifkan captchatests/Feature/OtpLoginControllerTest.php— Sama, captcha test diperbaikitests/Feature/PasswordHistoryTest.php— 8 test untuk UserObserver (simpan hash, custom reason, skip new user, pruning, dll)tests/Feature/PasswordResetFlowTest.php— 6 test untuk ForcePasswordResetController (form, redirect, sukses, history, reject reuse)tests/Feature/StrongPasswordRuleTest.php— 4 test baru untuk$userparameter, batas 10 entry, custom historySize; testerror_messagesdiadaptasi ke single-message patternReason for change:
Impact of change:
Related Issue
#1095
Steps to Reproduce
Sebelum:
Sesudah:
password_historiesvia observerChecklist
Technical Details
Arsitektur Observer
Validasi FormRequest
Setiap form request yang menerima input password baru menginstansiasi
StrongPassword:ChangePasswordRequest→ user dariauth()->user()ResetPasswordRequest→ user ditemukan dari email, diteruskan viaStrongPassword(user: $user)ForcePasswordResetRequest→ user dariauth()->user()StrongPassword::isNotInHistory()menggunakan prioritas:$this->user>auth()->user()> skip.Pesan Error Spesifik
StrongPassword::passes()mencatat jenis kegagalan via$this->failedRule:'length'→ "Password harus memiliki minimal N karakter."'complexity'→ "Password harus mengandung huruf kapital, huruf kecil, angka, dan karakter spesial."'history'→ "Password ini telah digunakan sebelumnya."'hibp'→ "Password ini telah bocor di HIBP."'weak_pattern'→ "Password terlalu lemah atau mudah ditebak."'common'→ "Password ini terlalu umum."message()hanya mengembalikan 1 pesan sesuai jenis kegagalan terakhir, bukan seluruh array.failedValidation()di FormRequest me-flash pesan ini kesession()->flash('error', ...)sehinggaflash_message.blade.phpmenampilkan notifikasi merah yang relevan.Configuration changes
config/password.php—'history_count' => 10Dependencies added
Tidak ada dependensi baru
Testing
Manual Testing
Automated Testing
Screenshots / Video
simplescreenrecorder-2026-07-15_10.59.18.mp4
Tidak ada perubahan UI
Breaking Changes
Tidak ada. Semua method existing (
setPasswordWithHistory,forcePasswordReset) tetap berfungsi. Perubahan hanya pada internal storage mechanism (dari manual ke observer).Migration Guide
Tidak diperlukan. Migration
2026_03_11_000001_create_password_histories_table.phpsudah ada di codebase.