spec-based form validation

integration-tests
Josha von Gizycki 7 years ago
parent 254ac47edc
commit d67290b4af

@ -1,4 +1,5 @@
@ci-color: #ccc; @ci-color: #ccc;
@error-color: #e00;
@accent-color: #efefef; @accent-color: #efefef;
@border-stack: 1px solid @ci-color; @border-stack: 1px solid @ci-color;
@text-padding-v: .2rem; @text-padding-v: .2rem;
@ -32,7 +33,8 @@ a:active {
"nav main sidebar" "nav main sidebar"
"footer footer footer"; "footer footer footer";
margin: auto; margin: auto;
max-width: 900px; min-width: 900px;
width: 80%;
border-top: ; border-top: ;
nav { nav {
@ -106,11 +108,33 @@ form {
grid-column: 2; grid-column: 2;
} }
.flash--error {
.flash;
border-color: @error-color;
.flash__heading--error {
margin: 0;
background-color: @error-color;
color: white;
margin-top: -.7rem;
margin-left: -.7rem;
margin-right: -.7rem;
}
}
.flash { .flash {
grid-column: 1/3; grid-column: 1 e("/") 3;
.thin-border; .thin-border;
border-left-width: @accent-border-width; border-left-width: @accent-border-width;
padding: .7rem; padding: .7rem;
.flash__field {
font-style: italic;
}
.flash__pred {
font-family: monospace;
}
} }
} }

@ -14,8 +14,7 @@
(hashers/check pw hash))] (hashers/check pw hash))]
(if pwmatch (if pwmatch
(-> (redirect "/") (-> (redirect "/")
(assoc-in [:session :ident] uname) (assoc-in [:session :ident] uname))
(assoc-in [:session :unode] unode))
(-> (redirect "/login") (-> (redirect "/login")
(assoc :flash :invalid-credentials))))) (assoc :flash :invalid-credentials)))))

@ -4,6 +4,7 @@
[compojure.route :as route] [compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]] [ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[ring.util.response :as rur] [ring.util.response :as rur]
[ring.middleware.session.cookie :as session-cookie]
[wanijo.auth.routes :refer [auth-routes]] [wanijo.auth.routes :refer [auth-routes]]
[wanijo.home.routes :refer [home-routes]] [wanijo.home.routes :refer [home-routes]]
[wanijo.schema.routes :refer [schema-routes]])) [wanijo.schema.routes :refer [schema-routes]]))
@ -23,4 +24,6 @@
(def app (def app
(-> app-routes (-> app-routes
(wrap-defaults site-defaults))) (wrap-defaults (assoc-in site-defaults
[:session :store]
(session-cookie/cookie-store {:key "1234567890123456"})))))

@ -1,5 +1,9 @@
(ns wanijo.schema.routes (ns wanijo.schema.routes
(:require [compojure.core :refer [defroutes GET]] (:require [compojure.core :refer [defroutes GET POST]]
[ring.util.anti-forgery :refer [anti-forgery-field]]
[ring.util.response :as resp]
[hiccup.form :as hform]
[clojure.spec.alpha :as spec]
[wanijo.domain.schema :as domain-schemas] [wanijo.domain.schema :as domain-schemas]
[wanijo.view :as view])) [wanijo.view :as view]))
@ -10,7 +14,8 @@
(view/layout! (view/layout!
:session session :session session
:content :content
[[:table [[:h1 "Ali jaki ijo"]
[:table
[:thead [:thead
[:tr [:tr
[:th "Nimi"] [:th "Nimi"]
@ -19,7 +24,29 @@
(for [schema schemas] (for [schema schemas]
[:tr [:tr
[:td (:name schema)] [:td (:name schema)]
[:td (:created_at schema)]])]]]))) [:td (:created_at schema)]])]]
[:h1 "Pali sin e jaki ijo"]
(hform/form-to
[:post "/schema/new"]
(view/spec-to-errmsg ::new-schema req)
(hform/label "name" "Nimi")
(hform/text-field {:required "required"}
"schema-name"
(get-in req [:params :schema-name]))
(hform/submit-button "Kama")
(anti-forgery-field))])))
(spec/def ::schema-name
(spec/and some? string? not-empty))
(spec/def ::new-schema
(spec/keys :req-un [::schema-name]))
(defn- new! [req]
(if (spec/valid? ::new-schema (:params req))
(resp/redirect "/schema")
(overview! req)))
(defroutes schema-routes (defroutes schema-routes
(GET "/schema" [] overview!)) (GET "/schema" [] overview!)
(POST "/schema/new" [] new!))

@ -1,6 +1,7 @@
(ns wanijo.view (ns wanijo.view
(:require [hiccup.page :refer [html5 (:require [hiccup.page :refer [html5
include-css]])) include-css]]
[clojure.spec.alpha :as spec]))
(defn btnlink (defn btnlink
([target caption] ([target caption]
@ -34,10 +35,28 @@
(str "O, " ident)])] (str "O, " ident)])]
(when authed? (when authed?
[:section.header-content [:section.header-content
(btnlink "/schema" "Jaki Ijo" "header-content__link") (btnlink "/schema" "Jaki ijo" "header-content__link")
(btnlink "/logout" "Lape" "header-content__link")])] (btnlink "/logout" "Lape" "header-content__link")])]
[:nav (when authed? "nav")] [:nav (when authed? "nav")]
(vec (concat [:main] content)) (vec (concat [:main] content))
[:aside (when authed? "aside")] [:aside (when authed? "aside")]
[:footer [:footer
[:small "Ilo pali e ijo"]]]]))) [:small "Ilo pali e ijo"]]]])))
(defn flash-error [content]
[:section.flash--error
[:h2.flash__heading--error "Pakala"]
content])
(defn spec-to-errmsg [spec-key req]
(when-let [spec-data (and (not-empty (:params req))
(spec/explain-data spec-key (:params req)))]
(flash-error
(->> (:clojure.spec.alpha/problems spec-data)
(map
(fn [prob]
[:p
"Field \""
[:span.flash__field (first (:path prob))]
"\" must comply to "
[:span.flash__pred (:pred prob)]]))))))

Loading…
Cancel
Save