Просмотр исходного кода

fix: db row keys encrypt/decrypt

Tienson Qin 1 месяц назад
Родитель
Сommit
0f3ec8c4eb

+ 19 - 6
src/main/frontend/handler/db_based/db_sync.cljs

@@ -106,6 +106,18 @@
     (assoc opts :headers (merge (or (:headers opts) {}) auth))
     opts))
 
+(declare fetch-json)
+
+(defn- fetch-graph-e2ee?
+  [base graph-uuid]
+  (if-not (and (string? base) (string? graph-uuid))
+    false
+    (p/let [resp (fetch-json (str base "/e2ee/graphs/" graph-uuid "/aes-key")
+                             {:method "GET"}
+                             {:response-schema :e2ee/graph-aes-key})
+            encrypted-aes-key (:encrypted-aes-key resp)]
+      (boolean (string? encrypted-aes-key)))))
+
 (declare coerce-http-response)
 
 (defn- fetch-json
@@ -214,7 +226,8 @@
         (if graph-id
           (p/do!
            (ldb/transact! repo [(sqlite-util/kv :logseq.kv/db-type "db")
-                                (sqlite-util/kv :logseq.kv/graph-uuid (uuid graph-id))])
+                                (sqlite-util/kv :logseq.kv/graph-uuid (uuid graph-id))
+                                (sqlite-util/kv :logseq.kv/graph-rtc-e2ee? true)])
            graph-id)
           (p/rejected (ex-info "db-sync missing graph id in create response"
                                {:type :db-sync/invalid-graph
@@ -261,6 +274,7 @@
                             (throw (ex-info "missing snapshot download url"
                                             {:graph graph-name
                                              :response download-resp})))
+                        e2ee? (fetch-graph-e2ee? base (str graph-uuid))
                         resp (js/fetch download-url (clj->js (with-auth-headers {:method "GET"})))]
                   (when-not (.-ok resp)
                     (throw (ex-info "snapshot download failed"
@@ -279,11 +293,10 @@
                                 total' (+ total (count rows))
                                 total-rows' (into total-rows rows)]
                             (when (seq total-rows')
-                              (let [e2ee? (snapshot-rows-e2ee? total-rows')]
-                                (p/do!
-                                 (state/<invoke-db-worker :thread-api/db-sync-import-kvs-rows
-                                                          graph total-rows' true graph-uuid e2ee?)
-                                 (state/<invoke-db-worker :thread-api/db-sync-finalize-kvs-import graph remote-tx))))
+                              (p/do!
+                               (state/<invoke-db-worker :thread-api/db-sync-import-kvs-rows
+                                                        graph total-rows' true graph-uuid e2ee?)
+                               (state/<invoke-db-worker :thread-api/db-sync-finalize-kvs-import graph remote-tx)))
                             total')
                           (let [value (.-value chunk)
                                 {:keys [rows buffer]} (parse-framed-chunk buffer value)

+ 0 - 2
src/main/frontend/handler/db_based/sync.cljs

@@ -1,11 +1,9 @@
 (ns frontend.handler.db-based.sync
   "Dispatch RTC calls between legacy RTC and db-sync implementations."
   (:require [frontend.config :as config]
-            [frontend.db :as db]
             [frontend.handler.db-based.db-sync :as db-sync-handler]
             [frontend.handler.db-based.rtc :as rtc-handler]
             [frontend.state :as state]
-            [logseq.db :as ldb]
             [promesa.core :as p]))
 
 (defn- db-sync-enabled? []

+ 22 - 3
src/main/frontend/worker/db_sync.cljs

@@ -492,7 +492,7 @@
 
 (defn <decrypt-kvs-rows
   [repo graph-id rows e2ee?]
-  (if-not (true? e2ee?)
+  (if-not e2ee?
     (p/resolved rows)
     (p/let [aes-key (<fetch-graph-aes-key-for-download repo graph-id)
             _ (when (nil? aes-key)
@@ -552,6 +552,22 @@
             (ldb/read-transit-str decrypted)
             value))))))
 
+(defn- <encrypt-keys-attrs
+  [aes-key keys]
+  (p/all (mapv (fn [[e a v t]]
+                 (if (contains? rtc-const/encrypt-attr-set a)
+                   (p/let [v' (<encrypt-text-value aes-key v)]
+                     [e a v' t])
+                   [e a v t])) keys)))
+
+(defn- <decrypt-keys-attrs
+  [aes-key keys]
+  (p/all (mapv (fn [[e a v t]]
+                 (if (contains? rtc-const/encrypt-attr-set a)
+                   (p/let [v' (<decrypt-text-value aes-key v)]
+                     [e a v' t])
+                   [e a v t])) keys)))
+
 (defn- encrypt-tx-item
   [aes-key item]
   (cond
@@ -622,7 +638,8 @@
                    (mapv (fn [[addr content addresses]]
                            (let [data (try-read-transit content)]
                              (if (and (not= data invalid-transit) (map? data))
-                               (p/let [data' (crypt/<encrypt-map aes-key rtc-const/encrypt-attr-set data)
+                               (p/let [keys' (<encrypt-keys-attrs aes-key (:keys data))
+                                       data' (assoc data :keys keys')
                                        content' (ldb/write-transit-str data')]
                                  [addr content' addresses])
                                (p/resolved [addr content addresses]))))
@@ -637,12 +654,14 @@
                    (mapv (fn [[addr content addresses]]
                            (let [data (try-read-transit content)]
                              (if (and (not= data invalid-transit) (map? data))
-                               (p/let [data' (crypt/<decrypt-map aes-key rtc-const/encrypt-attr-set data)
+                               (p/let [keys (<decrypt-keys-attrs aes-key (:keys data))
+                                       data' (assoc data :keys keys)
                                        content' (ldb/write-transit-str data')]
                                  [addr content' addresses])
                                (p/resolved [addr content addresses]))))
                          rows))]
       (vec items))))
+
 (defn- require-asset-field
   [repo field value context]
   (when (or (nil? value) (and (string? value) (string/blank? value)))

+ 1 - 3
src/main/frontend/worker/db_worker.cljs

@@ -618,9 +618,7 @@
   [repo rows reset? graph-id e2ee?]
   (p/let [_ (when reset?
               (close-db! repo))
-          rows* (if (true? e2ee?)
-                  (db-sync/<decrypt-kvs-rows repo graph-id rows e2ee?)
-                  (p/resolved rows))
+          rows* (db-sync/<decrypt-kvs-rows repo graph-id rows e2ee?)
           db (ensure-db-sync-import-db! repo reset?)]
     (when (seq rows*)
       (upsert-addr-content! db (rows->sqlite-binds rows*)))

+ 26 - 0
src/test/frontend/handler/db_based/db_sync_test.cljs

@@ -0,0 +1,26 @@
+(ns frontend.handler.db-based.db-sync-test
+  (:require [cljs.test :refer [deftest is async]]
+            [frontend.handler.db-based.db-sync :as db-sync]
+            [promesa.core :as p]))
+
+(deftest download-graph-e2ee-detection-test
+  (async done
+         (with-redefs [db-sync/fetch-json (fn [_ _ _]
+                                            (p/resolved {:encrypted-aes-key "k"}))]
+           (-> (p/let [enabled? (#'db-sync/fetch-graph-e2ee? "http://base" "graph-1")]
+                 (is (true? enabled?))
+                 (done))
+               (p/catch (fn [e]
+                          (is false (str e))
+                          (done)))))))
+
+(deftest download-graph-e2ee-missing-key-test
+  (async done
+         (with-redefs [db-sync/fetch-json (fn [_ _ _]
+                                            (p/resolved {}))]
+           (-> (p/let [enabled? (#'db-sync/fetch-graph-e2ee? "http://base" "graph-1")]
+                 (is (false? enabled?))
+                 (done))
+               (p/catch (fn [e]
+                          (is false (str e))
+                          (done)))))))