Files
2026-01-09 11:41:28 +01:00

103 lines
2.6 KiB
PHP

<?php
/**
* User OTP Model
* Manages email-based one-time passwords for two-factor authentication
*/
class UserOtp_model
{
protected static string $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 static function generateOTP($userId, $expiryMinutes = 10)
{
$db = \Config\Database::connect();
// 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',
'created_at' => date('Y-m-d H:i:s')
];
$db->table(self::$tablename)->insert($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 static function verifyOTP($userId, $otpCode)
{
$db = \Config\Database::connect();
// Get the most recent unused OTP for this user
$result = $db->table(self::$tablename)
->where('user_id', $userId)
->where('otp_code', $otpCode)
->where('used', 'F')
->where('expires_at >', date('Y-m-d H:i:s'))
->orderBy('created_at', 'DESC')
->limit(1)
->get()
->getRow();
if (!$result) {
return false;
}
// Mark OTP as used
$db->table(self::$tablename)
->where('id', $result->id)
->update(['used' => 'T']);
return true;
}
/**
* Clean up expired OTP codes
* @return int Number of deleted records
*/
public static function cleanupExpiredOTPs()
{
$db = \Config\Database::connect();
$db->table(self::$tablename)
->where('expires_at <', date('Y-m-d H:i:s'))
->orWhere('used', 'T')
->delete();
return $db->affectedRows();
}
/**
* Delete all OTP codes for a user
* @param int $userId User ID
*/
public static function deleteUserOTPs($userId)
{
$db = \Config\Database::connect();
$db->table(self::$tablename)
->where('user_id', $userId)
->delete();
}
}