You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.4 KiB
157 lines
4.4 KiB
(ns NoteHub.storage |
|
(:use [NoteHub.settings] |
|
[clojure.string :only (blank?)] |
|
[noir.util.crypt :only [encrypt]] |
|
[noir.options :only [dev-mode?]]) |
|
(:require [clj-redis.client :as redis])) |
|
|
|
; Initialize the data base |
|
(def db |
|
(redis/init |
|
(when-not (dev-mode?) |
|
{:url (get-setting :db-url)}))) |
|
|
|
(defn get-current-date [] |
|
(str (java.util.Date.))) |
|
|
|
; DB hierarchy levels |
|
(def note "note") |
|
(def published "published") |
|
(def edited "edited") |
|
(def views "views") |
|
(def password "password") |
|
(def sessions "sessions") |
|
(def short-url "short-url") |
|
(def publisher "publisher") |
|
|
|
(defn valid-publisher? [pid] |
|
(redis/hexists db publisher pid)) |
|
|
|
(defn register-publisher [pid] |
|
"Returns nil if given PID exists or a PSK otherwise" |
|
(when (not (valid-publisher? pid)) |
|
(let [psk (encrypt (str (rand-int Integer/MAX_VALUE) pid)) |
|
_ (redis/hset db publisher pid psk)] |
|
psk))) |
|
|
|
(defn revoke-publisher [pid] |
|
(redis/hdel db publisher pid)) |
|
|
|
(defn get-psk [pid] |
|
(redis/hget db publisher pid)) |
|
|
|
(defn create-session |
|
[] |
|
(let [token (encrypt (str (rand-int Integer/MAX_VALUE)))] |
|
(do (redis/sadd db sessions token) |
|
token))) |
|
|
|
(defn invalidate-session |
|
[token] |
|
; Jedis is buggy & returns an NPE for token == nil |
|
(when token |
|
(let [was-valid (redis/sismember db sessions token)] |
|
(do (redis/srem db sessions token) |
|
was-valid)))) |
|
|
|
; TODO: deprecated |
|
(defn update-note |
|
[noteID text passwd] |
|
(let [stored-password (redis/hget db password noteID)] |
|
(when (and stored-password (= passwd stored-password)) |
|
(redis/hset db edited noteID (get-current-date)) |
|
(redis/hset db note noteID text)))) |
|
|
|
(defn edit-note |
|
[noteID text] |
|
(do |
|
(redis/hset db edited noteID (get-current-date)) |
|
(redis/hset db note noteID text))) |
|
|
|
(defn add-note |
|
([noteID text] (add-note noteID text nil)) |
|
([noteID text passwd] |
|
(do |
|
(redis/hset db note noteID text) |
|
(redis/hset db published noteID (get-current-date)) |
|
(when (not (blank? passwd)) |
|
(redis/hset db password noteID passwd))))) |
|
|
|
(defn valid-password? [noteID passwd] |
|
(let [stored (redis/hget db password noteID)] |
|
(and stored (= stored passwd)))) |
|
|
|
(defn get-note |
|
[noteID] |
|
(let [text (redis/hget db note noteID)] |
|
(when text |
|
(do |
|
(redis/hincrby db views noteID 1) |
|
text)))) |
|
|
|
(defn get-note-views |
|
[noteID] |
|
(redis/hget db views noteID)) |
|
|
|
(defn get-note-statistics |
|
"Return views, publishing and editing timestamp" |
|
[noteID] |
|
{ :views (redis/hget db views noteID) |
|
:published (redis/hget db published noteID) |
|
:edited (redis/hget db edited noteID) }) |
|
|
|
(defn note-exists? |
|
[noteID] |
|
(redis/hexists db note noteID)) |
|
|
|
(defn delete-note |
|
[noteID] |
|
(doseq [kw [password views note]] |
|
; TODO: delete short url by looking for the title |
|
(redis/hdel db kw noteID))) |
|
|
|
(defn short-url-exists? |
|
"Checks whether the provided short url is taken (for testing only)" |
|
[url] |
|
(redis/hexists db short-url url)) |
|
|
|
(defn get-short-url [noteID] |
|
(redis/hget db short-url noteID)) |
|
|
|
(defn resolve-url |
|
"Resolves short url by providing all metadata of the request" |
|
[url] |
|
(let [value (redis/hget db short-url url)] |
|
(when value |
|
(read-string value)))) |
|
|
|
(defn delete-short-url |
|
"Deletes a short url (for testing only)" |
|
[noteID] |
|
(let [value (redis/hget db short-url noteID)] |
|
(do |
|
(redis/hdel db short-url noteID) |
|
(redis/hdel db short-url value)))) |
|
|
|
(defn create-short-url |
|
"Creates a short url for the given request metadata or noteID or extracts |
|
one if it was already created" |
|
[arg] |
|
(let [key (if (map? arg) (str (into (sorted-map) arg)) arg)] |
|
(if (short-url-exists? key) |
|
(redis/hget db short-url key) |
|
(let [hash-stream (partition 5 (repeatedly #(rand-int 36))) |
|
hash-to-string (fn [hash] |
|
(apply str |
|
; map first 10 numbers to digits |
|
; and the rest to chars |
|
(map #(char (+ (if (< 9 %) 87 48) %)) hash))) |
|
url (first |
|
(remove short-url-exists? |
|
(map hash-to-string hash-stream)))] |
|
(do |
|
; we create two mappings: key params -> short url and back, |
|
; s.t. we can later easily check whether a short url already exists |
|
(redis/hset db short-url url key) |
|
(redis/hset db short-url key url) |
|
url)))))
|
|
|