Tutorial 3 - Clojure Web Application Using Noir
Posted by: Deepali | 01 Mar 2013 | CommentsIn this tutorial we are going to cover how to manage a Session in Noir.
We need to provide the facility to users to login with their accounts.
So we have to first create pages for login and signup in our
src/finance_manager/views/welcome.clj file. Also we have to create a
table for users in our finance_manager_db database to store users
record.
First create table for users in src/finance-manager/models/db.clj
(defn create-user-table []
  (sql/with-connection
      db
      (sql/create-table
        :users
        [:id "SERIAL"]
        [:username "varchar(100)"]
        [:password "varchar(100)"]
       )
    )
)
Also write function to insert users record in users table. And a function to fetch user record from users table.
(defn add-user [user]
  (sql/with-connection
    db
    (sql/insert-record :users user)
  )
)
(defn get-user [username]
  (first
  (db-read "select * from users where username=?" username))
)
Open src/finance_manager/views/welcome.clj file and create pages for
login and signup.
(:require [noir.util.crypt :as crypt])
 ;;Login Page
(defpage "/" {:keys [error]}
  (common/layout
   [:div.error error]
   [:h2 "Login Page"]
   (form-to [:post "/login"]
     (label "username" "Username")
     (text-field "username")
      [:br]
     (label "password" "Password")
     (password-field "password")
     [:br]
     (submit-button {:class "btn"} "Login")
     (reset-button {:class "btn"} "Cancel")
   )
  )
)
;; Login Page Handler
(defpage [:post "/login"] user
  (let [getuser (db/get-user (:username user))]
          (if (and getuser (crypt/compare (:password user) (:password getuser)))
              (render "/homepage" (session/get :user))
              (render "/" (assoc user :error "Login Failed"))
          )
  )
)
;;Signup Page
(defpage "/signup" {:keys [error]}
  (common/layout
    [:h3 "Signup Form"]
    [:div.error error]
    (form-to [:post "/signup"]
      (label "username" "Username")
      (text-field "username")
      [:br]
      (label "password" "Password")
      (password-field "password")
      [:br]
      (submit-button "Signup")
      (reset-button "Cancel")
    )
  )
)
;; Signup Page Handler
(defpage [:post "/signup"] user
    (try
      (db/add-user (update-in user[:password] crypt/encrypt))
      (render "/homepage")
      (catch Exception ex
        (render "/signup" (assoc user :error (.getMessage ex)))
      )
    )
)
crypt/encrypt is used to encrypt the given password.
crypt/compare is used to compare the raw string with already encrypted
string.
For managing the session open src/finance_manager/views/welcome.clj
file.
(:require [noir.session :as session])
Then modify our [:post "/login"] and [:post "/signup"] pages.
(defpage [:post "/login"] user
     (let [getuser (db/get-user (:username user))]
              (if (and getuser (crypt/compare (:password user) (:password getuser)))
                (do
                   (session/put! :user (:username user))
                   (render "/homepage" (session/get :user))
                )
                 (render "/" (assoc user :error "Login Failed"))
              )
       )
)
(defpage [:post "/signup"] user
    (try
      (db/add-user (update-in user[:password] crypt/encrypt))
      (session/put! :user (:username user))
      (render "/homepage" (session/get! :user))
      (catch Exception ex
        (render "/signup" (assoc user :error (.getMessage ex)))
      )
    )
)
session/put! Associates the key with the given value in the session.
session/get Get the key’s value from the session, returns nil if it doesn’t exist.
Now create a page for logout to clear the session in
src/finance_manager/views/welcome.clj file.
 (defpage "/logout" []
  (session/clear!)
  (resp/redirect "/")) 
session/clear! Remove all data from the session.