diff --git a/backend/src/uxbox/media.clj b/backend/src/uxbox/media.clj index acd92bfe7..272bffcd7 100644 --- a/backend/src/uxbox/media.clj +++ b/backend/src/uxbox/media.clj @@ -17,6 +17,7 @@ [mount.core :refer [defstate]] [uxbox.config :as cfg] [uxbox.common.data :as d] + [uxbox.common.media :as cm] [uxbox.common.exceptions :as ex] [uxbox.common.spec :as us] [uxbox.media-storage :as mst] @@ -40,15 +41,14 @@ (s/def ::path (s/or :path fs/path? :string string? :file fs/file?)) -(s/def ::mtype string?) (s/def ::input (s/keys :req-un [::path] - :opt-un [::mtype])) + :opt-un [::cm/mtype])) (s/def ::width integer?) (s/def ::height integer?) -(s/def ::format #{:jpeg :webp :png :svg}) +(s/def ::format #{:jpeg :webp :png}) (s/def ::quality #(< 0 % 101)) (s/def ::thumbnail-params @@ -57,39 +57,11 @@ ;; Related info on how thumbnails generation ;; http://www.imagemagick.org/Usage/thumbnails/ -(def valid-media-types - #{"image/jpeg", "image/png", "image/webp", "image/svg+xml"}) - -(defn format->extension - [format] - (case format - :png ".png" - :jpeg ".jpg" - :webp ".webp" - :svg ".svg")) - -(defn format->mtype - [format] - (case format - :png "image/png" - :jpeg "image/jpeg" - :webp "image/webp" - :svg "image/svg+xml")) - -(defn mtype->format - [mtype] - (case mtype - "image/png" :png - "image/jpeg" :jpeg - "image/webp" :webp - "image/svg+xml" :svg - nil)) - (defn- generic-process [{:keys [input format quality operation] :as params}] (let [{:keys [path mtype]} input - format (or (mtype->format mtype) format) - ext (format->extension format) + format (or (cm/mtype->format mtype) format) + ext (cm/format->extension format) tmp (fs/create-tempfile :suffix ext)] (doto (ConvertCmd.) @@ -99,7 +71,7 @@ (fs/delete tmp) (assoc params :format format - :mtype (format->mtype format) + :mtype (cm/format->mtype format) :data (ByteArrayInputStream. thumbnail-data))))) (defmulti process :cmd) @@ -170,6 +142,9 @@ (finally (.release semaphore)))) + +;; --- Utility functions + (defn resolve-urls [row src dst] (s/assert map? row) @@ -201,7 +176,7 @@ (defn validate-media-type [media-type] - (when-not (valid-media-types media-type) + (when-not (cm/valid-media-types media-type) (ex/raise :type :validation :code :media-type-not-allowed :hint "Seems like you are uploading an invalid media object"))) @@ -211,14 +186,14 @@ (let [result (http/get! url {:as :byte-array}) data (:body result) content-type (get (:headers result) "content-type") - format (mtype->format content-type)] + format (cm/mtype->format content-type)] (if (nil? format) (ex/raise :type :validation :code :media-type-not-allowed :hint "Seems like the url points to an invalid media object.") (let [tempfile (fs/create-tempfile) base-filename (first (fs/split-ext (fs/name tempfile))) - filename (str base-filename (format->extension format))] + filename (str base-filename (cm/format->extension format))] (with-open [ostream (io/output-stream tempfile)] (.write ostream data)) {:filename filename diff --git a/backend/src/uxbox/services/mutations/media.clj b/backend/src/uxbox/services/mutations/media.clj index 90372e88e..e3f50c7be 100644 --- a/backend/src/uxbox/services/mutations/media.clj +++ b/backend/src/uxbox/services/mutations/media.clj @@ -11,6 +11,7 @@ (:require [clojure.spec.alpha :as s] [datoteka.core :as fs] + [uxbox.common.media :as cm] [uxbox.common.exceptions :as ex] [uxbox.common.spec :as us] [uxbox.common.uuid :as uuid] @@ -47,7 +48,7 @@ (s/def :uxbox$upload/filename ::us/string) (s/def :uxbox$upload/size ::us/integer) -(s/def :uxbox$upload/content-type media/valid-media-types) +(s/def :uxbox$upload/content-type cm/valid-media-types) (s/def :uxbox$upload/tempfile any?) (s/def ::upload @@ -154,7 +155,7 @@ name (str "thumbnail-" (first (fs/split-ext (fs/name (:path input)))) - (media/format->extension (:format thumb))) + (cm/format->extension (:format thumb))) path (ust/save! mst/media-storage name (:data thumb))] (-> thumb diff --git a/backend/src/uxbox/services/mutations/profile.clj b/backend/src/uxbox/services/mutations/profile.clj index 5cdb697f8..aec25ab8e 100644 --- a/backend/src/uxbox/services/mutations/profile.clj +++ b/backend/src/uxbox/services/mutations/profile.clj @@ -20,6 +20,7 @@ [uxbox.common.exceptions :as ex] [uxbox.common.spec :as us] [uxbox.common.uuid :as uuid] + [uxbox.common.media :as cm] [uxbox.config :as cfg] [uxbox.db :as db] [uxbox.emails :as emails] @@ -299,7 +300,7 @@ :height 256 :input {:path (fs/path (:tempfile file)) :mtype (:content-type file)}}) - name (str prefix (media/format->extension (:format thumb)))] + name (str prefix (cm/format->extension (:format thumb)))] (ust/save! mst/media-storage name (:data thumb)))) (defn- update-profile-photo diff --git a/common/uxbox/common/media.cljc b/common/uxbox/common/media.cljc new file mode 100644 index 000000000..2b0f38534 --- /dev/null +++ b/common/uxbox/common/media.cljc @@ -0,0 +1,65 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns uxbox.common.media + (:require + [clojure.spec.alpha :as s] + [cuerdas.core :as str])) + +(def valid-media-types + #{"image/jpeg", "image/png", "image/webp", "image/svg+xml"}) + +(def str-media-types (str/join "," valid-media-types)) + +(defn format->extension + [format] + (case format + :png ".png" + :jpeg ".jpg" + :webp ".webp" + :svg ".svg")) + +(defn format->mtype + [format] + (case format + :png "image/png" + :jpeg "image/jpeg" + :webp "image/webp" + :svg "image/svg+xml")) + +(defn mtype->format + [mtype] + (case mtype + "image/png" :png + "image/jpeg" :jpeg + "image/webp" :webp + "image/svg+xml" :svg + nil)) + +(def max-file-size (* 5 1024 1024)) + +(s/def ::id uuid?) +(s/def ::name string?) +(s/def ::width number?) +(s/def ::height number?) +(s/def ::created-at inst?) +(s/def ::modified-at inst?) +(s/def ::mtype string?) +(s/def ::uri string?) + +(s/def ::media-object + (s/keys :req-un [::id + ::name + ::width + ::height + ::mtype + ::created-at + ::modified-at + ::uri])) + diff --git a/frontend/src/uxbox/main/data/media.cljs b/frontend/src/uxbox/main/data/media.cljs index b122ea461..9b01ef506 100644 --- a/frontend/src/uxbox/main/data/media.cljs +++ b/frontend/src/uxbox/main/data/media.cljs @@ -12,6 +12,7 @@ [potok.core :as ptk] [uxbox.common.spec :as us] [uxbox.common.data :as d] + [uxbox.common.media :as cm] [uxbox.main.data.messages :as dm] [uxbox.main.store :as st] [uxbox.main.repo :as rp] @@ -24,40 +25,17 @@ ;; --- Specs -(s/def ::id uuid?) -(s/def ::name string?) -(s/def ::width number?) -(s/def ::height number?) -(s/def ::created-at inst?) -(s/def ::modified-at inst?) -(s/def ::mtype string?) -(s/def ::uri string?) - -(s/def ::media-object - (s/keys :req-un [::id - ::name - ::width - ::height - ::mtype - ::created-at - ::modified-at - ::uri])) - (s/def ::js-file #(instance? js/Blob %)) (s/def ::js-files (s/coll-of ::js-file)) -(def allowed-media-types #{"image/jpeg" "image/png" "image/webp" "image/svg+xml"}) -(def str-media-types (str/join "," allowed-media-types)) -(def max-file-size (* 5 1024 1024)) - ;; --- Utility functions (defn validate-file ;; Check that a file obtained with the file javascript API is valid. [file] - (when (> (.-size file) max-file-size) + (when (> (.-size file) cm/max-file-size) (throw (ex-info (tr "errors.media-too-large") {}))) - (when-not (contains? allowed-media-types (.-type file)) + (when-not (contains? cm/valid-media-types (.-type file)) (throw (ex-info (tr "errors.media-format-unsupported") {}))) file) diff --git a/frontend/src/uxbox/main/data/workspace/persistence.cljs b/frontend/src/uxbox/main/data/workspace/persistence.cljs index b264bbb64..defc51b66 100644 --- a/frontend/src/uxbox/main/data/workspace/persistence.cljs +++ b/frontend/src/uxbox/main/data/workspace/persistence.cljs @@ -13,6 +13,7 @@ [cljs.spec.alpha :as s] [potok.core :as ptk] [uxbox.common.data :as d] + [uxbox.common.media :as cm] [uxbox.common.geom.point :as gpt] [uxbox.common.pages :as cp] [uxbox.common.spec :as us] @@ -409,7 +410,7 @@ [file-id is-local media-object] (us/verify ::us/uuid file-id) (us/verify ::us/boolean is-local) - (us/verify ::di/media-object media-object) + (us/verify ::cm/media-object media-object) (ptk/reify ::upload-media-objects-result ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/uxbox/main/ui/workspace/left_toolbar.cljs b/frontend/src/uxbox/main/ui/workspace/left_toolbar.cljs index 5bcaaf133..2c60eab33 100644 --- a/frontend/src/uxbox/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/uxbox/main/ui/workspace/left_toolbar.cljs @@ -11,8 +11,8 @@ (ns uxbox.main.ui.workspace.left-toolbar (:require [rumext.alpha :as mf] + [uxbox.common.media :as cm] [uxbox.main.refs :as refs] - [uxbox.main.data.media :as di] [uxbox.main.data.workspace :as dw] [uxbox.main.store :as st] [uxbox.main.ui.components.file-uploader :refer [file-uploader]] @@ -74,7 +74,7 @@ :on-click on-image} [:* i/image - [:& file-uploader {:accept di/str-media-types + [:& file-uploader {:accept cm/str-media-types :multi true :input-ref file-input :on-selected on-files-selected}]]] diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs index cc099cde5..43d86c2d4 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/assets.cljs @@ -13,11 +13,11 @@ [cuerdas.core :as str] [rumext.alpha :as mf] [uxbox.common.data :as d] + [uxbox.common.media :as cm] [uxbox.common.pages :as cp] [uxbox.common.geom.shapes :as geom] [uxbox.common.geom.point :as gpt] [uxbox.main.ui.icons :as i] - [uxbox.main.data.media :as di] [uxbox.main.data.workspace :as dw] [uxbox.main.data.colors :as dcol] [uxbox.main.refs :as refs] @@ -114,7 +114,7 @@ [:span (str "\u00A0(") (count media-objects) ")"] ;; Unicode 00A0 is non-breaking space [:div.group-button {:on-click add-graphic} i/plus - [:& file-uploader {:accept di/str-media-types + [:& file-uploader {:accept cm/str-media-types :multi true :input-ref file-input :on-selected on-files-selected}]]]