From fc89b25a2f6a44a8dee147d2f434d4728cb66192 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Tue, 11 Nov 2014 12:24:44 +0000 Subject: [PATCH] Added very basic and not-very-secure authentication. Smeagol is now usable. --- .gitignore | 1 + README.md | 26 +++++++++++++-- resources/public/content/Introduction.md | 12 +++++-- resources/public/css/standard.css | 14 ++++++++- resources/public/passwd | 1 + resources/templates/auth.html | 33 +++++++++++++++++++ resources/templates/base.html | 11 ++++++- resources/templates/edit.html | 2 +- smeagol.log | 20 ------------ src/smeagol/authenticate.clj | 10 ++++++ src/smeagol/handler.clj | 2 +- src/smeagol/routes/wiki.clj | 40 +++++++++++++++++++++--- 12 files changed, 140 insertions(+), 32 deletions(-) create mode 100644 resources/public/passwd create mode 100644 resources/templates/auth.html delete mode 100644 smeagol.log create mode 100644 src/smeagol/authenticate.clj diff --git a/.gitignore b/.gitignore index 0ef5d3f..9c4d914 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +smeagol.log pom.xml pom.xml.asc *jar diff --git a/README.md b/README.md index 14fbdc4..c6089a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,28 @@ -# Welcome to Smeagol + Welcome to Smeagol! -Smeagol is a simple Git-backed Wiki inspired by [Gollum](https://github.com/gollum/gollum/wiki). +Smeagol is a simple Wiki engine inspired by [Gollum](https://github.com/gollum/gollum/wiki). Gollum is a Wiki engine written in Ruby, which uses a number of simple text formats including [Markdown](http://daringfireball.net/projects/markdown/), which uses [Git](http://git-scm.com/) to provide versioning and backup. I needed a new Wiki for a project and thought Gollum would be ideal - but unfortunately it doesn't provide user authentication, which I needed, and it was simpler for me to reimplement the bits I did need in Clojure than to modify Gollum. + +So at this stage Smeagol is a Wiki engine written in Clojure which uses Markdown as its text format, which does have user authentication, and which will soon use Git as its versioning and backup system. + +## Markup syntax + +Smeagol uses the Markdown format as provided by [markdown-clj](https://github.com/yogthos/markdown-clj), with the addition that anything enclosed in double square brackets, \[\[like this\]\], will be treated as a link into the wiki. + +## Security and authentication + +Currently security is very weak. There is currently a file called *passwd* in the *resources/public* directory, which contains a clojure map of username/plain-text password pairs thus: + + {:admin "admin"} + +that is to say, the username is a keyword and the corresponding password is a string. Obviously, this is a temporary solution while in development which I will fix later. + +## Todo + +* Git integration! Smeagol doesn't have any inbuilt versioning or backup mechanism; it's intended that Git will be used as that mechanism. But it isn't implemented yet. +* Image (and other media) upload. +* Improved security. +* Mechanism to add users through the user interface. +* Mechanism to change passwords through the user interface. ## Prerequisites diff --git a/resources/public/content/Introduction.md b/resources/public/content/Introduction.md index d08ede7..ac6c762 100644 --- a/resources/public/content/Introduction.md +++ b/resources/public/content/Introduction.md @@ -10,11 +10,19 @@ Smeagol uses the Markdown format as provided by [markdown-clj](https://github.co ## Security and authentication -Not done yet. +Currently security is very weak. There is currently a file called *passwd* in the *resources/public* directory, which contains a clojure map of username/plain-text password pairs thus: + + {:admin "admin"} + +that is to say, the username is a keyword and the corresponding password is a string. Obviously, this is a temporary solution while in development which I will fix later. ## Todo -Git integration! +* Git integration! Smeagol doesn't have any inbuilt versioning or backup mechanism; it's intended that Git will be used as that mechanism. But it isn't implemented yet. +* Image (and other media) upload. +* Improved security. +* Mechanism to add users through the user interface. +* Mechanism to change passwords through the user interface. ## Editing the framing content diff --git a/resources/public/css/standard.css b/resources/public/css/standard.css index 6fa4869..6f7a0ea 100644 --- a/resources/public/css/standard.css +++ b/resources/public/css/standard.css @@ -18,6 +18,13 @@ body { background:rgba(40,40,40,0.8); } +#user { + font-height: 66%; + float: right; + padding: 0.1em 0.75em; + margin: 0; +} + /* only needed for fly-out menu effect on tablet and phone stylesheets */ #nav-icon { display: none; @@ -120,10 +127,15 @@ input { background-color: white; } -input.submit { +input.action { background-color: green; } +input.action-dangerous { + color: white; + background-color: red; +} + input.required:after { content: " \*"; color: red; diff --git a/resources/public/passwd b/resources/public/passwd new file mode 100644 index 0000000..2123246 --- /dev/null +++ b/resources/public/passwd @@ -0,0 +1 @@ +{:admin "admin"} diff --git a/resources/templates/auth.html b/resources/templates/auth.html new file mode 100644 index 0000000..25594f8 --- /dev/null +++ b/resources/templates/auth.html @@ -0,0 +1,33 @@ +{% extends "templates/base.html" %} +{% block content %} + +
+ {{left-bar|safe}} +
+
+
+ {% if user %} +

+ + +

+ {% else %} +

+ + +

+

+ + +

+

+ + +

+ {% endif %} +
+
+{% endblock %} diff --git a/resources/templates/base.html b/resources/templates/base.html index 68c92dd..1d356c7 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -13,10 +13,19 @@ diff --git a/resources/templates/edit.html b/resources/templates/edit.html index 62f0288..e2570ad 100644 --- a/resources/templates/edit.html +++ b/resources/templates/edit.html @@ -13,7 +13,7 @@

