input('role') === 'siswa') { // ...maka validasi input 'nisn' dan 'password'. return [ 'nisn' => ['required', 'string'], 'password' => ['required', 'string'], ]; } // Jika tidak (untuk 'guru' dan 'penjaga perpus') return [ 'nip' => ['required', 'string'], 'password' => ['required', 'string'], ]; } /** * Mencoba untuk mengautentikasi kredensial dari request. * Ini adalah "otak" dari proses login yang berisi logika paling penting. * * @throws \Illuminate\Validation\ValidationException */ public function authenticate(): void { // Pastikan pengguna tidak mencoba login terlalu sering (mencegah brute-force). $this->ensureIsNotRateLimited(); // Ambil data yang dikirim dari form login. $roleDariForm = $this->input('role'); $allUsers = DummyDataService::getAllSiswa(); $inputPassword = $this->input('password'); $userArray = null; // Tentukan field mana yang akan menerima pesan error jika gagal (nisn atau email). $errorField = $this->filled('nisn') ? 'nisn' : 'nip'; // Cari data pengguna berdasarkan input yang diberikan. if ($this->filled('nisn')) { // Jika form diisi dengan 'nisn', cari pengguna berdasarkan 'nisn'. $userArray = collect($allUsers)->firstWhere('nisn', $this->input('nisn')); } else { // Jika tidak, cari pengguna berdasarkan 'nip'. $userArray = collect($allUsers)->firstWhere('nip', $this->input('nip')); } // Lakukan Pengecekan Kredensial dan Role. if ($userArray && $userArray['password'] === $inputPassword) { // Cek #2: Jika kredensial benar, apakah role pengguna sesuai dengan form yang digunakan? if (isset($userArray['role']) && $userArray['role'] === $roleDariForm) { // Buat objek User dari data dummy. $userModel = new User(); $userArray['name'] = $userArray['nama_lengkap']; $userModel->forceFill($userArray); // Loginkan pengguna secara resmi ke dalam sistem. Auth::login($userModel); // Reset hitungan percobaan login yang gagal. RateLimiter::clear($this->throttleKey()); return; // Proses autentikasi berhasil. } else { // Tambah hitungan percobaan login yang gagal. RateLimiter::hit($this->throttleKey()); // Ambil nama role asli pengguna untuk ditampilkan di pesan error. $actualRole = Str::title($userArray['role'] ?? 'Tidak Dikenal'); // Lemparkan error validasi khusus 'forbidden' dengan pesan yang jelas. throw ValidationException::withMessages([ 'forbidden' => "Akses ditolak. Akun ini terdaftar sebagai {$actualRole}.", ]); } } // Jika pengguna tidak ditemukan atau password salah. RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ $errorField => trans('auth.failed'), // Pesan error umum "These credentials do not match...". ]); } /** * Memastikan request login tidak dibatasi karena terlalu banyak percobaan. */ public function ensureIsNotRateLimited(): void { // Jika percobaan belum melebihi 5 kali, lanjutkan. if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { return; } // Jika sudah lebih dari 5 kali, lemparkan error 'throttle'. event(new Lockout($this)); $seconds = RateLimiter::availableIn($this->throttleKey()); throw ValidationException::withMessages([ 'email' => trans('auth.throttle', [ 'seconds' => $seconds, 'minutes' => ceil($seconds / 60), ]), ]); } /** * Mendapatkan kunci throttle untuk request ini. * Kunci ini unik untuk setiap pengguna (berdasarkan nisn/email) dan alamat IP. */ public function throttleKey(): string { // Gunakan 'nisn' jika ada, jika tidak, gunakan 'email' sebagai identitas. $loginIdentifier = $this->input('nisn') ?: $this->input('nip'); return Str::transliterate(Str::lower($loginIdentifier) . '|' . $this->ip()); } }