aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--project.clj1
-rw-r--r--src/ctf_website/models.clj10
-rw-r--r--src/ctf_website/models/flags.clj14
-rw-r--r--src/ctf_website/models/scoreboard.clj18
-rw-r--r--src/ctf_website/server.clj4
-rw-r--r--src/ctf_website/views/common.clj3
-rw-r--r--src/ctf_website/views/flag.clj25
-rw-r--r--src/ctf_website/views/home.clj39
9 files changed, 95 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 019a626..2a69a81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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"}]]]))))