$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); } }