Browse Source

feat(encryption): add ui to enter the secret phrase

Tienson Qin 5 years ago
parent
commit
289b31d5f5

+ 38 - 1
src/main/frontend/components/encryption.cljs

@@ -63,7 +63,7 @@
        [:button.inline-flex.justify-center.w-full.rounded-md.border.border-transparent.px-4.py-2.bg-indigo-600.text-base.leading-6.font-medium.text-white.shadow-sm.hover:bg-indigo-500.focus:outline-none.focus:border-indigo-700.focus:shadow-outline-indigo.transition.ease-in-out.duration-150.sm:text-sm.sm:leading-5
         {:type "button"
          :on-click (fn []
-                     (e/generate-mnemonic-and-save repo-url)
+                     (e/generate-mnemonic-and-save! repo-url)
                      (close-fn true))}
         (t :yes)]]
       [:span.mt-3.flex.w-full.rounded-md.shadow-sm.sm:mt-0.sm:w-auto
@@ -79,3 +79,40 @@
                      (close-fn encrypted?)
                      (close-modal-fn))]
       (encryption-setup-dialog-inner repo-url close-fn))))
+
+(rum/defcs encryption-input-secret-inner <
+  (rum/local "" ::secret)
+  [state repo-url close-fn]
+  (rum/with-context [[t] i18n/*tongue-context*]
+    (let [secret (get state ::secret)]
+      [:div
+      [:div.sm:flex.sm:items-start
+       [:div.mt-3.text-center.sm:mt-0.sm:text-left
+        [:h3#modal-headline.text-lg.leading-6.font-medium.text-gray-900
+         "Enter your secret phrase"]]]
+
+      [:input.form-input.block.w-full.sm:text-sm.sm:leading-5.my-2
+       {:auto-focus true
+        :style {:color "#000"}
+        :on-change (fn [e]
+                     (reset! secret (util/evalue e)))}]
+
+      [:div.mt-5.sm:mt-4.sm:flex.sm:flex-row-reverse
+       [:span.flex.w-full.rounded-md.shadow-sm.sm:ml-3.sm:w-auto
+        [:button.inline-flex.justify-center.w-full.rounded-md.border.border-transparent.px-4.py-2.bg-indigo-600.text-base.leading-6.font-medium.text-white.shadow-sm.hover:bg-indigo-500.focus:outline-none.focus:border-indigo-700.focus:shadow-outline-indigo.transition.ease-in-out.duration-150.sm:text-sm.sm:leading-5
+         {:type "button"
+          :on-click (fn []
+                      (let [value @secret]
+                        (when-not (string/blank? value) ; TODO: length or other checks
+                          (let [repo (state/get-current-repo)]
+                            (e/save-mnemonic! repo value)
+                            (close-fn true)))))}
+         "Submit"]]]])))
+
+(defn encryption-input-secret-dialog
+  [repo-url close-fn]
+  (fn [close-modal-fn]
+    (let [close-fn (fn [encrypted?]
+                     (close-fn encrypted?)
+                     (close-modal-fn))]
+      (encryption-input-secret-inner repo-url close-fn))))

+ 7 - 0
src/main/frontend/config.cljs

@@ -346,6 +346,13 @@
    (when repo
      (get-file-path repo (str app-name "/" config-file)))))
 
+(defn get-metadata-path
+  ([]
+   (get-metadata-path (state/get-current-repo)))
+  ([repo]
+   (when repo
+     (get-file-path repo (str app-name "/" metadata-file)))))
+
 (defn get-custom-css-path
   ([]
    (get-custom-css-path (state/get-current-repo)))

+ 11 - 9
src/main/frontend/encrypt.cljs

@@ -6,7 +6,8 @@
             [clojure.string :as str]
             ["bip39" :as bip39]
             ["buffer" :as buffer]
-            ["@kanru/rage-wasm" :as rage]))
+            ["@kanru/rage-wasm" :as rage]
+            [lambdaisland.glogi :as log]))
 
 (defonce age-pem-header-line "-----BEGIN AGE ENCRYPTED FILE-----")
 (defonce age-version-line "age-encryption.org/v1")
@@ -24,7 +25,7 @@
   [repo-url]
   (db-utils/get-key-value repo-url :db/secret-phrase))
 
-(defn- save-mnemonic
+(defn save-mnemonic!
   [repo-url mnemonic]
   (db/set-key-value repo-url :db/secret-phrase mnemonic)
   (db/set-key-value repo-url :db/encrypted? true))
@@ -33,11 +34,11 @@
   []
   (bip39/generateMnemonic 256))
 
-(defn generate-mnemonic-and-save
+(defn generate-mnemonic-and-save!
   [repo-url]
   (when-not (get-mnemonic repo-url)
     (let [mnemonic (generate-mnemonic)]
-      (save-mnemonic repo-url mnemonic))))
+      (save-mnemonic! repo-url mnemonic))))
 
 (defn- derive-key-from-mnemonic
   [mnemonic]
@@ -74,9 +75,10 @@
    (cond
      (and (encrypted-db? repo-url)
           (content-encrypted? content))
-     (let [content (utf8/encode content)
-           secret-key (get-secret-key repo-url)
-           decrypted (rage/decrypt_with_x25519 secret-key content)]
-       (utf8/decode decrypted))
+     (let [content (utf8/encode content)]
+       (if-let [secret-key (get-secret-key repo-url)]
+         (let [decrypted (rage/decrypt_with_x25519 secret-key content)]
+           (utf8/decode decrypted))
+         (log/error :encrypt/empty-secret-key (str "Can't find the secret key for repo: " repo-url))))
      :else
-     content)))
+     content)))

+ 9 - 0
src/main/frontend/handler/common.cljs

@@ -95,6 +95,15 @@
       (state/set-config! repo-url config)
       config)))
 
+(defn read-metadata!
+  [repo-url content]
+  (try
+   (reader/read-string content)
+   (catch js/Error e
+     (println "Parsing metadata file failed: ")
+     (js/console.dir e)
+     {})))
+
 (defn request-app-tokens!
   [ok-handler error-handler]
   (let [repos (state/get-repos)

+ 30 - 10
src/main/frontend/handler/repo.cljs

@@ -25,6 +25,7 @@
             [clojure.string :as string]
             [frontend.dicts :as dicts]
             [frontend.spec :as spec]
+            [frontend.encrypt :as encrypt]
             [goog.dom :as gdom]
             [goog.object :as gobj]
             [frontend.components.encryption :as encryption]))
@@ -193,12 +194,11 @@
                      (util/remove-nils))]
     (db/transact! repo-url all-data)))
 
-(defn parse-files-and-load-to-db!
-  [repo-url files {:keys [first-clone? delete-files delete-blocks re-render? re-render-opts] :as opts
-                   :or {re-render? true}}]
-  (state/set-loading-files! false)
-  (state/set-importing-to-db! true)
-  (let [file-paths (map :file/path files)
+(defn- parse-files-and-create-default-files!
+  [repo-url files delete-files delete-blocks file-paths first-clone? db-encrypted? re-render? re-render-opts encrypted?]
+  (let [files (if encrypted? (map (fn [file]
+                                    (update file :file/content encrypt/decrypt))
+                               files) files)
         parsed-files (filter
                       (fn [file]
                         (let [format (format/get-format (:file/path file))]
@@ -207,20 +207,40 @@
         blocks-pages (if (seq parsed-files)
                        (extract-handler/extract-all-blocks-pages repo-url parsed-files)
                        [])]
-    (reset-contents-and-blocks! repo-url files blocks-pages delete-files delete-blocks)
+    (reset-contents-and-blocks! repo-url files blocks-pages delete-files delete-blocks))
     (let [config-file (config/get-config-path)]
       (if (contains? (set file-paths) config-file)
         (when-let [content (some #(when (= (:file/path %) config-file)
                                     (:file/content %)) files)]
           (file-handler/restore-config! repo-url content true))))
-    (when first-clone?
+    (if (and first-clone? (not db-encrypted?))
       (state/set-modal!
        (encryption/encryption-setup-dialog
         repo-url
-        #(create-default-files! repo-url %))))
+        #(create-default-files! repo-url %)))
+      (create-default-files! repo-url db-encrypted?))
     (when re-render?
       (ui-handler/re-render-root! re-render-opts))
-    (state/set-importing-to-db! false)))
+  (state/set-importing-to-db! false))
+
+(defn parse-files-and-load-to-db!
+  [repo-url files {:keys [first-clone? delete-files delete-blocks re-render? re-render-opts] :as opts
+                   :or {re-render? true}}]
+  (state/set-loading-files! false)
+  (state/set-importing-to-db! true)
+  (let [file-paths (map :file/path files)]
+    (let [metadata-file (config/get-metadata-path)
+          metadata-content (some #(when (= (:file/path %) metadata-file)
+                                    (:file/content %)) files)
+          metadata (when metadata-content
+                     (common-handler/read-metadata! repo-url metadata-content))
+          db-encrypted? (:db/encrypted? metadata)]
+      (if db-encrypted?
+        (state/set-modal!
+         (encryption/encryption-input-secret-dialog
+          repo-url
+          #(parse-files-and-create-default-files! repo-url files delete-files delete-blocks file-paths first-clone? db-encrypted? re-render? re-render-opts true)))
+        (parse-files-and-create-default-files! repo-url files delete-files delete-blocks file-paths first-clone? db-encrypted? re-render? re-render-opts false)))))
 
 (defn load-repo-to-db!
   [repo-url {:keys [first-clone? diffs nfs-files]