Implement generic request validation

Ryan Rix 8 years ago
parent 2c8d99fd2c
commit 04114ad0cd

@ -8,6 +8,7 @@
[com.datomic/datomic-free "0.9.5201"]
[ring/ring-defaults "0.1.2"]
[com.cemerick/friend "0.2.0-SNAPSHOT"]
[prismatic/schema "0.4.3"]
[org.clojure/tools.nrepl "0.2.10"]]
:plugins [[lein-ring "0.9.2"]]
:ring {:handler verse.handler/app

@ -1,5 +1,7 @@
(ns verse.models.user
(:require [datomic.api :as d]
[cemerick.friend.credentials :refer (hash-bcrypt)]
[verse.coll :as coll]))
(defn get-by-username "Fetch a user object by their username" [username]
@ -11,3 +13,30 @@
:person/display-name "Ryan Rix"})
(coll/put {:person/username "dbutts"
:person/display-name "Dick McButtsky"}))
;; Input Validation
(def NewParms
"A schema for validating calls to `verse.models.user/new'"
{(s/required-key :username) s/Str
(s/optional-key :name) s/Str
(s/required-key :pass) s/Str
(s/required-key :passconf) s/Str
(s/required-key :email) s/Str
(s/required-key :toc-agree) s/Str
(s/required-key :age-agree) s/Str})
(def Rules
"A list of functions to evaluate, and their failing error message"
[(fn [parms] (if (s/check NewParms parms)
"Failed validation, ensure all fields are filled in."))
(fn [parms] (let [username (:username parms)]
(if (and username
(get-by-username username))
"Username already in use, try a new one.")))
(fn [parms] (if (not (= (:pass parms) (:passconf parms)))
"Password and password confirmation do not match."))
(fn [parms] (if (not (= "on" (:toc-agree parms)))
"You must agree to the terms of service."))
(fn [parms] (if (not (= "on" (:age-agree parms)))
"You must be at least 18 years of age to have an account on this site."))])

@ -26,6 +26,14 @@
:db/doc "A person's displayed name/handle"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :person/password
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/fulltext false
:db/doc "A person's password"
:db.install/_attribute :db.part/db}
;; Model
{:db/id #db/id[:db.part/db]
:db/ident :model/name

@ -30,3 +30,12 @@
(defn get-current-profile [session]
(let [id (:uid session)]
(coll/get-object id)))
(defn set-current-profile [session user]
(conj session {:uid (:db/id user)}))
(defn form-params-to-keywords "Converts a bunch form-params object from string keys to keyword keys" [parms]
(into {}
(map (fn [pair]
[(keyword (first pair)) (second pair)])

@ -0,0 +1,13 @@
(ns verse.validate
(:require [schema.core :as s]))
(defn validate "Validate a request map against a ruleset" [rules parms]
(let [massaged-parms (dissoc parms "__anti-forgery-token")]
(remove nil?
(apply (fn [rules-left errors]
(if (> (count rules-left) 0)
(let [rule (last rules-left)]
(recur (pop rules-left)
(conj errors (apply rule [massaged-parms]))))
[rules []]))))