Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Fix navigation bugs ocurring with session profiles
Browse files Browse the repository at this point in the history
[Re #47]
  • Loading branch information
Damian Hryniewicz committed Aug 31, 2021
1 parent 1562d16 commit cc810ba
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 157 deletions.
5 changes: 4 additions & 1 deletion resources/core/api/util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@
(defn wrap-authentication-required [handler auth-middleware]
(-> handler
(wrap-routes restrict-fn)
(wrap-routes auth-middleware)))<</hydrogen-session?>>
(wrap-routes auth-middleware)))

(defn wrap-authentication [handler auth-middleware]
(wrap-routes handler auth-middleware))<</hydrogen-session?>>
5 changes: 3 additions & 2 deletions resources/core/cljs/client.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
[re-frame.core :as rf]
[reagent.dom :as rd]
[<<namespace>>.client.breadcrumbs :as breadcrumbs]
[<<namespace>>.client.home :as home]<<#hydrogen-session?>>
[<<namespace>>.client.home :as home]
[<<namespace>>.client.navigation :as navigation]<<#hydrogen-session?>>
[<<namespace>>.client.landing :as landing]<</hydrogen-session?>>
[<<namespace>>.client.routes :as routes]<<#hydrogen-session-keycloak?>>
[<<namespace>>.client.session]<</hydrogen-session-keycloak?>>
Expand Down Expand Up @@ -104,6 +105,6 @@
(defn ^:export init []
(dev-setup)
(rf/dispatch-sync [::load-app])<<#hydrogen-session-keycloak?>>
(view/fix-query-params js/location.hash)<</hydrogen-session-keycloak?>>
(navigation/fix-query-params js/location.hash)<</hydrogen-session-keycloak?>>
(routes/app-routes)
(mount-root))
5 changes: 3 additions & 2 deletions resources/core/cljs/home.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
[<<namespace>>.client.breadcrumbs :as breadcrumbs]<<#hydrogen-session?>>
[<<namespace>>.client.session :as session]
[<<namespace>>.client.user :as user]<</hydrogen-session?>>
[<<namespace>>.client.view :as view]))
[<<namespace>>.client.view :as view]
[<<namespace>>.client.navigation :as navigation]))

(rf/reg-event-fx
::view.enter
Expand All @@ -34,7 +35,7 @@
(defn- logout []
[:div.logout
{:on-click #(do (rf/dispatch [::session/user-logout])
(view/redirect! "/#/landing"))}
(navigation/redirect! "/#/landing"))}
"Logout"])<</hydrogen-session?>>

