152 lines
4.7 KiB
PHP
152 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use CodeIgniter\Model;
|
|
|
|
/**
|
|
* Model untuk Login Attempts
|
|
*
|
|
* Digunakan untuk:
|
|
* - Mencatat semua percobaan login
|
|
* - Menghitung jumlah percobaan gagal
|
|
* - Implementasi account lockout
|
|
* - Monitoring dan audit trail
|
|
*/
|
|
class LoginAttemptModel extends Model
|
|
{
|
|
protected $table = 'login_attempts';
|
|
protected $primaryKey = 'id';
|
|
protected $useAutoIncrement = true;
|
|
protected $returnType = 'array';
|
|
protected $useSoftDeletes = false;
|
|
protected $protectFields = true;
|
|
protected $allowedFields = ['ip_address', 'username', 'user_id', 'success', 'user_agent', 'created_at'];
|
|
|
|
protected bool $allowEmptyInserts = false;
|
|
|
|
protected $useTimestamps = true;
|
|
protected $dateFormat = 'datetime';
|
|
protected $createdField = 'created_at';
|
|
protected $updatedField = null;
|
|
protected $deletedField = null;
|
|
|
|
protected $validationRules = [];
|
|
protected $validationMessages = [];
|
|
protected $skipValidation = true; // Skip validation karena data dari sistem
|
|
|
|
protected $beforeInsert = [];
|
|
protected $afterInsert = [];
|
|
protected $beforeUpdate = [];
|
|
protected $afterUpdate = [];
|
|
protected $beforeFind = [];
|
|
protected $afterFind = [];
|
|
protected $beforeDelete = [];
|
|
protected $afterDelete = [];
|
|
|
|
/**
|
|
* Mencatat percobaan login
|
|
*
|
|
* @param string $ipAddress IP address dari request
|
|
* @param string|null $username Username yang dicoba
|
|
* @param int|null $userId ID user jika login berhasil
|
|
* @param bool $success Status login (true = berhasil, false = gagal)
|
|
* @return bool True jika berhasil disimpan
|
|
*/
|
|
public function recordAttempt(string $ipAddress, ?string $username = null, ?int $userId = null, bool $success = false): bool
|
|
{
|
|
$request = service('request');
|
|
|
|
$data = [
|
|
'ip_address' => $ipAddress,
|
|
'username' => $username,
|
|
'user_id' => $userId,
|
|
'success' => $success ? 1 : 0,
|
|
'user_agent' => $request->getUserAgent()->getAgentString(),
|
|
];
|
|
|
|
try {
|
|
return $this->insert($data) !== false;
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Failed to record login attempt: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Menghitung jumlah percobaan gagal dalam periode tertentu
|
|
*
|
|
* @param string $ipAddress IP address
|
|
* @param int $minutes Periode waktu dalam menit (default: 15)
|
|
* @return int Jumlah percobaan gagal
|
|
*/
|
|
public function countFailedAttempts(string $ipAddress, int $minutes = 15): int
|
|
{
|
|
$timeLimit = date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"));
|
|
|
|
return $this->where('ip_address', $ipAddress)
|
|
->where('success', 0)
|
|
->where('created_at >=', $timeLimit)
|
|
->countAllResults(false);
|
|
}
|
|
|
|
/**
|
|
* Menghitung jumlah percobaan gagal untuk username tertentu
|
|
*
|
|
* @param string $username Username
|
|
* @param int $minutes Periode waktu dalam menit (default: 15)
|
|
* @return int Jumlah percobaan gagal
|
|
*/
|
|
public function countFailedAttemptsByUsername(string $username, int $minutes = 15): int
|
|
{
|
|
$timeLimit = date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"));
|
|
|
|
return $this->where('username', $username)
|
|
->where('success', 0)
|
|
->where('created_at >=', $timeLimit)
|
|
->countAllResults(false);
|
|
}
|
|
|
|
/**
|
|
* Menghapus record percobaan lama (cleanup)
|
|
*
|
|
* @param int $days Jumlah hari untuk menyimpan data (default: 30)
|
|
* @return int Jumlah record yang dihapus
|
|
*/
|
|
public function cleanupOldAttempts(int $days = 30): int
|
|
{
|
|
$timeLimit = date('Y-m-d H:i:s', strtotime("-{$days} days"));
|
|
|
|
return $this->where('created_at <', $timeLimit)->delete();
|
|
}
|
|
|
|
/**
|
|
* Mendapatkan semua percobaan login untuk IP tertentu
|
|
*
|
|
* @param string $ipAddress IP address
|
|
* @param int $limit Jumlah record yang diambil
|
|
* @return array Array of login attempts
|
|
*/
|
|
public function getAttemptsByIp(string $ipAddress, int $limit = 50): array
|
|
{
|
|
return $this->where('ip_address', $ipAddress)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll($limit);
|
|
}
|
|
|
|
/**
|
|
* Mendapatkan semua percobaan login untuk username tertentu
|
|
*
|
|
* @param string $username Username
|
|
* @param int $limit Jumlah record yang diambil
|
|
* @return array Array of login attempts
|
|
*/
|
|
public function getAttemptsByUsername(string $username, int $limit = 50): array
|
|
{
|
|
return $this->where('username', $username)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll($limit);
|
|
}
|
|
}
|
|
|