diff --git a/backend/src/uxbox/api/pages.clj b/backend/src/uxbox/api/pages.clj index 8a84591be..3094a1c8b 100644 --- a/backend/src/uxbox/api/pages.clj +++ b/backend/src/uxbox/api/pages.clj @@ -13,20 +13,41 @@ [uxbox.util.spec :as us] [uxbox.util.uuid :as uuid])) +;; --- Common Specs + +(s/def ::id ::us/uuid) +(s/def ::name string?) +(s/def ::project ::us/uuid) +(s/def ::version (s/and integer? pos?)) +(s/def ::data any?) +(s/def ::metadata any?) + +;; --- List Pages + +(s/def ::list-pages|query + (s/keys :req-un [::project])) + (defn list-pages - {:parameters {:query {:project [st/required st/uuid-str]}}} + {:parameters {:query ::list-pages|query} + :validation :spec} [{:keys [user parameters]}] (let [project (get-in parameters [:query :project]) message {:user user :project project :type :list-pages-by-project}] (-> (sv/query message) (p/then rsp/ok)))) +;; --- Create Page + +(s/def ::create-page|body + (s/keys :req-un [::data + ::metadata + ::project + ::name] + :opt-un [::id])) + (defn create-page - {:parameters {:body {:data [st/required] - :metadata [st/required] - :project [st/required st/uuid] - :name [st/required st/string] - :id [st/uuid]}}} + {:parameters {:body ::create-page|body} + :validation :spec} [{:keys [user parameters]}] (let [data (get parameters :body) message (assoc data :user user :type :create-page)] @@ -35,14 +56,23 @@ (let [loc (str "/api/pages/" (:id result))] (rsp/created loc result))))))) +;; --- Update Page + +(s/def ::update-page|path + (s/keys :req-un [::id])) + +(s/def ::update-page|body + (s/keys :req-un [::data + ::metadata + ::project + ::name + ::version] + :opt-un [::id])) + (defn update-page - {:parameters {:path {:id [st/required st/uuid-str]} - :body {:data [st/required] - :metadata [st/required] - :project [st/required st/uuid] - :name [st/required st/string] - :version [st/required st/integer] - :id [st/uuid]}}} + {:parameters {:path ::update-page|path + :body ::update-page|body} + :validation :spec} [{:keys [user parameters]}] (let [id (get-in parameters [:path :id]) data (get parameters :body) @@ -50,12 +80,21 @@ (->> (sv/novelty message) (p/map #(rsp/ok %))))) +;; --- Update Page Metadata + +(s/def ::update-page-metadata|path + (s/keys :req-un [::id])) + +(s/def ::update-page-metadata|body + (s/keys :req-un [::id + ::metadata + ::project + ::name])) + (defn update-page-metadata - {:parameters {:path {:id [st/required st/uuid-str]} - :body {:id [st/required st/uuid] - :metadata [st/required] - :project [st/required st/uuid] - :name [st/required st/string]}}} + {:parameters {:path ::update-page-metadata|path + :body ::update-page-metadata|body} + :validation :spec} [{:keys [user parameters]}] (let [id (get-in parameters [:path :id]) data (get parameters :body) @@ -63,20 +102,39 @@ (->> (sv/novelty message) (p/map rsp/ok)))) +;; --- Delete Page + +(s/def ::delete-page|path + (s/keys :req-un [::id])) + (defn delete-page - {:parameters {:path {:id [st/required st/uuid-str]}}} + {:parameters {:path ::delete-page|path} + :validation :spec} [{:keys [user parameters]}] (let [id (get-in parameters [:path :id]) message {:id id :type :delete-page :user user}] (-> (sv/novelty message) (p/then (constantly (rsp/no-content)))))) +;; --- Retrieve Page History + +(s/def ::max ::us/integer) +(s/def ::since ::us/integer) +(s/def ::pinned ::us/boolean) + +(s/def ::retrieve-page-history|path + (s/keys :req-un [::id])) + +(s/def ::retrieve-page-history|query + (s/keys :req-un [::max + ::since + ::pinned])) + (defn retrieve-page-history "Retrieve the page history" - {:parameters {:path {:id [st/required st/uuid-str]} - :query {:max [st/integer-str] - :since [st/integer-str] - :pinned [st/boolean-str]}}} + {:parameters {:path ::retrieve-page-history|path + :query ::retrieve-page-history|query} + :validation :spec} [{:keys [user parameters]}] (let [id (get-in parameters [:path :id]) data (get parameters :query) @@ -84,11 +142,21 @@ (->> (sv/query message) (p/map rsp/ok)))) +;; --- Update page history + +(s/def ::hid ::us/uuid) +(s/def ::label string?) + +(s/def ::update-page-history|path + (s/keys :req-un [::id ::hid])) + +(s/def ::update-page-history|body + (s/keys :req-un [::label ::pinned])) + (defn update-page-history - {:parameters {:path {:id [st/required st/uuid-str] - :hid [st/required st/uuid-str]} - :body {:label [st/required st/string] - :pinned [st/required st/boolean]}}} + {:parameters {:path ::update-page-history|path + :body ::update-page-history|body} + :validation :spec} [{:keys [user parameters]}] (let [{:keys [id hid]} (get parameters :path) message (assoc (get parameters :body) diff --git a/backend/src/uxbox/util/exceptions.clj b/backend/src/uxbox/util/exceptions.clj index 6d22b9b36..70db97db5 100644 --- a/backend/src/uxbox/util/exceptions.clj +++ b/backend/src/uxbox/util/exceptions.clj @@ -5,16 +5,27 @@ ;; Copyright (c) 2016 Andrey Antukh (ns uxbox.util.exceptions - "A helpers for work with exceptions.") + "A helpers for work with exceptions." + (:require [clojure.spec.alpha :as s])) + +(s/def ::type keyword?) +(s/def ::code keyword?) +(s/def ::mesage string?) +(s/def ::hint string?) +(s/def ::cause #(instance? Exception %)) +(s/def ::error-params + (s/keys :req-un [::type] + :opt-un [::code + ::hint + ::mesage + ::cause])) (defn error - [& {:keys [type code message] :or {type :unexpected} :as payload}] - {:pre [(keyword? type) (keyword? code)]} - (let [message (if message - (str message " / " (pr-str code) "") - (pr-str code)) - payload (assoc payload :type type)] - (ex-info message payload))) + [& {:keys [type code message hint cause] :as params}] + (s/assert ::error-params params) + (let [message (or message hint "") + payload (dissoc params :cause :message)] + (ex-info message payload cause))) (defmacro raise [& args] diff --git a/backend/src/uxbox/util/spec.clj b/backend/src/uxbox/util/spec.clj index bbfe81b19..fdf729369 100644 --- a/backend/src/uxbox/util/spec.clj +++ b/backend/src/uxbox/util/spec.clj @@ -25,11 +25,8 @@ [spec data] (let [result (s/conform spec data)] (if (= result ::s/invalid) - (ex/raise :type :validation - :code ::invalid - :message (s/explain-str spec data) - :context (s/explain-data spec data)) - result))) + [nil (s/explain-data spec data)] + [result nil]))) (defn valid? [spec data] @@ -41,7 +38,7 @@ (defn email? [v] - (and string? + (and (string? v) (re-matches email-rx v))) (defn instant? @@ -100,20 +97,21 @@ ;; --- Default Specs -(s/def ::integer-string (s/conformer integer-conformer str)) -(s/def ::uuid-string (s/conformer uuid-conformer str)) -(s/def ::boolean-string (s/conformer boolean-conformer boolean-unformer)) -(s/def ::positive-integer #(< 0 % Long/MAX_VALUE)) +(s/def ::integer (s/conformer integer-conformer str)) +(s/def ::uuid (s/conformer uuid-conformer str)) +(s/def ::boolean (s/conformer boolean-conformer boolean-unformer)) +(s/def ::positive pos?) +(s/def ::negative neg?) (s/def ::uploaded-file any?) -(s/def ::uuid uuid?) (s/def ::bytes bytes?) (s/def ::path path?) +(s/def ::email email?) -(s/def ::id ::uuid-string) +;; TODO: deprecated +(s/def ::id ::uuid) (s/def ::name string?) (s/def ::username string?) (s/def ::password string?) (s/def ::version integer?) -(s/def ::email email?) (s/def ::token string?) diff --git a/backend/src/uxbox/util/transit.clj b/backend/src/uxbox/util/transit.clj index 649b99dd4..15c25c0b2 100644 --- a/backend/src/uxbox/util/transit.clj +++ b/backend/src/uxbox/util/transit.clj @@ -6,6 +6,7 @@ (ns uxbox.util.transit (:require [cognitect.transit :as t] + [clojure.java.io :as io] [uxbox.util.time :as dt]) (:import java.io.ByteArrayInputStream java.io.ByteArrayOutputStream @@ -52,7 +53,7 @@ ([data] (decode data nil)) ([data opts] - (with-open [input (ByteArrayInputStream. data)] + (with-open [input (io/input-stream data)] (read! (reader input opts))))) (defn encode