diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn
index 6f14c22..75955df 100644
--- a/env/dev/resources/config.edn
+++ b/env/dev/resources/config.edn
@@ -1,4 +1,6 @@
{:dev true
:port 3000
+ :creator-password "creator"
+ :user-password "user"
;; when :nrepl-port is set the application starts the nREPL server on load
:nrepl-port 7000}
diff --git a/env/prod/resources/config.edn b/env/prod/resources/config.edn
index b48cfbd..ec36ac6 100644
--- a/env/prod/resources/config.edn
+++ b/env/prod/resources/config.edn
@@ -1,2 +1,4 @@
{:production true
+ :creator-password "xxx"
+ :user-password "yyy"
:port 3000}
diff --git a/project.clj b/project.clj
index 5b4d0aa..2b19329 100644
--- a/project.clj
+++ b/project.clj
@@ -31,7 +31,8 @@
[markdown-clj "0.9.98"]
[clj-exif-orientation "0.2.1"]
[markdown-clj "0.9.98"]
- [clj-time "0.8.0"]]
+ [clj-time "0.8.0"]
+ [buddy/buddy-auth "1.4.1"]]
:min-lein-version "2.0.0"
diff --git a/resources/templates/detail.html b/resources/templates/detail.html
index 2cd86ca..6fe67bb 100644
--- a/resources/templates/detail.html
+++ b/resources/templates/detail.html
@@ -31,7 +31,7 @@
diff --git a/resources/templates/layout.html b/resources/templates/layout.html
index a183257..d97379f 100644
--- a/resources/templates/layout.html
+++ b/resources/templates/layout.html
@@ -8,9 +8,11 @@
@@ -52,8 +60,8 @@
{% style "/assets/bootstrap/css/bootstrap.min.css" %}
@@ -63,6 +71,7 @@
{% script "/assets/jquery/jquery.min.js" %}
diff --git a/resources/templates/login.html b/resources/templates/login.html
new file mode 100644
index 0000000..4ef0ae3
--- /dev/null
+++ b/resources/templates/login.html
@@ -0,0 +1,26 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+
+
+
+
Um die Seite anzusehen oder die Aktion auszuführen wird ein Passwort benötigt.
+
+
+
+
+
+{% endblock %}
diff --git a/src/clj/yenu/handler.clj b/src/clj/yenu/handler.clj
index 6b30711..99df19e 100644
--- a/src/clj/yenu/handler.clj
+++ b/src/clj/yenu/handler.clj
@@ -1,6 +1,7 @@
(ns yenu.handler
(:require [compojure.core :refer [routes wrap-routes]]
[yenu.layout :refer [error-page]]
+ [yenu.routes.auth :refer [auth-routes]]
[yenu.routes.core :refer [core-routes]]
[yenu.routes.admin :refer [admin-routes]]
[compojure.route :as route]
@@ -14,12 +15,22 @@
(def app-routes
(routes
+ (-> #'auth-routes
+ (wrap-routes middleware/wrap-csrf)
+ (wrap-routes middleware/wrap-identity)
+ (wrap-routes middleware/wrap-formats))
(-> #'core-routes
(wrap-routes middleware/wrap-csrf)
- (wrap-routes middleware/wrap-formats))
+ (wrap-routes middleware/wrap-formats)
+ (wrap-routes middleware/wrap-identity)
+ (wrap-routes middleware/wrap-auth)
+ )
(-> #'admin-routes
(wrap-routes middleware/wrap-csrf)
- (wrap-routes middleware/wrap-formats))
+ (wrap-routes middleware/wrap-formats)
+ (wrap-routes middleware/wrap-identity)
+ (wrap-routes middleware/wrap-auth)
+ )
(route/not-found
(:body
(error-page {:status 404
diff --git a/src/clj/yenu/layout.clj b/src/clj/yenu/layout.clj
index 598d424..fb30e21 100644
--- a/src/clj/yenu/layout.clj
+++ b/src/clj/yenu/layout.clj
@@ -8,6 +8,7 @@
[clj-time.format :as time-format])
(:use [markdown.core]))
+(declare ^:dynamic *identity*)
(declare ^:dynamic *app-context*)
(parser/set-resource-path! (clojure.java.io/resource "templates"))
(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
@@ -26,7 +27,9 @@
(assoc params
:page template
:csrf-token *anti-forgery-token*
- :servlet-context *app-context*)))
+ :servlet-context *app-context*
+ :identity *identity*
+ )))
"text/html; charset=utf-8"))
(defn error-page
diff --git a/src/clj/yenu/middleware.clj b/src/clj/yenu/middleware.clj
index bce0d00..bb4f57f 100644
--- a/src/clj/yenu/middleware.clj
+++ b/src/clj/yenu/middleware.clj
@@ -1,14 +1,21 @@
(ns yenu.middleware
(:require [yenu.env :refer [defaults]]
[clojure.tools.logging :as log]
- [yenu.layout :refer [*app-context* error-page]]
+ [yenu.layout :refer [*app-context* *identity* error-page]]
[ring.middleware.anti-forgery :refer [wrap-anti-forgery]]
[ring.middleware.webjars :refer [wrap-webjars]]
[ring.middleware.format :refer [wrap-restful-format]]
[yenu.config :refer [env]]
[ring.middleware.flash :refer [wrap-flash]]
[immutant.web.middleware :refer [wrap-session]]
- [ring.middleware.defaults :refer [site-defaults wrap-defaults]])
+ [ring.middleware.defaults :refer [site-defaults wrap-defaults]]
+ [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]
+ [buddy.auth.accessrules :refer [wrap-access-rules]]
+ [buddy.auth.backends.session :refer [session-backend]]
+ [buddy.auth.accessrules :refer [restrict]]
+ [ring.util.response :refer [redirect]]
+ [buddy.auth.accessrules :refer [success error]]
+ [buddy.auth :refer [authenticated?]])
(:import [javax.servlet ServletContext]))
(defn wrap-context [handler]
@@ -38,29 +45,56 @@
(defn wrap-csrf [handler]
(wrap-anti-forgery
- handler
- {:error-response
- (error-page
- {:status 403
- :title "Invalid anti-forgery token"})}))
+ handler
+ {:error-response
+ (error-page
+ {:status 403
+ :title "Invalid anti-forgery token"})}))
+
+(defn wrap-identity [handler]
+ (fn [request]
+ (binding [*identity* (get-in request [:session :identity])]
+ (handler request))))
(defn wrap-formats [handler]
(let [wrapped (wrap-restful-format
- handler
- {:formats [:json-kw :transit-json :transit-msgpack]})]
+ handler
+ {:formats [:json-kw :transit-json :transit-msgpack]})]
(fn [request]
;; disable wrap-formats for websockets
;; since they're not compatible with this middleware
((if (:websocket? request) handler wrapped) request))))
+(defn wrap-auth [handler]
+ (let [backend (session-backend)]
+ (-> handler
+ (wrap-access-rules {:rules rules :on-error on-error})
+ (wrap-authentication backend)
+ (wrap-authorization backend))))
+
+(defn on-error [request response]
+ (redirect "/login"))
+
+(defn creator-access [request]
+ (let [identity (:identity request)]
+ (if (= identity :creator)
+ true
+ (error "Not a creator."))))
+
+(def rules
+ [{:uris ["/upload" "/statistics" "/comments"]
+ :handler creator-access}
+ {:pattern #"^/.*"
+ :handler authenticated?}])
+
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
wrap-webjars
wrap-flash
(wrap-session {:cookie-attrs {:http-only true}})
(wrap-defaults
- (-> site-defaults
- (assoc-in [:security :anti-forgery] false)
- (dissoc :session)))
+ (-> site-defaults
+ (assoc-in [:security :anti-forgery] false)
+ (dissoc :session)))
wrap-context
wrap-internal-error))
diff --git a/src/clj/yenu/routes/admin.clj b/src/clj/yenu/routes/admin.clj
index af11800..04a5653 100644
--- a/src/clj/yenu/routes/admin.clj
+++ b/src/clj/yenu/routes/admin.clj
@@ -42,4 +42,9 @@
(-> (upload-file file)
(images/process-image)
(add-image-to-database title description tags))
- (redirect "/")))
+ (redirect "/"))
+
+ (GET "/statistics" []
+ (layout/render "statistics.html"))
+ (GET "/comments" []
+ (layout/render "comments.html")))
diff --git a/src/clj/yenu/routes/auth.clj b/src/clj/yenu/routes/auth.clj
new file mode 100644
index 0000000..c2af0f2
--- /dev/null
+++ b/src/clj/yenu/routes/auth.clj
@@ -0,0 +1,30 @@
+(ns yenu.routes.auth
+ (:require [yenu.layout :as layout]
+ [compojure.core :refer [defroutes GET POST]]
+ [yenu.config :refer [env]]
+ [ring.util.response :refer [redirect]]))
+
+(defn valid-identity [password]
+ (cond
+ (= password (:creator-password env)) :creator
+ (= password (:user-password env)) :user))
+
+(defn login! [request]
+ (let [password (get-in request [:form-params "password"])
+ session (:session request)
+ user-identity (valid-identity password)]
+ (if user-identity
+ (let [updated-session (assoc session :identity user-identity)]
+ (-> (redirect "/")
+ (assoc :session updated-session))))))
+
+(defn logout! [request]
+ (-> (redirect "/")
+ (assoc :session {})))
+
+(defroutes auth-routes
+ (GET "/login" []
+ (layout/render "login.html"))
+ (POST "/login" [] login!)
+
+ (GET "/logout" [] logout!))
diff --git a/src/clj/yenu/routes/core.clj b/src/clj/yenu/routes/core.clj
index d1b1268..a168fbe 100644
--- a/src/clj/yenu/routes/core.clj
+++ b/src/clj/yenu/routes/core.clj
@@ -35,6 +35,7 @@
(let [filename (str hash "." ext)]
(file-response (images/data-path "gallery" type filename))))
+
(defroutes core-routes
(GET "/" []
(redirect "/page/1"))
@@ -48,10 +49,4 @@
;;:ext #"(png|jpg)"
]
[type hash ext]
- (image-file type hash ext))
-
- (GET "/statistics" []
- (layout/render "statistics.html"))
- (GET "/comments" []
- (layout/render "comments.html")))
-
+ (image-file type hash ext)))