diff --git a/project.clj b/project.clj index d106a9f..d69830c 100644 --- a/project.clj +++ b/project.clj @@ -16,6 +16,7 @@ [com.taoensso/encore "2.91.1"] [lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]] [com.cemerick/url "0.1.1"] + [ring/ring-anti-forgery "1.1.0"] [ring-server "0.4.0"] [selmer "1.10.9"] [org.clojure/tools.logging "0.4.0"] diff --git a/resources/templates/auth.html b/resources/templates/auth.html index abb8385..87ffbe2 100644 --- a/resources/templates/auth.html +++ b/resources/templates/auth.html @@ -2,6 +2,7 @@ {% block content %}
+ {% csrf-field %} {% if user %}

diff --git a/resources/templates/edit-css.html b/resources/templates/edit-css.html index 80037d1..bd5b50f 100644 --- a/resources/templates/edit-css.html +++ b/resources/templates/edit-css.html @@ -3,6 +3,7 @@ {% block content %}

+ {% csrf-field %}

diff --git a/resources/templates/edit-user.html b/resources/templates/edit-user.html index a99d1dd..7a41dd8 100644 --- a/resources/templates/edit-user.html +++ b/resources/templates/edit-user.html @@ -3,6 +3,7 @@ {% block content %}

+ {% csrf-field %}

diff --git a/resources/templates/edit.html b/resources/templates/edit.html index a5672a7..39496eb 100644 --- a/resources/templates/edit.html +++ b/resources/templates/edit.html @@ -7,6 +7,7 @@ {% block content %}

+ {% csrf-field %}

diff --git a/resources/templates/passwd.html b/resources/templates/passwd.html index b316475..e7fd0f0 100644 --- a/resources/templates/passwd.html +++ b/resources/templates/passwd.html @@ -2,6 +2,7 @@ {% block content %}

+ {% csrf-field %}

diff --git a/resources/templates/upload.html b/resources/templates/upload.html index 47c1555..6533878 100644 --- a/resources/templates/upload.html +++ b/resources/templates/upload.html @@ -19,6 +19,7 @@ {% endif %} {% else %} + {% csrf-field %}

