 ;; Since this module is dependent on bidi, let's provide some sample
 ;; bidi routes that can be used as-is or to demonstrate.
 
-(defn new-login-get-handler [handlers-p post-handler-key]
+(defn new-login-get-handler [handlers-p post-handler-key {:keys [boilerplate] :as opts}]
   (fn [{{{requested-uri :value} "requested-uri"} :cookies
         routes :modular.bidi/routes}]
-    {:status 200
-     :body
-     (html
-      [:body
-       [:form {:method "POST" :style "border: 1px dotted #555"
-               :action (bidi/path-for routes (get @handlers-p post-handler-key))}
-        (when requested-uri
-          [:input {:type "hidden" :name :requested-uri :value requested-uri}])
-        [:div
-         [:label {:for "username"} "Username"]
-         [:input {:id "username" :name "username" :type "input"}]]
-        [:div
-         [:label {:for "password"} "Password"]
-         [:input {:id "password" :name "password" :type "password"}]]
-        [:input {:type "submit" :value "Login"}]
-        ]])}))
+    (let [form
+          [:form {:method "POST" :style "border: 1px dotted #555"
+                  :action (bidi/path-for routes (get @handlers-p post-handler-key))}
+           (when requested-uri
+             [:input {:type "hidden" :name :requested-uri :value requested-uri}])
+           [:div
+            [:label {:for "username"} "Username"]
+            [:input {:id "username" :name "username" :type "input"}]]
+           [:div
+            [:label {:for "password"} "Password"]
+            [:input {:id "password" :name "password" :type "password"}]]
+           [:input {:type "submit" :value "Login"}]
+           ]]
+      {:status 200
+       :body (if boilerplate (boilerplate (html form)) (html [:body form]))})))
 
 (defn new-login-post-handler [handlers-p get-handler-key {:keys [authorizer http-session-store] :as opts}]
   (s/validate {:authorizer (s/protocol UserPasswordAuthorizer)
-               :http-session-store (s/protocol HttpSessionStore)} opts)
+               :http-session-store (s/protocol HttpSessionStore)}
+              opts)
   (fn [{{username "username" password "password" requested-uri "requested-uri"} :form-params
         routes :modular.bidi/routes}]
 

  structure, or a function that takes the component and returns a bidi
  route structure."  [routes context]
  (->ProtectedBidiRoutes routes context))

  (routes [this] (routes (:login this)))
  (context [this] (context (:login this))))

(def new-default-protection-domain-schema {(s/optional-key :session-timeout-in-seconds) s/Int
                                           (s/optional-key :boilerplate) (s/=> 1)})

(defn new-default-protection-domain [opts]
  (s/validate new-default-protection-domain-schema opts)
  (map->ProtectionDomain
   {:login (if-let [boilerplate (:boilerplate opts)]
             (new-login-form :boilerplate boilerplate)
             (new-login-form))
    :authorizer (new-map-backed-user-registry {"malcolm" "password"})
    :http-session-store (new-atom-backed-session-store
                         (or (:session-timeout-in-seconds opts)
                             10))}))

;; Now that we have a protection domain, we want the ability to create
