From a8c96d84f0ff679d621b1cbed59c3fa4ca2975d1 Mon Sep 17 00:00:00 2001 From: Xujiacheng Date: Fri, 23 Jan 2026 23:55:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC?= =?UTF-8?q?=20API=E3=80=81=E6=95=B0=E6=8D=AE=E5=BA=93=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=92=8C=E5=89=8D=E7=AB=AF=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 + apps/extension/extension-dist.zip | Bin 50450 -> 206804 bytes apps/extension/package.json | 2 +- apps/extension/public/manifest.json | 16 +- apps/extension/src/background.js | 21 ++ apps/extension/src/content/main.js | 245 ++++++++++++++++ apps/extension/src/lib/extStorage.js | 49 ++++ .../extension/src/options/pages/LoginPage.vue | 2 +- apps/extension/src/options/pages/MyPage.vue | 2 +- apps/extension/src/popup/PopupApp.vue | 84 +++++- apps/extension/vite.config.js | 9 +- apps/server/migrations/0004_credentials.sql | 17 ++ apps/server/package.json | 4 +- .../src/__tests__/credentials.api.test.js | 115 ++++++++ apps/server/src/__tests__/credentials.test.js | 66 +++++ apps/server/src/app.js | 90 ++++++ apps/server/src/config.js | 4 +- apps/server/src/index.js | 88 +----- apps/server/src/lib/crypto.js | 41 +++ apps/server/src/lib/reauth.js | 13 + apps/server/src/routes/admin.routes.js | 129 +++++++++ apps/server/src/routes/auth.routes.js | 1 + apps/server/src/routes/credentials.routes.js | 151 ++++++++++ apps/web/src/App.vue | 7 +- apps/web/src/pages/LoginPage.vue | 1 + apps/web/src/pages/MyPage.vue | 8 +- apps/web/src/pages/PasswordManagerPage.vue | 266 ++++++++++++++++++ apps/web/src/pages/PublicPage.vue | 2 +- apps/web/src/router.js | 11 +- docs/开发框架约束.md | 14 +- .../2026-01-22-add-dnd-sorting/design.md | 24 ++ .../2026-01-22-add-dnd-sorting/proposal.md | 18 ++ .../specs/api/spec.md | 35 +++ .../2026-01-22-add-dnd-sorting/tasks.md | 12 + .../2026-01-23-add-password-manager/design.md | 33 +++ .../proposal.md | 20 ++ .../specs/api/spec.md | 41 +++ .../specs/password-manager/spec.md | 44 +++ .../2026-01-23-add-password-manager/tasks.md | 31 ++ openspec/specs/api/spec.md | 40 +++ openspec/specs/password-manager/spec.md | 64 +++++ package-lock.json | 4 +- spec/openapi.yaml | 240 ++++++++++++++++ 43 files changed, 1957 insertions(+), 110 deletions(-) create mode 100644 apps/extension/src/background.js create mode 100644 apps/extension/src/content/main.js create mode 100644 apps/server/migrations/0004_credentials.sql create mode 100644 apps/server/src/__tests__/credentials.api.test.js create mode 100644 apps/server/src/__tests__/credentials.test.js create mode 100644 apps/server/src/app.js create mode 100644 apps/server/src/lib/crypto.js create mode 100644 apps/server/src/lib/reauth.js create mode 100644 apps/server/src/routes/credentials.routes.js create mode 100644 apps/web/src/pages/PasswordManagerPage.vue create mode 100644 openspec/changes/archive/2026-01-22-add-dnd-sorting/design.md create mode 100644 openspec/changes/archive/2026-01-22-add-dnd-sorting/proposal.md create mode 100644 openspec/changes/archive/2026-01-22-add-dnd-sorting/specs/api/spec.md create mode 100644 openspec/changes/archive/2026-01-22-add-dnd-sorting/tasks.md create mode 100644 openspec/changes/archive/2026-01-23-add-password-manager/design.md create mode 100644 openspec/changes/archive/2026-01-23-add-password-manager/proposal.md create mode 100644 openspec/changes/archive/2026-01-23-add-password-manager/specs/api/spec.md create mode 100644 openspec/changes/archive/2026-01-23-add-password-manager/specs/password-manager/spec.md create mode 100644 openspec/changes/archive/2026-01-23-add-password-manager/tasks.md create mode 100644 openspec/specs/password-manager/spec.md diff --git a/.env.example b/.env.example index 350b80c..c5bec08 100644 --- a/.env.example +++ b/.env.example @@ -15,5 +15,8 @@ DATABASE_SSL=false # Auth AUTH_JWT_SECRET=change_me_long_random +# Credential encryption (base64-encoded 32-byte key) +CREDENTIAL_MASTER_KEY=change_me_base64_32_bytes + # Admin (only this email is treated as admin) ADMIN_EMAIL=admin@example.com diff --git a/apps/extension/extension-dist.zip b/apps/extension/extension-dist.zip index 05622f81be06eeac559f1ab38925941e46f74ee5..8f6b94ed6467101187223d10c87157b4b6efcd38 100644 GIT binary patch delta 137754 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%0D0;Y%{+h^~ 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

