diff --git a/backend/src/app/binfile/cleaner.clj b/backend/src/app/binfile/cleaner.clj new file mode 100644 index 000000000..1f4d29ea1 --- /dev/null +++ b/backend/src/app/binfile/cleaner.clj @@ -0,0 +1,44 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.binfile.cleaner + "A collection of helpers for perform cleaning of artifacts; mainly + for recently imported shapes." + (:require + [app.common.data :as d] + [app.common.uuid :as uuid])) + +(defn- fix-shape-shadow-color + "Some shapes can come with invalid `id` property on shadow colors + caused by incorrect uuid parsing bug that should be already fixed; + this function removes the invalid id from the data structure." + [shape] + (let [fix-color + (fn [{:keys [id] :as color}] + (if (uuid? id) + color + (if (and (string? id) + (re-matches uuid/regex id)) + (assoc color :id (uuid/uuid id)) + (dissoc color :id)))) + + fix-shadow + (fn [shadow] + (d/update-when shadow :color fix-color)) + + xform + (map fix-shadow)] + + (d/update-when shape :shadow + (fn [shadows] + (into [] xform shadows))))) + +(defn clean-shape-post-decode + "A shape procesor that expected to be executed after schema decoding + process but before validation." + [shape] + (-> shape + (fix-shape-shadow-color))) diff --git a/backend/src/app/binfile/v3.clj b/backend/src/app/binfile/v3.clj index dc6bf7b80..07e953d68 100644 --- a/backend/src/app/binfile/v3.clj +++ b/backend/src/app/binfile/v3.clj @@ -8,6 +8,7 @@ "A ZIP based binary file exportation" (:refer-clojure :exclude [read]) (:require + [app.binfile.cleaner :as bfl] [app.binfile.common :as bfc] [app.binfile.migrations :as bfm] [app.common.data :as d] @@ -594,16 +595,25 @@ (defn- read-file-components [{:keys [::bfc/input ::file-id ::entries]}] - (->> (keep (match-component-entry-fn file-id) entries) - (reduce (fn [result {:keys [id entry]}] - (let [object (->> (read-entry input entry) - (decode-component) - (validate-component))] - (if (= id (:id object)) - (assoc result id object) - result))) - {}) - (not-empty))) + (let [clean-component-post-decode + (fn [component] + (d/update-when component :objects + (fn [objects] + (reduce-kv (fn [objects id shape] + (assoc objects id (bfl/clean-shape-post-decode shape))) + objects + objects))))] + (->> (keep (match-component-entry-fn file-id) entries) + (reduce (fn [result {:keys [id entry]}] + (let [object (->> (read-entry input entry) + (decode-component) + (clean-component-post-decode) + (validate-component))] + (if (= id (:id object)) + (assoc result id object) + result))) + {}) + (not-empty)))) (defn- read-file-typographies [{:keys [::bfc/input ::file-id ::entries]}] @@ -631,7 +641,9 @@ (reduce (fn [result {:keys [id entry]}] (let [object (->> (read-entry input entry) (decode-shape) + (bfl/clean-shape-post-decode) (validate-shape))] + (if (= id (:id object)) (assoc result id object) result))) diff --git a/backend/src/app/rpc/commands/files.clj b/backend/src/app/rpc/commands/files.clj index 39b3d6c02..58a37810c 100644 --- a/backend/src/app/rpc/commands/files.clj +++ b/backend/src/app/rpc/commands/files.clj @@ -238,6 +238,7 @@ (db/update! conn :file {:data (blob/encode (:data file)) :version (:version file) + :modified-at (dt/now) :features (db/create-array conn "text" (:features file))} {:id id}) diff --git a/backend/src/app/rpc/commands/files_thumbnails.clj b/backend/src/app/rpc/commands/files_thumbnails.clj index f4c5e3d14..2455807dd 100644 --- a/backend/src/app/rpc/commands/files_thumbnails.clj +++ b/backend/src/app/rpc/commands/files_thumbnails.clj @@ -180,8 +180,7 @@ (def ^:private schema:get-file-data-for-thumbnail [:map {:title "get-file-data-for-thumbnail"} - [:file-id ::sm/uuid] - [:features {:optional true} ::cfeat/features]]) + [:file-id ::sm/uuid]]) (def ^:private schema:partial-file @@ -211,7 +210,6 @@ (fmg/migrate-file)))] (-> (cfeat/get-team-enabled-features cf/flags team) - (cfeat/check-client-features! (:features params)) (cfeat/check-file-features! (:features file))) {:file-id file-id diff --git a/common/src/app/common/files/migrations.cljc b/common/src/app/common/files/migrations.cljc index 734b3e429..1c08ad474 100644 --- a/common/src/app/common/files/migrations.cljc +++ b/common/src/app/common/files/migrations.cljc @@ -28,6 +28,7 @@ [app.common.types.container :as ctn] [app.common.types.file :as ctf] [app.common.types.shape :as cts] + [app.common.types.shape.interactions :as ctsi] [app.common.types.shape.shadow :as ctss] [app.common.uuid :as uuid] [clojure.set :as set] @@ -847,9 +848,6 @@ (update :pages-index update-vals update-container) (update :components update-vals update-container)))) -(def ^:private valid-shadow? - (sm/lazy-validator ::ctss/shadow)) - (defmethod migrate-data "legacy-44" [data _] (letfn [(fix-shadow [shadow] @@ -861,7 +859,7 @@ (update-object [object] (let [xform (comp (map fix-shadow) - (filter valid-shadow?))] + (filter ctss/valid-shadow?))] (d/update-when object :shadow #(into [] xform %)))) (update-container [container] @@ -1036,7 +1034,7 @@ (update-shape [shape] (let [xform (comp (map fix-shadow) - (filter valid-shadow?))] + (filter ctss/valid-shadow?))] (d/update-when shape :shadow #(into [] xform %)))) (update-container [container] @@ -1207,11 +1205,11 @@ object)) (update-container [container] - (d/update-when container :objects update-vals update-object))] + (d/update-when container :objects d/update-vals update-object))] (-> data - (update :pages-index update-vals update-container) - (update :components update-vals update-container)))) + (update :pages-index d/update-vals update-container) + (update :components d/update-vals update-container)))) (defmethod migrate-data "legacy-67" [data _] @@ -1222,8 +1220,8 @@ (d/update-when container :objects update-vals update-object))] (-> data - (update :pages-index update-vals update-container) - (update :components update-vals update-container)))) + (update :pages-index d/update-vals update-container) + (update :components d/update-vals update-container)))) (defmethod migrate-data "0001-remove-tokens-from-groups" [data _] @@ -1237,8 +1235,33 @@ (dissoc :applied-tokens))) (update-page [page] - (d/update-when page :objects update-vals update-object))] - (update data :pages-index update-vals update-page))) + (d/update-when page :objects d/update-vals update-object))] + + (update data :pages-index d/update-vals update-page))) + +(defmethod migrate-data "0002-clean-shape-interactions" + [data _] + (let [decode-fn (sm/decoder ctsi/schema:interaction sm/json-transformer) + validate-fn (sm/validator ctsi/schema:interaction) + + xform + (comp + (map decode-fn) + (filter validate-fn)) + + update-object + (fn [object] + (d/update-when object :interactions + (fn [interactions] + (into [] xform interactions)))) + + update-container + (fn [container] + (d/update-when container :objects d/update-vals update-object))] + + (-> data + (update :pages-index d/update-vals update-container) + (update :components d/update-vals update-container)))) (def available-migrations (into (d/ordered-set) @@ -1294,4 +1317,5 @@ "legacy-65" "legacy-66" "legacy-67" - "0001-remove-tokens-from-groups"])) + "0001-remove-tokens-from-groups" + "0002-clean-shape-interactions"])) diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index 23d32e3e7..64eaa1f9b 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -864,7 +864,7 @@ choices))] {:pred pred :type-properties - {:title "contains" + {:title "contains any" :description "contains predicate"}}))}) (register! diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index 5033965db..fc70ff61e 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -211,7 +211,7 @@ [:interactions {:optional true} [:vector {:gen/max 2} ::ctsi/interaction]] [:shadow {:optional true} - [:vector {:gen/max 1} ::ctss/shadow]] + [:vector {:gen/max 1} ctss/schema:shadow]] [:blur {:optional true} ::ctsb/blur] [:grow-type {:optional true} [::sm/one-of grow-types]] diff --git a/common/src/app/common/types/shape/shadow.cljc b/common/src/app/common/types/shape/shadow.cljc index 1b37dd3e9..c00a1ce82 100644 --- a/common/src/app/common/types/shape/shadow.cljc +++ b/common/src/app/common/types/shape/shadow.cljc @@ -26,7 +26,9 @@ [:hidden :boolean] [:color ::ctc/color]]) -(sm/register! ::shadow schema:shadow) - (def check-shadow (sm/check-fn schema:shadow)) + +(def valid-shadow? + (sm/validator schema:shadow)) + diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index a8e731ff1..450bcd0f3 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -89,14 +89,16 @@ (mf/with-effect [file-id revn visible? thumbnail-id] (when (and visible? (not thumbnail-id)) - (->> (ask-for-thumbnail file-id revn) - (rx/subs! (fn [thumbnail-id] - (st/emit! (dd/set-file-thumbnail file-id thumbnail-id))) - (fn [cause] - (log/error :hint "unable to render thumbnail" - :file-if file-id - :revn revn - :message (ex-message cause))))))) + (let [subscription + (->> (ask-for-thumbnail file-id revn) + (rx/subs! (fn [thumbnail-id] + (st/emit! (dd/set-file-thumbnail file-id thumbnail-id))) + (fn [cause] + (log/error :hint "unable to render thumbnail" + :file-if file-id + :revn revn + :message (ex-message cause)))))] + (partial rx/dispose! subscription)))) [:div {:class (stl/css :grid-item-th) :style {:background-color bg-color} diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index 5b1fe0467..f05981d1d 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -432,7 +432,7 @@ (let [id (obj/get self "$id") value (mapv #(shadow-defaults (parser/parse-shadow %)) value)] (cond - (not (sm/validate [:vector ::ctss/shadow] value)) + (not (sm/validate [:vector ctss/schema:shadow] value)) (u/display-not-valid :shadows value) (not (r/check-permission plugin-id "content:write")) diff --git a/frontend/src/app/util/http.cljs b/frontend/src/app/util/http.cljs index 47f382366..98177688c 100644 --- a/frontend/src/app/util/http.cljs +++ b/frontend/src/app/util/http.cljs @@ -50,7 +50,8 @@ [headers] (into {} (map vec) (seq (.entries ^js headers)))) -(def default-headers +(defn default-headers + [] {"x-frontend-version" (:full cfg/version)}) (defn fetch @@ -74,7 +75,7 @@ headers (cond-> headers (not omit-default-headers) - (d/merge default-headers)) + (merge (default-headers))) headers (-update-headers body headers) diff --git a/frontend/src/app/worker/thumbnails.cljs b/frontend/src/app/worker/thumbnails.cljs index 658429c19..cca294cb0 100644 --- a/frontend/src/app/worker/thumbnails.cljs +++ b/frontend/src/app/worker/thumbnails.cljs @@ -42,12 +42,11 @@ :http-body body}))) (defn- request-data-for-thumbnail - [file-id revn features] + [file-id revn] (let [path "api/rpc/command/get-file-data-for-thumbnail" params {:file-id file-id :revn revn - :strip-frames-with-thumbnails true - :features features} + :strip-frames-with-thumbnails true} request {:method :get :uri (u/join cf/public-uri path) :credentials "include" @@ -86,6 +85,6 @@ nil))) (defmethod impl/handler :thumbnails/generate-for-file - [{:keys [file-id revn features] :as message} _] - (->> (request-data-for-thumbnail file-id revn features) + [{:keys [file-id revn] :as message} _] + (->> (request-data-for-thumbnail file-id revn) (rx/map render-thumbnail)))