From d67290b4affd2f13aec3c1ca03c65c64f148e318 Mon Sep 17 00:00:00 2001 From: Josha von Gizycki Date: Mon, 26 Mar 2018 21:32:17 +0200 Subject: [PATCH] spec-based form validation --- resources/app/stylesheets/app.less | 28 ++++++++++++++++++++++-- src/wanijo/auth/routes.clj | 3 +-- src/wanijo/handler.clj | 5 ++++- src/wanijo/schema/routes.clj | 35 ++++++++++++++++++++++++++---- src/wanijo/view.clj | 23 ++++++++++++++++++-- 5 files changed, 83 insertions(+), 11 deletions(-) diff --git a/resources/app/stylesheets/app.less b/resources/app/stylesheets/app.less index 82f243c..e550d54 100644 --- a/resources/app/stylesheets/app.less +++ b/resources/app/stylesheets/app.less @@ -1,4 +1,5 @@ @ci-color: #ccc; +@error-color: #e00; @accent-color: #efefef; @border-stack: 1px solid @ci-color; @text-padding-v: .2rem; @@ -32,7 +33,8 @@ a:active { "nav main sidebar" "footer footer footer"; margin: auto; - max-width: 900px; + min-width: 900px; + width: 80%; border-top: ; nav { @@ -106,11 +108,33 @@ form { 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 { - grid-column: 1/3; + grid-column: 1 e("/") 3; .thin-border; border-left-width: @accent-border-width; padding: .7rem; + + .flash__field { + font-style: italic; + } + + .flash__pred { + font-family: monospace; + } } } diff --git a/src/wanijo/auth/routes.clj b/src/wanijo/auth/routes.clj index 883f101..7656b5c 100644 --- a/src/wanijo/auth/routes.clj +++ b/src/wanijo/auth/routes.clj @@ -14,8 +14,7 @@ (hashers/check pw hash))] (if pwmatch (-> (redirect "/") - (assoc-in [:session :ident] uname) - (assoc-in [:session :unode] unode)) + (assoc-in [:session :ident] uname)) (-> (redirect "/login") (assoc :flash :invalid-credentials))))) diff --git a/src/wanijo/handler.clj b/src/wanijo/handler.clj index 3857080..406d28f 100644 --- a/src/wanijo/handler.clj +++ b/src/wanijo/handler.clj @@ -4,6 +4,7 @@ [compojure.route :as route] [ring.middleware.defaults :refer [wrap-defaults site-defaults]] [ring.util.response :as rur] + [ring.middleware.session.cookie :as session-cookie] [wanijo.auth.routes :refer [auth-routes]] [wanijo.home.routes :refer [home-routes]] [wanijo.schema.routes :refer [schema-routes]])) @@ -23,4 +24,6 @@ (def app (-> app-routes - (wrap-defaults site-defaults))) + (wrap-defaults (assoc-in site-defaults + [:session :store] + (session-cookie/cookie-store {:key "1234567890123456"}))))) diff --git a/src/wanijo/schema/routes.clj b/src/wanijo/schema/routes.clj index 54ce2c7..59a945e 100644 --- a/src/wanijo/schema/routes.clj +++ b/src/wanijo/schema/routes.clj @@ -1,5 +1,9 @@ (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.view :as view])) @@ -10,7 +14,8 @@ (view/layout! :session session :content - [[:table + [[:h1 "Ali jaki ijo"] + [:table [:thead [:tr [:th "Nimi"] @@ -19,7 +24,29 @@ (for [schema schemas] [:tr [: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 - (GET "/schema" [] overview!)) + (GET "/schema" [] overview!) + (POST "/schema/new" [] new!)) diff --git a/src/wanijo/view.clj b/src/wanijo/view.clj index 12adb0f..f05c177 100644 --- a/src/wanijo/view.clj +++ b/src/wanijo/view.clj @@ -1,6 +1,7 @@ (ns wanijo.view (:require [hiccup.page :refer [html5 - include-css]])) + include-css]] + [clojure.spec.alpha :as spec])) (defn btnlink ([target caption] @@ -34,10 +35,28 @@ (str "O, " ident)])] (when authed? [:section.header-content - (btnlink "/schema" "Jaki Ijo" "header-content__link") + (btnlink "/schema" "Jaki ijo" "header-content__link") (btnlink "/logout" "Lape" "header-content__link")])] [:nav (when authed? "nav")] (vec (concat [:main] content)) [:aside (when authed? "aside")] [:footer [: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)]]))))))