diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | project.clj | 1 | ||||
-rw-r--r-- | src/ctf_website/models.clj | 10 | ||||
-rw-r--r-- | src/ctf_website/models/flags.clj | 14 | ||||
-rw-r--r-- | src/ctf_website/models/scoreboard.clj | 18 | ||||
-rw-r--r-- | src/ctf_website/server.clj | 4 | ||||
-rw-r--r-- | src/ctf_website/views/common.clj | 3 | ||||
-rw-r--r-- | src/ctf_website/views/flag.clj | 25 | ||||
-rw-r--r-- | src/ctf_website/views/home.clj | 39 |
9 files changed, 95 insertions, 20 deletions
@@ -4,3 +4,4 @@ pom.xml /classes/ .lein-deps-sum .lein-failures +sdb.db diff --git a/project.clj b/project.clj index a99efe2..633f99a 100644 --- a/project.clj +++ b/project.clj @@ -2,6 +2,7 @@ :description "FIXME: write this!" :dependencies [[org.clojure/clojure "1.3.0"] [noir "1.2.1"] + [simpledb "0.1.4"] [net.sf.jpam/jpam "1.1"]] :main ctf-website.server) diff --git a/src/ctf_website/models.clj b/src/ctf_website/models.clj new file mode 100644 index 0000000..a6f43f8 --- /dev/null +++ b/src/ctf_website/models.clj @@ -0,0 +1,10 @@ +(ns ctf-website.models + (:require [simpledb.core :as db] + [ctf-website.models.flags :as flags] + [ctf-website.models.scoreboard :as scoreboard])) + +(defn initialize [] + (db/init) + (when-not (db/get :flags) + (flags/init!) + (scoreboard/init!))) diff --git a/src/ctf_website/models/flags.clj b/src/ctf_website/models/flags.clj new file mode 100644 index 0000000..f25573f --- /dev/null +++ b/src/ctf_website/models/flags.clj @@ -0,0 +1,14 @@ +(ns ctf-website.models.flags + (:require [simpledb.core :as db] + [ctf-website.models.scoreboard :as scoreboard])) + +(defn init! [] + (db/put! :flags {})) + +(defn submit! [username flag] + (let [flag-info (get (db/get :flags) flag)] + (if (nil? flag-info) + false + (do + (scoreboard/update! username flag-info) + true)))) diff --git a/src/ctf_website/models/scoreboard.clj b/src/ctf_website/models/scoreboard.clj new file mode 100644 index 0000000..c03f018 --- /dev/null +++ b/src/ctf_website/models/scoreboard.clj @@ -0,0 +1,18 @@ +(ns ctf-website.models.scoreboard + (:import java.util.Date) + (:require [simpledb.core :as db])) + +(defn init! [] + (db/put! :scoreboard {})) + +(defn update! [username flag-info] + (db/update! + :scoreboard + (fn [board] + (assoc-in board [username flag-info] (str (Date.)))))) + +(defn get-scores [] + (db/get :scoreboard)) + +(defn has [username flag-info] + (not (nil? (get (get (db/get :scoreboard) username) flag-info)))) diff --git a/src/ctf_website/server.clj b/src/ctf_website/server.clj index 95e5309..afdac9d 100644 --- a/src/ctf_website/server.clj +++ b/src/ctf_website/server.clj @@ -1,5 +1,6 @@ (ns ctf-website.server - (:require [noir.server :as server])) + (:require [noir.server :as server] + [ctf-website.models :as models])) (server/load-views "src/ctf_website/views/") @@ -16,6 +17,7 @@ (defn -main [& m] (let [mode (keyword (or (first m) :dev)) port (Integer. (get (System/getenv) "PORT" "80"))] + (models/initialize) (server/start port {:mode mode :jetty-options {:ssl? true :ssl-port 443 diff --git a/src/ctf_website/views/common.clj b/src/ctf_website/views/common.clj index 7f0712e..21d21fd 100644 --- a/src/ctf_website/views/common.clj +++ b/src/ctf_website/views/common.clj @@ -5,8 +5,7 @@ (defpartial layout [& content] (html5 [:head - [:title "ctf-website"] - (include-css "/css/reset.css")] + [:title "ctf-website"]] [:body [:div#wrapper content]])) diff --git a/src/ctf_website/views/flag.clj b/src/ctf_website/views/flag.clj index c174215..ca16294 100644 --- a/src/ctf_website/views/flag.clj +++ b/src/ctf_website/views/flag.clj @@ -1,22 +1,17 @@ (ns ctf-website.views.flag (:require [ctf-website.views.common :as common] + [ctf-website.models.flags :as flags] [noir.session :as session]) (:use [noir.core :only [defpage]] - [hiccup.core :only [html]])) - -(def no-session - (common/layout - [:p "You seem to have lost your session. Try to " - [:a {:href "login"} "login"] - " again."])) - -(def good - (common/layout - [:p "Your flag was accepted."])) + [hiccup.page-helpers :only [link-to]])) (defpage [:post "/flag"] {:keys [flag]} - (let [username (session/get :user)] - (if (nil? username) - no-session - good))) + (common/layout + (let [username (session/get :user)] + (if (nil? username) + [:p "You seem to have lost your session. Try to " + (link-to "login" "login") " again."] + (if (flags/submit! username flag) + [:p "Your flag was accepted."] + [:p "Your flag was rejected."]))))) diff --git a/src/ctf_website/views/home.clj b/src/ctf_website/views/home.clj index 566a9ca..a2263ec 100644 --- a/src/ctf_website/views/home.clj +++ b/src/ctf_website/views/home.clj @@ -1,20 +1,55 @@ (ns ctf-website.views.home (:require [ctf-website.views.common :as common] + [ctf-website.models.scoreboard :as scoreboard] [noir.session :as session]) - (:use [noir.core :only [defpage]] + (:use [noir.core :only [defpage defpartial]] [hiccup.core :only [h]])) +(defn sorted-flags [scores] + (sort (set (mapcat keys (vals scores))))) + +(defn sorted-users [scores] + (sort (keys scores))) + +(defpartial + table-header [flag] + [:th flag]) + +(defpartial + table-cell [scores user flag] + [:td (get (get scores user) flag)]) + +(defpartial + table-row [scores flags user] + [:tr + [:td user] + (map (partial table-cell scores user) flags)]) + +(defpartial + scoreboard-table [scores] + (let [flags (sorted-flags scores) + users (sorted-users scores)] + [:table {:border "1"} + [:thead + [:th "Competitor"] + (map table-header flags)] + [:tbody + (map (partial table-row scores flags) users)]])) + (defpage "/" [] (let [username (session/get :user)] (common/layout [:h1 "Austin 2600 CTF server"] + (scoreboard-table (scoreboard/get-scores)) (if (nil? username) [:a {:href "login"} "Compete"] [:form {:method "POST" :action "flag"} [:p (str "Submit flag as " (h username) ":") [:input {:type "text" - :name "flag"}] + :name "flag" + :value (when (not (scoreboard/has username "test")) + "b46911b2d927d89bc2b1143a7f5d9c20")}] [:input {:type "submit" :value "Submit"}]]])))) |