- +

diff --git a/smeagol.log b/smeagol.log deleted file mode 100644 index 1d93bde..0000000 --- a/smeagol.log +++ /dev/null @@ -1,20 +0,0 @@ -2014-Nov-09 20:07:44 +0000 fletcher INFO [smeagol.handler] - --=[ smeagol started successfully using the development profile ]=- -2014-Nov-09 20:32:47 +0000 fletcher INFO [smeagol.handler] - smeagol is shutting down... -2014-Nov-09 20:32:47 +0000 fletcher INFO [smeagol.handler] - shutdown complete! -2014-Nov-09 20:33:00 +0000 fletcher INFO [smeagol.handler] - --=[ smeagol started successfully using the development profile ]=- -2014-Nov-09 20:35:05 +0000 fletcher INFO [smeagol.handler] - smeagol is shutting down... -2014-Nov-09 20:35:05 +0000 fletcher INFO [smeagol.handler] - shutdown complete! -2014-Nov-09 20:35:19 +0000 fletcher INFO [smeagol.handler] - --=[ smeagol started successfully using the development profile ]=- -2014-Nov-09 21:07:26 +0000 fletcher INFO [smeagol.handler] - smeagol is shutting down... -2014-Nov-09 21:07:26 +0000 fletcher INFO [smeagol.handler] - shutdown complete! -2014-Nov-09 21:07:40 +0000 fletcher INFO [smeagol.handler] - --=[ smeagol started successfully using the development profile ]=- -2014-Nov-09 21:10:52 +0000 fletcher INFO [smeagol.handler] - smeagol is shutting down... -2014-Nov-09 21:10:52 +0000 fletcher INFO [smeagol.handler] - shutdown complete! -2014-Nov-10 07:24:44 +0000 fletcher INFO [smeagol.handler] - --=[ smeagol started successfully using the development profile ]=- -2014-Nov-10 13:15:36 +0000 fletcher INFO [smeagol.handler] - smeagol is shutting down... -2014-Nov-10 13:15:37 +0000 fletcher INFO [smeagol.handler] - shutdown complete! diff --git a/src/smeagol/authenticate.clj b/src/smeagol/authenticate.clj new file mode 100644 index 0000000..67f4f6e --- /dev/null +++ b/src/smeagol/authenticate.clj @@ -0,0 +1,10 @@ +(ns smeagol.authenticate (:require [noir.io :as io])) + +(defn authenticate + "Return true if this username/password pair match, false otherwise" + [username password] + (let [path (str (io/resource-path) "passwd") + users (read-string (slurp path)) + user (keyword username)] + (println (str "Checking for user " user " with password " password " in " users " from " path)) + (.equals (user users) password))) \ No newline at end of file diff --git a/src/smeagol/handler.clj b/src/smeagol/handler.clj index afe8733..1c223d3 100644 --- a/src/smeagol/handler.clj +++ b/src/smeagol/handler.clj @@ -73,7 +73,7 @@ :middleware (load-middleware) :ring-defaults (mk-defaults false) ;; add access rules here - :access-rules [{:redirect "/login" + :access-rules [{:redirect "auth" :rule user-access}] ;; serialize/deserialize the following data formats ;; available formats: diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index 93395e8..05a1c11 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -3,6 +3,9 @@ (:require [compojure.core :refer :all] [noir.io :as io] [noir.response :as response] + [noir.util.route :as route] + [noir.session :as session] + [smeagol.authenticate :as auth] [smeagol.layout :as layout] [smeagol.util :as util])) @@ -31,9 +34,11 @@ {:title content :left-bar (util/md->html "/content/_edit-left-bar.md") :header (util/md->html "/content/_header.md") - :content (if exists? (io/slurp-resource file-name) "")})))) + :content (if exists? (io/slurp-resource file-name) "") + :user (session/get :user)})))) (defn local-links + "Rewrite text in `html-src` surrounded by double square brackets as a local link into this wiki." [html-src] (clojure.string/replace html-src #"\[\[[^\[\]]*\]\]" #(let [text (clojure.string/replace %1 #"[\[\]]" "")] @@ -52,9 +57,34 @@ {:title content :left-bar (util/md->html "/content/_left-bar.md") :header (util/md->html "/content/_header.md") - :content (local-links (util/md->html file-name))}) + :content (local-links (util/md->html file-name)) + :user (session/get :user)}) true (response/redirect (str "edit?content=" content))))) +(defn auth-page + "Render the auth page" + [request] + (let [params (keywordize-keys (:params request)) + username (:username params) + password (:password params) + action (:action params) + user (session/get :user)] + (println (str "Action = " action)) + (cond + (= action "Logout!") + (do + (session/remove! :user) + (response/redirect "wiki")) + (and username password (auth/authenticate username password)) + (do + (session/put! :user username) + (response/redirect "wiki")) + true + (layout/render "auth.html" + {:title (if user (str "Logout " user) "Log in") + :left-bar (util/md->html "/content/_left-bar.md") + :header (util/md->html "/content/_header.md") + :user user})))) (defn about-page [] (layout/render "about.html")) @@ -62,6 +92,8 @@ (defroutes wiki-routes (GET "/wiki" request (wiki-page request)) (GET "/" request (wiki-page request)) - (GET "/edit" request (edit-page request)) - (POST "/edit" request (edit-page request)) + (GET "/edit" request (route/restricted (edit-page request))) + (POST "/edit" request (route/restricted (edit-page request))) + (GET "/auth" request (auth-page request)) + (POST "/auth" request (auth-page request)) (GET "/about" [] (about-page)))