TD3?TO&(7 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 delta 1505 zcmca|o@Y`Q^MnB2(`!v*R3Ex;b!B8=u$>qyF*$UFc>UZ-=lz%r1&+N}+vEK9=G{fd zS`L@-C;gedf?cI(&D#@VyWTEat1xFz)fd4X6`vVDJh(hT;@+W6+$=Vd{(sYceKnt( zIXO0QhrDQm(frk0woTRvTQcKakj=S8&rJC|TPE?$&i}`AuCsX{r{>rMGlbikC-{i}`wxMOseUnOqq%Bg*CNQh89$lj$ z7R;F#rR|&Yl8b%y{!h#S-pni_3=9k$44_c1{XLKUBNGF|O;(VI3`1FFNvd9PS$b#) zCj;}^8wHscd-5|&E4UdLH$PzXVwMBx+5Yi(iWV?tjDY&MfO-n@3rY+0GD>oDCI_sL z0mhSWK9izA+k4+X{8Ng{GaoNBYqZVyHPOt_He#_mSMb8qOsrR4t=E6I>f*dv^D5Gx zJ#Ca+F#S^JmX8e~Sw2^HFW4(RDgu2=}Iv;L7>1=qQ zV@{}Ue#675ZClF~6IJH;CTy-=n;PVE$ctO!)`NPk%+-^hE$e8KPB4G^l~ea+$^t2? zaC4h06DR3yT<<2h#XsXZ!{Oe^-poJOJV+{W)ZgN2$kFC~D0yF&%DtaU_1)sve=n_n zclvyXwwIOLRmR?Jrd$bpCiAyG{v@-Csb)?<@+}Dsx6RKp>y7HOR_;$+tE$!Th5gdw zk`F=WA8!-+sPlitx~mWGzOC4_c7MNyS0BIU{keB!*fhU#Wu7$nUS~d8CT#CDmv8I# zZ2YZYKS648Bb#YGC{!P7TsXA~7%vLIkmUu2YHng)W?E`-iC$K5eja9Yu)JnwU|`__ zYKZN3l*C zr(}J{Q*YKwc}=Rdpx&z_Y#Tj_E&{w zI+2@C?z-#z^AY>UbLZ_8ZwK(_@T#Po&3Zn0){^7T)ov9(GkO%dVb-PH8baX;Wr`Q4 zG8~h3oWAkk(f|K8r<=H)J9vS0*QSWmkHBdU zlNDIGHoI_itY$jBcJjH+29wJ<#5ap>ImE&Y46DhvcIblz6n2&{fd!`THUtaY-<`uU z-9e67YWi^*W+&8gWV)Cvvl{cd8wJxpDl^M~v`vqbWtJAX2n=vUvS$S+dyo>b=`M22 zDoiY_(@)AW8=7FId"] + "host_permissions": [""], + "content_scripts": [ + { + "matches": [""], + "js": ["content.js"], + "run_at": "document_idle", + "type": "module" + } + ] } diff --git a/apps/extension/src/background.js b/apps/extension/src/background.js new file mode 100644 index 0000000..644265e --- /dev/null +++ b/apps/extension/src/background.js @@ -0,0 +1,21 @@ +const PENDING_KEY = "bb_pending_credential"; +const PENDING_TAB_KEY = "bb_pending_tab_id"; + +function openPopup() { + if (typeof chrome === "undefined" || !chrome.action?.openPopup) return; + chrome.action.openPopup().catch(() => { + // ignore if popup cannot be opened (no user gesture) + }); +} + +chrome.runtime.onMessage.addListener((msg, sender) => { + if (!msg || msg.type !== "CREDENTIAL_CAPTURED") return; + + const payload = msg.payload || {}; + chrome.storage.local.set({ + [PENDING_KEY]: payload, + [PENDING_TAB_KEY]: sender?.tab?.id || null + }, () => { + openPopup(); + }); +}); diff --git a/apps/extension/src/content/main.js b/apps/extension/src/content/main.js new file mode 100644 index 0000000..895173b --- /dev/null +++ b/apps/extension/src/content/main.js @@ -0,0 +1,245 @@ + +function getOrigin() { + return window.location.origin; +} + +function hasChromeStorage() { + return typeof chrome !== "undefined" && chrome.storage?.local; +} + +function storageGet(keys) { + return new Promise((resolve) => { + if (!hasChromeStorage()) return resolve({}); + chrome.storage.local.get(keys, (res) => resolve(res || {})); + }); +} + + +async function getToken() { + const res = await storageGet(["bb_token"]); + return res.bb_token || ""; +} + + +async function apiFetch(path, options = {}) { + const headers = new Headers(options.headers || {}); + if (!headers.has("Accept")) headers.set("Accept", "application/json"); + if (!(options.body instanceof FormData) && options.body != null) { + headers.set("Content-Type", "application/json"); + } + + const token = await getToken(); + if (token) headers.set("Authorization", `Bearer ${token}`); + + const base = (typeof chrome !== "undefined" && chrome.runtime?.getURL) + ? (import.meta?.env?.VITE_SERVER_BASE_URL || "http://localhost:3001") + : "http://localhost:3001"; + + const res = await fetch(`${base}${path}`, { ...options, headers }); + const contentType = res.headers.get("content-type") || ""; + const isJson = contentType.includes("application/json"); + const payload = isJson ? await res.json().catch(() => null) : await res.text().catch(() => ""); + + if (!res.ok) { + const message = payload?.message || `HTTP ${res.status}`; + const err = new Error(message); + err.status = res.status; + err.payload = payload; + throw err; + } + return payload; +} + +function ensureStyles() { + if (document.getElementById("bb-cred-style")) return; + const style = document.createElement("style"); + style.id = "bb-cred-style"; + style.textContent = ` + .bb-cred-selector{position:fixed;z-index:2147483646;background:#fff;border:1px solid rgba(0,0,0,0.12);box-shadow:0 10px 24px rgba(0,0,0,0.15);border-radius:10px;padding:6px;min-width:240px;max-width:320px;} + .bb-cred-item{display:flex;flex-direction:column;gap:4px;padding:8px;border-radius:8px;cursor:pointer;} + .bb-cred-item:hover{background:rgba(13,148,136,0.08);} + .bb-cred-site{font-size:12px;color:#64748b;} + .bb-cred-user{font-weight:700;color:#0f172a;} + `; + document.head.appendChild(style); +} + +async function fetchCredentials({ includePassword = false, siteOrigin }) { + const qs = new URLSearchParams(); + if (siteOrigin) qs.set("siteOrigin", siteOrigin); + if (includePassword) qs.set("includePassword", "true"); + + return apiFetch(`/credentials?${qs.toString()}`); +} + +function findUsernameInput(form, passwordInput) { + if (!form) return null; + const inputs = Array.from(form.querySelectorAll("input")); + const pwdIndex = inputs.indexOf(passwordInput); + const candidates = inputs.filter((el, idx) => { + if (el.type === "password") return false; + if (el.disabled || el.readOnly) return false; + if (idx > pwdIndex && pwdIndex !== -1) return false; + const t = (el.type || "text").toLowerCase(); + return t === "text" || t === "email" || t === "tel"; + }); + return candidates[candidates.length - 1] || null; +} + +function findPasswordInput(anchor) { + if (!anchor) return null; + if (anchor instanceof HTMLInputElement && anchor.type === "password") return anchor; + const form = anchor.closest("form"); + if (form) return form.querySelector("input[type='password']"); + + let cur = anchor.parentElement; + let depth = 0; + while (cur && depth < 4) { + const found = cur.querySelector("input[type='password']"); + if (found) return found; + cur = cur.parentElement; + depth++; + } + return null; +} + +function createSelector(anchorEl, creds, onSelect) { + ensureStyles(); + const rect = anchorEl.getBoundingClientRect(); + const panel = document.createElement("div"); + panel.className = "bb-cred-selector"; + panel.style.left = `${Math.max(8, rect.left)}px`; + panel.style.top = `${rect.bottom + 6}px`; + panel.style.maxWidth = `${Math.min(360, window.innerWidth - rect.left - 8)}px`; + + creds.forEach((c) => { + const item = document.createElement("div"); + item.className = "bb-cred-item"; + item.innerHTML = `

${c.username}
${c.siteOrigin}
`; + item.addEventListener("click", () => { + onSelect(c); + cleanup(); + }); + panel.appendChild(item); + }); + + document.body.appendChild(panel); + + function cleanup() { + panel.remove(); + document.removeEventListener("pointerdown", onDocClick, true); + } + + function onDocClick(e) { + if (!panel.contains(e.target) && e.target !== anchorEl) cleanup(); + } + + document.addEventListener("pointerdown", onDocClick, true); + return cleanup; +} + +let lastAnchor = null; +let lastShownAt = 0; + +async function showSelectorForInput(anchorEl) { + if (!anchorEl) return; + const now = Date.now(); + if (lastAnchor === anchorEl && now - lastShownAt < 300) return; + lastAnchor = anchorEl; + lastShownAt = now; + + const passwordInput = findPasswordInput(anchorEl); + if (!passwordInput) return; + const form = passwordInput.closest("form"); + const usernameInput = findUsernameInput(form, passwordInput) || (anchorEl.type !== "password" ? anchorEl : null); + const siteOrigin = getOrigin(); + + let creds = []; + try { + creds = await fetchCredentials({ includePassword: false, siteOrigin }); + } catch { + return; + } + if (!Array.isArray(creds) || creds.length === 0) return; + + createSelector(anchorEl, creds, async (cred) => { + try { + const full = await fetchCredentials({ includePassword: true, siteOrigin }); + + const target = full.find((x) => x.id === cred.id); + if (!target) return; + if (usernameInput) { + usernameInput.value = target.username; + usernameInput.dispatchEvent(new Event("input", { bubbles: true })); + } + if (passwordInput) { + passwordInput.value = target.password || ""; + passwordInput.dispatchEvent(new Event("input", { bubbles: true })); + } + } catch { + // ignore + } + }); +} + +function handleInputFocus(e) { + const el = e.target; + if (!(el instanceof HTMLInputElement)) return; + const t = (el.type || "text").toLowerCase(); + if (t !== "password" && t !== "text" && t !== "email" && t !== "tel") return; + showSelectorForInput(el); +} + +async function handleFormSubmit(e) { + const form = e.target; + if (!(form instanceof HTMLFormElement)) return; + const pwd = form.querySelector("input[type='password']"); + if (!pwd) return; + const usernameInput = findUsernameInput(form, pwd); + + const username = usernameInput?.value?.trim(); + const password = pwd.value?.trim(); + if (!username || !password) return; + + const token = await getToken(); + if (!token) return; + + const siteOrigin = getOrigin(); + let existing = []; + try { + existing = await fetchCredentials({ includePassword: true, siteOrigin }); + } catch { + // if we cannot fetch, still allow prompt to save + existing = []; + } + + const sameUser = Array.isArray(existing) + ? existing.find((c) => c.username === username) + : null; + + if (sameUser && sameUser.password === password) { + return; + } + + const reason = sameUser ? "update" : "new"; + + if (typeof chrome !== "undefined" && chrome.runtime?.sendMessage) { + chrome.runtime.sendMessage({ + type: "CREDENTIAL_CAPTURED", + payload: { + siteOrigin, + username, + password, + reason + } + }); + } +} + +function init() { + document.addEventListener("focusin", handleInputFocus, true); + document.addEventListener("click", handleInputFocus, true); + document.addEventListener("submit", handleFormSubmit, true); +} + +init(); diff --git a/apps/extension/src/lib/extStorage.js b/apps/extension/src/lib/extStorage.js index 99b1b62..96f4642 100644 --- a/apps/extension/src/lib/extStorage.js +++ b/apps/extension/src/lib/extStorage.js @@ -1,5 +1,8 @@ const TOKEN_KEY = "bb_token"; const LOCAL_STATE_KEY = "bb_local_state_v1"; +const PENDING_CREDENTIAL_KEY = "bb_pending_credential"; +const REAUTH_TOKEN_KEY = "bb_reauth_token"; +const REAUTH_EXPIRES_KEY = "bb_reauth_expires_at"; function hasChromeStorage() { return typeof chrome !== "undefined" && chrome.storage?.local; @@ -41,3 +44,49 @@ export async function saveLocalState(state) { } localStorage.setItem(LOCAL_STATE_KEY, JSON.stringify(state)); } + +export async function getPendingCredential() { + if (hasChromeStorage()) { + const res = await chrome.storage.local.get([PENDING_CREDENTIAL_KEY]); + return res[PENDING_CREDENTIAL_KEY] || null; + } + try { + return JSON.parse(localStorage.getItem(PENDING_CREDENTIAL_KEY) || "") || null; + } catch { + return null; + } +} + +export async function clearPendingCredential() { + if (hasChromeStorage()) { + await chrome.storage.local.remove([PENDING_CREDENTIAL_KEY]); + return; + } + localStorage.removeItem(PENDING_CREDENTIAL_KEY); +} + +export async function setReauthToken(token, expiresAt) { + if (hasChromeStorage()) { + await chrome.storage.local.set({ + [REAUTH_TOKEN_KEY]: token || "", + [REAUTH_EXPIRES_KEY]: expiresAt || "" + }); + return; + } + localStorage.setItem(REAUTH_TOKEN_KEY, token || ""); + localStorage.setItem(REAUTH_EXPIRES_KEY, expiresAt || ""); +} + +export async function getReauthToken() { + if (hasChromeStorage()) { + const res = await chrome.storage.local.get([REAUTH_TOKEN_KEY, REAUTH_EXPIRES_KEY]); + return { + token: res[REAUTH_TOKEN_KEY] || "", + expiresAt: res[REAUTH_EXPIRES_KEY] || "" + }; + } + return { + token: localStorage.getItem(REAUTH_TOKEN_KEY) || "", + expiresAt: localStorage.getItem(REAUTH_EXPIRES_KEY) || "" + }; +} diff --git a/apps/extension/src/options/pages/LoginPage.vue b/apps/extension/src/options/pages/LoginPage.vue index 05cf685..5191cad 100644 --- a/apps/extension/src/options/pages/LoginPage.vue +++ b/apps/extension/src/options/pages/LoginPage.vue @@ -55,7 +55,7 @@ async function submit() {
- +

{{ error }}

diff --git a/apps/extension/src/options/pages/MyPage.vue b/apps/extension/src/options/pages/MyPage.vue index 9b5645c..7a96ac3 100644 --- a/apps/extension/src/options/pages/MyPage.vue +++ b/apps/extension/src/options/pages/MyPage.vue @@ -79,7 +79,7 @@ onMounted(load);
- +
diff --git a/apps/extension/src/popup/PopupApp.vue b/apps/extension/src/popup/PopupApp.vue index 193f286..4df6f95 100644 --- a/apps/extension/src/popup/PopupApp.vue +++ b/apps/extension/src/popup/PopupApp.vue @@ -1,7 +1,7 @@ + + + + diff --git a/apps/web/src/pages/PublicPage.vue b/apps/web/src/pages/PublicPage.vue index 020b890..859204e 100644 --- a/apps/web/src/pages/PublicPage.vue +++ b/apps/web/src/pages/PublicPage.vue @@ -139,7 +139,7 @@ onMounted(loadFolders);
- + { const loggedIn = Boolean(tokenRef.value); - // 主页(/)永远是公共首页;不因登录态自动跳转 + // 已登录访问首页时,跳转到个人页 + if (to.path === "/" && loggedIn) return { path: "/my" }; // 已登录访问登录页:直接去“我的” if (to.path === "/login" && loggedIn) return { path: "/my" }; @@ -30,6 +33,10 @@ router.beforeEach(async (to) => { return { path: "/login", query: { next: to.fullPath } }; } + if (to.path === "/passwords" && !loggedIn) { + return { path: "/login", query: { next: to.fullPath } }; + } + // 管理界面:仅管理员可见 if (to.path.startsWith("/admin")) { if (!loggedIn) return { path: "/login", query: { next: to.fullPath } }; diff --git a/docs/开发框架约束.md b/docs/开发框架约束.md index d1ecd17..a929466 100644 --- a/docs/开发框架约束.md +++ b/docs/开发框架约束.md @@ -85,4 +85,16 @@ AI 创建项目时,默认使用以下结构;如项目类型不适用,可 - 先指出冲突点,并请求用户确认是否允许偏离约束。 - 未明确要求时: - 不引入与约束无关的“额外页面/功能/组件/花哨配置”。 - - 保持最小可用、可验证、可维护的实现。 \ No newline at end of file + - 保持最小可用、可验证、可维护的实现。 + +7. 发布版本号约束(强约束) + +- **每次发布必须迭代版本号**,并同步更新以下位置(缺一不可): + - 后端版本:`apps/server/package.json` + - Web 版本:`apps/web/package.json` + - 插件版本:`apps/extension/package.json` + - 插件清单版本:`apps/extension/public/manifest.json` +- 发布后必须验证构建产物里的插件版本已更新:`apps/extension/dist/manifest.json`。 +- 当前统一版本从 **1.0.0** 开始。 +- 默认规则:仅递增最后一位(patch),例如 1.0.0 → 1.0.1 → 1.0.2。 +- 只有在用户明确要求时,才允许变更中间位(minor);否则不得修改。 \ No newline at end of file diff --git a/openspec/changes/archive/2026-01-22-add-dnd-sorting/design.md b/openspec/changes/archive/2026-01-22-add-dnd-sorting/design.md new file mode 100644 index 0000000..bdf4284 --- /dev/null +++ b/openspec/changes/archive/2026-01-22-add-dnd-sorting/design.md @@ -0,0 +1,24 @@ +# Design: Persistent ordering + touch-friendly DnD + +## Database +- Add `sort_order integer not null default 0` to `bookmarks`. +- Add indexes to support ordered listing: + - `(user_id, folder_id, sort_order)` + +## API +- Extend `Bookmark` DTO/schema with `sortOrder`. +- Add `POST /bookmarks/reorder` similar to existing `/folders/reorder`: + - Input: `{ folderId: uuid|null, orderedIds: uuid[] }` + - Validates `orderedIds` is a permutation of all bookmarks for that user+folder (excluding deleted). + - Transactionally updates `sort_order` for each id. + +## Web UI +- Replace native HTML5 drag/drop with a touch-capable approach. + - Implementation choice: `sortablejs` (small, proven, touch-friendly). + - Bind Sortable to: + - Folder header list (per parent group) for folder ordering. + - Each open folder’s bookmark list for bookmark ordering. +- Root group is rendered as a first-class group and can also be reordered. + +## Compatibility +- If the DB schema lacks ordering columns (fresh/old DB), endpoints should return a clear 409 prompting `db:migrate`. diff --git a/openspec/changes/archive/2026-01-22-add-dnd-sorting/proposal.md b/openspec/changes/archive/2026-01-22-add-dnd-sorting/proposal.md new file mode 100644 index 0000000..de16a62 --- /dev/null +++ b/openspec/changes/archive/2026-01-22-add-dnd-sorting/proposal.md @@ -0,0 +1,18 @@ +# Change: Add persistent drag-and-drop sorting (folders + bookmarks) + +## Why +Users need to reorder folders and bookmarks via drag-and-drop (including mobile/touch) and have that order persist across reloads. Current HTML5 drag/drop is unreliable on mobile and ordering is not stored for bookmarks. + +## What Changes +- Add persistent ordering for bookmarks (new DB column and API endpoint to reorder within a folder). +- Use a touch-friendly drag-and-drop implementation in the web UI for: + - Reordering folders within the same parent. + - Reordering bookmarks within the same folder. +- Keep the root group (no folder) as a first-class group in the UI. + +## Impact +- Affected specs: API (OpenAPI-backed) +- Affected code: + - Server: migrations, bookmarks routes, admin routes, row DTO mapping + - Web: MyPage and AdminPage UI ordering and drag/drop + - OpenAPI: Bookmark schema and reorder endpoint diff --git a/openspec/changes/archive/2026-01-22-add-dnd-sorting/specs/api/spec.md b/openspec/changes/archive/2026-01-22-add-dnd-sorting/specs/api/spec.md new file mode 100644 index 0000000..893928a --- /dev/null +++ b/openspec/changes/archive/2026-01-22-add-dnd-sorting/specs/api/spec.md @@ -0,0 +1,35 @@ +## ADDED Requirements + +### Requirement: Folder ordering persistence +The system SHALL persist folder ordering per user per parent folder. + +#### Scenario: List folders returns stable ordered result +- **GIVEN** an authenticated user +- **WHEN** the user calls `GET /folders` +- **THEN** the server returns folders ordered by `(parentId, sortOrder, name)` + +#### Scenario: Reorder folders within the same parent +- **GIVEN** an authenticated user +- **WHEN** the user calls `POST /folders/reorder` with `parentId` and `orderedIds` +- **THEN** the server persists the new order and returns `{ ok: true }` + +### Requirement: Bookmark ordering persistence +The system SHALL persist bookmark ordering per user per folder. + +#### Scenario: List my bookmarks returns stable ordered result +- **GIVEN** an authenticated user +- **WHEN** the user calls `GET /bookmarks` +- **THEN** the server returns bookmarks ordered by `(folderId, sortOrder, updatedAt desc)` + +#### Scenario: Reorder bookmarks within the same folder +- **GIVEN** an authenticated user +- **WHEN** the user calls `POST /bookmarks/reorder` with `folderId` and `orderedIds` +- **THEN** the server persists the new order and returns `{ ok: true }` + +### Requirement: Root group treated consistently +The system SHALL treat `folderId=null` bookmarks as belonging to the root group. + +#### Scenario: Reorder root-group bookmarks +- **GIVEN** an authenticated user +- **WHEN** the user calls `POST /bookmarks/reorder` with `folderId=null` +- **THEN** the server reorders root-group bookmarks and returns `{ ok: true }` diff --git a/openspec/changes/archive/2026-01-22-add-dnd-sorting/tasks.md b/openspec/changes/archive/2026-01-22-add-dnd-sorting/tasks.md new file mode 100644 index 0000000..52afcac --- /dev/null +++ b/openspec/changes/archive/2026-01-22-add-dnd-sorting/tasks.md @@ -0,0 +1,12 @@ +## 1. Implementation +- [ ] Add DB support for bookmark ordering (migration + init schema) +- [ ] Expose bookmark ordering in DTOs and OpenAPI schema +- [ ] Add API endpoint to reorder bookmarks within the same folder +- [ ] Ensure list endpoints return folders/bookmarks in stable order (parent+sortOrder, etc.) +- [ ] Implement touch-friendly drag sorting in Web UI for folders and bookmarks +- [ ] Treat root group (folderId null) as a first-class group for display and bookmark reorder +- [ ] Add basic verification steps (build + manual smoke checklist) + +## 2. Spec Updates +- [ ] Update OpenAPI contract for bookmark sortOrder and reorder endpoint +- [ ] Update OpenSpec API capability delta requirements diff --git a/openspec/changes/archive/2026-01-23-add-password-manager/design.md b/openspec/changes/archive/2026-01-23-add-password-manager/design.md new file mode 100644 index 0000000..6832ce2 --- /dev/null +++ b/openspec/changes/archive/2026-01-23-add-password-manager/design.md @@ -0,0 +1,33 @@ +## Context +We need a password manager across extension and web, with admin visibility and per-user isolation. Non-admin users must re-verify their login password to view plaintext. + +## Goals / Non-Goals +- Goals: + - Save credentials with explicit confirmation. + - Autofill selector for saved accounts per site. + - Admin can view all users’ credentials. + - Non-admin must re-verify password before plaintext reveal. + - Encrypt credentials at rest. +- Non-Goals: + - Browser-level credential integration outside the extension. + - Password sharing between users. + +## Decisions +- Site key = URL origin (scheme + host + port). +- Storage model: one row per (user_id, site_origin, username), allowing multiple accounts per site. +- Encrypt password using AES-256-GCM with server-side master key (env), store iv + tag + ciphertext. +- Use a session-only toggle to reveal plaintext in the web UI (sessionStorage; reset on browser close). +- Extension content script detects login forms; popup asks to save; only on confirm does it call API. + +## Risks / Trade-offs +- Storing decryptable passwords increases risk. Mitigation: encryption at rest, strict auth, session-only plaintext reveal, audit logging (future). + +## Migration Plan +- Add DB migration for credential tables and indexes. +- Add API endpoints and update OpenAPI. +- Implement extension flows and web UI. +- Add tests for CRUD, reauth, admin access. + +## Open Questions +- Confirm site matching scope (origin vs eTLD+1). +- Save prompt triggers on form submit (username + password present). diff --git a/openspec/changes/archive/2026-01-23-add-password-manager/proposal.md b/openspec/changes/archive/2026-01-23-add-password-manager/proposal.md new file mode 100644 index 0000000..016d0da --- /dev/null +++ b/openspec/changes/archive/2026-01-23-add-password-manager/proposal.md @@ -0,0 +1,20 @@ +# Change: Add password manager (Web + Extension) + +## Why +Provide built-in credential saving and autofill for users, with centralized management and admin oversight. + +## What Changes +- Add credential save + autofill flows in the extension (explicit user confirmation required). +- Add a Web password management page (desktop only) with view/edit/delete. +- Add APIs for credential CRUD and admin access; plaintext view available during the current browser session. +- Add database schema for credential storage (per-user, per-site, multiple accounts). +- Add tests for API and DB flows. + +## Impact +- Affected specs: api, password-manager +- Affected code: apps/server, apps/web, apps/extension, migrations, spec/openapi.yaml + +## Assumptions (confirm) +- “同一网站” is defined as the URL origin (scheme + host + port). +- The extension prompts on form submit after username + password are provided. +- Credentials are stored encrypted at rest and decrypted server-side for plaintext display. diff --git a/openspec/changes/archive/2026-01-23-add-password-manager/specs/api/spec.md b/openspec/changes/archive/2026-01-23-add-password-manager/specs/api/spec.md new file mode 100644 index 0000000..f54b3aa --- /dev/null +++ b/openspec/changes/archive/2026-01-23-add-password-manager/specs/api/spec.md @@ -0,0 +1,41 @@ +## ADDED Requirements + +### Requirement: Credential storage API +The system SHALL provide authenticated CRUD APIs for credentials scoped to the current user. + +#### Scenario: Create credential +- **WHEN** an authenticated user calls `POST /credentials` with `siteOrigin`, `username`, and `password` +- **THEN** the server stores the credential and returns the created record + +#### Scenario: List credentials +- **WHEN** an authenticated user calls `GET /credentials?siteOrigin=...` +- **THEN** the server returns the matching credentials for that user + +#### Scenario: Update credential +- **WHEN** an authenticated user calls `PATCH /credentials/{id}` +- **THEN** the server updates the credential and returns the updated record + +#### Scenario: Delete credential +- **WHEN** an authenticated user calls `DELETE /credentials/{id}` +- **THEN** the server deletes the credential + +### Requirement: Credential plaintext reveal +The system SHALL allow authenticated users to request plaintext passwords for their own credentials. + +#### Scenario: User requests plaintext +- **GIVEN** an authenticated user +- **WHEN** the user requests plaintext credential data +- **THEN** the server returns plaintext passwords for that user + +#### Scenario: Admin requests plaintext +- **GIVEN** an authenticated admin user +- **WHEN** the admin requests plaintext credential data +- **THEN** the server returns plaintext passwords for the target user + +### Requirement: Admin credential access +The system SHALL allow an admin to list and manage any user’s credentials. + +#### Scenario: Admin lists user credentials +- **GIVEN** an authenticated admin user +- **WHEN** the admin calls `GET /admin/users/{id}/credentials` +- **THEN** the server returns that user’s credentials diff --git a/openspec/changes/archive/2026-01-23-add-password-manager/specs/password-manager/spec.md b/openspec/changes/archive/2026-01-23-add-password-manager/specs/password-manager/spec.md new file mode 100644 index 0000000..9fdc61a --- /dev/null +++ b/openspec/changes/archive/2026-01-23-add-password-manager/specs/password-manager/spec.md @@ -0,0 +1,44 @@ +## ADDED Requirements + +### Requirement: Extension save prompt +The extension SHALL prompt the user to save credentials when a login form is detected and filled. + +#### Scenario: Save confirmed +- **WHEN** the user confirms “保存/记住密码” in the prompt +- **THEN** the extension sends the credential to the server for storage + +#### Scenario: Save canceled +- **WHEN** the user cancels or dismisses the prompt +- **THEN** the extension MUST NOT store the credential + +### Requirement: Extension autofill selector +The extension SHALL show a credential selector near login fields for sites with saved accounts. + +#### Scenario: Select credential +- **GIVEN** a site with multiple saved credentials +- **WHEN** the user opens the selector and chooses one +- **THEN** the username and password fields are filled with that credential + +### Requirement: Web password manager (desktop only) +The web app SHALL provide a desktop-only password manager view. + +#### Scenario: Desktop view +- **WHEN** the user visits the password manager page on desktop +- **THEN** the page is visible and provides list/edit/delete + +#### Scenario: Mobile view hidden +- **WHEN** the user visits the password manager page on mobile +- **THEN** the page is hidden or redirects to a notice page + +### Requirement: Plaintext visibility control +The system SHALL allow a user to reveal plaintext passwords for their own credentials during the current browser session. + +#### Scenario: User reveals plaintext +- **GIVEN** a non-admin user +- **WHEN** the user chooses to reveal plaintext +- **THEN** the UI shows plaintext passwords during the current browser session + +#### Scenario: Admin view +- **GIVEN** an admin user +- **WHEN** the admin views credentials +- **THEN** plaintext is visible diff --git a/openspec/changes/archive/2026-01-23-add-password-manager/tasks.md b/openspec/changes/archive/2026-01-23-add-password-manager/tasks.md new file mode 100644 index 0000000..8a3aeed --- /dev/null +++ b/openspec/changes/archive/2026-01-23-add-password-manager/tasks.md @@ -0,0 +1,31 @@ +## 1. Spec +- [x] 1.1 Update OpenSpec deltas for api/password-manager +- [x] 1.2 Update OpenAPI 3.1 contract (spec/openapi.yaml) + +## 2. Database +- [x] 2.1 Add migrations for credential storage tables + indexes + +## 3. Server +- [x] 3.1 Implement credential CRUD APIs +- [x] 3.2 Enable plaintext credential access +- [x] 3.3 Implement admin credential access APIs + +## 4. Extension +- [x] 4.1 Add content script for detecting login forms +- [x] 4.2 Add save-credential prompt + confirm flow +- [x] 4.3 Add autofill selector UI on login fields + +## 5. Web +- [x] 5.1 Add desktop-only password manager page +- [x] 5.2 Add session-based plaintext toggle +- [x] 5.3 Add admin view for all users + +## 6. Tests +- [x] 6.1 API tests for CRUD + plaintext + admin access +- [x] 6.2 DB migration verification + +## 7. Verification +- [x] 7.1 Specs updated in openspec/specs +- [x] 7.2 OpenAPI updated and validated +- [x] 7.3 DB migration applied +- [x] 7.4 Server tests executed diff --git a/openspec/specs/api/spec.md b/openspec/specs/api/spec.md index c2f733e..4d0ff16 100644 --- a/openspec/specs/api/spec.md +++ b/openspec/specs/api/spec.md @@ -63,3 +63,43 @@ The system SHALL treat exactly one configured email as an administrator and allo - **GIVEN** an authenticated admin user - **WHEN** the admin calls `GET /admin/users/{id}/bookmarks` - **THEN** the server returns `200` and that user's bookmarks + +### Requirement: Credential storage API +The system SHALL provide authenticated CRUD APIs for credentials scoped to the current user. + +#### Scenario: Create credential +- **WHEN** an authenticated user calls `POST /credentials` with `siteOrigin`, `username`, and `password` +- **THEN** the server stores the credential and returns the created record + +#### Scenario: List credentials +- **WHEN** an authenticated user calls `GET /credentials?siteOrigin=...` +- **THEN** the server returns the matching credentials for that user + +#### Scenario: Update credential +- **WHEN** an authenticated user calls `PATCH /credentials/{id}` +- **THEN** the server updates the credential and returns the updated record + +#### Scenario: Delete credential +- **WHEN** an authenticated user calls `DELETE /credentials/{id}` +- **THEN** the server deletes the credential + +### Requirement: Credential plaintext access +The system SHALL allow authenticated users to request plaintext passwords for their own credentials. + +#### Scenario: User requests plaintext +- **GIVEN** an authenticated user +- **WHEN** the user calls `GET /credentials?includePassword=true` +- **THEN** the server returns plaintext passwords for that user + +#### Scenario: Admin requests plaintext for a user +- **GIVEN** an authenticated admin user +- **WHEN** the admin calls `GET /admin/users/{id}/credentials?includePassword=true` +- **THEN** the server returns plaintext passwords for that user + +### Requirement: Admin credential management +The system SHALL allow an admin to list and manage any user’s credentials. + +#### Scenario: Admin lists user credentials +- **GIVEN** an authenticated admin user +- **WHEN** the admin calls `GET /admin/users/{id}/credentials` +- **THEN** the server returns that user’s credentials diff --git a/openspec/specs/password-manager/spec.md b/openspec/specs/password-manager/spec.md new file mode 100644 index 0000000..24a69b3 --- /dev/null +++ b/openspec/specs/password-manager/spec.md @@ -0,0 +1,64 @@ +# Capability: Password Manager + +## Purpose +Define password-manager behavior across the extension and web UI. + +## Requirements + +### Requirement: Extension save prompt +The extension SHALL prompt the user to save credentials when a login form is detected and submitted. + +#### Scenario: Save confirmed +- **WHEN** the user confirms “保存/记住密码” in the prompt +- **THEN** the extension sends the credential to the server for storage + +#### Scenario: Save canceled +- **WHEN** the user cancels or dismisses the prompt +- **THEN** the extension MUST NOT store the credential + +#### Scenario: Save prompt suppressed for matching credential +- **GIVEN** a previously saved credential for the same `siteOrigin` and `username` +- **WHEN** the user submits the same password +- **THEN** the save prompt is not shown + +#### Scenario: Save prompt update for password change +- **GIVEN** a previously saved credential for the same `siteOrigin` and `username` +- **WHEN** the user submits a different password +- **THEN** the prompt message indicates a password update + +#### Scenario: Save prompt for new username +- **GIVEN** a site with saved credentials +- **WHEN** the user submits a username that does not exist +- **THEN** the prompt message indicates a new account + +### Requirement: Extension autofill selector +The extension SHALL show a credential selector near login fields for sites with saved accounts. + +#### Scenario: Select credential +- **GIVEN** a site with multiple saved credentials +- **WHEN** the user opens the selector and chooses one +- **THEN** the username and password fields are filled with that credential + +### Requirement: Web password manager (desktop only) +The web app SHALL provide a desktop-only password manager view. + +#### Scenario: Desktop view +- **WHEN** the user visits the password manager page on desktop +- **THEN** the page is visible and provides list/edit/delete + +#### Scenario: Mobile view hidden +- **WHEN** the user visits the password manager page on mobile +- **THEN** the page is hidden or redirects to a notice page + +### Requirement: Plaintext visibility control +The system SHALL allow a user to reveal plaintext passwords for their own credentials during the current browser session. + +#### Scenario: User reveals plaintext +- **GIVEN** a non-admin user +- **WHEN** the user chooses to reveal plaintext +- **THEN** the UI shows plaintext passwords during the current browser session + +#### Scenario: Admin view +- **GIVEN** an admin user +- **WHEN** the admin views credentials +- **THEN** plaintext is visible diff --git a/package-lock.json b/package-lock.json index ac3c2f9..8227caa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ } }, "apps/extension": { - "version": "0.0.0", + "version": "1.0.3", "dependencies": { "@browser-bookmark/shared": "file:../../packages/shared", "vue": "^3.5.24", @@ -31,7 +31,7 @@ }, "apps/server": { "name": "@browser-bookmark/server", - "version": "0.1.0", + "version": "1.0.4", "dependencies": { "@browser-bookmark/shared": "file:../../packages/shared", "@fastify/cors": "^11.2.0", diff --git a/spec/openapi.yaml b/spec/openapi.yaml index e174803..92d40e5 100644 --- a/spec/openapi.yaml +++ b/spec/openapi.yaml @@ -13,6 +13,7 @@ tags: - name: ImportExport - name: Sync - name: Admin + - name: Credentials components: securitySchemes: bearerAuth: @@ -113,6 +114,53 @@ components: - type: 'null' required: [id, userId, folderId, sortOrder, title, url, urlNormalized, urlHash, visibility, source, updatedAt, deletedAt] + Credential: + type: object + properties: + id: + type: string + format: uuid + userId: + type: string + format: uuid + siteOrigin: + type: string + username: + type: string + password: + anyOf: + - type: string + - type: 'null' + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + required: [id, userId, siteOrigin, username, createdAt, updatedAt] + + CredentialCreate: + type: object + properties: + siteOrigin: + type: string + username: + type: string + password: + type: string + required: [siteOrigin, username, password] + + CredentialPatch: + type: object + properties: + siteOrigin: + type: string + username: + type: string + password: + type: string + + FolderPatch: type: object properties: @@ -275,6 +323,105 @@ paths: schema: $ref: '#/components/schemas/User' + /credentials: + get: + tags: [Credentials] + summary: List my credentials + operationId: listCredentials + security: + - bearerAuth: [] + parameters: + - in: query + name: siteOrigin + required: false + schema: + type: string + - in: query + name: includePassword + required: false + schema: + type: boolean + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Credential' + post: + tags: [Credentials] + summary: Create credential + operationId: createCredential + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialCreate' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Credential' + + /credentials/{id}: + patch: + tags: [Credentials] + summary: Update credential + operationId: updateCredential + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialPatch' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Credential' + delete: + tags: [Credentials] + summary: Delete credential + operationId: deleteCredential + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + format: uuid + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + required: [ok] + /folders: get: tags: [Folders] @@ -684,6 +831,99 @@ paths: summary: List a user's folders (admin only) operationId: adminListUserFolders security: + + /admin/users/{id}/credentials: + get: + tags: [Admin] + summary: List a user's credentials + operationId: adminListUserCredentials + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + format: uuid + - in: query + name: includePassword + required: false + schema: + type: boolean + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Credential' + + /admin/users/{userId}/credentials/{credentialId}: + patch: + tags: [Admin] + summary: Update a user's credential + operationId: adminUpdateUserCredential + security: + - bearerAuth: [] + parameters: + - in: path + name: userId + required: true + schema: + type: string + format: uuid + - in: path + name: credentialId + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CredentialPatch' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Credential' + delete: + tags: [Admin] + summary: Delete a user's credential + operationId: adminDeleteUserCredential + security: + - bearerAuth: [] + parameters: + - in: path + name: userId + required: true + schema: + type: string + format: uuid + - in: path + name: credentialId + required: true + schema: + type: string + format: uuid + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + required: [ok] - bearerAuth: [] parameters: - in: path