Browse Source

feat(rtc,crypt): store&import device-id&keys

rcmerci 1 year ago
parent
commit
ea80dd2976

+ 2 - 2
src/main/frontend/worker/crypt.cljs

@@ -44,12 +44,12 @@
 
 (defn <import-public-key
   [jwk]
-  (assert (map? jwk) jwk)
+  (assert (instance? js/Object jwk) jwk)
   (js/crypto.subtle.importKey "jwk" jwk key-algorithm true #js["encrypt"]))
 
 (defn <import-private-key
   [jwk]
-  (assert (map? jwk) jwk)
+  (assert (instance? js/Object jwk) jwk)
   (js/crypto.subtle.importKey "jwk" jwk key-algorithm true #js["decrypt"]))
 
 (comment

+ 4 - 2
src/main/frontend/worker/db_worker.cljs

@@ -12,6 +12,7 @@
             [frontend.worker.db-listener :as db-listener]
             [frontend.worker.db-metadata :as worker-db-metadata]
             [frontend.worker.db.migrate :as db-migrate]
+            [frontend.worker.device :as worker-device]
             [frontend.worker.export :as worker-export]
             [frontend.worker.file :as file]
             [frontend.worker.handler.page :as worker-page]
@@ -24,6 +25,7 @@
             [frontend.worker.state :as worker-state] ;; [frontend.worker.undo-redo :as undo-redo]
             [frontend.worker.undo-redo2 :as undo-redo]
             [frontend.worker.util :as worker-util]
+            [goog.object :as gobj]
             [logseq.common.config :as common-config]
             [logseq.common.util :as common-util]
             [logseq.db :as ldb]
@@ -32,7 +34,6 @@
             [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.outliner.op :as outliner-op]
-            [goog.object :as gobj]
             [promesa.core :as p]
             [shadow.cljs.modern :refer [defclass]]
             [logseq.db.frontend.schema :as db-schema]
@@ -429,7 +430,8 @@
   (init
    [_this rtc-ws-url]
    (reset! worker-state/*rtc-ws-url rtc-ws-url)
-   (init-sqlite-module!))
+   (p/do (worker-device/<ensure-device-metadata!)
+         (init-sqlite-module!)))
 
   (storeMetadata
    [_this repo metadata-str]

+ 43 - 13
src/main/frontend/worker/device.cljs

@@ -1,20 +1,50 @@
 (ns frontend.worker.device
   "Each device is assigned an id, and has some metadata(e.g. public&private-key for each device)"
-  (:require [datascript.core :as d]
+  (:require ["/frontend/idbkv" :as idb-keyval]
+            [datascript.core :as d]
             [frontend.worker.crypt :as crypt]
-            [frontend.worker.state :as worker-state]
             [promesa.core :as p]))
 
+;;; TODO: move frontend.idb to deps/, then we can use it in both frontend and db-worker
+;;; now, I just direct use "/frontend/idbkv" here
+(defonce ^:private store (delay (idb-keyval/newStore "localforage" "keyvaluepairs" 2)))
+
+(defn- <get-item
+  [key']
+  (when (and key' @store)
+    (idb-keyval/get key' @store)))
+
+(defn- <set-item!
+  [key' value]
+  (when (and key' @store)
+    (idb-keyval/set key' value @store)))
+
+(def ^:private item-key-device-id "device-id")
+(def ^:private item-key-device-public-key-jwk "device-public-key-jwk")
+(def ^:private item-key-device-private-key-jwk "device-private-key-jwk")
+
+(defonce *device-id (atom nil :validator uuid?))
+(defonce *device-public-key (atom nil :validator #(instance? js/CryptoKey %)))
+(defonce *device-private-key (atom nil :validator #(instance? js/CryptoKey %)))
+
 (defn <ensure-device-metadata!
   "Generate new device entity if not exists"
-  [repo]
-  (let [conn (worker-state/get-client-ops-conn repo)]
-    (assert (some? conn) repo)
-    (assert (empty? (d/datoms @conn :device/uuid)) "device entity already exists")
-    (p/let [device-uuid (d/squuid)
-            {:keys [publicKey privateKey]} (crypt/<gen-key-pair)
-            public-key-jwk (crypt/<export-key publicKey)
-            private-key-jwk (crypt/<export-key privateKey)]
-      (d/transact! conn [{:device/uuid device-uuid
-                          :device/public-key-jwk public-key-jwk
-                          :device/private-key-jwk private-key-jwk}]))))
+  []
+  (p/let [device-uuid (<get-item item-key-device-id)]
+    (when-not device-uuid
+      (p/let [device-uuid (d/squuid)
+              {:keys [publicKey privateKey]} (crypt/<gen-key-pair)
+              public-key-jwk (crypt/<export-key publicKey)
+              private-key-jwk (crypt/<export-key privateKey)]
+        (<set-item! item-key-device-id (str device-uuid))
+        (<set-item! item-key-device-public-key-jwk public-key-jwk)
+        (<set-item! item-key-device-private-key-jwk private-key-jwk)))
+
+    (p/let [device-uuid-str (<get-item item-key-device-id)
+            device-public-key-jwk (<get-item item-key-device-public-key-jwk)
+            device-public-key (crypt/<import-public-key device-public-key-jwk)
+            device-private-key-jwk (<get-item item-key-device-private-key-jwk)
+            device-private-key (crypt/<import-private-key device-private-key-jwk)]
+      (reset! *device-id (uuid device-uuid-str))
+      (reset! *device-public-key device-public-key)
+      (reset! *device-private-key device-private-key))))