add ability for checked failure handling to get validation errors list
'validate' functions now add params to the request under :validation-errors when validations fail. if the fail-response used is a function, the request that gets passed in is the last request map that was used in the most recent validation instead of the original
This commit is contained in:
parent
228a2eff39
commit
bc9e2a8912
|
@ -7,13 +7,19 @@
|
||||||
[schema.core :as s]
|
[schema.core :as s]
|
||||||
[cheshire.core :as json]
|
[cheshire.core :as json]
|
||||||
[clj-webtoolbox.response :as response]
|
[clj-webtoolbox.response :as response]
|
||||||
[clj-webtoolbox.routes.core :refer [destructure-route-bindings]]))
|
[clj-webtoolbox.routes.core :refer [destructure-route-bindings]]
|
||||||
|
[clj-webtoolbox.utils :refer [pred-> request?]]))
|
||||||
|
|
||||||
|
(defn no-errors? [request]
|
||||||
|
(not (seq (:validation-errors request))))
|
||||||
|
|
||||||
(defmacro threaded-checks [request checks fail-response]
|
(defmacro threaded-checks [request checks fail-response]
|
||||||
`(or (some-> ~request ~@checks)
|
`(let [result# (pred-> ~request no-errors? ~@checks)]
|
||||||
|
(if (request? result#)
|
||||||
(if (response? ~fail-response)
|
(if (response? ~fail-response)
|
||||||
~fail-response
|
~fail-response
|
||||||
(~fail-response ~request))))
|
(~fail-response result#))
|
||||||
|
result#)))
|
||||||
|
|
||||||
(def default-wrap-checks-error-response
|
(def default-wrap-checks-error-response
|
||||||
(-> (response/content "Handler checks did not all pass.")
|
(-> (response/content "Handler checks did not all pass.")
|
||||||
|
@ -110,6 +116,12 @@
|
||||||
(assoc-in request [:safe-params :body] (:body request))
|
(assoc-in request [:safe-params :body] (:body request))
|
||||||
(update-in request [:safe-params] merge (:body request))))
|
(update-in request [:safe-params] merge (:body request))))
|
||||||
|
|
||||||
|
(defn- assoc-validation-error [request param]
|
||||||
|
(update-in
|
||||||
|
request
|
||||||
|
[:validation-errors]
|
||||||
|
#(if % (conj % param) [param])))
|
||||||
|
|
||||||
(defn validate
|
(defn validate
|
||||||
"Validates the specified parameter using function f which gets passed the value
|
"Validates the specified parameter using function f which gets passed the value
|
||||||
of the parameter. If f returns a 'truthy' value the parameter is marked safe.
|
of the parameter. If f returns a 'truthy' value the parameter is marked safe.
|
||||||
|
@ -120,7 +132,8 @@
|
||||||
([request parent param f]
|
([request parent param f]
|
||||||
(let [k (if (sequential? param) (concat [parent] param) [parent param])]
|
(let [k (if (sequential? param) (concat [parent] param) [parent param])]
|
||||||
(if (f (get-in request k))
|
(if (f (get-in request k))
|
||||||
(safe request parent [param])))))
|
(safe request parent [param])
|
||||||
|
(assoc-validation-error request param)))))
|
||||||
|
|
||||||
(defn validate-schema
|
(defn validate-schema
|
||||||
"Validates the specified parameter by checking it against the given schema.
|
"Validates the specified parameter by checking it against the given schema.
|
||||||
|
@ -130,7 +143,8 @@
|
||||||
([request parent param schema]
|
([request parent param schema]
|
||||||
(let [k (if (sequential? param) (concat [parent] param) [parent param])]
|
(let [k (if (sequential? param) (concat [parent] param) [parent param])]
|
||||||
(if (nil? (s/check schema (get-in request k)))
|
(if (nil? (s/check schema (get-in request k)))
|
||||||
(safe request parent [param])))))
|
(safe request parent [param])
|
||||||
|
(assoc-validation-error request param)))))
|
||||||
|
|
||||||
(defn validate-body
|
(defn validate-body
|
||||||
"Validates the request body using function f which gets passed the body of
|
"Validates the request body using function f which gets passed the body of
|
||||||
|
@ -138,7 +152,8 @@
|
||||||
likely will want to transform the body first before validation."
|
likely will want to transform the body first before validation."
|
||||||
[request f & [copy-into-params?]]
|
[request f & [copy-into-params?]]
|
||||||
(if (f (:body request))
|
(if (f (:body request))
|
||||||
(safe-body request copy-into-params?)))
|
(safe-body request copy-into-params?)
|
||||||
|
(assoc-validation-error request :body)))
|
||||||
|
|
||||||
(defn validate-body-schema
|
(defn validate-body-schema
|
||||||
"Validates the request body by checking it against the given schema. If it
|
"Validates the request body by checking it against the given schema. If it
|
||||||
|
@ -146,7 +161,8 @@
|
||||||
first before validation."
|
first before validation."
|
||||||
[request schema & [copy-into-params?]]
|
[request schema & [copy-into-params?]]
|
||||||
(if (nil? (s/check schema (:body request)))
|
(if (nil? (s/check schema (:body request)))
|
||||||
(safe-body request copy-into-params?)))
|
(safe-body request copy-into-params?)
|
||||||
|
(assoc-validation-error request :body)))
|
||||||
|
|
||||||
(defn transform
|
(defn transform
|
||||||
"Transforms the specified parameter using function f which gets passed the value
|
"Transforms the specified parameter using function f which gets passed the value
|
||||||
|
|
31
src/clj_webtoolbox/utils.clj
Normal file
31
src/clj_webtoolbox/utils.clj
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
(ns clj-webtoolbox.utils)
|
||||||
|
|
||||||
|
(defmacro pred->
|
||||||
|
"Threads exp through the forms (via ->) as long as (pred exp)
|
||||||
|
returns logical true values. Returns whatever exp was at
|
||||||
|
the time threading stopped (either due to a false return
|
||||||
|
from pred or because all forms were executed)."
|
||||||
|
[expr pred & forms]
|
||||||
|
(let [g (gensym)
|
||||||
|
pstep (fn [step]
|
||||||
|
`(if (~pred ~g)
|
||||||
|
(-> ~g ~step)
|
||||||
|
~g))]
|
||||||
|
`(let [~g ~expr
|
||||||
|
~@(interleave
|
||||||
|
(repeat g)
|
||||||
|
(map pstep forms))]
|
||||||
|
~g)))
|
||||||
|
|
||||||
|
(defn request?
|
||||||
|
"True if the supplied value is a valid request map."
|
||||||
|
[req]
|
||||||
|
;; TODO: probably don't need this many tests, just being overly cautious about
|
||||||
|
;; making sure this won't confuse a response map with a request map
|
||||||
|
(and (map? req)
|
||||||
|
(keyword? (:scheme req))
|
||||||
|
(keyword? (:request-method req))
|
||||||
|
(contains? req :server-port)
|
||||||
|
(contains? req :server-name)
|
||||||
|
(contains? req :remote-addr)
|
||||||
|
(contains? req :uri)))
|
Reference in a new issue