storage layer made more BL independent
This commit is contained in:
+26
-40
@@ -18,21 +18,13 @@
|
|||||||
(def sessions "sessions")
|
(def sessions "sessions")
|
||||||
(def short-url "short-url")
|
(def short-url "short-url")
|
||||||
|
|
||||||
; Concatenates all fields to a string
|
|
||||||
(defn build-key
|
|
||||||
"Returns a storage-key for the given note coordinates"
|
|
||||||
[[year month day] title]
|
|
||||||
(print-str year month day title))
|
|
||||||
|
|
||||||
(defn create-session
|
(defn create-session
|
||||||
"Creates a random session token"
|
|
||||||
[]
|
[]
|
||||||
(let [token (encrypt (str (rand-int Integer/MAX_VALUE)))]
|
(let [token (encrypt (str (rand-int Integer/MAX_VALUE)))]
|
||||||
(do (redis/sadd db sessions token)
|
(do (redis/sadd db sessions token)
|
||||||
token)))
|
token)))
|
||||||
|
|
||||||
(defn invalidate-session
|
(defn invalidate-session
|
||||||
"Invalidates given session"
|
|
||||||
[token]
|
[token]
|
||||||
; Jedis is buggy & returns an NPE for token == nil
|
; Jedis is buggy & returns an NPE for token == nil
|
||||||
(when token
|
(when token
|
||||||
@@ -41,49 +33,43 @@
|
|||||||
was-valid))))
|
was-valid))))
|
||||||
|
|
||||||
(defn update-note
|
(defn update-note
|
||||||
"Updates a note with the given store key if the specified password is correct"
|
[noteID text passwd]
|
||||||
[key text passwd]
|
(let [stored-password (redis/hget db password noteID)]
|
||||||
(let [stored-password (redis/hget db password key)]
|
|
||||||
(when (and stored-password (= passwd stored-password))
|
(when (and stored-password (= passwd stored-password))
|
||||||
(redis/hset db note key text))))
|
(redis/hset db note noteID text))))
|
||||||
|
|
||||||
(defn set-note
|
(defn add-note
|
||||||
"Creates a note with the given title and text in the given date namespace"
|
([noteID text] (add-note noteID text nil))
|
||||||
([date title text] (set-note date title text nil))
|
([noteID text passwd]
|
||||||
([date title text passwd]
|
(do
|
||||||
(let [key (build-key date title)]
|
(redis/hset db note noteID text)
|
||||||
(do
|
(when (not (blank? passwd))
|
||||||
(redis/hset db note key text)
|
(redis/hset db password noteID passwd)))))
|
||||||
(when (not (blank? passwd))
|
|
||||||
(redis/hset db password key passwd))))))
|
|
||||||
|
|
||||||
(defn get-note
|
(defn get-note
|
||||||
"Gets the note from the given date namespaces for the specified title"
|
[noteID]
|
||||||
[date title]
|
(let [text (redis/hget db note noteID)]
|
||||||
(let [key (build-key date title)
|
|
||||||
text (redis/hget db note key)]
|
|
||||||
(when text
|
(when text
|
||||||
(do
|
(do
|
||||||
(redis/hincrby db views key 1)
|
(redis/hincrby db views noteID 1)
|
||||||
text))))
|
text))))
|
||||||
|
|
||||||
(defn get-note-views
|
(defn get-note-views
|
||||||
"Returns the number of views for the specified date and note title"
|
"Returns the number of views for the specified noteID"
|
||||||
[date title]
|
[noteID]
|
||||||
(redis/hget db views (build-key date title)))
|
(redis/hget db views noteID))
|
||||||
|
|
||||||
(defn note-exists?
|
(defn note-exists?
|
||||||
"Returns true if the note with the specified title and date exists"
|
"Returns true if the note with the specified noteID"
|
||||||
[date title]
|
[noteID]
|
||||||
(redis/hexists db note (build-key date title)))
|
(redis/hexists db note noteID))
|
||||||
|
|
||||||
(defn delete-note
|
(defn delete-note
|
||||||
"Deletes the note with the specified coordinates"
|
"Deletes the note with the specified coordinates"
|
||||||
[date title]
|
[noteID]
|
||||||
(let [key (build-key date title)]
|
(doseq [kw [password views note]]
|
||||||
(doseq [kw [password views note]]
|
; TODO: delete short url by looking for the title
|
||||||
; TODO: delete short url by looking for the title
|
(redis/hdel db kw noteID)))
|
||||||
(redis/hdel db kw key))))
|
|
||||||
|
|
||||||
(defn short-url-exists?
|
(defn short-url-exists?
|
||||||
"Checks whether the provided short url is taken (for testing only)"
|
"Checks whether the provided short url is taken (for testing only)"
|
||||||
@@ -99,10 +85,10 @@
|
|||||||
|
|
||||||
(defn delete-short-url
|
(defn delete-short-url
|
||||||
"Deletes a short url (for testing only)"
|
"Deletes a short url (for testing only)"
|
||||||
[key]
|
[noteID]
|
||||||
(let [value (redis/hget db short-url key)]
|
(let [value (redis/hget db short-url noteID)]
|
||||||
(do
|
(do
|
||||||
(redis/hdel db short-url key)
|
(redis/hdel db short-url noteID)
|
||||||
(redis/hdel db short-url value))))
|
(redis/hdel db short-url value))))
|
||||||
|
|
||||||
(defn create-short-url
|
(defn create-short-url
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
(:import
|
(:import
|
||||||
[java.util Calendar]))
|
[java.util Calendar]))
|
||||||
|
|
||||||
|
; Concatenates all fields to a string
|
||||||
|
(defn build-key
|
||||||
|
"Returns a storage-key for the given note coordinates"
|
||||||
|
[[year month day] title]
|
||||||
|
(print-str year month day title))
|
||||||
|
|
||||||
(defn get-hash
|
(defn get-hash
|
||||||
"A simple hash-function, which computes a hash from the text field
|
"A simple hash-function, which computes a hash from the text field
|
||||||
content and given session number. It is intended to be used as a spam
|
content and given session number. It is intended to be used as a spam
|
||||||
@@ -103,8 +109,9 @@
|
|||||||
; Update Note Page
|
; Update Note Page
|
||||||
(defpage "/:year/:month/:day/:title/edit" {:keys [year month day title]}
|
(defpage "/:year/:month/:day/:title/edit" {:keys [year month day title]}
|
||||||
(input-form "/update-note" :update
|
(input-form "/update-note" :update
|
||||||
(html (hidden-field :key (build-key [year month day] title)))
|
(let [noteID (build-key [year month day] title)]
|
||||||
(get-note [year month day] title) :enter-passwd))
|
(html (hidden-field :key noteID))
|
||||||
|
(get-note noteID) :enter-passwd)))
|
||||||
|
|
||||||
; New Note Page
|
; New Note Page
|
||||||
(defpage "/new" {}
|
(defpage "/new" {}
|
||||||
@@ -118,16 +125,16 @@
|
|||||||
(wrap
|
(wrap
|
||||||
(create-short-url params)
|
(create-short-url params)
|
||||||
(select-keys params [:title :theme :header-font :text-font])
|
(select-keys params [:title :theme :header-font :text-font])
|
||||||
(get-note [year month day] title)))
|
(get-note (build-key [year month day] title))))
|
||||||
|
|
||||||
; Provides Markdown of the specified note
|
; Provides Markdown of the specified note
|
||||||
(defpage "/:year/:month/:day/:title/export" {:keys [year month day title]}
|
(defpage "/:year/:month/:day/:title/export" {:keys [year month day title]}
|
||||||
(when-let [md-text (get-note [year month day] title)]
|
(when-let [md-text (get-note (build-key [year month day] title))]
|
||||||
(content-type "text/plain; charset=utf-8" md-text)))
|
(content-type "text/plain; charset=utf-8" md-text)))
|
||||||
|
|
||||||
; Provides the number of views of the specified note
|
; Provides the number of views of the specified note
|
||||||
(defpage "/:year/:month/:day/:title/stats" {:keys [year month day title]}
|
(defpage "/:year/:month/:day/:title/stats" {:keys [year month day title]}
|
||||||
(when-let [views (get-note-views [year month day] title)]
|
(when-let [views (get-note-views (build-key [year month day] title))]
|
||||||
(layout (get-message :statistics)
|
(layout (get-message :statistics)
|
||||||
[:table#stats.helvetica.central-element
|
[:table#stats.helvetica.central-element
|
||||||
[:tr
|
[:tr
|
||||||
@@ -167,11 +174,11 @@
|
|||||||
; TODO: replace to ccs/take when it gets fixed
|
; TODO: replace to ccs/take when it gets fixed
|
||||||
proposed-title (apply str (take max-length title-uncut))
|
proposed-title (apply str (take max-length title-uncut))
|
||||||
date [year month day]
|
date [year month day]
|
||||||
title (first (drop-while #(note-exists? date %)
|
title (first (drop-while #(note-exists? (build-key date %))
|
||||||
(cons proposed-title
|
(cons proposed-title
|
||||||
(map #(str proposed-title "-" (+ 2 %)) (range)))))]
|
(map #(str proposed-title "-" (+ 2 %)) (range)))))]
|
||||||
(do
|
(do
|
||||||
(set-note date title draft password)
|
(add-note (build-key date title) draft password)
|
||||||
(redirect (url year month day title))))
|
(redirect (url year month day title))))
|
||||||
(response 400))))
|
(response 400))))
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
(ns NoteHub.test.storage
|
(ns NoteHub.test.storage
|
||||||
(:use [NoteHub.storage] [clojure.test]))
|
(:use [NoteHub.storage]
|
||||||
|
[NoteHub.views.pages]
|
||||||
|
[clojure.test]))
|
||||||
|
|
||||||
(def date [2012 06 03])
|
(def date [2012 06 03])
|
||||||
(def test-title "Some title.")
|
(def test-title "Some title.")
|
||||||
@@ -25,29 +27,29 @@
|
|||||||
(short-url-exists? url))))))
|
(short-url-exists? url))))))
|
||||||
(testing "of correct note creation"
|
(testing "of correct note creation"
|
||||||
(is (= (do
|
(is (= (do
|
||||||
(set-note date test-title test-note)
|
(add-note (build-key date test-title) test-note)
|
||||||
(get-note date test-title))
|
(get-note (build-key date test-title)))
|
||||||
test-note))
|
test-note))
|
||||||
(is (= "1" (get-note-views date test-title)))
|
(is (= "1" (get-note-views (build-key date test-title))))
|
||||||
(is (= (do
|
(is (= (do
|
||||||
(get-note date test-title)
|
(get-note (build-key date test-title))
|
||||||
(get-note-views date test-title))
|
(get-note-views (build-key date test-title)))
|
||||||
"2")))
|
"2")))
|
||||||
(testing "of note update"
|
(testing "of note update"
|
||||||
(is (= (do
|
(is (= (do
|
||||||
(set-note date test-title test-note "12345qwert")
|
(add-note (build-key date test-title) test-note "12345qwert")
|
||||||
(get-note date test-title))
|
(get-note (build-key date test-title)))
|
||||||
test-note))
|
test-note))
|
||||||
(is (= (do
|
(is (= (do
|
||||||
(update-note (build-key date test-title) "update" "12345qwert")
|
(update-note (build-key date test-title) "update" "12345qwert")
|
||||||
(get-note date test-title))
|
(get-note (build-key date test-title)))
|
||||||
"update"))
|
"update"))
|
||||||
(is (= (do
|
(is (= (do
|
||||||
(update-note (build-key date test-title) "not authorized" "44444")
|
(update-note (build-key date test-title) "not authorized" "44444")
|
||||||
(get-note date test-title))
|
(get-note (build-key date test-title)))
|
||||||
"update")))
|
"update")))
|
||||||
(testing "of the note access"
|
(testing "of the note access"
|
||||||
(is (not= (get-note date test-title) "any text")))
|
(is (not= (get-note (build-key date test-title)) "any text")))
|
||||||
(testing "session management"
|
(testing "session management"
|
||||||
(let [s1 (create-session)
|
(let [s1 (create-session)
|
||||||
s2 (create-session)
|
s2 (create-session)
|
||||||
@@ -58,9 +60,9 @@
|
|||||||
(is (not (invalidate-session "wrongtoken")))
|
(is (not (invalidate-session "wrongtoken")))
|
||||||
(is (invalidate-session s3))))
|
(is (invalidate-session s3))))
|
||||||
(testing "of note existence"
|
(testing "of note existence"
|
||||||
(is (note-exists? date test-title))
|
(is (note-exists? (build-key date test-title)))
|
||||||
(is (not (do
|
(is (not (do
|
||||||
(delete-note date test-title)
|
(delete-note (build-key date test-title))
|
||||||
(note-exists? date test-title))))
|
(note-exists? (build-key date test-title)))))
|
||||||
(is (not (note-exists? [2013 06 03] test-title)))
|
(is (not (note-exists? (build-key [2013 06 03] test-title))))
|
||||||
(is (not (note-exists? date "some title"))))))
|
(is (not (note-exists? (build-key date "some title")))))))
|
||||||
|
|||||||
@@ -6,16 +6,15 @@
|
|||||||
[clojure.test]))
|
[clojure.test]))
|
||||||
|
|
||||||
(defn substring? [a b]
|
(defn substring? [a b]
|
||||||
(not (= nil
|
(not (= nil (re-matches (re-pattern (str "(?s).*" a ".*")) b))))
|
||||||
(re-matches (re-pattern (str "(?s).*" a ".*")) b))))
|
|
||||||
(def date [2012 6 3])
|
(def date [2012 6 3])
|
||||||
(def test-title "some-title")
|
(def test-title "some-title")
|
||||||
(def test-note "# This is a test note.\nHello _world_. Motörhead, тест.")
|
(def test-note "# This is a test note.\nHello _world_. Motörhead, тест.")
|
||||||
|
|
||||||
(defn create-testnote-fixture [f]
|
(defn create-testnote-fixture [f]
|
||||||
(set-note date test-title test-note)
|
(add-note (build-key date test-title) test-note)
|
||||||
(f)
|
(f)
|
||||||
(delete-note date test-title))
|
(delete-note (build-key date test-title)))
|
||||||
|
|
||||||
(use-fixtures :each create-testnote-fixture)
|
(use-fixtures :each create-testnote-fixture)
|
||||||
|
|
||||||
@@ -23,8 +22,8 @@
|
|||||||
|
|
||||||
(deftest testing-fixture
|
(deftest testing-fixture
|
||||||
(testing "Was a not created?"
|
(testing "Was a not created?"
|
||||||
(is (= (get-note date test-title) test-note))
|
(is (= (get-note (build-key date test-title)) test-note))
|
||||||
(is (note-exists? date test-title))))
|
(is (note-exists? (build-key date test-title)))))
|
||||||
|
|
||||||
(deftest export-test
|
(deftest export-test
|
||||||
(testing "Markdown export"
|
(testing "Markdown export"
|
||||||
@@ -42,12 +41,12 @@
|
|||||||
{:session-key session-key
|
{:session-key session-key
|
||||||
:draft test-note
|
:draft test-note
|
||||||
:session-value (str (get-hash (str test-note session-key)))}) 302))
|
:session-value (str (get-hash (str test-note session-key)))}) 302))
|
||||||
(is (note-exists? date title))
|
(is (note-exists? (build-key date title)))
|
||||||
(is (substring? "Hello _world_"
|
(is (substring? "Hello _world_"
|
||||||
((send-request (url year month day title)) :body)))
|
((send-request (url year month day title)) :body)))
|
||||||
(is (do
|
(is (do
|
||||||
(delete-note date title)
|
(delete-note (build-key date title))
|
||||||
(not (note-exists? date title)))))))
|
(not (note-exists? (build-key date title))))))))
|
||||||
|
|
||||||
(deftest note-update
|
(deftest note-update
|
||||||
(let [session-key (create-session)
|
(let [session-key (create-session)
|
||||||
@@ -62,7 +61,7 @@
|
|||||||
:draft "test note"
|
:draft "test note"
|
||||||
:password "qwerty"
|
:password "qwerty"
|
||||||
:session-value (str (get-hash (str "test note" session-key)))}) 302))
|
:session-value (str (get-hash (str "test note" session-key)))}) 302))
|
||||||
(is (note-exists? date title))
|
(is (note-exists? (build-key date title)))
|
||||||
(is (substring? "test note"
|
(is (substring? "test note"
|
||||||
((send-request (url year month day title)) :body)))
|
((send-request (url year month day title)) :body)))
|
||||||
(is (has-status
|
(is (has-status
|
||||||
@@ -82,8 +81,8 @@
|
|||||||
(is (substring? "UPDATED CONTENT"
|
(is (substring? "UPDATED CONTENT"
|
||||||
((send-request (url year month day title)) :body)))
|
((send-request (url year month day title)) :body)))
|
||||||
(is (do
|
(is (do
|
||||||
(delete-note date title)
|
(delete-note (build-key date title))
|
||||||
(not (note-exists? date title)))))))
|
(not (note-exists? (build-key date title))))))))
|
||||||
|
|
||||||
(deftest requests
|
(deftest requests
|
||||||
(testing "HTTP Status"
|
(testing "HTTP Status"
|
||||||
|
|||||||
Reference in New Issue
Block a user