diff --git a/console-ui/public/portal/index.html b/console-ui/public/portal/index.html index 2ed0b05..b484d37 100644 --- a/console-ui/public/portal/index.html +++ b/console-ui/public/portal/index.html @@ -676,7 +676,7 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return { var p = S.profile || {}; if (p.role !== 'admin') return; var s = setupSteps(); - if (s.daemon && s.config && s.key) return; // 三件齊=安裝真的完成,不再打擾 + if (s.daemon && s.key) return; // t54 起只剩兩件:設定改由小幫手輸入帳密自取,不再下載檔案 var cfg = window.ARCRUN_CONFIG || {}; var daemonUrl = cfg.daemonDownload || 'https://raw.githubusercontent.com/youlinhsieh/arcrun-rag-bundles/main/daemon/ArcrunRAG-mac-unsigned.zip'; var row = function (done, id, html) { @@ -686,7 +686,7 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return { var el = document.createElement('div'); el.id = 'setup-checklist'; el.style.cssText = 'position:fixed;right:20px;bottom:20px;z-index:60;max-width:400px;width:calc(100% - 40px);padding:18px 20px;border-radius:14px;background:rgba(var(--amber-rgb),.10);border:1px solid rgba(var(--amber-rgb),.45);backdrop-filter:blur(8px);font-size:14px;line-height:1.65'; - el.innerHTML = '還差 ' + (3 - (s.daemon?1:0) - (s.config?1:0) - (s.key?1:0)) + ' 步,安裝就真的完成了' + el.innerHTML = '還差 ' + (2 - (s.daemon?1:0) - (s.key?1:0)) + ' 步,安裝就真的完成了' + row(s.daemon, 'daemon', '下載同步小幫手(把資料夾變成知識庫)
' + (daemonUrl @@ -695,10 +695,10 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return { // 誠實降級(leo 判準:按了連到錯的機制=不友善):沒有可用下載點時 // 不放死連結,說明現況並讓這步可手動打勾,不卡住清單。 : '封測期由我們直接寄給你安裝檔(Mac 版);' - + '收到後回來按 我已經裝好了')) - + row(s.config, 'config', - '下載設定檔 放到 ~/.arcrun-rag/config.json
' - + '下載 config.json') + + '收到後回來按 我已經裝好了。') + // t54(leo:「最好的就是把它的帳密直接輸入」):設定不再是一個要下載的檔案—— + // 小幫手第一次開啟會問網址+帳密,自己去換設定。 + + '
裝好第一次開啟時,貼上這個網址+你的帳號密碼就連上了,不用下載設定檔。
') + row(s.key, 'key', '啟用 AI 問答aistudio.google.com 免費申請)
' + ' ' @@ -708,24 +708,7 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return { document.body.appendChild(el); var dl = document.getElementById('sc-daemon'); if (dl) dl.addEventListener('click', function () { markStep('daemon'); }); - var cb = document.getElementById('sc-config'); - if (cb) cb.addEventListener('click', function (ev) { - ev.preventDefault(); - var conf = { - watch_folders: [], - manifest: '~/.arcrun-rag/manifest.json', - cypher_url: cfg.apiBase || '', - namespace: cfg.tenant || '', - library: 'kb', - extractor: 'claude', - email: (S.profile && S.profile.email) || '' - }; - var a = document.createElement('a'); - a.href = 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(conf, null, 2)); - a.download = 'config.json'; - document.body.appendChild(a); a.click(); a.remove(); - markStep('config'); - }); + // t54:config.json 下載鈕已移除(設定由小幫手憑帳密自取) var kb = document.getElementById('sc-key-save'); if (kb) kb.addEventListener('click', function () { var k = (document.getElementById('sc-key').value || '').trim(); diff --git a/cypher-executor/src/routes/portal.ts b/cypher-executor/src/routes/portal.ts index 15e63fa..8c1d872 100644 --- a/cypher-executor/src/routes/portal.ts +++ b/cypher-executor/src/routes/portal.ts @@ -699,6 +699,46 @@ function toPublicLibrary(rec: PortalRecord) { }; } +// POST /portal/daemon/config — body {email, password}。同步小幫手憑「用戶剛設的帳密」 +// 直接換到自己的設定(t54,leo 07-25:「最好的就是把它的帳密直接輸入」)—— +// 用戶不必再下載 config.json 丟隱藏資料夾,托盤第一次開啟輸入網址+帳密就上工。 +// 認證=與 /portal/login 同一把(同樣吃節流與停用檢查);回傳只含連線設定,不含任何知識內容。 +portalRouter.post('/portal/daemon/config', (c) => + run(c, async () => { + const body = (await c.req.json().catch(() => null)) as { email?: string; password?: string } | null; + const email = String(body?.email ?? '').trim().toLowerCase(); + const password = String(body?.password ?? ''); + if (!email || !password) return c.json({ error: 'email 與 password 必填' }, 400); + if (await isLocked(c.env, email)) { + return c.json({ error: '登入失敗次數過多,已暫時鎖定,請 15 分鐘後再試' }, 429); + } + const recordId = await findUserRecordId(c.env, email); + const rec = recordId ? await getRecordById(c.env, recordId) : null; + if (!rec) { + await recordLoginFail(c.env, email); + return c.json({ error: 'email 或密碼錯誤' }, 401); + } + if ((rec.values.status ?? '') !== 'active') return c.json({ error: '帳號已停用' }, 403); + if (!(await verifyPassword(password, rec.values.password_hash ?? ''))) { + await recordLoginFail(c.env, email); + return c.json({ error: 'email 或密碼錯誤' }, 401); + } + await clearLoginFail(c.env, email); + const tenant = portalTenant(c.env); + return c.json({ + success: true, + config: { + cypher_url: new URL(c.req.url).origin, + namespace: tenant, + library: 'kb', + extractor: 'claude', + email, + instance_name: String(rec.values.display_name ?? ''), + }, + }); + }), +); + // POST /portal/admin/chat-key — body {key}。站內啟用 AI 問答(t53,leo 07-25: // 「他進到網站要去給 gemini API Key」——不再回安裝器)。手法=G10 直嵌同款: // 改寫 tenant 的 rag_chat workflow 記錄,把 x-goog-api-key 換成實值(KV 覆寫=重推)。