1 Namespaces

(ns exam-vault.routes.gateway
  (:require [compojure.core :refer :all]
	    [ring.util.response :as resp]
	    [net.cgrand.enlive-html :as enlive]
	    [hiccup.form :refer [form-to text-field password-field submit-button]]
	    [exam-vault.leechness :as leech]
	    [exam-vault.views.layout :as layout]))

2 Login Regex

(def login-regex #"(?i)[A-Z]\d{7}")

3 Gateway Display

(defn gateway-display []
  (layout/login [:section {:class "gateway"}
		 [:header
		  [:div {:class "verse-logo"} "logo"]
		  [:h1 "Welcome to " [:strong "NCLVerse"]]]
		 (form-to
		  [:post "/login"]
		  (text-field {:class "username" :placeholder "NCL StudentID"} "username")
		  (password-field {:class "password" :placeholder "Password"} "password")
		  (submit-button "Login"))]))

4 Scraper

(defn scraper [name pass]
  (leech/ness name pass))

5 Get credentials

(defn get-credentials [page]
  (let [area (enlive/select page [:#uname :span])
	details (apply str (some :content area))
	student-id (second (re-find #"\((\d+)\)" details))
	name (second (re-find #"(.*)\(" details))]
    {:id student-id :name (clojure.string/trim name)}))

6 Get modules

(defn get-modules [page]
  (let [modules (mapcat :content (enlive/select (enlive/select page [:#topmenu]) [:a]))]
    {:modules (clojure.string/join " " modules)}))
(defn exam-scrape [id password]
  (if-let [page (enlive/html-snippet (:body (:response (scraper id password))))]
    (if (and (get-credentials page) (get-modules page)) 
      (merge (get-credentials page) (get-modules page)) false) false))

7 Validation

When there's a valid login, but the app is not yet ready, show an alert message.
(defn valid? [username pass] (re-matches login-regex username))

7.1 Check for Demo

(defn demo? [username pass] (and (= username "demo") (= pass "please")))
(defn in? [cookies] (let [verify #(contains? cookies %)]
		      (and (verify "id") (verify "name") (verify "modules"))))
(def demo-response (assoc (resp/redirect "/") :cookies {"id" {:value "B0123456"} "name" {:value "The Dude"} "modules" {:value "CSC3221 CSC3223 CSC3324 CSC3423 CSC3621"}}))
(defn login [username password cookies]
  (cond (demo? username password) demo-response
	(valid? username password)
	(let [ness-data (exam-scrape username password)] (assoc (resp/redirect "/") :cookies ness-data))
	:else (gateway-display)))
(defn logout [req]
  (let [clear-value {:value "" :max-age 0}]
    (update-in (resp/redirect "/login") [:cookies] merge {"id" clear-value "name" clear-value "modules" clear-value})))
Find a way to flash alerts when the login is wrong
(defroutes gateway-routes
  (GET "/login" {cookies :cookies} (if (in? cookies) (resp/redirect "/") (gateway-display)))
  (POST "/login" [username password :as {cookies :cookies}]
	(cond (demo? username password) demo-response
	      (valid? username password)
	      (let [ness-data (exam-scrape username password)] (assoc (resp/redirect "/") :cookies ness-data))
	      :else (gateway-display)))
  (POST "/logout" req (logout req)))