From 392a5f82ecbc6f824e4efee9ff4eeb5fca3540f2 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Fri, 14 Feb 2020 16:08:17 +0000 Subject: [PATCH] These are the genuine improvements out of today 1. Table sorting 2. Fixed edit page title bugette 3. SimpleMDE working again. --- resources/i18n/en-GB.edn | 2 ++ resources/templates/edit-users.html | 23 ++++++++---- resources/templates/edit.html | 6 ++-- resources/templates/list-uploads.html | 19 +++++++--- src/smeagol/routes/wiki.clj | 51 ++++++++++++--------------- src/smeagol/util.clj | 50 ++++++++++++++++++++++++-- 6 files changed, 107 insertions(+), 44 deletions(-) diff --git a/resources/i18n/en-GB.edn b/resources/i18n/en-GB.edn index 6f4d8b2..442f097 100644 --- a/resources/i18n/en-GB.edn +++ b/resources/i18n/en-GB.edn @@ -131,6 +131,8 @@ "Smeagol has been unable to find some of the resources on which it depends, possibly because of misconfiguration or missing environment variables." ;; used in sanity check report + :sortable "You can sort this table by selecting column headers" + ;; used for sortable tables :user-lacks-field "User record in the passwd file lacks a field" ;; used in sanity check report :username-prompt "Username" ;; text of the username widget prompt on edit user page diff --git a/resources/templates/edit-users.html b/resources/templates/edit-users.html index 2621576..06d0d2e 100644 --- a/resources/templates/edit-users.html +++ b/resources/templates/edit-users.html @@ -1,10 +1,18 @@ {% extends "templates/base.html" %} +{% block extra-headers %} + {% script "/vendor/node_modules/tablesort/dist/tablesort.min.js" %} +{% endblock %} {% block content %}
- - - +

+ {% i18n sortable %} +

