Twofactor authentication and strong password

This commit is contained in:
2025-10-17 14:52:45 +02:00
parent 71a688f97f
commit dbd8c8aed2
17 changed files with 3055 additions and 14 deletions
@@ -0,0 +1,95 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* User OTP Model
* Manages email-based one-time passwords for two-factor authentication
*/
class UserOtp_model extends MY_Model
{
protected $tablename = "user_otp_codes";
/**
* Generate and store a new OTP code for a user
* @param int $userId User ID
* @param int $expiryMinutes Expiry time in minutes (default 10)
* @return string The generated OTP code
*/
public function generateOTP($userId, $expiryMinutes = 10)
{
// Generate 6-digit OTP
$otpCode = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
// Calculate expiry time
$expiresAt = date('Y-m-d H:i:s', strtotime("+{$expiryMinutes} minutes"));
// Store OTP in database
$data = [
'user_id' => $userId,
'otp_code' => $otpCode,
'expires_at' => $expiresAt,
'used' => 'F'
];
// Use direct insert since this table doesn't have audit columns
$this->db->insert($this->tablename, $data);
return $otpCode;
}
/**
* Verify an OTP code for a user
* @param int $userId User ID
* @param string $otpCode The OTP code to verify
* @return bool True if valid, false otherwise
*/
public function verifyOTP($userId, $otpCode)
{
// Get the most recent unused OTP for this user
$sql = "
SELECT * FROM {$this->tablename}
WHERE user_id = ?
AND otp_code = ?
AND used = 'F'
AND expires_at > NOW()
ORDER BY created_at DESC
LIMIT 1
";
$query = $this->db->query($sql, [$userId, $otpCode]);
if ($query->num_rows() == 0) {
return false;
}
$result = $query->row();
// Mark OTP as used (use direct update since this table doesn't have audit columns)
$this->db->where('id', $result->id);
$this->db->update($this->tablename, ['used' => 'T']);
return true;
}
/**
* Clean up expired OTP codes
* @return int Number of deleted records
*/
public function cleanupExpiredOTPs()
{
$this->sql = "DELETE FROM {$this->tablename} WHERE expires_at < NOW() OR used = 'T'";
$this->db->query($this->sql);
return $this->db->affected_rows();
}
/**
* Delete all OTP codes for a user
* @param int $userId User ID
*/
public function deleteUserOTPs($userId)
{
$this->db->where('user_id', $userId);
$this->db->delete($this->tablename);
}
}