db->execute( 'INSERT INTO login_codes (user_id, code_hash, purpose, expires_at) VALUES (?, ?, ?, ?)', [(int) $user['id'], password_hash($code, PASSWORD_DEFAULT), $purpose, $expiresAt] ); $name = htmlspecialchars((string) $user['full_name'], ENT_QUOTES, 'UTF-8'); $this->mailer->send( (string) $user['email'], 'Your Fat Bottom Grille verification code', "
Hi {$name},
Your verification code is {$code}.
It expires in 10 minutes.
" ); return (bool) $this->config->get('mailgun.enabled', false) ? null : $code; } public function verify(int $userId, string $code, string $purpose = 'login'): bool { $record = $this->db->fetch( 'SELECT * FROM login_codes WHERE user_id = ? AND purpose = ? AND used_at IS NULL AND expires_at > CURRENT_TIMESTAMP ORDER BY id DESC LIMIT 1', [$userId, $purpose] ); if ($record === null || !password_verify($code, (string) $record['code_hash'])) { return false; } $this->db->execute('UPDATE login_codes SET used_at = CURRENT_TIMESTAMP WHERE id = ?', [(int) $record['id']]); return true; } }