/sandbar

A Clojure web application library with higher level abstractions for Compojure and Ring

Primary LanguageClojureEclipse Public License 1.0EPL-1.0

Sandbar

Sandbar is a web application library which is designed to be used with Compojure and/or Ring. It builds on these projects providing the following additional features:

  • Session and flash as a global map
  • Authorization and authentication, including built-in support for form-based authentication
  • Forms and form validation

More documentation is located in the Sandbar Wiki.

You may also be interested in joining the Sandbar Google Group.

Sessions

Replace wrap-session with wrap-stateful-session and downstream from any wrapped handler you may access the session through a map interface.


(defn form-authentication [request]
  (do (session-put! :auth-redirect-uri (:uri request))
      (redirect "/login")))

(defn get-auth-success-redirect []
  (or (session-get :auth-redirect-uri)
      (property-lookup adapter :login-page)))

Flash is supported as well with flash-put! and flash-get.

For more detailed documentation see the Stateful Sessions page in the Sandbar Wiki.

Forms and Form Validation

Create a simple form with one textfield and validate its input.


(defform user-form "/user/edit"
  :fields [(hidden :id)
           (textfield "Username" :username)]
  :load #(db/find-user %)
  :on-cancel "/"
  :on-success
  #(do
     (db/store-user %)
     (set-flash-value! :user-message "User has been saved.")
     "/")
  :validator
  #(if (< (count (:username %)) 5)
     (add-validation-error % :username "Username must have at least 5 chars.")
     %))

(defroutes routes
  (user-form (fn [request form] (layout form))))

For more detailed documentation see the Forms or Form Validation pages in the Sandbar Wiki.

Authentication and Authorization

Create a security policy…


(def security-policy
     [#"/admin.*"                   :admin 
      #"/permission-denied.*"       :any
      #"/login.*"                   :any 
      #".*\.(css|js|png|jpg|gif)$"  :any 
      #".*"                         #{:admin :user}])

…and an authenticator.


(defauth form-auth
  :type :form
  :load (fn [username password]
          (merge (database/find-user username) {:login-password password}))
  :validator #(if (= (:password %) (:login-password %))
                %
                (add-validation-error % "Incorrect username or password!")))

Add the authenticator to your routes.


(defroutes routes
  (form-auth (fn [request content] (layout content)))
  (ANY "*" [] (layout (home-view))))

Add the with-security wrapper, passing it the security policy and the authenticator.


(def app
     (-> routes
       (with-security security-policy form-auth)
       wrap-stateful-session))

Use it!


(ensure-any-role #{:user :admin}
  (disintegrate "something"))

For more detailed documentation see the Authentication and Authorization page in the Sandbar Wiki.

Other Examples

Within Sandbar are some working examples which may be helpful. The Sandbar Examples project contains other examples of Sandbar usage. You may also want to take a look at the Clojure Web project which uses Sandbar in the Authentication examples.

Using Sandbar in your project

Leiningen

Add [sandbar/sandbar "0.4.0-SNAPSHOT"] to your :dependencies in project.clj.

Maven

Add the following dependency:

<dependency>
  <groupId>sandbar</groupId>
  <artifactId>sandbar</artifactId>
  <version>0.4.0-SNAPSHOT</version>
</dependency>

which comes from Clojars…

<repository>
  <id>clojars.org</id>
  <url>http://clojars.org/repo</url>
</repository>

Please note that any code with a namespace prefix of sandbar.dev is very pre-alpha. It will change often and may not work.

License

Copyright © 2010 Brenton Ashworth

Thanks to Allen Rohner for his help with this project.

Distributed under the Eclipse Public License, the same as Clojure uses. See the file COPYING.