(defn main []
Expand Down
65 changes: 65 additions & 0 deletions resources/core/cljs/navigation.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/

{{=<< >>=}}
(ns <<namespace>>.client.navigation
(:require <<#hydrogen-ssr?>>[pushy.core :as pushy]
[secretary.core :as secretary]
<</hydrogen-ssr?>><<#hydrogen-session-keycloak?>>[clojure.string :as str]
<</hydrogen-session-keycloak?>>[re-frame.core :as rf]))<<#hydrogen-ssr?>>

(def history (pushy/pushy secretary/dispatch!
(fn [x] (when (secretary/locate-route x) x))))

(defn redirect! [path]
(pushy/set-token! history path))

(defn start!
"Start navigation's event listeners (to process links and such)"
[]
(pushy/start! history))<</hydrogen-ssr?>><<^hydrogen-ssr?>>

(defn redirect! [loc]
(set! (.-location js/window) loc))<</hydrogen-ssr?>>

(rf/reg-fx
:redirect
(fn [loc]
(redirect! loc)))<<#hydrogen-session-keycloak?>>

(defn remove-query-param [loc-hash param]
(let [[path query-params] (str/split loc-hash #"\?")]
(if query-params
(->>
(str/split query-params #"\&")
(remove
#(str/starts-with? % (str (name param) "=")))
(str/join "&")
(conj [path])
(filter seq)
(str/join "?"))
path)))

(defn get-query-param [loc-hash param]
(let [[_ query-params] (str/split loc-hash #"\?")]
(when query-params
(some->
(some
#(when (str/starts-with? % (str (name param) "=")) %)
(str/split query-params #"\&"))
(str/split #"\=")
(second)))))

(defn fix-query-params
"This function makes sure that query params list in location url
starts with a question mark instead of an ampersand.
It assumes that the only scenario when this happens is when
keycloak appends its params necessary for the auth process
and when the first query param doesn't come with a ? instead of &:
`/foobar&state=...&session_state=...&code=...`."
[loc-hash]
(when (and (str/index-of loc-hash "&state=")
(not (str/index-of loc-hash "?")))
(redirect! (str/replace loc-hash "&state=" "?state="))))<</hydrogen-session-keycloak?>>
6 changes: 3 additions & 3 deletions resources/core/cljs/routes.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
[<<namespace>>.client.session :as session]
[<<namespace>>.client.user :as user]
[<<namespace>>.client.util :as util]<</hydrogen-session?>>
[<<namespace>>.client.view :as view]))
[<<namespace>>.client.navigation :as navigation]))

(defn hook-browser-navigation! []
(doto (History.)
Expand Down Expand Up @@ -203,7 +203,7 @@
(rf/dispatch [:go-to [::hydrogen-demo.shop-item/view item-id]]))

(defroute "*" []
(view/redirect! "/#/landing"))
(navigation/redirect! "/#/landing"))

;; --------------------
(hook-browser-navigation!))<</hydrogen-session?>><<^hydrogen-session?>>
Expand Down Expand Up @@ -244,7 +244,7 @@
(rf/dispatch [:go-to [::hydrogen-demo.shop-item/view item-id]]))

(defroute "*" []
(view/redirect! "/#/home"))
(navigation/redirect! "/#/home"))

;; --------------------
(hook-browser-navigation!))<</hydrogen-session?>>
49 changes: 2 additions & 47 deletions resources/core/cljs/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

{{=<< >>=}}
(ns <<namespace>>.client.view
(:require <<#hydrogen-session-keycloak?>>[clojure.string :as str]
<</hydrogen-session-keycloak?>>[re-frame.core :as rf]))
(:require [re-frame.core :as rf]))

(rf/reg-sub
::active-view
Expand All @@ -17,14 +16,6 @@
(fn [db [_ active-view]]
(assoc db :active-view active-view)))

(defn redirect! [loc]
(set! (.-location js/window) loc))

(rf/reg-fx
:redirect
(fn [loc]
(redirect! loc)))

(defmulti view-display #(when (vector? %) (first %)))

(defmethod view-display :default
Expand All @@ -35,40 +26,4 @@
[]
(let [active-view (rf/subscribe [::active-view])]
(fn []
[view-display @active-view])))<<#hydrogen-session-keycloak?>>

(defn remove-query-param [loc-hash param]
(let [[path query-params] (str/split loc-hash #"\?")]
(if query-params
(->>
(str/split query-params #"\&")
(remove
#(str/starts-with? % (str (name param) "=")))
(str/join "&")
(conj [path])
(filter seq)
(str/join "?"))
path)))

(defn get-query-param [loc-hash param]
(let [[_ query-params] (str/split loc-hash #"\?")]
(when query-params
(some->
(some
#(when (str/starts-with? % (str (name param) "=")) %)
(str/split query-params #"\&"))
(str/split #"\=")
(second)))))

(defn fix-query-params
"This function makes sure that query params list in location url
starts with a question mark instead of an ampersand.
It assumes that the only scenario when this happens is when
keycloak appends its params necessary for the auth process
and when the first query param doesn't come with a ? instead of &:
`localhost/#/foobar&state=...&session_state=...&code=...`."
[loc-hash]
(when (and (str/index-of loc-hash "&state=")
(not (str/index-of loc-hash "?")))
(redirect! (str/replace loc-hash "&state=" "?state="))))<</hydrogen-session-keycloak?>>
[view-display @active-view])))
6 changes: 3 additions & 3 deletions resources/session/cognito/cljs/landing.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{{=<< >>=}}
(ns <<namespace>>.client.landing
(:require [re-frame.core :as rf]
[reagent.core :as reagent]
[reagent.core :as r]
[<<namespace>>.client.session :as session]
[<<namespace>>.client.theme :as theme]
[<<namespace>>.client.view :as view]))
Expand All @@ -14,14 +14,14 @@
::view.enter
(fn [_ _]
{:dispatch [::view/set-active-view [::view]]
:redirect "/#/landing"}))
:redirect "/<<^hydrogen-ssr?>>#/<</hydrogen-ssr?>>landing"}))

(rf/reg-event-fx
::view.leave
(fn [_ _]
{}))

(def credentials (reagent/atom {:username "" :password ""}))
(def credentials (r/atom {:username "" :password ""}))

(defn swap-input! [event atom field]
(swap! atom assoc field (.. event -target -value)))
Expand Down
2 changes: 1 addition & 1 deletion resources/session/cognito/cljs/session.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
(fn [_ _]
{:dispatch-n [[::set-token-and-schedule-refresh]
[::set-auth-error nil]]
:redirect "/#/home"}))
:redirect "/<<^hydrogen-ssr?>>#/<</hydrogen-ssr?>>home"}))

