From acb94216c8c96a7e1efedee566293bfbda971d2c Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Mon, 23 Mar 2026 15:55:58 -0300 Subject: [PATCH] fix(providers): secure Zed import route and add dashboard UI component --- package-lock.json | 26 ++++ package.json | 6 +- .../(dashboard)/dashboard/providers/page.tsx | 41 +++++ src/app/api/providers/zed/import/route.ts | 146 +++++++++--------- 4 files changed, 147 insertions(+), 72 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c736483..cae47b4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "http-proxy-middleware": "^3.0.5", "https-proxy-agent": "^8.0.0", "jose": "^6.1.3", + "keytar": "^7.9.0", "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", "next": "^16.1.6", @@ -54,6 +55,7 @@ "@tailwindcss/postcss": "^4.1.18", "@types/bcryptjs": "^3.0.0", "@types/better-sqlite3": "^7.6.13", + "@types/keytar": "^4.4.0", "@types/node": "^25.2.3", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", @@ -3431,6 +3433,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/keytar": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@types/keytar/-/keytar-4.4.0.tgz", + "integrity": "sha512-cq/NkUUy6rpWD8n7PweNQQBpw2o0cf5v6fbkUVEpOB9VzzIvyPvSEId1/goIj+MciW2v1Lw5mRimKO01XgE9EA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", @@ -8106,6 +8115,23 @@ "node": ">=4.0" } }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keytar/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "license": "MIT" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index bb3fb029..232f0f3e 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.27.1", "@monaco-editor/react": "^4.7.0", + "@swc/helpers": "0.5.19", "bcryptjs": "^3.0.3", "better-sqlite3": "^12.6.2", "bottleneck": "^2.19.5", @@ -92,6 +93,7 @@ "http-proxy-middleware": "^3.0.5", "https-proxy-agent": "^8.0.0", "jose": "^6.1.3", + "keytar": "^7.9.0", "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", "next": "^16.1.6", @@ -110,14 +112,14 @@ "uuid": "^13.0.0", "wreq-js": "^2.0.1", "zod": "^4.3.6", - "zustand": "^5.0.10", - "@swc/helpers": "0.5.19" + "zustand": "^5.0.10" }, "devDependencies": { "@playwright/test": "^1.58.2", "@tailwindcss/postcss": "^4.1.18", "@types/bcryptjs": "^3.0.0", "@types/better-sqlite3": "^7.6.13", + "@types/keytar": "^4.4.0", "@types/node": "^25.2.3", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", diff --git a/src/app/(dashboard)/dashboard/providers/page.tsx b/src/app/(dashboard)/dashboard/providers/page.tsx index b0bcc4c4..e3db03bb 100644 --- a/src/app/(dashboard)/dashboard/providers/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/page.tsx @@ -99,6 +99,7 @@ export default function ProvidersPage() { const [showAddAnthropicCompatibleModal, setShowAddAnthropicCompatibleModal] = useState(false); const [testingMode, setTestingMode] = useState(null); const [testResults, setTestResults] = useState(null); + const [importingZed, setImportingZed] = useState(false); const notify = useNotificationStore(); const t = useTranslations("providers"); const tc = useTranslations("common"); @@ -123,6 +124,33 @@ export default function ProvidersPage() { fetchData(); }, []); + const handleZedImport = async () => { + setImportingZed(true); + try { + const res = await fetch("/api/providers/zed/import", { method: "POST" }); + const data = await res.json(); + if (res.ok && data.success) { + if (data.count > 0) { + notify.success( + `Imported ${data.count} credentials from Zed IDE (${data.providers.join(", ")}).` + ); + // Refresh connections silently + const connectionsRes = await fetch("/api/providers"); + const connectionsData = await connectionsRes.json(); + if (connectionsRes.ok) setConnections(connectionsData.connections || []); + } else { + notify.info("No supported OAuth credentials found in Zed IDE."); + } + } else { + notify.error(data.error || "Failed to import from Zed IDE."); + } + } catch (error) { + notify.error("Network error while trying to import from Zed."); + } finally { + setImportingZed(false); + } + }; + const getProviderStats = (providerId, authType) => { const providerConnections = connections.filter( (c) => c.provider === providerId && c.authType === authType @@ -269,6 +297,19 @@ export default function ProvidersPage() {
+