Skip to content

Instantly share code, notes, and snippets.

@aisamu
Created February 4, 2020 20:59
Show Gist options
  • Save aisamu/c92600e34f29675ba49d8d443ef1bc3d to your computer and use it in GitHub Desktop.
Save aisamu/c92600e34f29675ba49d8d443ef1bc3d to your computer and use it in GitHub Desktop.
(ns apij.controllers.session
(:require [apij.lib.experience :as experience]
[apij.lib.json :as json]
[apij.models.user :as user]
[apij.models.visitor :as v]
[clojure.tools.logging :as log]
[copterj.stage :as stage]
[liberator.core :refer [defresource]]
[liberator.representation
:refer
[as-response parse-request-entity ring-response]]))
(defn- session-data [session image-url-root]
(let [{vid :id} v/*profile*
[eversion outcomes] (experience/outcomes vid)
outcomes (assoc outcomes "booking-vip?" (v/booking-vip? vid))]
(log/spy {:session-id (:id session)
:visitor-id vid
:workflow (:workflow session)
:stage (name (stage/current))
:image-url-root image-url-root
:experience {:path outcomes
:version eversion
:id (last (experience/serialize vid))}})))
(defn- jsonp-config [session] (ring-response (format "var rkConfig=%s;" (json/->json session)) {}))
(def resource-defaults
{:initialize-context (fn [{:keys [request representation resource] :as ctx}]
{::identity (-> request :identification/identity)})})
(defresource resource
[{:keys [datomic image-url-root] :as app}]
resource-defaults
:available-media-types ["application/javascript" "text/javascript" "application/json" "application/edn"]
:allowed-methods [:get :post :delete :put]
:last-modified (fn [ctx] (System/currentTimeMillis))
:allowed? (fn [{{params :params method :request-method} :request :as ctx}]
(if (#{:get :delete} method)
true
(let [{request-entity :request-entity} (parse-request-entity ctx)
{{:keys [email-address passphrase] :as raw-user} :user
perm-auth :perm-auth
accept-cookies :accept-cookies} (if (map? request-entity) request-entity params)]
(cond
raw-user
(let [conn (:connection datomic)
{:keys [user]} (and email-address passphrase
(user/authenticate conn email-address passphrase))]
(when user
(cond-> {:identification/identity user ::identity user}
perm-auth (assoc :identification/token
(let [resp (user/commit-actions! conn
[[:add-token {:id (:id user)
:duration (* 1000 60 60 24 30)}]])]
(-> resp :security-tokens :add-token))))))
(boolean? accept-cookies)
{:apij.middleware.cookies/send-cookies? accept-cookies}))))
:put! (fn [{{session :session} :request identity :identification/identity :as ctx}]
(when identity
(swap! session assoc :identification/method ::put :identification/identifier (:id identity)))
{})
:post! (fn [{{session :session} :request identity :identification/identity :as ctx}]
(when identity
(swap! session assoc :identification/method ::put :identification/identifier (:id identity)))
{})
:post-redirect? false
:new? false
:respond-with-entity? true
:delete! (fn [{{session :session} :request :as ctx}]
(reset! session nil)
{:identification/token nil ::identity nil})
;; https://stackoverflow.com/questions/20963273/spa-best-practices-for-authentication-and-session-management
:handle-ok (fn [{{session :session} :request identity' ::identity}]
(-> @session
(session-data image-url-root)
(assoc :identity (user/sanitize identity'))))
:as-response (fn [sresponse ctx]
(let [no-cache-headers {"Cache-Control" "no-cache, no-store"
"Expires" "0"
"Pragma" "no-cache"}
media-type (get-in ctx [:representation :media-type])]
(-> (if (#{"application/javascript" "text/javascript"} media-type)
(jsonp-config sresponse)
sresponse)
(as-response ctx)
(update :headers merge no-cache-headers)
(merge (select-keys ctx [:identification/token
:apij.middleware.cookies/send-cookies?]))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment