Skip to content

Conversation

@ShoeBoom
Copy link
Owner

Add a Settings component providing Backup & Restore functionality for
synced user settings. Implement exportSettings to serialize current
rankings, quick bangs, and bang aliases into a JSON file and trigger a
download. Implement importSettings to accept a JSON file, validate its
structure, and apply contained rankings, quick_bangs, and bang_aliases
to storage with error handling and user feedback.

Wire the new Settings component into the main page navigation. Rename
the lucide-solid Settings icon import to SettingsIcon to avoid naming
conflict with the component.

Provide transient success/error status messages that auto-clear after a
few seconds. Validate backup format and handle malformed input with a
clear error message.

Add a Settings component providing Backup & Restore functionality for
synced user settings. Implement exportSettings to serialize current
rankings, quick bangs, and bang aliases into a JSON file and trigger a
download. Implement importSettings to accept a JSON file, validate its
structure, and apply contained rankings, quick_bangs, and bang_aliases
to storage with error handling and user feedback.

Wire the new Settings component into the main page navigation. Rename
the lucide-solid Settings icon import to SettingsIcon to avoid naming
conflict with the component.

Provide transient success/error status messages that auto-clear after a
few seconds. Validate backup format and handle malformed input with a
clear error message.
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Jan 16, 2026

Deploying searchtuner with  Cloudflare Pages  Cloudflare Pages

Latest commit: edf70bb
Status: ✅  Deploy successful!
Preview URL: https://1c1e8a5e.searchtuner.pages.dev
Branch Preview URL: https://backup-support.searchtuner.pages.dev

View logs

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 16, 2026

Greptile Summary

This PR introduces a backup and restore feature for synced user settings including domain rankings, quick bangs, and bang aliases. The UI provides export functionality to download settings as JSON and import to restore from previous backups.

Key changes:

  • Created new Settings.tsx component with export/import functionality
  • Integrated Settings component into navigation in main.tsx
  • Added validation for backup file format with success/error feedback

Critical issues found:

  • Validation uses typeof === "object" for rankings and bang_aliases, which incorrectly accepts arrays since arrays are objects in JavaScript. This allows malformed data like {"rankings": []} to pass validation and corrupt storage.
  • Version check only validates truthiness rather than explicitly checking for version 1, allowing any truthy version number to be accepted.

These validation bugs could allow users to import malformed backups that break the extension's functionality.

Confidence Score: 2/5

  • This PR has critical validation bugs that could corrupt user data during import
  • The type validation logic has flaws that allow arrays to be imported as objects for rankings and bang_aliases fields. This could lead to data corruption when users import malformed backups, breaking core functionality. The version validation is also too permissive. These are straightforward fixes but the bugs are critical enough to warrant fixing before merge.
  • Pay close attention to apps/extension/src/entrypoints/pages/components/Settings.tsx - validation logic needs stricter type checking

Important Files Changed

Filename Overview
apps/extension/src/entrypoints/pages/components/Settings.tsx Added backup/restore UI with export and import functionality. Critical validation bugs allow arrays to pass object type checks for rankings and bang_aliases, and version validation is too permissive.
apps/extension/src/entrypoints/pages/main.tsx Wired Settings component into navigation and renamed icon import to avoid naming conflict. Clean implementation with no issues.

Sequence Diagram

sequenceDiagram
    participant User
    participant Settings as Settings Component
    participant Browser as Browser Storage
    participant FileSystem as File System

    alt Export Settings
        User->>Settings: Click "Export Settings"
        Settings->>Browser: Get syncedRankings()
        Browser-->>Settings: rankings data
        Settings->>Browser: Get quickBangsData()
        Browser-->>Settings: quick_bangs data
        Settings->>Browser: Get bangAliasesData()
        Browser-->>Settings: bang_aliases data
        Settings->>Settings: Create SyncSettingsBackup object
        Settings->>Settings: JSON.stringify with formatting
        Settings->>Settings: Create Blob and download link
        Settings->>FileSystem: Trigger download
        FileSystem-->>User: searchtuner-backup-YYYY-MM-DD.json
    end

    alt Import Settings
        User->>Settings: Click "Import Settings"
        Settings->>User: Open file picker
        User->>Settings: Select JSON file
        Settings->>FileSystem: Read file content
        FileSystem-->>Settings: JSON text
        Settings->>Settings: JSON.parse backup
        Settings->>Settings: Validate version and data structure
        alt Validation passes
            Settings->>Browser: setValue(rankings) if present
            Settings->>Browser: setValue(quick_bangs) if present
            Settings->>Browser: setValue(bang_aliases) if present
            Browser-->>Settings: Success
            Settings->>User: Show success message (3s)
        else Validation fails
            Settings->>User: Show error message (5s)
        end
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

}

// Import each setting if present
if (backup.data.rankings && typeof backup.data.rankings === "object") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: typeof === "object" also returns true for arrays, allowing [] to be imported as rankings which should be an object.

Suggested change
if (backup.data.rankings && typeof backup.data.rankings === "object") {
if (backup.data.rankings && typeof backup.data.rankings === "object" && !Array.isArray(backup.data.rankings)) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/extension/src/entrypoints/pages/components/Settings.tsx
Line: 73:73

Comment:
**logic:** `typeof === "object"` also returns true for arrays, allowing `[]` to be imported as rankings which should be an object.

```suggestion
				if (backup.data.rankings && typeof backup.data.rankings === "object" && !Array.isArray(backup.data.rankings)) {
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +81 to +83
if (
backup.data.bang_aliases &&
typeof backup.data.bang_aliases === "object"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: typeof === "object" also returns true for arrays, allowing [] to be imported as bang_aliases which should be an object.

Suggested change
if (
backup.data.bang_aliases &&
typeof backup.data.bang_aliases === "object"
if (
backup.data.bang_aliases &&
typeof backup.data.bang_aliases === "object" &&
!Array.isArray(backup.data.bang_aliases)
) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/extension/src/entrypoints/pages/components/Settings.tsx
Line: 81:83

Comment:
**logic:** `typeof === "object"` also returns true for arrays, allowing `[]` to be imported as bang_aliases which should be an object.

```suggestion
				if (
					backup.data.bang_aliases &&
					typeof backup.data.bang_aliases === "object" &&
					!Array.isArray(backup.data.bang_aliases)
				) {
```

How can I resolve this? If you propose a fix, please make it concise.


// Validate backup structure
if (
!backup.version ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Version check is too loose - accepts any truthy version number instead of specifically validating version 1.

Suggested change
!backup.version ||
backup.version !== 1 ||
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/extension/src/entrypoints/pages/components/Settings.tsx
Line: 65:65

Comment:
**logic:** Version check is too loose - accepts any truthy version number instead of specifically validating version 1.

```suggestion
					backup.version !== 1 ||
```

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants