db = new Database(); } public function createToken(string $email, int $hoursValid = 1): string { $cleanEmail = strtolower(trim($email)); $this->deleteByEmail($cleanEmail); $token = bin2hex(random_bytes(32)); // 64 hex chars $expiresAt = date('Y-m-d H:i:s', time() + ($hoursValid * 3600)); $sql = "INSERT INTO home_password_resets (email, token, expires_at) VALUES (:email, :token, :expires_at)"; $this->db->query($sql); $this->db->bind(':email', $cleanEmail); $this->db->bind(':token', $token); $this->db->bind(':expires_at', $expiresAt); $this->db->execute(); return $token; } public function getByToken(string $token): ?array { $cleanToken = trim($token); $sql = "SELECT * FROM home_password_resets WHERE LOWER(token) = LOWER(:token)"; $this->db->query($sql); $this->db->bind(':token', $cleanToken); $record = $this->db->single(); if (!$record) { return null; } // Check expiration if (new DateTime() > new DateTime($record['expires_at'])) { $this->deleteToken($cleanToken); return null; } return $record; } public function deleteByEmail(string $email): bool { $cleanEmail = strtolower(trim($email)); $sql = "DELETE FROM home_password_resets WHERE LOWER(email) = LOWER(:email)"; $this->db->query($sql); $this->db->bind(':email', $cleanEmail); return $this->db->execute(); } public function deleteToken(string $token): bool { $sql = "DELETE FROM home_password_resets WHERE LOWER(token) = LOWER(:token)"; $this->db->query($sql); $this->db->bind(':token', trim($token)); return $this->db->execute(); } }