From 084db50b9e0dc9f062afe27576c5f60a60d18cdb Mon Sep 17 00:00:00 2001 From: Eric Ihli Date: Tue, 10 Nov 2020 04:36:10 -0800 Subject: [PATCH] Add session middleware --- db/run.sh | 2 +- web/deps.edn | 1 + web/dev/user.clj | 17 ++- web/resources/server/config.edn | 2 +- web/src/com/darklimericks/server/handlers.clj | 63 ++++++---- .../com/darklimericks/server/interceptors.clj | 41 +++++- .../com/darklimericks/server/limericks.clj | 21 +++- web/src/com/darklimericks/server/system.clj | 14 ++- web/src/com/darklimericks/server/util.clj | 8 +- web/src/com/darklimericks/server/views.clj | 119 +++++++----------- web/src/com/darklimericks/util/identicon.clj | 3 +- 11 files changed, 172 insertions(+), 119 deletions(-) diff --git a/db/run.sh b/db/run.sh index 11f283c..87ce107 100755 --- a/db/run.sh +++ b/db/run.sh @@ -10,5 +10,5 @@ docker run \ -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \ -e POSTGRES_USER=$POSTGRES_USER \ -v $PGDATA:/var/lib/postgresql/data \ - -p 5432:5432 \ + -p 127.0.0.1:5432:5432 \ darklimericks-db diff --git a/web/deps.edn b/web/deps.edn index e120ced..a276347 100644 --- a/web/deps.edn +++ b/web/deps.edn @@ -26,4 +26,5 @@ :paths ["src" "resources"] :aliases {:dev {:extra-paths ["dev"] :extra-deps {hawk {:mvn/version "0.2.11"} + seancorfield/depstar {:mvn/version "1.1.132"} ring/ring-devel {:mvn/version "1.8.2"}}}}} diff --git a/web/dev/user.clj b/web/dev/user.clj index 286bafa..a5f6795 100644 --- a/web/dev/user.clj +++ b/web/dev/user.clj @@ -49,7 +49,7 @@ (defn init [] (repl/halt) - (-> "server/config.edn" + (-> "config.edn" io/resource slurp ig/read-string @@ -62,6 +62,7 @@ (defn reset [] (repl/halt)) + (comment (init) (auto-reset) @@ -73,14 +74,12 @@ (map string/lower-case) (map #(identicon/generate % 128)))) - (do - (repeatedly - 5 - (fn [] - (car/wcar - (-> state/system :database.kv/connection) - (car-mq/enqueue "limericks" '((A 8) (A 8) (B 4) (B 4) (A 8)))))) - nil) + (repeatedly + 5 + (fn [] + (car/wcar + (-> state/system :database.kv/connection) + (car-mq/enqueue "limericks" '((A 8) (A 8) (B 4) (B 4) (A 8)))))) (car/wcar (-> state/system :database.kv/connection) diff --git a/web/resources/server/config.edn b/web/resources/server/config.edn index 7239024..e3ee043 100644 --- a/web/resources/server/config.edn +++ b/web/resources/server/config.edn @@ -1,5 +1,5 @@ {:app/logging {:min-level :debug} - :app/server {:port 8000 :handler #ig/ref :app/handler} + :app/server {:port 80 :handler #ig/ref :app/handler} :app/cache {} :worker/limerick-gen {:kv #ig/ref :database.kv/connection :db #ig/ref :database.sql/connection} diff --git a/web/src/com/darklimericks/server/handlers.clj b/web/src/com/darklimericks/server/handlers.clj index c6b42ae..d5d78fd 100644 --- a/web/src/com/darklimericks/server/handlers.clj +++ b/web/src/com/darklimericks/server/handlers.clj @@ -4,6 +4,8 @@ [reitit.ring :as ring] [clojure.string :as string] [clojure.core.async :as async] + [taoensso.carmine :as car] + [taoensso.carmine.message-queue :as car-mq] [com.darklimericks.server.util :as util] [com.darklimericks.db.albums :as db.albums] [com.darklimericks.db.limericks :as db.limericks] @@ -26,6 +28,7 @@ {:status 200 :headers {"Content-Type" "text/html; charset=utf-8"} :body (hiccup/html (views/home + db request recent-albums artists-by-album))}))) @@ -35,27 +38,16 @@ (defn limerick-generation-post-handler [db cache] (fn [{{:keys [scheme]} :params :as request}] - (let [tasks (:tasks @cache)] - (let [task-id (java.util.UUID/randomUUID) - limerick-chan (limericks/generate-limerick cache scheme task-id)] - (swap! cache assoc-in [:tasks task-id] {:status :pending}) - (async/go - (let [limerick (async/path req :com.darklimericks.server.system/artist - {:artist-id (:artist/id artist)})} + {:artist-id (:artist/id artist) + :artist-name (:artist/name artist)})} (:artist/name artist)])] [:div.fl.w-50.pa2 (for [artist left-hand-side-artists] @@ -170,8 +169,10 @@ albums))] {:status 200 :headers {"Content-Type" "text/html; charset=utf-8"} - :body (views/page - "Dark Limericks" + :body (views/wrapper + db + request + {} [:div [:div.f3.pt3.light-yellow (->> artist @@ -188,10 +189,26 @@ request :com.darklimericks.server.system/album {:artist-id (:artist/id artist) - :album-id (:album/id album)})] + :artist-name (util/slug (:artist/name artist)) + :album-id (:album/id album) + :album-name (util/slug (:album/name album))})] (map-indexed (fn [index limerick] [:a.f5.washed-yellow.db {:href (format "%s#%s" album-url (inc index))} (:limerick/name limerick)]) (get limericks (:album/id album))))])])}))) + +(defn submit-limericks-get-handler [db] + (fn [request] + {:status 200 + :headers {"Content-Type" "text/html; charset=uft-8"} + :session (if (empty? (:session request)) + {:session-id (java.util.UUID/randomUUID)} + (:session request)) + :body (views/wrapper + db + request + {} + (views/submit-limericks request))})) + diff --git a/web/src/com/darklimericks/server/interceptors.clj b/web/src/com/darklimericks/server/interceptors.clj index 454b621..28822b5 100644 --- a/web/src/com/darklimericks/server/interceptors.clj +++ b/web/src/com/darklimericks/server/interceptors.clj @@ -3,7 +3,10 @@ [muuntaja.interceptor :as muuntaja-interceptor] [reitit.interceptor.sieppari :as sieppari] [ring.middleware.keyword-params :refer [keyword-params-request]] + [ring.middleware.session] + [ring.middleware.session.memory :as mem] [taoensso.timbre :as timbre] + [taoensso.carmine.ring :as carmine.ring] [reitit.core :as reitit] [reitit.coercion :as coercion] [reitit.impl :as impl])) @@ -18,11 +21,11 @@ (def logging-interceptor {:enter (fn [{:keys [request] :as ctx}] - (timbre/info + #_(timbre/info (str "Entering " (dissoc request ::reitit/match))) ctx) - :exit (fn [{:keys [response] :as ctx}] - (timbre/info + :leave (fn [{:keys [response] :as ctx}] + #_(timbre/info (str "Exiting " (dissoc response ::reitit/match))) ctx)}) @@ -38,3 +41,35 @@ (let [coerced (coercion/coerce-request coercers request)] (assoc-in ctx [:request :parameters] coerced)) ctx))))}) + +(defn- session-options + [cache options] + {:store (options :store (carmine.ring/carmine-store cache)) + :cookie-name (options :cookie-name "ring-session") + :cookie-attrs (merge {:path "/" + :http-only true} + (options :cookie-attrs) + (if-let [root (options :root)] + {:path root}))}) + +(defn session-interceptor + ([cache] + (session-interceptor cache {})) + ([cache options] + (let [options (session-options cache options)] + {:enter + (fn [ctx] + (update + ctx + :request + ring.middleware.session/session-request + options)) + :leave + (fn [{:keys [response request] :as ctx}] + (update + ctx + :response + ring.middleware.session/session-response + request + options))})) + ) diff --git a/web/src/com/darklimericks/server/limericks.clj b/web/src/com/darklimericks/server/limericks.clj index ad4cd75..1a44587 100644 --- a/web/src/com/darklimericks/server/limericks.clj +++ b/web/src/com/darklimericks/server/limericks.clj @@ -5,6 +5,7 @@ [com.darklimericks.db.artists :as artists] [com.darklimericks.db.albums :as albums] [com.darklimericks.db.limericks :as db.limericks] + [com.darklimericks.util.identicon :as identicon] [com.darklimericks.linguistics.core :as linguistics] [com.owoga.prhyme.limerick :as limerick] [com.owoga.prhyme.data.dictionary :as dict] @@ -18,6 +19,8 @@ "Expected a letter followed by an integer.") (let [text (re-find #"[a-zA-Z]+" (first tokens)) count (Integer/parseInt (re-find #"\d+" (first tokens)))] + (assert (and (< 5 count) (< count 14)) + "Expected syllable counts between 5 and 14.") [(rest tokens) (conj ctx [text count])])) (or (= 4 (count tokens)) @@ -77,7 +80,7 @@ (nil? album-id)) (throw (ex-info "Nil artist or album" {:artist artist :album album-id}))) - [(:artist/id artist) album-id]) + ^:new-album [(:artist/id artist) album-id]) :else (let [artist-name (linguistics/gen-artist) @@ -88,7 +91,7 @@ (nil? album-id)) (throw (ex-info "Nil artist or album" {:artist artist-id :album album-id}))) - [artist-id album-id])))) + ^:new-album ^:new-artist [artist-id album-id])))) (defn get-limerick-name [lines] (->> lines @@ -118,10 +121,16 @@ (defn generate-limerick-worker [db scheme] (let [limerick (limerick/rhyme-from-scheme - dict/prhyme-dict - darklyrics-markov-2 - scheme) - [artist-id album-id] (get-artist-and-album-for-new-limerick db)] + dict/prhyme-dict + darklyrics-markov-2 + scheme) + album-artist (get-artist-and-album-for-new-limerick db) + [artist-id album-id] album-artist + album (albums/album db album-id)] + (when (:new-album (meta album-artist)) + (identicon/generate (-> (:album/name album) + string/lower-case + (string/replace #" " "-")) 128)) (db.limericks/insert-limerick db (get-limerick-name limerick) diff --git a/web/src/com/darklimericks/server/system.clj b/web/src/com/darklimericks/server/system.clj index 5af7ad8..9ebbc82 100644 --- a/web/src/com/darklimericks/server/system.clj +++ b/web/src/com/darklimericks/server/system.clj @@ -5,6 +5,7 @@ [next.jdbc :as jdbc] [environ.core :refer [env]] [taoensso.carmine.message-queue :as car-mq] + [ring.middleware.session :refer [wrap-session]] [reitit.http :as http] [reitit.ring :as ring] [reitit.coercion.spec] @@ -46,6 +47,9 @@ (defmethod ig/init-key :database.kv/connection [_ config] config) +(defmethod ig/init-key :app/session-store [_ {:keys [cache]}] + {}) + (defmethod ig/prep-key :database.sql/connection [_ _] {:jdbcUrl (str "jdbc:postgresql://localhost:5432/?user=" (or (env :postgres-user) @@ -79,14 +83,17 @@ {:name ::limerick-generation-task :post {:handler (handlers/limerick-generation-post-handler db cache)} :get {:handler (handlers/limerick-generation-get-handler db cache)}}] + ["/submit" + {:name ::submit + :get {:handler (handlers/submit-limericks-get-handler db)}}] ["/limericks" - ["/:artist-id/:album-id" + ["/{artist-name}-{artist-id}/{album-name}-{album-id}" {:name ::album :coercion reitit.coercion.spec/coercion :parameters {:path {:artist-id int? :album-id int?}} :get {:handler (handlers/limericks-get-handler db cache)}}] - ["/:artist-id" + ["/{artist-name}-{artist-id}" {:name ::artist :coercion reitit.coercion.spec/coercion :parameters {:path {:artist-id int?}} @@ -94,7 +101,8 @@ ["/assets/*" handlers/resource-handler]]] (http/router routes - {:data {:interceptors [interceptors/coerce-request-interceptor + {:data {:interceptors [(interceptors/session-interceptor cache) + interceptors/coerce-request-interceptor interceptors/logging-interceptor interceptors/format-interceptor (parameters-interceptor) diff --git a/web/src/com/darklimericks/server/util.clj b/web/src/com/darklimericks/server/util.clj index b713b77..1f58a16 100644 --- a/web/src/com/darklimericks/server/util.clj +++ b/web/src/com/darklimericks/server/util.clj @@ -1,5 +1,6 @@ (ns com.darklimericks.server.util - (:require [reitit.core :as reitit])) + (:require [reitit.core :as reitit] + [clojure.string :as string])) (defn route-name->path ([request name] @@ -8,3 +9,8 @@ (->> name (#(reitit/match-by-name (::reitit/router request) % params)) reitit/match->path))) + +(defn slug [s] + (-> s + (string/replace #"\s+" "_") + string/lower-case)) diff --git a/web/src/com/darklimericks/server/views.clj b/web/src/com/darklimericks/server/views.clj index f047515..76375f6 100644 --- a/web/src/com/darklimericks/server/views.clj +++ b/web/src/com/darklimericks/server/views.clj @@ -7,7 +7,7 @@ [com.darklimericks.server.util :as util])) (defn wrapper - ([db opts & body] + ([db request opts & body] (let [default-opts {:title "Dark Limericks"} opts (merge default-opts opts) title (:title opts) @@ -25,7 +25,11 @@ [:a.link.dim.washed-yellow {:href "/"} "DarkLimericks.com"]] [:div.w-50-ns.w-90.center.bg-dark-gray.pa2 [:div.f6.lh-copy.flex.justify-between - [:a.washed-yellow.pl1 {:href "#"} "SUBMIT LIMERICKS"] + [:a.washed-yellow.pl1 + {:href (util/route-name->path + request + :com.darklimericks.server.system/submit)} + "SUBMIT LIMERICKS"] [:span.dark-yellow (format "METAL LIMERICKS - CURRENTLY %d ALBUMS FROM %d+ BANDS" @@ -69,70 +73,22 @@ [:strong (string/upper-case letter)]]))] [:div.f6.lh-copy.flex.justify-between - [:a.washed-yellow.pr1 {:href "#"} "SUBMIT LIMERICKS"] - [:span.dark-yellow "METAL LIMERICKS - CURRENTLY 0 ALBUMS FROM 0+ BANDS"] + [:a.washed-yellow.pr1 + {:href (util/route-name->path + request + :com.darklimericks.server.system/submit)} + "SUBMIT LIMERICKS"] + [:span.dark-yellow + (format + "METAL LIMERICKS - CURRENTLY %d ALBUMS FROM %d+ BANDS" + num-albums + num-artists)] [:a.washed-yellow.pl1 {:href "#"} "LINKS"]]]])))) -(defn page [title & body] - (page/html5 - [:head - [:meta {:charset "utf-8"}] - [:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}] - (page/include-css "/assets/tachyons.css") - [:title title] - [:link {:rel "shortcut icon" :href "/assets/favicon.ico"}]] - [:body.tc.washed-yellow.bg-near-black.avenir - [:h1 - [:a.link.dim.washed-yellow {:href "/"} "DarkLimericks.com"]] - [:div.w-50-ns.w-90.center.bg-dark-gray.pa2 - [:div.f6.lh-copy.flex.justify-between - [:a.washed-yellow.pl1 {:href "#"} "SUBMIT LIMERICKS"] - [:span.dark-yellow "METAL LIMERICKS - CURRENTLY 0 ALBUMS FROM 0+ BANDS"] - [:a.washed-yellow.pr1 {:href "#"} "LINKS"]] - [:div.flex.items-stretch.bg-near-black.flex-wrap.flex-nowrap-l.f6 - (let [letters (map (comp str char) (range 97 123))] - (for [letter letters] - [:a.link.washed-yellow.bg-mid-gray.pv2.w1.w-100-ns.flex-auto - {:href (format "/%s.html" letter) - :style "margin: 1px;"} - [:strong (string/upper-case letter)]]))] - [:div.flex.items-center.justify-center.pv2 - [:span.f6.ph2 "Search the darkness for limericks most heartless"] - [:form.ph2 - {:method "GET" :action "#"} - [:input.bg-white.w4.w5-ns - {:type "text" - :name "search" - :id "search" - :value ""}]]] - [:div.bg-near-black.br4.pa2 - body] - - [:div.flex.items-center.justify-center.pv2 - [:span.f6.ph2 "Search the darkness for limericks most heartless"] - [:form.ph2 - {:method "GET" :action "#"} - [:input.bg-white.w4.w5-ns - {:type "text" - :name "search" - :id "search" - :value ""}]]] - - [:div.flex.items-stretch.w-100.bg-near-black - (let [letters (map (comp str char) (range 97 123))] - (for [letter letters] - [:a.washed-yellow.bg-mid-gray.w-100.pv2.flex-grow-1 - {:href (format "/%s.html" letter) - :style "margin: 1px;"} - (string/upper-case letter)]))] - [:div.f6.lh-copy.flex.justify-between - [:a.washed-yellow.pl1 {:href "#"} "SUBMIT LIMERICKS"] - [:span.dark-yellow "METAL LIMERICKS - CURRENTLY 0 ALBUMS FROM 0+ BANDS"] - [:a.washed-yellow.pr1 {:href "#"} "LINKS"]]]])) - -(defn home [request recent-albums artists-by-album] - (page - "Dark Limericks" +(defn home [db request recent-albums artists-by-album] + (wrapper + db + request [:div.f3.light-yellow.pb3 "Welcome to DARK LIMERICKS !"] [:div.f6.washed-yellow.pb3 @@ -159,7 +115,12 @@ {:href (util/route-name->path request :com.darklimericks.server.system/artist - {:artist-id (:album/artist_id album)})} + {:artist-id (:album/artist_id album) + :artist-name (-> album + :album/id + artists-by-album + :artist/name + util/slug)})} (-> album :album/id (artists-by-album) :artist/name)]] [:div.p2 [:a.link.washed-yellow.f6 @@ -167,12 +128,14 @@ request :com.darklimericks.server.system/album {:artist-id (:album/artist_id album) - :album-id (:album/id album)})} - (format "\"%s\"" (:album/name album))]]])] - (form/form-to - [:post (util/route-name->path request :com.darklimericks.server.system/limerick-generation-task)] - (form/text-field "scheme") - (form/submit-button "Generate dark limerick")))) + :artist-name (-> album + :album/id + artists-by-album + :artist/name + util/slug) + :album-id (:album/id album) + :album-name (util/slug (:album/name album))})} + (format "\"%s\"" (:album/name album))]]])])) (defn limerick-tasks [tasks] [:ul @@ -192,3 +155,17 @@ [:h3.f3.washed-yellow (format "%s. %s" (inc i) name)]] (for [line lines] [:div line])])) + +(defn submit-limericks + [{{:keys [session-id]} :session :as request}] + [:div + [:h1 "Submit Limericks"] + (form/form-to + [:post (util/route-name->path + request + :com.darklimericks.server.system/limerick-generation-task)] + (form/text-field "scheme") + (form/submit-button "Generate dark limerick")) + [:div + "Currently processing " + session-id]]) diff --git a/web/src/com/darklimericks/util/identicon.clj b/web/src/com/darklimericks/util/identicon.clj index d5a12f0..5c23aa5 100644 --- a/web/src/com/darklimericks/util/identicon.clj +++ b/web/src/com/darklimericks/util/identicon.clj @@ -116,7 +116,8 @@ (fill-background draw size) (.setColor draw color) (draw-it draw tile-size 0 (to-bools md5)) - (ImageIO/write icon "png" (File. (file-name identifier size))))) + (ImageIO/write icon "png" (File. (file-name identifier size))) + file-name)) (comment (generate "foobar-bazz" 128))