Browse Source

feat(rtc,e2ee): add 'forgot-password' setting

force-reset e2ee password and user's rsa-key-pair
all encrypted graphs in server will be undecipherable
rcmerci 3 weeks ago
parent
commit
2b84d729d0

+ 45 - 1
src/main/frontend/components/settings.cljs

@@ -1199,6 +1199,42 @@
   [:div.panel-wrap.is-collaboration.mb-8
    (settings-rtc-members)])
 
+(rum/defc forgot-password
+  [token refresh-token user-uuid]
+  (let [[new-password set-new-password!] (hooks/use-state "")
+        [forgot? set-forgot?] (hooks/use-state false)
+        [force-reset-status set-force-reset-status!] (hooks/use-state nil)
+        <force-reset-password-fn
+        (fn []
+          (-> (p/do!
+               (set-force-reset-status! "Force resetting password ...")
+               (state/<invoke-db-worker :thread-api/reset-user-rsa-key-pair
+                                        token refresh-token user-uuid new-password)
+               (set-force-reset-status! "Force reset password successfully!"))
+              (p/catch (fn [e]
+                         (log/error :forgot-password e)
+                         (set-force-reset-status! "Failed to force reset password.")))))]
+    (if forgot?
+      [:div.flex.flex-col.gap-4
+       [:label.opacity-70 {:for "new-password"} "Set new Password"]
+       (shui/toggle-password
+        {:id "new-password"
+         :value new-password
+         :on-change #(set-new-password! (util/evalue %))})
+       (when force-reset-status [:p force-reset-status])
+       (shui/button
+        {:on-click <force-reset-password-fn
+         :disabled (string/blank? new-password)}
+        "Force Reset Password")]
+      [:div.flex.flex-col
+       [:p
+        "If you forget your password, you can force a reset of the E2EE password.
+The cost is that all currently encrypted graph data stored on the server will become undecipherable,
+and you will need to re-upload the graphs from the client after resetting the password."]
+       (shui/button
+        {:on-click #(set-forgot? true)}
+        "Forgot Password?")])))
+
 (rum/defc reset-encryption-password
   [current-password new-password {:keys [set-new-password!
                                          reset-password-status
@@ -1297,7 +1333,15 @@
              (reset-encryption-password current-password new-password
                                         {:reset-password-status reset-password-status
                                          :set-new-password! set-new-password!
-                                         :on-click on-submit})])))])])
+                                         :on-click on-submit})
+
+             [:br]
+             (forgot-password token refresh-token user-uuid)
+
+             ]
+
+
+            )))])])
 
 (rum/defc mcp-server-row
   [t]

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

@@ -95,8 +95,22 @@
                                             :encrypted-private-key encrypted-private-key-str
                                             :reset-private-key reset-private-key}))]
       (when (:ex-data response)
-        (throw (ex-info (:ex-message response)
-                        (assoc (:ex-data response) :type :rtc.exception/upload-user-rsa-key-pair-error)))))))
+        (throw (ex-info (:ex-message response) (:ex-data response)))))))
+
+(defn task--reset-user-rsa-key-pair
+  "Reset rsa-key-pair in server."
+  [get-ws-create-task user-uuid public-key encrypted-private-key]
+  (assert (and public-key encrypted-private-key))
+  (m/sp
+    (let [exported-public-key-str (ldb/write-transit-str (c.m/<? (crypt/<export-public-key public-key)))
+          encrypted-private-key-str (ldb/write-transit-str encrypted-private-key)
+          resp (m/? (ws-util/send&recv get-ws-create-task
+                                       {:action "reset-user-rsa-key-pair"
+                                        :user-uuid user-uuid
+                                        :public-key exported-public-key-str
+                                        :encrypted-private-key encrypted-private-key-str}))]
+      (when (:ex-data resp)
+        (throw (ex-info (:ex-message resp) (:ex-data resp)))))))
 
 (defn task--fetch-user-rsa-key-pair
   "Fetches the user's RSA key pair from server.
@@ -232,6 +246,20 @@
       (catch Cancelled _)
       (catch :default e e))))
 
+(def-thread-api :thread-api/reset-user-rsa-key-pair
+  [token refresh-token user-uuid new-password]
+  (m/sp
+    (try
+      (let [{:keys [get-ws-create-task]} (ws-util/gen-get-ws-create-map--memoized (ws-util/get-ws-url token))]
+        (when (some? (m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid)))
+          (let [{:keys [publicKey privateKey]} (c.m/<? (crypt/<generate-rsa-key-pair))
+                encrypted-private-key (c.m/<? (crypt/<encrypt-private-key new-password privateKey))]
+            (m/? (task--reset-user-rsa-key-pair get-ws-create-task user-uuid publicKey encrypted-private-key))
+            (c.m/<? (<save-e2ee-password refresh-token new-password))
+            nil)))
+      (catch Cancelled _)
+      (catch :default e e))))
+
 (def-thread-api :thread-api/reset-e2ee-password
   [token refresh-token user-uuid new-password]
   (m/sp

+ 0 - 1
src/main/frontend/worker/rtc/exception.cljs

@@ -30,7 +30,6 @@ the server will put it to s3 and return its presigned-url to clients."}
   :rtc.exception/fetch-user-rsa-key-pair-error {:doc "Failed to fetch user RSA key pair from server"}
   :rtc.exception/fetch-user-rsa-public-key-error {:doc "Failed to fetch user RSA public-key from server"}
   :rtc.exception/fetch-graph-aes-key-error {:doc "Failed to fetch graph AES key from server"}
-  :rtc.exception/upload-user-rsa-key-pair-error {:doc "Failed to upload user RSA key pair to server"}
   :rtc.exception/not-found-user-rsa-key-pair {:doc "user rsa-key-pair not found"}
   :rtc.exception/not-found-graph-aes-key {:doc "graph aes-key not found"})
 

+ 11 - 2
src/main/frontend/worker/rtc/malli_schema.cljs

@@ -253,12 +253,16 @@
       [:map
        [:encrypted-aes-key [:maybe :string]]]]
      ["fetch-user-rsa-public-key"
-       [:map
-        [:public-key [:maybe :string]]]]
+      [:map
+       [:public-key [:maybe :string]]]]
      ["upload-user-rsa-key-pair"
       [:map
        [:public-key :string]
        [:encrypted-private-key :string]]]
+     ["reset-user-rsa-key-pair"
+      [:map
+       [:public-key :string]
+       [:encrypted-private-key :string]]]
 
      [nil data-from-ws-schema-fallback]]))
 
@@ -377,6 +381,11 @@
         [:public-key {:optional true} :string]
         [:encrypted-private-key :string]
         [:reset-private-key {:optional true} :boolean]]]
+      ["reset-user-rsa-key-pair"
+       [:map
+        [:user-uuid :uuid]
+        [:public-key :string]
+        [:encrypted-private-key :string]]]
       ["fetch-user-rsa-key-pair"
        [:map
         [:user-uuid :uuid]]]