0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

Merge pull request #3672 from penpot/hiru-automatic-validation

🎉 Do file validation on each file change
This commit is contained in:
Aitor Moreno 2023-09-27 13:57:44 +02:00 committed by GitHub
commit e39a0bb8b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 23 deletions

View file

@ -24,7 +24,8 @@ export PENPOT_FLAGS="\
enable-rpc-rlimit \ enable-rpc-rlimit \
enable-soft-rpc-rlimit \ enable-soft-rpc-rlimit \
enable-webhooks \ enable-webhooks \
enable-access-tokens"; enable-access-tokens \
disable-file-validation";
# export PENPOT_DATABASE_URI="postgresql://172.17.0.1:5432/penpot" # export PENPOT_DATABASE_URI="postgresql://172.17.0.1:5432/penpot"
# export PENPOT_DATABASE_USERNAME="penpot" # export PENPOT_DATABASE_USERNAME="penpot"

View file

@ -15,7 +15,8 @@ export PENPOT_FLAGS="\
enable-fdata-storage-objets-map \ enable-fdata-storage-objets-map \
disable-secure-session-cookies \ disable-secure-session-cookies \
enable-smtp \ enable-smtp \
enable-access-tokens"; enable-access-tokens \
disable-file-validation";
set -ex set -ex

View file

@ -6,9 +6,11 @@
(ns app.rpc.commands.files-update (ns app.rpc.commands.files-update
(:require (:require
[app.common.data :as d]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.files.features :as ffeat] [app.common.files.features :as ffeat]
[app.common.files.migrations :as pmg] [app.common.files.migrations :as pmg]
[app.common.files.validate :as val]
[app.common.logging :as l] [app.common.logging :as l]
[app.common.pages :as cp] [app.common.pages :as cp]
[app.common.pages.changes :as cpc] [app.common.pages.changes :as cpc]
@ -55,7 +57,8 @@
::sm/set-of-strings] ::sm/set-of-strings]
[:changes {:optional true} ::changes] [:changes {:optional true} ::changes]
[:changes-with-metadata {:optional true} [:changes-with-metadata {:optional true}
[:vector ::change-with-metadata]]]) [:vector ::change-with-metadata]]
[:skip-validate {:optional true} :boolean]])
(sm/def! ::update-file-result (sm/def! ::update-file-result
[:vector {:title "UpdateFileResults"} [:vector {:title "UpdateFileResults"}
@ -156,7 +159,7 @@
(l/trace :hint "update-file" :time (dt/format-duration elapsed)))))))) (l/trace :hint "update-file" :time (dt/format-duration elapsed))))))))
(defn update-file (defn update-file
[{:keys [::db/conn ::mtx/metrics] :as cfg} {:keys [profile-id id changes changes-with-metadata] :as params}] [{:keys [::db/conn ::mtx/metrics] :as cfg} {:keys [profile-id id changes changes-with-metadata skip-validate] :as params}]
(let [file (get-file conn id) (let [file (get-file conn id)
features (->> (concat (:features file) features (->> (concat (:features file)
(:features params)) (:features params))
@ -176,12 +179,24 @@
(wrap-with-objects-map-context)) (wrap-with-objects-map-context))
file (assoc file :features features) file (assoc file :features features)
;; TODO: this ruins performance.
;; We must find some other way to do general validation.
libraries (when (and (cf/flags :file-validation)
(not skip-validate))
(-> (->> (files/get-file-libraries conn (:id file))
(map #(get-file conn (:id %)))
(map #(update % :data blob/decode))
(d/index-by :id))
(assoc (:id file) file)))
changes (if changes-with-metadata changes (if changes-with-metadata
(->> changes-with-metadata (mapcat :changes) vec) (->> changes-with-metadata (mapcat :changes) vec)
(vec changes)) (vec changes))
params (-> params params (-> params
(assoc :file file) (assoc :file file)
(assoc :libraries libraries)
(assoc :changes changes) (assoc :changes changes)
(assoc ::created-at (dt/now)))] (assoc ::created-at (dt/now)))]
@ -210,12 +225,12 @@
:team-id (:team-id file)})))))) :team-id (:team-id file)}))))))
(defn- update-file* (defn- update-file*
[{:keys [::db/conn] :as cfg} {:keys [profile-id file changes session-id ::created-at] :as params}] [{:keys [::db/conn] :as cfg} {:keys [profile-id file libraries changes session-id ::created-at skip-validate] :as params}]
(let [;; Process the file data in the CLIMIT context; scheduling it (let [;; Process the file data in the CLIMIT context; scheduling it
;; to be executed on a separated executor for avoid to do the ;; to be executed on a separated executor for avoid to do the
;; CPU intensive operation on vthread. ;; CPU intensive operation on vthread.
file (-> (climit/configure cfg :update-file) file (-> (climit/configure cfg :update-file)
(climit/submit! (partial update-file-data file changes)))] (climit/submit! (partial update-file-data file libraries changes skip-validate)))]
(db/insert! conn :file-change (db/insert! conn :file-change
{:id (uuid/next) {:id (uuid/next)
@ -249,23 +264,28 @@
(get-lagged-changes conn params)))) (get-lagged-changes conn params))))
(defn- update-file-data (defn- update-file-data
[file changes] [file libraries changes skip-validate]
(-> file (let [validate (fn [file]
(update :revn inc) (when (and (cf/flags :file-validation)
(update :data (fn [data] (not skip-validate))
(cond-> data (val/validate-file file libraries :throw? true)))]
:always (-> file
(-> (blob/decode) (update :revn inc)
(assoc :id (:id file)) (update :data (fn [data]
(pmg/migrate-data)) (cond-> data
:always
(-> (blob/decode)
(assoc :id (:id file))
(pmg/migrate-data))
(and (contains? ffeat/*current* "components/v2") (and (contains? ffeat/*current* "components/v2")
(not (contains? ffeat/*previous* "components/v2"))) (not (contains? ffeat/*previous* "components/v2")))
(ctf/migrate-to-components-v2) (ctf/migrate-to-components-v2)
:always :always
(-> (cp/process-changes changes) (cp/process-changes changes))))
(blob/encode))))))) (d/tap-r validate)
(update :data blob/encode))))
(defn- take-snapshot? (defn- take-snapshot?
"Defines the rule when file `data` snapshot should be saved." "Defines the rule when file `data` snapshot should be saved."

View file

@ -67,7 +67,8 @@
:enable-smtp :enable-smtp
:enable-quotes :enable-quotes
:enable-fdata-storage-pointer-map :enable-fdata-storage-pointer-map
:enable-fdata-storage-objets-map]) :enable-fdata-storage-objets-map
:disable-file-validation])
(def test-init-sql (def test-init-sql
["alter table project_profile_rel set unlogged;\n" ["alter table project_profile_rel set unlogged;\n"

View file

@ -412,7 +412,8 @@
:revn (:revn file) :revn (:revn file)
:session-id sid :session-id sid
:changes changes :changes changes
:features features}] :features features
:skip-validate true}]
(->> (rp/cmd! :update-file params) (->> (rp/cmd! :update-file params)
(rx/tap #(dom/reload-current-window))))))))) (rx/tap #(dom/reload-current-window)))))))))