From 962a3624b77bbbcd4b437e2e0923e6e4f1750108 Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 24 Jul 2016 15:32:03 -0400 Subject: [PATCH] better handling of user login/logout and passing user-id's to views when logging in/out, there is a small window where the server's session state and the client-side state and view subscriptions will not exactly align and some view subscription updates (because mtgcoll.client.auth/user-profile was updated) will get treated as unauthorized. this change is admittedly somewhat quick/hacky, but basically the idea is to track the sente connection state (which is true when sente is both connected and a handshake event has been received) in a reagent atom. if false, we hide the entire ui and show a "connecting ..." message. not super pretty, but it's only shown to the user briefly and it solves the problem. i'll need to revisit this at some point and wrap it up in some library code or something somewhere to make the whole method prettier to use in the future --- src/mtgcoll/client/auth.cljs | 4 ++ src/mtgcoll/client/components/auth.cljs | 12 +++-- src/mtgcoll/client/page.cljs | 67 +++++++++++++------------ src/mtgcoll/client/views.cljs | 9 ++++ src/mtgcoll/routes/auth.clj | 2 +- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/mtgcoll/client/auth.cljs b/src/mtgcoll/client/auth.cljs index 34005e2..72cf7e3 100644 --- a/src/mtgcoll/client/auth.cljs +++ b/src/mtgcoll/client/auth.cljs @@ -19,6 +19,10 @@ [] (not (nil? @user-profile))) +(defn get-username + [] + (:username @user-profile)) + (defn set-user-profile! [profile] (reset! user-profile profile)) diff --git a/src/mtgcoll/client/components/auth.cljs b/src/mtgcoll/client/components/auth.cljs index 774ecbe..4bf68b4 100644 --- a/src/mtgcoll/client/components/auth.cljs +++ b/src/mtgcoll/client/components/auth.cljs @@ -25,9 +25,15 @@ (ajax/POST (->url "/login") :params {:username username :password password} :on-error #(reset! error "Invalid username/password.") - :on-success (fn [_] - (on-close) - (views/reconnect!)))))) + :on-success (fn [response] + ; i'm sick and fucking tired of using cljs-ajax. it's a bloated piece + ; of shit that has always been too easy to use in a wrong way and when + ; it happens, it's almost always unclear what the fuck is wrong. + ; this is the last fucking project where i will be using it. + (let [user-profile (clojure.walk/keywordize-keys response)] + (on-close) + (views/reconnect!) + (auth/set-user-profile! user-profile))))))) on-key-up (fn [e] (if (= 13 (.-keyCode e)) (on-submit)))] diff --git a/src/mtgcoll/client/page.cljs b/src/mtgcoll/client/page.cljs index 44c9c51..05b5eb3 100644 --- a/src/mtgcoll/client/page.cljs +++ b/src/mtgcoll/client/page.cljs @@ -5,7 +5,8 @@ [webtools.reagent.bootstrap :as bs] [webtools.cljs.utils :refer [->url]] [mtgcoll.client.auth :as auth] - [mtgcoll.client.components.auth :refer [login-form]])) + [mtgcoll.client.components.auth :refer [login-form]] + [mtgcoll.client.views :as views])) (defonce error (r/atom nil)) @@ -25,36 +26,40 @@ (defn app-body [page-component] - (let [active-breadcrumb @active-breadcrumb] - [:div#app-body.container - [bs/Navbar {:inverse true} - [bs/Navbar.Header - [bs/Navbar.Brand - [:a#logo {:href "#/"} - [:span [:img {:src (->url "/img/mtg_icon.png")}]] - "Card Collection"]]] - [bs/Navbar.Collapse - [bs/Nav - [bs/NavItem {:href "#/owned" :active (= :owned active-breadcrumb)} "Owned"] - [bs/NavItem {:href "#/all" :active (= :all active-breadcrumb)} "All"] - [bs/NavItem {:href "#/sets" :active (= :sets active-breadcrumb)} "Sets"] - [bs/NavItem {:href "#/stats" :active (= :stats active-breadcrumb)} "Statistics"]] - (if (auth/auth-required?) - [bs/Nav {:pull-right true} - (if (auth/authenticated?) - [bs/NavDropdown {:title (:username @auth/user-profile)} - [bs/MenuItem {:on-click #(auth/logout!)} "Logout"]] - [bs/NavItem {:on-click auth/show-login-form!} "Login"])])]] - [bs/Modal - {:show (boolean @error) - :on-hide clear-error!} - [bs/Modal.Header [bs/Modal.Title "Error"]] - [bs/Modal.Body - [:p @error]] - [bs/Modal.Footer - [bs/Button {:on-click clear-error!} "Close"]]] - [login-form] - page-component])) + (if (views/connected?) + (let [active-breadcrumb @active-breadcrumb] + [:div#app-body.container + [bs/Navbar {:inverse true} + [bs/Navbar.Header + [bs/Navbar.Brand + [:a#logo {:href "#/"} + [:span [:img {:src (->url "/img/mtg_icon.png")}]] + "Card Collection"]]] + [bs/Navbar.Collapse + [bs/Nav + [bs/NavItem {:href "#/owned" :active (= :owned active-breadcrumb)} "Owned"] + [bs/NavItem {:href "#/all" :active (= :all active-breadcrumb)} "All"] + [bs/NavItem {:href "#/sets" :active (= :sets active-breadcrumb)} "Sets"] + [bs/NavItem {:href "#/stats" :active (= :stats active-breadcrumb)} "Statistics"]] + (if (auth/auth-required?) + [bs/Nav {:pull-right true} + (if (auth/authenticated?) + [bs/NavDropdown {:title (:username @auth/user-profile)} + [bs/MenuItem {:on-click (fn [_] + (auth/logout!) + (views/reconnect!))} "Logout"]] + [bs/NavItem {:on-click auth/show-login-form!} "Login"])])]] + [bs/Modal + {:show (boolean @error) + :on-hide clear-error!} + [bs/Modal.Header [bs/Modal.Title "Error"]] + [bs/Modal.Body + [:p @error]] + [bs/Modal.Footer + [bs/Button {:on-click clear-error!} "Close"]]] + [login-form] + page-component]) + [:h1 "Connecting ..."])) (defn page [page-component] diff --git a/src/mtgcoll/client/views.cljs b/src/mtgcoll/client/views.cljs index e205ccf..3e07113 100644 --- a/src/mtgcoll/client/views.cljs +++ b/src/mtgcoll/client/views.cljs @@ -1,11 +1,18 @@ (ns mtgcoll.client.views (:require + [reagent.core :as r] [taoensso.sente :as sente] [views.reagent.sente.client :as vr] [mtgcoll.client.auth :as auth])) (defonce sente-socket (atom {})) +(defonce connected (r/atom false)) + +(defn connected? + [] + (boolean @connected)) + (defn chsk-exists? [] (not (nil? (:chsk @sente-socket)))) @@ -34,6 +41,7 @@ (= :chsk/handshake ev-id) (let [[_ _ handshake-data] ev-data {:keys [user]} handshake-data] + (reset! connected true) (auth/set-user-profile! user)) (= :chsk/recv id) @@ -47,6 +55,7 @@ (defn reconnect! [] (clear-keepalive-interval!) + (reset! connected false) (sente/chsk-reconnect! (:chsk @sente-socket))) (defn init! diff --git a/src/mtgcoll/routes/auth.clj b/src/mtgcoll/routes/auth.clj index c7c62dd..7749214 100644 --- a/src/mtgcoll/routes/auth.clj +++ b/src/mtgcoll/routes/auth.clj @@ -12,7 +12,7 @@ (if-let [user (auth/validate-credentials username password)] (do (log/info username " logged in.") - (-> (response/content "ok") + (-> (response/json user) (session/set-from-request request) (session/assoc :user user))) (do