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
This commit is contained in:
parent
20ab3c0693
commit
962a3624b7
|
@ -19,6 +19,10 @@
|
|||
[]
|
||||
(not (nil? @user-profile)))
|
||||
|
||||
(defn get-username
|
||||
[]
|
||||
(:username @user-profile))
|
||||
|
||||
(defn set-user-profile!
|
||||
[profile]
|
||||
(reset! user-profile profile))
|
||||
|
|
|
@ -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)))]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue