From b25412991baab758a39e95d4230c3e6cad56990a Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Tue, 11 Nov 2014 21:37:34 +0000 Subject: [PATCH] Well, that's Git integration working. Not complete; it ought to be possible to view the log of the current page, and previous versions - but it's a start. --- .gitignore | 1 + project.clj | 6 ++--- resources/public/content/Introduction.md | 8 +++---- resources/public/passwd | 3 ++- resources/templates/edit.html | 5 ++++ src/smeagol/authenticate.clj | 30 +++++++++++++++++++++--- src/smeagol/routes/wiki.clj | 24 ++++++++++++++----- 7 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 9c4d914..42d8f11 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ pom.xml.asc /classes/ /target/ /checkouts/ +/resources/public/content/.git .lein-deps-sum .lein-repl-history .lein-plugins/ diff --git a/project.clj b/project.clj index 46b7c28..6b95352 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject smeagol "0.1.0-SNAPSHOT" +(defproject smeagol "0.2.0-SNAPSHOT" :description "A simple Git-backed Wiki inspired by Gollum" :url "http://example.com/FIXME" :dependencies [[org.clojure/clojure "1.6.0"] @@ -7,8 +7,8 @@ [selmer "0.7.2"] [com.taoensso/timbre "3.3.1"] [com.taoensso/tower "3.0.2"] - [markdown-clj "0.9.55" - :exclusions [com.keminglabs/cljx]] + [markdown-clj "0.9.55" :exclusions [com.keminglabs/cljx]] + [clj-jgit "0.8.1"] [environ "1.0.0"] [im.chit/cronj "1.4.2"] [noir-exception "0.2.2"] diff --git a/resources/public/content/Introduction.md b/resources/public/content/Introduction.md index 23fa4bc..7f6cee0 100644 --- a/resources/public/content/Introduction.md +++ b/resources/public/content/Introduction.md @@ -2,7 +2,7 @@ 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. +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 uses Git as its versioning and backup system. ## Markup syntax @@ -10,15 +10,15 @@ Smeagol uses the Markdown format as provided by [markdown-clj](https://github.co ## 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: +Currently security is very weak. There is currently a file called *passwd* in the *resources/public* directory, which contains a clojure map of which maps username to maps with plain-text passwords and emails thus: - {:admin "admin"} + {:admin {:password "admin" :email "admin@localhost"} + :adam {:password "secret" :email "adam@localhost"}} 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 editor. The editor is at present very primitive - right back from the beginnings of the Web. It would be nice to have a rich embedded editor like [Hallo](https://github.com/bergie/hallo) or [Aloha](http://aloha-editor.org/Content.Node/index.html) but I havenven't (yet) had time to integrate them! * Improved security. Having the passwords in plain text rather than encrypted is just basically poor; having the passwd file in *public* space is also poor (although I believe it cannot be accessed via HTTP). Essentially, authentication mechanisms should be pluggable, and at present they aren't; diff --git a/resources/public/passwd b/resources/public/passwd index 2123246..fd73249 100644 --- a/resources/public/passwd +++ b/resources/public/passwd @@ -1 +1,2 @@ -{:admin "admin"} +{:admin {:password "admin" :email "admin@localhost"}} + diff --git a/resources/templates/edit.html b/resources/templates/edit.html index e2570ad..bcf477e 100644 --- a/resources/templates/edit.html +++ b/resources/templates/edit.html @@ -11,6 +11,11 @@
+

+ + +

diff --git a/src/smeagol/authenticate.clj b/src/smeagol/authenticate.clj index 67f4f6e..5fd990a 100644 --- a/src/smeagol/authenticate.clj +++ b/src/smeagol/authenticate.clj @@ -1,10 +1,34 @@ (ns smeagol.authenticate (:require [noir.io :as io])) +;; Smeagol: a very simple Wiki engine +;; Copyright (C) 2014 Simon Brooke + +;; 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. + (defn authenticate - "Return true if this username/password pair match, false otherwise" + "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 + (.equals (:password (user users)) password))) + +(defn get-email + "Return the email address associated with this `username`." + [username] + (let [path (str (io/resource-path) "passwd") + users (read-string (slurp path)) + user (keyword username)] + (:email (user users)))) \ No newline at end of file diff --git a/src/smeagol/routes/wiki.clj b/src/smeagol/routes/wiki.clj index 1039348..b19557c 100644 --- a/src/smeagol/routes/wiki.clj +++ b/src/smeagol/routes/wiki.clj @@ -18,6 +18,7 @@ (ns smeagol.routes.wiki (:use clojure.walk) (:require [compojure.core :refer :all] + [clj-jgit.porcelain :as git] [noir.io :as io] [noir.response :as response] [noir.util.route :as route] @@ -27,11 +28,21 @@ [smeagol.util :as util])) (defn process-source - "Process `source-text` and save it to the specified `file-path`, finally redirecting to wiki-page" - [file-path source-text request] - (let [params (keywordize-keys (:params request)) - content (or (:content params) "Introduction")] + "Process `source-text` and save it to the specified `file-path`, committing it + to Git and finally redirecting to wiki-page." + [params] + (let [source-text (:src params) + content (:content params) + file-name (str content ".md") + file-path (str (io/resource-path) "/content/" file-name) + exists? (.exists (clojure.java.io/as-file file-path)) + git-repo (git/load-repo (str (io/resource-path) "/content/.git")) + user (session/get :user) + email (auth/get-email user) + summary (:summary params)] (spit file-path source-text) + (if (not exists?) (git/git-add git-repo file-name)) + (git/git-commit git-repo summary {:name user :email email}) (response/redirect (str "/wiki?" content)) )) @@ -45,14 +56,15 @@ file-name (str "/content/" content ".md") file-path (str (io/resource-path) file-name) exists? (.exists (clojure.java.io/as-file file-path))] - (cond src-text (process-source file-path src-text request) + (cond src-text (process-source params) true (layout/render "edit.html" {: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) "") - :user (session/get :user)})))) + :user (session/get :user) + :exists exists?})))) (defn local-links "Rewrite text in `html-src` surrounded by double square brackets as a local link into this wiki."