diff --git a/src/smeagol/layout.clj b/src/smeagol/layout.clj index 8157d3c..cd72809 100644 --- a/src/smeagol/layout.clj +++ b/src/smeagol/layout.clj @@ -4,6 +4,7 @@ smeagol.layout (:require [selmer.parser :as parser] [clojure.string :as s] + [ring.util.anti-forgery :refer [anti-forgery-field]] [ring.util.response :refer [content-type response]] [compojure.response :refer [Renderable]] [environ.core :refer [env]] @@ -34,6 +35,8 @@ (def template-path "templates/") +(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field))) + (deftype RenderableTemplate [template params] Renderable diff --git a/src/smeagol/middleware.clj b/src/smeagol/middleware.clj index 7e047d0..ecf835c 100644 --- a/src/smeagol/middleware.clj +++ b/src/smeagol/middleware.clj @@ -5,6 +5,7 @@ [environ.core :refer [env]] [selmer.middleware :refer [wrap-error-page]] [prone.middleware :refer [wrap-exceptions]] + [ring.middleware.anti-forgery :refer [wrap-anti-forgery]] [noir-exception.core :refer [wrap-internal-error]])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -39,11 +40,13 @@ (def development-middleware [wrap-error-page - wrap-exceptions]) + wrap-exceptions + wrap-anti-forgery]) (def production-middleware - [#(wrap-internal-error % :log (fn [e] (timbre/error e)))]) + [#(wrap-internal-error % :log (fn [e] (timbre/error e))) + wrap-anti-forgery]) (defn load-middleware [] diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index 614f515..f921aad 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -7,7 +7,6 @@ [cemerick.url :refer (url url-encode url-decode)] [compojure.core :refer :all] [clj-jgit.porcelain :as git] - [environ.core :refer [env]] [noir.io :as io] [noir.response :as response] [noir.util.route :as route] @@ -46,18 +45,10 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def content-dir - (or - (env :smeagol-content-dir) - (cjio/file (io/resource-path) "content"))) - - - (defn get-git-repo "Get the git repository for my content, creating it if necessary" [] - (hist/load-or-init-repo content-dir)) + (hist/load-or-init-repo util/content-dir)) (defn process-source @@ -67,7 +58,7 @@ (let [source-text (:src params) page (:page params) file-name (str page suffix) - file-path (cjio/file content-dir file-name) + file-path (cjio/file util/content-dir file-name) exists? (.exists (cjio/as-file file-path)) git-repo (get-git-repo) user (session/get :user) @@ -96,7 +87,7 @@ src-text (:src params) page (or (:page params) default) file-name (str page suffix) - file-path (cjio/file content-dir file-name) + file-path (cjio/file util/content-dir file-name) exists? (.exists (cjio/as-file file-path)) user (session/get :user)] (if (not exists?) @@ -105,10 +96,10 @@ (cond src-text (process-source params suffix request) true (layout/render template - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (str (util/get-message :edit-title-prefix request) " " page) :page page - :side-bar (md->html (slurp (cjio/file content-dir side-bar))) + :side-bar (md->html (slurp (cjio/file util/content-dir side-bar))) :content (if exists? (slurp file-path) "") :exists exists?})))))) @@ -125,13 +116,13 @@ (let [params (keywordize-keys (:params request)) page (or (:page params) (util/get-message :default-page-title request)) file-name (str page ".md") - file-path (cjio/file content-dir file-name) + file-path (cjio/file util/content-dir file-name) exists? (.exists (clojure.java.io/as-file file-path))] (cond exists? (do (timbre/info (format "Showing page '%s' from file '%s'" page file-path)) (layout/render "wiki.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title page :page page :content (md->html (slurp file-path)) @@ -146,10 +137,10 @@ (let [params (keywordize-keys (:params request)) page (url-decode (or (:page params) (util/get-message :default-page-title request))) file-name (str page ".md") - repo-path content-dir] + repo-path util/content-dir] (timbre/info (format "Showing history of page '%s'" page)) (layout/render "history.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (str "History of " page) :page page :history (hist/find-history repo-path file-name)})))) @@ -162,7 +153,7 @@ upload (:upload params) uploaded (if upload (ul/store-upload params))] (layout/render "upload.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (util/get-message :file-upload-title request) :uploaded uploaded :is-image (and @@ -184,10 +175,10 @@ page (url-decode (or (:page params) (util/get-message :default-page-title request))) version (:version params) file-name (str page ".md") - content (hist/fetch-version content-dir file-name version)] + content (hist/fetch-version util/content-dir file-name version)] (timbre/info (format "Showing version '%s' of page '%s'" version page)) (layout/render "wiki.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (str (util/get-message :vers-col-hdr request) " " version " of " page) :page page :content (md->html content)})))) @@ -202,10 +193,10 @@ file-name (str page ".md")] (timbre/info (format "Showing diff between version '%s' of page '%s' and current" version page)) (layout/render "wiki.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (str (util/get-message :diff-title-prefix request)" " version " of " page) :page page - :content (d2h/diff2html (hist/diff content-dir file-name version))})))) + :content (d2h/diff2html (hist/diff util/content-dir file-name version))})))) (defn auth-page @@ -229,7 +220,7 @@ (response/redirect redirect-to)) true (layout/render "auth.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (if user (str (util/get-message :logout-link request) " " user) (util/get-message :login-link request)) :redirect-to ((:headers request) "referer")}))))) @@ -246,7 +237,7 @@ (auth/evaluate-password pass1 pass2) (auth/change-pass user oldpass pass2))] (layout/render "passwd.html" - (merge (util/standard-params request content-dir) + (merge (util/standard-params request) {:title (str (util/get-message :chpass-title-prefix request) " " user) :message (if changed? (util/get-message :chpass-success request)) :error (cond diff --git a/src/smeagol/util.clj b/src/smeagol/util.clj index 5fb0092..6e48e73 100644 --- a/src/smeagol/util.clj +++ b/src/smeagol/util.clj @@ -1,9 +1,10 @@ (ns ^{:doc "Miscellaneous utility functions supporting Smeagol." :author "Simon Brooke"} smeagol.util - (:require [noir.session :as session] - [clojure.java.io :as cljio] + (:require [clojure.java.io :as cjio] + [environ.core :refer [env]] [noir.io :as io] + [noir.session :as session] [scot.weft.i18n.core :as i18n] [smeagol.authenticate :as auth] [smeagol.configuration :refer [config]] @@ -33,14 +34,20 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(def content-dir + (or + (env :smeagol-content-dir) + (cjio/file (io/resource-path) "content"))) + + (defn standard-params "Return a map of standard parameters to pass to the template renderer." - [request content-dir] + [request] (let [user (session/get :user)] {:user user :admin (auth/get-admin user) - :side-bar (md->html (slurp (cljio/file content-dir "_side-bar.md"))) - :header (md->html (slurp (cljio/file content-dir "_header.md"))) + :side-bar (md->html (slurp (cjio/file content-dir "_side-bar.md"))) + :header (md->html (slurp (cjio/file content-dir "_header.md"))) :version (System/getProperty "smeagol.version")})) @@ -51,7 +58,7 @@ (merge (i18n/get-messages ((:headers request) "accept-language") - (.getAbsolutePath (cljio/file (io/resource-path) ".." "i18n")) + (.getAbsolutePath (cjio/file (io/resource-path) ".." "i18n")) "en-GB") config))