Added 'list uploaded files' page, only accessible if logged in.

This commit is contained in:
Simon Brooke 2020-02-07 19:01:30 +00:00
parent 84360110fc
commit da3bde16d0
8 changed files with 138 additions and 22 deletions

2
.gitignore vendored
View file

@ -18,3 +18,5 @@ smeagol.log*
/node_modules/
.DS_Store
resources/public/content/uploads/

View file

@ -5,6 +5,7 @@
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
:dependencies [[clj-jgit "0.8.10"]
[clj-yaml "0.4.0"]
[clojure.java-time "0.3.2"]
[com.cemerick/url "0.1.1"]
[com.fzakaria/slf4j-timbre "0.3.7"]
[com.stuartsierra/component "0.4.0"]
@ -17,6 +18,7 @@
[im.chit/cronj "1.4.4"]
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
[markdown-clj "0.9.99" :exclusions [com.keminglabs/cljx]]
[me.raynes/fs "1.4.6"]
[noir-exception "0.2.5"]
[org.clojars.simon_brooke/internationalisation "1.0.3"]
[org.clojure/clojure "1.8.0"]

View file

@ -83,6 +83,8 @@
:file-upload-title "Upload a file" ;; title for the file upload page
:is-admin-prompt "Is administrator?"
:here "here" ;; used in sanity check report
:history-link "History" ;; text of the history link on the content frame
:history-title-prefix "History of" ;; prefix of the title on the history page
:home-link "Home" ;; text of the home link on the menu
:is-not-directory "is not a directory"
;; (of a file or directory) used in sanity check report
@ -90,6 +92,8 @@
;; (of a file or directory) used in sanity check report
:is-not-writable "is not writable"
;; (of a file or directory) used in sanity check report
:list-files "List uploaded files"
;; title of the 'List uploaded Files' page
:login-label "Log in!" ;; text of the login widget on the login page
:login-link "Log in" ;; text of the login link on the menu
:login-prompt "To edit this wiki"
@ -98,8 +102,7 @@
:logout-link "Log out" ;; text of the logout link on the menu
:logged-in-as "You are logged in as"
;; text of the 'logged in as' label on the menu
:history-link "History" ;; text of the history link on the content frame
:history-title-prefix "History of" ;; prefix of the title on the history page
:matching "matching" ;; 'matching' in e.g. 'list files matching fred'
:new-pass-prompt "New password" ;; text of the new password widget prompt on the change
;; password and edit user pages
:no-admin-users "There are no users in the 'passwd' file with administrative privileges"

View file

@ -10,4 +10,6 @@
+ \*\***bold**\*\*
+ \__italic_\_
More documentation [here](http://daringfireball.net/projects/markdown/syntax)
More documentation [here](http://daringfireball.net/projects/markdown/syntax)
Your <a href="list-uploads">uploaded files are listed here</a>.

View file

@ -0,0 +1,34 @@
{% extends "templates/base.html" %}
{% block content %}
<div id="content" class="list-uploads">
<form action="list-uploads" method="post">
{% csrf-field %}
<p class="widget">
<label for="search">{% i18n matching %}</label>
<input name="search" id="search" type="text" value="{{search}}" required/>
</p>
</form>
<table>
<tr>
<th>Name</th>
<th>Uploaded</th>
<th>Type this</th>
<th>To get this</th>
</tr>
{% for entry in files %}
<tr>
<th>{{entry.base-name}}</th>
<td>{{entry.modified}}</td>
<td>
{% if entry.is-image %} ![{{entry.name|capitalize}}](uploads/{{entry.base-name}}) {% else %} [{{entry.name|capitalize}}](uploads/{{entry.base-name}}) {% endif %}
</td>
<td>
{% if entry.is-image %} <img src="uploads/{{entry.base-name}}" alt="{{entry.name|capitalize}}"/> {% else %} <a href="uploads/{{entry.base-name}}">link</a> {% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}

View file

@ -34,5 +34,8 @@
</p>
</form>
{% endif %}
<p>
Your <a href="list-uploads">uploaded files are listed here</a>.
</p>
</div>
{% endblock %}

View file

@ -7,6 +7,8 @@
[clojure.string :as cs]
[clojure.walk :refer :all]
[compojure.core :refer :all]
[java-time :as jt]
[me.raynes.fs :as fs]
[noir.io :as io]
[noir.response :as response]
[noir.util.route :as route]
@ -161,6 +163,75 @@
:page page
:history (hist/find-history repo-path file-name)}))))
(def image-extns #{".gif" ".jpg" ".jpeg" ".png"})
(defn format-instant
"Format this `unix-time`, expected to be a Long, into something human readable.
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"))
([^Long unix-time ^String template]
(jt/format
(java-time/formatter template)
(java.time.LocalDateTime/ofInstant
(java-time/instant unix-time)
(java.time.ZoneOffset/systemDefault)))))
(defn list-uploads-page
"Render a list of all uploaded files"
[request]
(let
[params (keywordize-keys (:params request))
data-path (str util/content-dir "/uploads/")
files
(map
#(zipmap
[:base-name :is-image :modified :name]
[(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 %)])
(remove
#(or (cs/starts-with? (fs/name %) ".")
(fs/directory? %))
(file-seq (clojure.java.io/file data-path))))]
(layout/render
"list-uploads.html"
(merge (util/standard-params request)
{:title (str
(util/get-message :list-files request)
(if
(:search params)
(str " " (util/get-message :matching request))))
:search (:search params)
:files (if
(:search params)
(try
(let [pattern (re-pattern (:search params))]
(filter
#(re-find pattern (:base-name %))
files))
(catch Exception _ files))
files)
}))))
(map
#(zipmap
[:base-name :is-image :modified :name]
[(fs/base-name %)
(if
(and (fs/extension %) (image-extns (cs/lower-case (fs/extension %))))
true false)
(fs/mod-time %)
(fs/name %)])
(file-seq (clojure.java.io/file "resources/public/content/uploads")))
(defn upload-page
"Render a form to allow the upload of a file."
[request]
@ -174,23 +245,17 @@
(if
uploaded
(do
(git/git-add git-repo uploaded)
(git/git-add git-repo (str data-path (fs/name uploaded)))
(git/git-commit git-repo summary {:name user :email (auth/get-email user)})))
(layout/render "upload.html"
(merge (util/standard-params request)
{:title (util/get-message :file-upload-title request)
:uploaded uploaded
:is-image (and
:uploaded (if uploaded (fs/base-name uploaded))
:is-image (if
uploaded
(or
(cs/ends-with? uploaded ".gif")
(cs/ends-with? uploaded ".jpg")
(cs/ends-with? uploaded ".jpeg")
(cs/ends-with? uploaded ".png")
(cs/ends-with? uploaded ".GIF")
(cs/ends-with? uploaded ".JPG")
(cs/ends-with? uploaded ".PNG")))}))))
(image-extns
(cs/lower-case
(fs/extension uploaded))))}))))
(defn version-page
"Render a specific historical version of a page"
@ -286,8 +351,10 @@
(defroutes wiki-routes
(GET "/wiki" request (wiki-page request))
(GET "/" request (wiki-page request))
(GET "/auth" request (auth-page request))
(POST "/auth" request (auth-page request))
(GET "/changes" request (diff-page request))
(GET "/delete-user" request (route/restricted (admin/delete-user request)))
(GET "/edit" request (route/restricted (edit-page request)))
(POST "/edit" request (route/restricted (edit-page request)))
@ -297,11 +364,12 @@
(GET "/edit-user" request (route/restricted (admin/edit-user request)))
(POST "/edit-user" request (route/restricted (admin/edit-user request)))
(GET "/history" request (history-page request))
(GET "/list-uploads" request (route/restricted (list-uploads-page request)))
(POST "/list-uploads" request (route/restricted (list-uploads-page request)))
(GET "/version" request (version-page request))
(GET "/changes" request (diff-page request))
(GET "/auth" request (auth-page request))
(POST "/auth" request (auth-page request))
(GET "/passwd" request (passwd-page request))
(POST "/passwd" request (passwd-page request))
(GET "/upload" request (route/restricted (upload-page request)))
(POST "/upload" request (route/restricted (upload-page request))))
(POST "/upload" request (route/restricted (upload-page request)))
(GET "/wiki" request (wiki-page request))
)

View file

@ -49,7 +49,9 @@
"Store an upload both to the file system and to the database.
The issue with storing an upload is moving it into place.
If `params` are passed as a map, it is expected that this is a map from
an HTTP POST operation of a form with type `multipart/form-data`."
an HTTP POST operation of a form with type `multipart/form-data`.
On success, returns the file object uploaded."
[params path]
(let [upload (:upload params)
tmp-file (:tempfile upload)
@ -63,7 +65,7 @@
(do
(.renameTo tmp-file
(File. (str path filename)))
filename)
(File. (str path filename)))
(catch Exception x
(timbre/error (str "Failed to move " tmp-file " to " path filename "; " (type x) ": " (.getMessage x)))
(throw x)))