From b456ca6fe0d7019ed98eafde3c78db8576723757 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 7 Oct 2026 13:13:17 +0000 Subject: [PATCH] :bug: Accept an empty suffix on export asset items The export form sends `""` when the user types no suffix, and the legacy `/api/export` surface took a plain string there. The job schema asked for `::sm/text` (not blank) instead, so every suffix-less export died with `:params-validation` before reaching the worker. The suffix is a free-form filename fragment the worker concatenates as-is, so the schema takes any string now, empty included. AI-assisted-by: glm-5.3-flash --- backend/src/app/tasks/export_assets.clj | 5 ++++- .../backend_tests/rpc/commands/jobs_test.clj | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/backend/src/app/tasks/export_assets.clj b/backend/src/app/tasks/export_assets.clj index b6538b5289..8b46cc8729 100644 --- a/backend/src/app/tasks/export_assets.clj +++ b/backend/src/app/tasks/export_assets.clj @@ -40,7 +40,10 @@ [:object-id ::sm/uuid] [:type [::sm/one-of #{:png :jpeg :webp :svg :pdf}]] [:name ::sm/text] - [:suffix {:optional true} ::sm/text] + ;; a plain string on purpose, empty included: the export form sends + ;; `""` when the user types no suffix, and the legacy `/api/export` + ;; surface took it that way; the worker concatenates it as-is + [:suffix {:optional true} :string] [:scale ::sm/number] [:share-id {:optional true} ::sm/uuid]]) diff --git a/backend/test/backend_tests/rpc/commands/jobs_test.clj b/backend/test/backend_tests/rpc/commands/jobs_test.clj index 20b8850d97..5c5e1ba2f9 100644 --- a/backend/test/backend_tests/rpc/commands/jobs_test.clj +++ b/backend/test/backend_tests/rpc/commands/jobs_test.clj @@ -251,10 +251,29 @@ [(export-item file-id :type :psd)])] (t/is (not (th/success? out))) - (t/is (= :data-validation (th/ex-code (:error out)))) + ;; refused by the RPC wrapper before the command runs (the same + ;; `:params-validation` a real caller sees over HTTP) + (t/is (= :params-validation (th/ex-code (:error out)))) (t/testing "and nothing was created" (t/is (zero? (count-jobs)))))) +(t/deftest create-export-assets-job-accepts-an-empty-suffix + ;; the export form sends `""` when the user types no suffix (it is the + ;; normal case, not an edge): the legacy `/api/export` surface took a + ;; plain string, so the job must take it too + (let [profile (th/create-profile* 1) + file-id (first (:file-ids (import-fixture! profile))) + item (assoc (export-item file-id) :suffix "") + out (create-export-assets-job (:id profile) [item])] + + (t/is (th/success? out)) + + (t/testing "and the empty suffix is frozen as-is for the worker" + (let [job (jobs/get-job th/*system* (:id (:result out))) + job-def (jobs/get-job-def (::jobs/defs th/*system*) :export-assets) + params (jobs/decode-params job-def (:params job))] + (t/is (= "" (:suffix (first (:exports params))))))))) + (t/deftest create-export-assets-job-accepts-a-file-nameable-through-a-share ;; the viewer that renders a file through a public share exports the ;; same way every share fetch goes: the share id names the file, the