fix: large title decrypt

This commit is contained in:
Tienson Qin
2026-01-30 20:23:54 +08:00
parent 7f72a6d02c
commit 2b97e34539
2 changed files with 46 additions and 35 deletions

View File

@@ -5,7 +5,6 @@
[clojure.string :as string]
[datascript.core :as d]
[datascript.storage :refer [IStorage]]
[frontend.common.crypt :as crypt]
[frontend.worker-common.util :as worker-util]
[frontend.worker.handler.page :as worker-page]
[frontend.worker.shared-service :as shared-service]
@@ -185,8 +184,8 @@
(defn- assoc-datom-value
[datom new-value]
(let [[op e a _v & rest] datom]
(into [op e a new-value] rest)))
(let [[op e a _v & others] datom]
(into [op e a new-value] others)))
(defn- large-title-object
[asset-uuid asset-type]
@@ -571,8 +570,7 @@
asset-type large-title-asset-type
url (asset-url base graph-id asset-uuid asset-type)]
(p/let [payload (if aes-key
(p/let [payload-str (sync-crypt/<encrypt-text-value aes-key
(ldb/write-transit-str title))]
(p/let [payload-str (sync-crypt/<encrypt-text-value aes-key title)]
(.encode text-encoder payload-str))
(p/resolved title))
headers (merge {"content-type" "text/plain; charset=utf-8"
@@ -602,11 +600,12 @@
{:repo repo :status (.-status resp)}))
(p/let [buf (.arrayBuffer resp)
payload (js/Uint8Array. buf)
payload-str (.decode text-decoder payload)
data (if aes-key
(p/let [payload-str (.decode text-decoder payload)]
(sync-crypt/<decrypt-text-value aes-key payload-str))
(p/resolved payload))]
(.decode text-decoder data))))))
(-> (sync-crypt/<decrypt-text-value aes-key payload-str)
(p/catch (fn [_] payload-str)))
(p/resolved payload-str))]
data)))))
(defn- offload-large-titles
[tx-data {:keys [repo graph-id upload-fn aes-key]}]
@@ -632,18 +631,28 @@
(p/recur (rest remaining) (conj acc item))))))))
(defn- rehydrate-large-titles!
[repo {:keys [graph-id download-fn aes-key]}]
[repo {:keys [graph-id download-fn aes-key tx-data]}]
(when-let [conn (worker-state/get-datascript-conn repo)]
(let [download-fn (or download-fn download-large-title!)
graph-id (or graph-id (get-graph-id repo))
items (->> (d/datoms @conn :eavt)
(keep (fn [datom]
(when (= large-title-object-attr (:a datom))
(let [obj (:v datom)]
(when (large-title-object? obj)
{:e (:e datom)
:obj obj})))))
(distinct))]
items (if (seq tx-data)
(->> tx-data
(keep (fn [item]
(when (and (vector? item)
(= :db/add (nth item 0))
(= large-title-object-attr (nth item 2))
(large-title-object? (nth item 3)))
{:e (nth item 1)
:obj (nth item 3)})))
(distinct))
(->> (d/datoms @conn :eavt)
(keep (fn [datom]
(when (= large-title-object-attr (:a datom))
(let [obj (:v datom)]
(when (large-title-object? obj)
{:e (:e datom)
:obj obj})))))
(distinct)))]
(when (seq items)
(p/let [aes-key (or aes-key
(when (sync-crypt/graph-e2ee? repo)

View File

@@ -5,7 +5,7 @@
[frontend.worker.state :as worker-state]
[frontend.worker.sync :as db-sync]
[frontend.worker.sync.client-op :as client-op]
[logseq.db :as ldb]
[frontend.worker.sync.crypt :as sync-crypt]
[logseq.db.test.helper :as db-test]
[logseq.outliner.core :as outliner-core]
[promesa.core :as p]))
@@ -22,11 +22,15 @@
(d/listen! db-conn ::listen-db
(fn [tx-report]
(db-sync/enqueue-local-tx! test-repo tx-report))))
(try
(f)
(finally
(reset! worker-state/*datascript-conns db-prev)
(reset! worker-state/*client-ops-conns ops-prev)))))
(let [result (f)
cleanup (fn []
(reset! worker-state/*datascript-conns db-prev)
(reset! worker-state/*client-ops-conns ops-prev))]
(if (p/promise? result)
(p/finally result cleanup)
(do
(cleanup)
result)))))
(defn- setup-parent-child
[]
@@ -358,10 +362,8 @@
_ (#'db-sync/upload-large-title! test-repo "graph-1" title aes-key)
body @captured-body]
(is (instance? js/Uint8Array body))
(let [decoded (.decode (js/TextDecoder.) body)
encrypted (ldb/read-transit-str decoded)]
(p/let [decrypted (crypt/<decrypt-uint8array aes-key encrypted)
title' (.decode (js/TextDecoder.) decrypted)]
(let [payload-str (.decode (js/TextDecoder.) body)]
(p/let [title' (sync-crypt/<decrypt-text-value aes-key payload-str)]
(is (= title title')))))
(p/finally
(fn []
@@ -377,8 +379,7 @@
config-prev @worker-state/*db-sync-config]
(reset! worker-state/*db-sync-config {:http-base "https://example.com"})
(-> (p/let [aes-key (crypt/<generate-aes-key)
encrypted (crypt/<encrypt-uint8array aes-key (.encode (js/TextEncoder.) title))
payload-str (ldb/write-transit-str encrypted)
payload-str (sync-crypt/<encrypt-text-value aes-key title)
payload-bytes (.encode (js/TextEncoder.) payload-str)]
(set! js/fetch
(fn [_url _opts]
@@ -402,11 +403,12 @@
(deftest rehydrate-large-title-test
(testing "rehydrate fills empty title from object storage"
(async done
(let [conn (db-test/create-conn)
block-uuid (random-uuid)
_ (d/transact! conn [{:db/id (d/tempid :db.part/user)
:block/uuid block-uuid}])
block-id (d/entid @conn [:block/uuid block-uuid])
(let [conn (db-test/create-conn-with-blocks
{:pages-and-blocks
[{:page {:block/title "rehydrate-page"}
:blocks [{:block/title "rehydrate-block"}]}]})
block (db-test/find-block-by-content @conn "rehydrate-block")
block-id (:db/id block)
tx-data [[:db/add block-id :block/title ""]
[:db/add block-id :logseq.property.sync/large-title-object
{:asset-uuid "title-1" :asset-type "txt"}]]