(rf/reg-fx
::do-user-login
Expand Down
2 changes: 1 addition & 1 deletion resources/session/keycloak/cljs/landing.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
::view.enter
(fn [_ _]
{:dispatch [::view/set-active-view [::view]]
:redirect "/#/home"}))
:redirect "/<<^hydrogen-ssr?>>#/<</hydrogen-ssr?>>home"}))

(rf/reg-event-fx
::view.leave
Expand Down
16 changes: 8 additions & 8 deletions resources/session/keycloak/cljs/session.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
(:require [clojure.spec.alpha :as s]
[re-frame.core :as rf]
[<<namespace>>.client.session.oidc-sso :as oidc-sso]
[<<namespace>>.client.view :as view]))
[<<namespace>>.client.navigation :as navigation]))

;; Keycloak Javascript library is not designed to be used in a
;; functional way. When you create a keycloak object to interact with
Expand All @@ -32,9 +32,9 @@
(or
(nil? @keycloak)
(and
(view/get-query-param js/location.hash "state")
(view/get-query-param js/location.hash "session_state")
(view/get-query-param js/location.hash "code"))))
(navigation/get-query-param js/location.hash "state")
(navigation/get-query-param js/location.hash "session_state")
(navigation/get-query-param js/location.hash "code"))))

(rf/reg-event-fx
::set-auth-error
Expand Down Expand Up @@ -143,9 +143,9 @@
(defn- remove-keycloak-process-query-params
[location-hash]
(-> location-hash
(view/remove-query-param :state)
(view/remove-query-param :code)
(view/remove-query-param :session_state)))
(navigation/remove-query-param :state)
(navigation/remove-query-param :code)
(navigation/remove-query-param :session_state)))

(rf/reg-event-fx
::on-login-success
Expand All @@ -171,7 +171,7 @@
(handle-keycloak-obj-change keycloak-obj)
;; Since we sometime turn &state into ?state, Keycloak
;; is unable to clean up after itself.
(view/redirect! (remove-keycloak-process-query-params js/location.hash)))))
(navigation/redirect! (remove-keycloak-process-query-params js/location.hash)))))
(.catch #(rf/dispatch [::set-auth-error "Failed to initialize Keycloak"]))))))

(rf/reg-fx
Expand Down
65 changes: 65 additions & 0 deletions resources/ssr/client_substitutes/landing.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/

{{=<< >>=}}
(ns <<namespace>>.client.landing
"This namespace is there to solve cross-platform compatibility for BE and FE when doing isomorphic rendering"
(:require [re-frame.core :as rf]
[<<namespace>>.client.theme :as theme]
[<<namespace>>.client.view :as view]))

(rf/reg-event-fx
::view.enter
(fn [_ _]
{:dispatch [::view/set-active-view [::view]]
:redirect "/landing"}))

(rf/reg-event-fx
::view.leave
(fn [_ _]
{}))

(def credentials (atom {:username "" :password ""}))

(defn swap-input! [event atom field]
(swap! atom assoc field (.. event -target -value)))

(defn login-form []
[:div.login-form-container
[:form.login-form
[:div.form-field
[:img.form-field__icon {:src "images/email-address.svg"}]
[:input.form-field__input
{:type "email"
:auto-complete "username"
:placeholder "Email"
:id "email"
:value (:username @credentials)
:on-change #(swap-input! % credentials :username)}]]
[:div.form-field
[:img.form-field__icon {:src "images/password.svg"}]
[:input.form-field__input
{:type "password"
:auto-complete "current-password"
:placeholder "Password"
:id "password"
:value (:password @credentials)
:on-change #(swap-input! % credentials :password)}]]]
[:button.btn.btn--gradient "Login"]])

(defn header []
[:header
[:h1 "Hydrogen"]])

(defn main []
(let [theme (rf/subscribe [::theme/get-theme])]
(fn []
[:div.landing-container
{:class (str "theme-" (name @theme))}
[header]
[login-form]])))

(defmethod view/view-display ::view
[_]
[main])
Loading

0 comments on commit cc810ba

Please sign in to comment.