+
{% i18n edit-col-hdr %}{% i18n del-col-hdr %}
+ + + + {% for user in users %} @@ -13,11 +21,12 @@ {% endfor %} - - - - + +
{% i18n user-title-prefix %}{% i18n edit-col-hdr %}{% i18n del-col-hdr %}
{% i18n del-col-hdr %} {{user}}
{% i18n add-user-label %}
{% i18n add-user-label %}
+ {% endblock %} diff --git a/resources/templates/edit.html b/resources/templates/edit.html index 36426dc..44ee54a 100644 --- a/resources/templates/edit.html +++ b/resources/templates/edit.html @@ -1,11 +1,11 @@ {% extends "templates/base.html" %} {% block extra-headers %} - {% ifequal js-from ":cloudflare" %} + {% ifequal js-from ":cdnjs" %} {% else %} - {% style "/vendor/simplemde/dist/simplemde.min.css" %} - {% script "/vendor/simplemde/dist/simplemde.min.js" %} + {% style "vendor/simplemde/dist/simplemde.min.css" %} + {% script "vendor/simplemde/dist/simplemde.min.js" %} {% endifequal %} {% endblock %} diff --git a/resources/templates/list-uploads.html b/resources/templates/list-uploads.html index e759dac..4289485 100644 --- a/resources/templates/list-uploads.html +++ b/resources/templates/list-uploads.html @@ -1,4 +1,10 @@ {% extends "templates/base.html" %} +{% block extra-headers %} + {% script "/vendor/node_modules/tablesort/dist/tablesort.min.js" %} + {% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.number.min.js" %} + {% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.date.min.js" %} + {% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.monthname.min.js" %} +{% endblock %} {% block content %}
@@ -9,12 +15,15 @@

- - +

+ {% i18n sortable %} +

+
+ - + {% for entry in files %} @@ -26,9 +35,11 @@ - {% endfor %}
Name Uploaded Type thisTo get thisTo get this
{% if entry.is-image %} {{entry.name|capitalize}} {% else %} link {% endif %}
+ {% endblock %} diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index c87dbef..104b6e0 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -161,7 +161,8 @@ (log/info (format "Showing history of page '%s'" page)) (layout/render "history.html" (merge (util/standard-params request) - {:title (util/get-message :history-title-prefix request) + {:title (str (util/get-message :history-title-prefix request) + " " page) :page page :history (hist/find-history repo-path file-name)})))) @@ -175,7 +176,7 @@ If `template` is supplied, use that as the formatting template as specified for java.time.Formatter. Assumes system default timezone. Returns a string." ([^Long unix-time] - (format-instant unix-time "EEEE, dd MMMM YYYY")) + (format-instant unix-time "dd MMMM YYYY")) ([^Long unix-time ^String template] (jt/format (java-time/formatter template) @@ -188,33 +189,26 @@ [request] (let [params (keywordize-keys (:params request)) - cl (count (io/resource-path)) files - (map - #(zipmap - [:base-name :is-image :modified :name :resource] - [(fs/base-name %) - (if - (and (fs/extension %) - (image-extns (cs/lower-case (fs/extension %)))) - true false) - (if - (fs/mod-time %) - (format-instant (fs/mod-time %))) - (fs/name %) - (try - (subs (str (fs/absolute %)) cl) - (catch StringIndexOutOfBoundsException x - (log/error "Could not resolve relative path for" % - ";\n resource-path is:" (io/resource-path) - ";\n absolute path is:" (fs/absolute %) - ";\n data-path is:" util/upload-dir - ";\n content path is:" (:content-dir config)) - %))]) - (remove - #(or (cs/starts-with? (fs/name %) ".") - (fs/directory? %)) - (file-seq (clojure.java.io/file util/upload-dir))))] + (sort-by + (juxt :name (fn [x] (- 0 (count (:resource x))))) + (map + #(zipmap + [:base-name :is-image :modified :name :resource] + [(fs/base-name %) + (if + (and (fs/extension %) + (image-extns (cs/lower-case (fs/extension %)))) + true false) + (if + (fs/mod-time %) + (format-instant (fs/mod-time %))) + (fs/name %) + (util/local-url %)]) + (remove + #(or (cs/starts-with? (fs/name %) ".") + (fs/directory? %)) + (file-seq (clojure.java.io/file util/upload-dir)))))] (log/info (with-out-str (pprint files))) (layout/render "list-uploads.html" @@ -236,6 +230,7 @@ files) })))) + ;;;; end of list-uploads section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn upload-page diff --git a/src/smeagol/util.clj b/src/smeagol/util.clj index 1ef44df..d33ee32 100644 --- a/src/smeagol/util.clj +++ b/src/smeagol/util.clj @@ -2,6 +2,7 @@ :author "Simon Brooke"} smeagol.util (:require [clojure.java.io :as cjio] + [clojure.string :as cs] [environ.core :refer [env]] [me.raynes.fs :as fs] [noir.io :as io] @@ -10,7 +11,7 @@ [smeagol.authenticate :as auth] [smeagol.configuration :refer [config]] [smeagol.formatting :refer [md->html]] - [taoensso.timbre :as timbre])) + [taoensso.timbre :as log])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; @@ -49,6 +50,51 @@ (def upload-dir (str (cjio/file content-dir "uploads"))) +(def local-url-base + (let [a (str (fs/absolute content-dir))] + (subs a 0 (- (count a) (count "content"))))) + +(defn not-servable-reason + "As a string, the reason this `file-path` cannot safely be served, or `nil` + if it is safe to serve. This reason may be logged, but should *not* be + shown to remote users, as it would allow file system probing." + [file-path] + (let [path (fs/absolute file-path)] + (cond + (cs/includes? file-path "..") + (cs/join " " file-path + "Attempts to ascend the file hierarchy are disallowed.") + (not (cs/starts-with? path local-url-base)) + (cs/join " " [path "is not servable"]) + (not (fs/exists? path)) + (cs/join " " [path "does not exist"]) + (not (fs/readable? path)) + (cs/join " " [path "is not readable"])))) + +(defn local-url? + "True if this `file-path` can be served as a local URL, else false." + [file-path] + (empty? (not-servable-reason file-path))) + +(defn local-url + "Return a local URL for this `file-path`, or a deliberate 404 if none + can be safely served." + [file-path] + (try + (let [path (fs/absolute file-path) + problem (not-servable-reason path)] + (if + (empty? problem) + (subs (str path) (count local-url-base)) + (do + (log/error + "In `smeagol.util/local-url `" file-path "` is not a servable resource.") + (str "404-not-found?path=" file-path)))) + (catch Exception any + (log/error + "In `smeagol.util/local-url `" file-path "` is not a servable resource:" any) + (str "404-not-found?path=" file-path)))) + (defn standard-params "Return a map of standard parameters to pass to the template renderer." [request] @@ -69,7 +115,7 @@ messages (try (i18n/get-messages specifier "i18n" "en-GB") (catch Exception any - (timbre/error + (log/error any (str "Failed to parse accept-language header '"