diff --git a/resources/passwd b/resources/passwd index a4caeb6..3744ac1 100644 --- a/resources/passwd +++ b/resources/passwd @@ -1 +1 @@ -{:admin {:admin true, :email "info@weft.scot", password "admin"}} +{:admin {:admin true, :email "info@weft.scot", :password "admin"}} \ No newline at end of file diff --git a/resources/public/content/Internal Link.md b/resources/public/content/Internal Link.md index af3e85c..6582d38 100644 --- a/resources/public/content/Internal Link.md +++ b/resources/public/content/Internal Link.md @@ -1 +1 @@ -This is the page linked to from the left bar. \ No newline at end of file +This is the page linked to from the [[Introduction]] page. \ No newline at end of file diff --git a/resources/templates/edit-users.html b/resources/templates/edit-users.html index 15ffc35..674f981 100644 --- a/resources/templates/edit-users.html +++ b/resources/templates/edit-users.html @@ -2,11 +2,20 @@ {% block content %}
-
{% endblock %} diff --git a/src/smeagol/authenticate.clj b/src/smeagol/authenticate.clj index 2678e20..38d17f9 100644 --- a/src/smeagol/authenticate.clj +++ b/src/smeagol/authenticate.clj @@ -101,6 +101,7 @@ {keywd (merge user {:password (password/encrypt newpass)})}))) + (timbre/info (str "Successfully changed password for user " username)) true)) (catch Exception any (timbre/error @@ -145,11 +146,27 @@ (spit password-file-path (merge users {(keyword username) (merge user full-details)})) + (timbre/info (str "Successfully added user " username)) true) (catch Exception any (timbre/error - (format "Changing password failed for user %s failed: %s (%s)" + (format "Adding user %s failed: %s (%s)" username (.getName (.getClass any)) (.getMessage any))) false)))) +(defn delete-user + "Delete the user with this `username` from the password file." + [username] + (let [users (get-users)] + (try + (locking password-file-path + (spit password-file-path + (dissoc users (keyword username))) + (timbre/info (str "Successfully deleted user " username)) + true) + (catch Exception any + (timbre/error + (format "Deleting user %s failed: %s (%s)" + username (.getName (.getClass any)) (.getMessage any))) + false)))) diff --git a/src/smeagol/routes/admin.clj b/src/smeagol/routes/admin.clj new file mode 100644 index 0000000..4fd45ca --- /dev/null +++ b/src/smeagol/routes/admin.clj @@ -0,0 +1,84 @@ +(ns ^{:doc "Render all the main pages of a very simple Wiki engine." + :author "Simon Brooke"} + smeagol.routes.admin + (:require [clojure.walk :refer :all] + [noir.session :as session] + [taoensso.timbre :as timbre] + [smeagol.authenticate :as auth] + [smeagol.layout :as layout] + [smeagol.util :as util])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; Smeagol: a very simple Wiki engine. +;;;; +;;;; 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 +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +(defn edit-users + "Put a list of users on-screen for editing." + [request] + (let [params (keywordize-keys (:params request)) + user (session/get :user)] + (layout/render "edit-users.html" + (merge (util/standard-params request) + {:title "Select user to edit" + :users (auth/list-users)})))) + +(defn delete-user + "Delete a user." + [request] + (let [params (keywordize-keys (:params request)) + target (:target params) + deleted (auth/delete-user target) + message (if deleted (str "Successfully deleted user " target)) + error (if (not deleted) (str "Could not delete user " target))] + (layout/render "edit-users.html" + (merge (util/standard-params request) + {:title "Select user to edit" + :message message + :error error + :users (auth/list-users)})))) + + +(defn edit-user + "Put an individual user's details on screen for editing." + [request] + (let [params (keywordize-keys (:params request)) + target (:target params) + pass1 (:pass1 params) + password (if (and pass1 (auth/evaluate-password pass1 (:pass2 params))) pass1) + stored (if (:email params) + (auth/add-user target password (:email params) (:admin params))) + message (if stored (str "User " target " was stored successfully.")) + error (if (and (:email params) (not stored)) + (str "User " target " was not stored.")) + details (auth/fetch-user-details target)] + (if message + (timbre/info message)) + (if error + (timbre/warn error)) + (layout/render "edit-user.html" + (merge (util/standard-params request) + {:title (str "Edit user " target) + :message message + :error error + :target target + :details details})))) diff --git a/src/smeagol/routes/params.clj b/src/smeagol/routes/params.clj new file mode 100644 index 0000000..e69de29 diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index f04f66b..d95b1d9 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -3,10 +3,9 @@ smeagol.routes.wiki (:require [clojure.walk :refer :all] [clojure.java.io :as cjio] - [clojure.string :as cs] + [cemerick.url :refer (url url-encode url-decode)] [compojure.core :refer :all] [clj-jgit.porcelain :as git] - [cemerick.url :refer (url url-encode url-decode)] [markdown.core :as md] [noir.io :as io] [noir.response :as response] @@ -17,7 +16,8 @@ [smeagol.diff2html :as d2h] [smeagol.layout :as layout] [smeagol.util :as util] - [smeagol.history :as hist])) + [smeagol.history :as hist] + [smeagol.routes.admin :as admin])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; @@ -42,19 +42,6 @@ ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn local-links - "Rewrite text in `html-src` surrounded by double square brackets as a local link into this wiki." - [^String html-src] - (cs/replace html-src #"\[\[[^\[\]]*\]\]" - #(let [text (clojure.string/replace %1 #"[\[\]]" "") - encoded (url-encode text) - ;; I use '\_' to represent '_' in wiki markup, because - ;; '_' is meaningful in Markdown. However, this needs to - ;; be stripped out when interpreting local links. - munged (cs/replace encoded #"%26%2395%3B" "_")] - (format "%s" munged text)))) - - (defn get-git-repo "Get the git repository for my content, creating it if necessary" [] @@ -64,17 +51,6 @@ (git/git-init path)))) -(defn standard-params - "Return a map of standard parameters to pass to the template renderer." - [request] - (let [user (session/get :user)] - {:user user - :admin (auth/get-admin user) - :side-bar (local-links (util/md->html "/content/_side-bar.md")) - :header (local-links (util/md->html "/content/_header.md")) - :version (System/getProperty "smeagol.version")})) - - (defn process-source "Process `source-text` and save it to the specified `file-path`, committing it to Git and finally redirecting to wiki-page." @@ -113,14 +89,16 @@ file-path (str (io/resource-path) "content/" page suffix) exists? (.exists (cjio/as-file file-path)) user (session/get :user)] - (if (not exists?) (timbre/info (format "File '%s' not found; creating a new file" file-path))) + (if (not exists?) + (timbre/info (format "File '%s' not found; creating a new file" file-path)) + (timbre/info (format "Opening '%s' for editing" file-path))) (cond src-text (process-source params suffix) true (layout/render template - (merge (standard-params request) + (merge (util/standard-params request) {:title (str "Edit " page) :page page - :side-bar (local-links (util/md->html side-bar)) + :side-bar (util/local-links (util/md->html side-bar)) :content (if exists? (io/slurp-resource (str "/content/" page suffix)) "") :exists exists?})))))) @@ -131,43 +109,6 @@ (edit-page request "stylesheet" ".css" "edit-css.html" "/content/_edit-side-bar.md")) -(defn edit-users - "Put a list of users on-screen for editing." - [request] - (let [params (keywordize-keys (:params request)) - user (session/get :user)] - (layout/render "edit-users.html" - (merge (standard-params request) - {:title "Select user to edit" - :users (auth/list-users)})))) - - -(defn edit-user - "Put an individual user's details on screen for editing." - [request] - (let [params (keywordize-keys (:params request)) - target (:target params) - pass1 (:pass1 params) - password (if (and pass1 (auth/evaluate-password pass1 (:pass2 params))) pass1) - stored (if (:email params) - (auth/add-user target password (:email params) (:admin params))) - message (if stored (str "User " target " was stored successfully.")) - error (if (and (:email params) (not stored)) - (str "User " target " was not stored.")) - details (auth/fetch-user-details target)] - (if message - (timbre/info message)) - (if error - (timbre/warn error)) - (layout/render "edit-user.html" - (merge (standard-params request) - {:title (str "Edit user " target) - :message message - :error error - :target target - :details details})))) - - (defn wiki-page "Render the markdown page specified in this `request`, if any. If none found, redirect to edit-page" [request] @@ -177,12 +118,14 @@ file-path (str (io/resource-path) file-name) exists? (.exists (clojure.java.io/as-file file-path))] (cond exists? - (layout/render "wiki.html" - (merge (standard-params request) - {:title page - :page page - :content (local-links (util/md->html file-name)) - :editable true})) + (do + (timbre/info (format "Showing page '%s'" page)) + (layout/render "wiki.html" + (merge (util/standard-params request) + {:title page + :page page + :content (util/local-links (util/md->html file-name)) + :editable true}))) true (response/redirect (str "edit?page=" page))))) @@ -195,7 +138,7 @@ file-name (str page ".md") repo-path (str (io/resource-path) "/content/")] (layout/render "history.html" - (merge (standard-params request) + (merge (util/standard-params request) {:title (str "History of " page) :page page :history (hist/find-history repo-path file-name)})))) @@ -210,10 +153,10 @@ file-name (str page ".md") repo-path (str (io/resource-path) "/content/")] (layout/render "wiki.html" - (merge (standard-params request) + (merge (util/standard-params request) {:title (str "Version " version " of " page) :page page - :content (local-links + :content (util/local-links (md/md-to-html-string (hist/fetch-version repo-path file-name version)))})))) @@ -228,7 +171,7 @@ file-name (str page ".md") repo-path (str (io/resource-path) "/content/")] (layout/render "wiki.html" - (merge (standard-params request) + (merge (util/standard-params request) {:title (str "Changes since version " version " of " page) :page page :content (d2h/diff2html (hist/diff repo-path file-name version))})))) @@ -255,11 +198,11 @@ (response/redirect redirect-to)) true (layout/render "auth.html" - (merge (standard-params request) + (merge (util/standard-params request) {:title (if user (str "Logout " user) "Log in") :redirect-to ((:headers request) "referer") - :side-bar (local-links (util/md->html "/content/_side-bar.md")) - :header (local-links (util/md->html "/content/_header.md")) + :side-bar (util/local-links (util/md->html "/content/_side-bar.md")) + :header (util/local-links (util/md->html "/content/_header.md")) :user user}))))) @@ -279,23 +222,24 @@ (not (= pass1 pass2)) "Your proposed passwords don't match" true "Your password was not changed")] ;; but I don't know why... (layout/render "passwd.html" - (merge (standard-params request) + (merge (util/standard-params request) {:title (str "Change passord for " user) - :side-bar (local-links (util/md->html "/content/_side-bar.md")) - :header (local-links (util/md->html "/content/_header.md")) + :side-bar (util/local-links (util/md->html "/content/_side-bar.md")) + :header (util/local-links (util/md->html "/content/_header.md")) :message message})))) (defroutes wiki-routes (GET "/wiki" request (wiki-page request)) (GET "/" request (wiki-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))) (GET "/edit-css" request (route/restricted (edit-css-page request))) (POST "/edit-css" request (route/restricted (edit-css-page request))) - (GET "/edit-users" request (route/restricted (edit-users request))) - (GET "/edit-user" request (route/restricted (edit-user request))) - (POST "/edit-user" request (route/restricted (edit-user request))) + (GET "/edit-users" request (route/restricted (admin/edit-users request))) + (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 "/version" request (version-page request)) (GET "/changes" request (diff-page request)) diff --git a/src/smeagol/util.clj b/src/smeagol/util.clj index 791b77b..8a45339 100644 --- a/src/smeagol/util.clj +++ b/src/smeagol/util.clj @@ -1,8 +1,12 @@ (ns ^{:doc "Miscellaneous utility functions supporting Smeagol." :author "Simon Brooke"} smeagol.util - (:require [noir.io :as io] - [markdown.core :as md])) + (:require [clojure.string :as cs] + [cemerick.url :refer (url url-encode url-decode)] + [noir.io :as io] + [noir.session :as session] + [markdown.core :as md] + [smeagol.authenticate :as auth])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; @@ -31,3 +35,28 @@ "reads a markdown file from public/md and returns an HTML string" [filename] (md/md-to-html-string (io/slurp-resource filename))) + + +(defn local-links + "Rewrite text in `html-src` surrounded by double square brackets as a local link into this wiki." + [^String html-src] + (cs/replace html-src #"\[\[[^\[\]]*\]\]" + #(let [text (clojure.string/replace %1 #"[\[\]]" "") + encoded (url-encode text) + ;; I use '\_' to represent '_' in wiki markup, because + ;; '_' is meaningful in Markdown. However, this needs to + ;; be stripped out when interpreting local links. + munged (cs/replace encoded #"%26%2395%3B" "_")] + (format "%s" munged text)))) + + +(defn standard-params + "Return a map of standard parameters to pass to the template renderer." + [request] + (let [user (session/get :user)] + {:user user + :admin (auth/get-admin user) + :side-bar (local-links (md->html "/content/_side-bar.md")) + :header (local-links (md->html "/content/_header.md")) + :version (System/getProperty "smeagol.version")})) +