mirror of
https://github.com/logseq/logseq.git
synced 2026-05-23 12:14:06 +00:00
fix: assets not encrypted
This commit is contained in:
@@ -163,6 +163,34 @@
|
||||
(-> (if (string? file) file (.arrayBuffer file))
|
||||
(p/then db-asset/<get-file-array-buffer-checksum)))
|
||||
|
||||
(defn- ->uint8
|
||||
[payload]
|
||||
(cond
|
||||
(instance? js/Uint8Array payload)
|
||||
payload
|
||||
|
||||
(instance? js/ArrayBuffer payload)
|
||||
(js/Uint8Array. payload)
|
||||
|
||||
(and (exists? js/ArrayBuffer)
|
||||
(.isView js/ArrayBuffer payload))
|
||||
(js/Uint8Array. (.-buffer payload) (.-byteOffset payload) (.-byteLength payload))
|
||||
|
||||
(array? payload)
|
||||
(js/Uint8Array. payload)
|
||||
|
||||
(sequential? payload)
|
||||
(js/Uint8Array. (clj->js payload))
|
||||
|
||||
(and (object? payload)
|
||||
(= "Buffer" (aget payload "type"))
|
||||
(array? (aget payload "data")))
|
||||
(js/Uint8Array. (aget payload "data"))
|
||||
|
||||
:else
|
||||
(throw (ex-info "unsupported binary payload"
|
||||
{:payload-type (str (type payload))}))))
|
||||
|
||||
(defn <get-all-assets
|
||||
[]
|
||||
(when-let [path (config/get-current-repo-assets-root)]
|
||||
@@ -276,6 +304,9 @@
|
||||
(catch :default e
|
||||
(log/info :read-asset e)
|
||||
(throw (ex-info "read-asset failed" {:type :rtc.exception/read-asset-failed} e))))
|
||||
asset-file (if aes-key
|
||||
(->uint8 asset-file)
|
||||
asset-file)
|
||||
asset-file* (if (not aes-key)
|
||||
asset-file
|
||||
(ldb/write-transit-str
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[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]
|
||||
@@ -729,14 +730,24 @@
|
||||
(fn [prev]
|
||||
(p/then prev (fn [_] (task)))))))
|
||||
|
||||
(defn- <exported-graph-aes-key
|
||||
[repo graph-id]
|
||||
(if (sync-crypt/graph-e2ee? repo)
|
||||
(p/let [aes-key (sync-crypt/<ensure-graph-aes-key repo graph-id)
|
||||
_ (when (nil? aes-key)
|
||||
(fail-fast :db-sync/missing-field {:repo repo :field :aes-key}))]
|
||||
(crypt/<export-aes-key aes-key))
|
||||
(p/resolved nil)))
|
||||
|
||||
(defn- upload-remote-asset!
|
||||
[repo graph-id asset-uuid asset-type checksum]
|
||||
(let [base (http-base-url)]
|
||||
(if (and (seq base) (seq graph-id) (seq asset-type) (seq checksum))
|
||||
(worker-state/<invoke-main-thread :thread-api/rtc-upload-asset
|
||||
repo nil (str asset-uuid) asset-type checksum
|
||||
(asset-url base graph-id (str asset-uuid) asset-type)
|
||||
{:extra-headers (auth-headers)})
|
||||
(p/let [exported-aes-key (<exported-graph-aes-key repo graph-id)]
|
||||
(worker-state/<invoke-main-thread :thread-api/rtc-upload-asset
|
||||
repo exported-aes-key (str asset-uuid) asset-type checksum
|
||||
(asset-url base graph-id (str asset-uuid) asset-type)
|
||||
{:extra-headers (auth-headers)}))
|
||||
(p/rejected (ex-info "missing asset upload info"
|
||||
{:repo repo
|
||||
:asset-uuid asset-uuid
|
||||
@@ -749,10 +760,11 @@
|
||||
[repo graph-id asset-uuid asset-type]
|
||||
(let [base (http-base-url)]
|
||||
(if (and (seq base) (seq graph-id) (seq asset-type))
|
||||
(worker-state/<invoke-main-thread :thread-api/rtc-download-asset
|
||||
repo nil (str asset-uuid) asset-type
|
||||
(asset-url base graph-id (str asset-uuid) asset-type)
|
||||
{:extra-headers (auth-headers)})
|
||||
(p/let [exported-aes-key (<exported-graph-aes-key repo graph-id)]
|
||||
(worker-state/<invoke-main-thread :thread-api/rtc-download-asset
|
||||
repo exported-aes-key (str asset-uuid) asset-type
|
||||
(asset-url base graph-id (str asset-uuid) asset-type)
|
||||
{:extra-headers (auth-headers)}))
|
||||
(p/rejected (ex-info "missing asset download info"
|
||||
{:repo repo
|
||||
:asset-uuid asset-uuid
|
||||
|
||||
28
src/test/frontend/handler/assets_test.cljs
Normal file
28
src/test/frontend/handler/assets_test.cljs
Normal file
@@ -0,0 +1,28 @@
|
||||
(ns frontend.handler.assets-test
|
||||
(:require [cljs.test :refer [deftest is]]
|
||||
[frontend.handler.assets :as assets]))
|
||||
|
||||
(defn- uint8->vec
|
||||
[^js payload]
|
||||
(js->clj (js/Array.from payload)))
|
||||
|
||||
(deftest coerce-array-buffer-to-uint8-test
|
||||
(let [source (js/Uint8Array. #js [1 2 3])
|
||||
output (#'assets/->uint8 (.-buffer source))]
|
||||
(is (instance? js/Uint8Array output))
|
||||
(is (= [1 2 3] (uint8->vec output)))))
|
||||
|
||||
(deftest coerce-array-buffer-view-to-uint8-test
|
||||
(let [source (js/Uint8Array. #js [9 8 7 6])
|
||||
view (js/DataView. (.-buffer source) 1 2)
|
||||
output (#'assets/->uint8 view)]
|
||||
(is (instance? js/Uint8Array output))
|
||||
(is (= [8 7] (uint8->vec output)))))
|
||||
|
||||
(deftest coerce-buffer-like-object-to-uint8-test
|
||||
(let [buffer-like #js {:type "Buffer"
|
||||
:data #js [10 11 12]}
|
||||
output (#'assets/->uint8 buffer-like)]
|
||||
(is (instance? js/Uint8Array output))
|
||||
(is (= [10 11 12] (uint8->vec output)))))
|
||||
|
||||
@@ -541,3 +541,97 @@
|
||||
(is (= [{:asset-uuid "title-1" :asset-type "txt"}] @download-calls))
|
||||
(is (= "rehydrated-title" (:block/title block))))
|
||||
(p/finally done))))))))
|
||||
|
||||
(deftest upload-remote-asset-passes-exported-aes-key-for-e2ee-test
|
||||
(async done
|
||||
(let [calls (atom [])
|
||||
exported-aes-key (js/Uint8Array. #js [1 2 3])]
|
||||
(-> (p/with-redefs [db-sync/http-base-url (fn [] "https://base")
|
||||
sync-crypt/graph-e2ee? (fn [_repo] true)
|
||||
sync-crypt/<ensure-graph-aes-key (fn [_repo _graph-id]
|
||||
(p/resolved :aes-key))
|
||||
crypt/<export-aes-key (fn [_aes-key]
|
||||
(p/resolved exported-aes-key))
|
||||
worker-state/get-id-token (fn [] "id-token")
|
||||
worker-state/<invoke-main-thread (fn [op & args]
|
||||
(swap! calls conj {:op op :args args})
|
||||
(p/resolved nil))]
|
||||
(#'db-sync/upload-remote-asset! test-repo
|
||||
"graph-1"
|
||||
(random-uuid)
|
||||
"png"
|
||||
"checksum"))
|
||||
(p/then (fn [_]
|
||||
(is (= 1 (count @calls)))
|
||||
(let [{:keys [op args]} (first @calls)
|
||||
[_repo exported-key _asset-uuid _asset-type _checksum _url opts] args]
|
||||
(is (= :thread-api/rtc-upload-asset op))
|
||||
(is (= exported-aes-key exported-key))
|
||||
(is (= "Bearer id-token"
|
||||
(get-in opts [:extra-headers "authorization"]))))
|
||||
(done)))
|
||||
(p/catch (fn [error]
|
||||
(is false (str error))
|
||||
(done)))))))
|
||||
|
||||
(deftest download-remote-asset-passes-exported-aes-key-for-e2ee-test
|
||||
(async done
|
||||
(let [calls (atom [])
|
||||
exported-aes-key (js/Uint8Array. #js [7 8 9])]
|
||||
(-> (p/with-redefs [db-sync/http-base-url (fn [] "https://base")
|
||||
sync-crypt/graph-e2ee? (fn [_repo] true)
|
||||
sync-crypt/<ensure-graph-aes-key (fn [_repo _graph-id]
|
||||
(p/resolved :aes-key))
|
||||
crypt/<export-aes-key (fn [_aes-key]
|
||||
(p/resolved exported-aes-key))
|
||||
worker-state/get-id-token (fn [] "id-token")
|
||||
worker-state/<invoke-main-thread (fn [op & args]
|
||||
(swap! calls conj {:op op :args args})
|
||||
(p/resolved nil))]
|
||||
(#'db-sync/download-remote-asset! test-repo
|
||||
"graph-1"
|
||||
(random-uuid)
|
||||
"png"))
|
||||
(p/then (fn [_]
|
||||
(is (= 1 (count @calls)))
|
||||
(let [{:keys [op args]} (first @calls)
|
||||
[_repo exported-key _asset-uuid _asset-type _url opts] args]
|
||||
(is (= :thread-api/rtc-download-asset op))
|
||||
(is (= exported-aes-key exported-key))
|
||||
(is (= "Bearer id-token"
|
||||
(get-in opts [:extra-headers "authorization"]))))
|
||||
(done)))
|
||||
(p/catch (fn [error]
|
||||
(is false (str error))
|
||||
(done)))))))
|
||||
|
||||
(deftest upload-remote-asset-does-not-export-aes-key-when-not-e2ee-test
|
||||
(async done
|
||||
(let [calls (atom [])
|
||||
ensure-calls (atom 0)]
|
||||
(-> (p/with-redefs [db-sync/http-base-url (fn [] "https://base")
|
||||
sync-crypt/graph-e2ee? (fn [_repo] false)
|
||||
sync-crypt/<ensure-graph-aes-key (fn [_repo _graph-id]
|
||||
(swap! ensure-calls inc)
|
||||
(p/resolved :aes-key))
|
||||
crypt/<export-aes-key (fn [_aes-key]
|
||||
(p/rejected (ex-info "unexpected export" {})))
|
||||
worker-state/<invoke-main-thread (fn [op & args]
|
||||
(swap! calls conj {:op op :args args})
|
||||
(p/resolved nil))]
|
||||
(#'db-sync/upload-remote-asset! test-repo
|
||||
"graph-1"
|
||||
(random-uuid)
|
||||
"png"
|
||||
"checksum"))
|
||||
(p/then (fn [_]
|
||||
(is (zero? @ensure-calls))
|
||||
(is (= 1 (count @calls)))
|
||||
(let [{:keys [op args]} (first @calls)
|
||||
[_repo exported-key] args]
|
||||
(is (= :thread-api/rtc-upload-asset op))
|
||||
(is (nil? exported-key)))
|
||||
(done)))
|
||||
(p/catch (fn [error]
|
||||
(is false (str error))
|
||||
(done)))))))
|
||||
|
||||
Reference in New Issue
Block a user