129 lines
4.8 KiB
Clojure
129 lines
4.8 KiB
Clojure
(ns^{:doc "Render web pages using Selmer templating markup."
|
|
:author "Simon Brooke"}
|
|
youyesyet.layout
|
|
(:require [adl-support.filters :refer :all]
|
|
[adl-support.tags :as tags]
|
|
[clojure.string :refer [lower-case]]
|
|
[clojure.tools.logging :as log]
|
|
[markdown.core :refer [md-to-html-string]]
|
|
[ring.util.http-response :refer [content-type ok]]
|
|
[ring.util.anti-forgery :refer [anti-forgery-field]]
|
|
[ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
|
|
[selmer.parser :as parser]
|
|
[selmer.filters :as filters]
|
|
[youyesyet.config :refer [env]]
|
|
[youyesyet.db.core :as db]
|
|
))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;;
|
|
;;;; youyesyet.layout: lay out Selmer-templated web pages.
|
|
;;;;
|
|
;;;; This program is free software; you can redistribute it and/or
|
|
;;;; modify it under the terms of the GNU General Public License
|
|
;;;; as published by the Free Software Foundation; either version 2
|
|
;;;; of the License, or (at your option) any later version.
|
|
;;;;
|
|
;;;; This program is distributed in the hope that it will be useful,
|
|
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;;;; GNU General Public License for more details.
|
|
;;;;
|
|
;;;; You should have received a copy of the GNU General Public License
|
|
;;;; along with this program; if not, write to the Free Software
|
|
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
;;;; USA.
|
|
;;;;
|
|
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
|
|
;;;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
(declare ^:dynamic *app-context*)
|
|
(def ^:dynamic *user* nil)
|
|
|
|
(parser/set-resource-path! (clojure.java.io/resource "templates"))
|
|
(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
|
|
(filters/add-filter! :markdown (fn [content] [:safe (md-to-html-string content)]))
|
|
(tags/add-tags)
|
|
|
|
;; role assignments change only rarely.
|
|
(def get-user-roles
|
|
"Return, as a set, the names of the roles of which this `user` is a member."
|
|
(memoize
|
|
(fn [user]
|
|
(if
|
|
user
|
|
(do
|
|
(log/debug (str "seeking roles for user " user))
|
|
(let [roles
|
|
(set (map #(lower-case (:name %)) (db/list-roles-by-canvasser db/*db* user)))]
|
|
(log/debug (str "found roles " roles " for user " user))
|
|
roles))))))
|
|
|
|
|
|
(defn render-with-session
|
|
"renders the HTML `template` located relative to resources/templates in
|
|
the context of this session and with these parameters."
|
|
;; TODO: I'm passing `session` through into render. The default luminus
|
|
;; setup doesn't do this, and Dmitri is an awful lot better at this stuff
|
|
;; than me so there's almost certainly a reason it doesn't.
|
|
[template session & [params]]
|
|
(let [user (:user session)]
|
|
(log/debug (str "layout/render-with-session: template: '" template "'"))
|
|
(content-type
|
|
(ok
|
|
(parser/render-file
|
|
template
|
|
(merge params
|
|
{:page template
|
|
:csrf-token *anti-forgery-token*
|
|
:user user
|
|
:user-roles (get-user-roles user)
|
|
:site-title (:site-title env)
|
|
:version (System/getProperty "youyesyet.version")})))
|
|
"text/html; charset=utf-8")))
|
|
|
|
|
|
(defn render
|
|
"renders the HTML `template` located relative to resources/templates in
|
|
the context of this session and with these parameters."
|
|
[template & [params]]
|
|
(log/debug (str "layout/render: template: '" template "'"))
|
|
(content-type
|
|
(ok
|
|
(parser/render-file
|
|
template
|
|
(merge params
|
|
{:page template
|
|
:csrf-token *anti-forgery-token*
|
|
:user *user*
|
|
:user-roles (get-user-roles *user*)
|
|
:site-title (:site-title env)
|
|
:version (System/getProperty "youyesyet.version")})))
|
|
"text/html; charset=utf-8"))
|
|
|
|
|
|
|
|
(defn error-page
|
|
"error-details should be a map containing the following keys:
|
|
:status - error status
|
|
:title - error title (optional)
|
|
:message - detailed error message (optional)
|
|
returns a response map with the error page as the body
|
|
and the status specified by the status key"
|
|
[error-details]
|
|
(log/debug "Showing error page: " error-details)
|
|
{:status (:status error-details)
|
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
|
:body (parser/render-file
|
|
"error.html"
|
|
(assoc
|
|
error-details
|
|
:site-title (:site-title env)
|
|
:title
|
|
(str "Apologies, we have a problem: "
|
|
(:title error-details))
|
|
:error (:message error-details)
|
|
:message nil))})
|