mirror of
https://github.com/penpot/penpot.git
synced 2025-02-20 13:55:34 -05:00
♻️ Minor refactor of auth data-flow.
This fixes many issues related to using penpot on-premise instances on different domain than localhost. This changes ensures correct data flow of authenticated and not authenticated sessions.
This commit is contained in:
parent
ece914303a
commit
2596ad27c3
10 changed files with 95 additions and 56 deletions
|
@ -58,7 +58,9 @@
|
||||||
(assoc response :cookies {cookie-name {:path "/"
|
(assoc response :cookies {cookie-name {:path "/"
|
||||||
:http-only true
|
:http-only true
|
||||||
:value id
|
:value id
|
||||||
:same-site (if cors? :none :strict)
|
:same-site (cond (not secure?) :lax
|
||||||
|
cors? :none
|
||||||
|
:else :strict)
|
||||||
:secure secure?}})))
|
:secure secure?}})))
|
||||||
|
|
||||||
(defn- clear-cookies
|
(defn- clear-cookies
|
||||||
|
|
|
@ -335,9 +335,9 @@
|
||||||
;; --- MUTATION: Logout
|
;; --- MUTATION: Logout
|
||||||
|
|
||||||
(s/def ::logout
|
(s/def ::logout
|
||||||
(s/keys :req-un [::profile-id]))
|
(s/keys :opt-un [::profile-id]))
|
||||||
|
|
||||||
(sv/defmethod ::logout
|
(sv/defmethod ::logout {:auth false}
|
||||||
[{:keys [session] :as cfg} _]
|
[{:keys [session] :as cfg} _]
|
||||||
(with-meta {}
|
(with-meta {}
|
||||||
{:transform-response (:delete session)}))
|
{:transform-response (:delete session)}))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.data.users
|
(ns app.main.data.users
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.exceptions :as ex]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
@ -90,6 +91,8 @@
|
||||||
|
|
||||||
;; --- EVENT: fetch-profile
|
;; --- EVENT: fetch-profile
|
||||||
|
|
||||||
|
(declare logout)
|
||||||
|
|
||||||
(def profile-fetched?
|
(def profile-fetched?
|
||||||
(ptk/type? ::profile-fetched))
|
(ptk/type? ::profile-fetched))
|
||||||
|
|
||||||
|
@ -102,18 +105,18 @@
|
||||||
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(cond-> state
|
||||||
(assoc :profile-id id)
|
(is-authenticated? profile)
|
||||||
(assoc :profile profile)))
|
(-> (assoc :profile-id id)
|
||||||
|
(assoc :profile profile))))
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ state _]
|
(effect [_ state _]
|
||||||
(let [profile (:profile state)]
|
(when-let [profile (:profile state)]
|
||||||
(when (not= uuid/zero (:id profile))
|
|
||||||
(swap! storage assoc :profile profile)
|
(swap! storage assoc :profile profile)
|
||||||
(i18n/set-locale! (:lang profile))
|
(i18n/set-locale! (:lang profile))
|
||||||
(some-> (:theme profile)
|
(some-> (:theme profile)
|
||||||
(theme/set-current-theme!)))))))
|
(theme/set-current-theme!))))))
|
||||||
|
|
||||||
(defn fetch-profile
|
(defn fetch-profile
|
||||||
[]
|
[]
|
||||||
|
@ -154,38 +157,65 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
|
(when (is-authenticated? profile)
|
||||||
(let [team-id (:default-team-id profile)]
|
(let [team-id (:default-team-id profile)]
|
||||||
(->> (rx/concat
|
(->> (rx/of (profile-fetched profile)
|
||||||
(rx/of (profile-fetched profile)
|
(fetch-teams)
|
||||||
(fetch-teams))
|
(rt/nav' :dashboard-projects {:team-id team-id}))
|
||||||
(->> (rx/of (rt/nav' :dashboard-projects {:team-id team-id}))
|
(rx/observe-on :async)))))))
|
||||||
(rx/delay 1000)))
|
|
||||||
(rx/observe-on :async))))))
|
|
||||||
|
|
||||||
(s/def ::login-params
|
(s/def ::login-params
|
||||||
(s/keys :req-un [::email ::password]))
|
(s/keys :req-un [::email ::password]))
|
||||||
|
|
||||||
|
(declare login-from-register)
|
||||||
|
|
||||||
(defn login
|
(defn login
|
||||||
[{:keys [email password] :as data}]
|
[{:keys [email password] :as data}]
|
||||||
(us/verify ::login-params data)
|
(us/verify ::login-params data)
|
||||||
(ptk/reify ::login
|
(ptk/reify ::login
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ stream]
|
||||||
(let [{:keys [on-error on-success]
|
(let [{:keys [on-error on-success]
|
||||||
:or {on-error rx/throw
|
:or {on-error rx/throw
|
||||||
on-success identity}} (meta data)
|
on-success identity}} (meta data)
|
||||||
params {:email email
|
params {:email email
|
||||||
:password password
|
:password password
|
||||||
:scope "webapp"}]
|
:scope "webapp"}]
|
||||||
(->> (rx/timer 100)
|
|
||||||
(rx/mapcat #(rp/mutation :login params))
|
;; NOTE: We can't take the profile value from login because
|
||||||
(rx/tap on-success)
|
;; there are cases when login is successfull but the cookie is
|
||||||
(rx/catch on-error)
|
;; not set properly (because of possible misconfiguration).
|
||||||
|
;; So, we proceed to make an additional call to fetch the
|
||||||
|
;; profile, and ensure that cookie is set correctly. If
|
||||||
|
;; profile fetch is successful, we mark the user logged in, if
|
||||||
|
;; the returned profile is an NOT authenticated profile, we
|
||||||
|
;; proceed to logout and show an error message.
|
||||||
|
|
||||||
|
(rx/merge
|
||||||
|
(->> (rp/mutation :login params)
|
||||||
|
(rx/map fetch-profile)
|
||||||
|
(rx/catch on-error))
|
||||||
|
|
||||||
|
(->> stream
|
||||||
|
(rx/filter profile-fetched?)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map deref)
|
||||||
|
(rx/filter (complement is-authenticated?))
|
||||||
|
(rx/tap on-error)
|
||||||
|
(rx/map #(ex/raise :type :authentication))
|
||||||
|
(rx/observe-on :async))
|
||||||
|
|
||||||
|
(->> stream
|
||||||
|
(rx/filter profile-fetched?)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/map deref)
|
||||||
|
(rx/filter is-authenticated?)
|
||||||
(rx/map (fn [profile]
|
(rx/map (fn [profile]
|
||||||
(with-meta profile
|
(with-meta profile
|
||||||
{::ev/source "login"})))
|
{::ev/source "login"})))
|
||||||
|
(rx/tap on-success)
|
||||||
(rx/map logged-in)
|
(rx/map logged-in)
|
||||||
(rx/observe-on :async))))
|
(rx/observe-on :async)))))
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ _ _]
|
(effect [_ _ _]
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[app.main.data.users :as du]
|
[app.main.data.users :as du]
|
||||||
[app.main.sentry :as sentry]
|
[app.main.sentry :as sentry]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
[cljs.pprint :refer [pprint]]
|
[cljs.pprint :refer [pprint]]
|
||||||
|
@ -48,7 +49,9 @@
|
||||||
;; here and not in app.main.errors because of circular dependency.
|
;; here and not in app.main.errors because of circular dependency.
|
||||||
(defmethod ptk/handle-error :authentication
|
(defmethod ptk/handle-error :authentication
|
||||||
[_]
|
[_]
|
||||||
(ts/schedule (st/emitf (du/logout))))
|
(let [msg (tr "errors.auth.unable-to-login")]
|
||||||
|
(st/emit! (du/logout))
|
||||||
|
(ts/schedule 500 (st/emitf (dm/warn msg)))))
|
||||||
|
|
||||||
|
|
||||||
;; That are special case server-errors that should be treated
|
;; That are special case server-errors that should be treated
|
||||||
|
|
|
@ -73,14 +73,14 @@
|
||||||
:dashboard-font-providers
|
:dashboard-font-providers
|
||||||
:dashboard-team-members
|
:dashboard-team-members
|
||||||
:dashboard-team-settings)
|
:dashboard-team-settings)
|
||||||
(when profile
|
|
||||||
(let [props (:props profile)]
|
|
||||||
[:*
|
[:*
|
||||||
#_[:div.modal-wrapper
|
#_[:div.modal-wrapper
|
||||||
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
#_[:& app.main.ui.onboarding/onboarding-templates-modal]
|
||||||
[:& app.main.ui.onboarding/onboarding-modal]
|
#_[:& app.main.ui.onboarding/onboarding-modal]
|
||||||
#_[:& app.main.ui.onboarding/onboarding-team-modal]
|
#_[:& app.main.ui.onboarding/onboarding-team-modal]
|
||||||
]
|
]
|
||||||
|
(when-let [props (some-> profile (get :props {}))]
|
||||||
(cond
|
(cond
|
||||||
(and cf/onboarding-form-id
|
(and cf/onboarding-form-id
|
||||||
(not (:onboarding-questions-answered props false)))
|
(not (:onboarding-questions-answered props false)))
|
||||||
|
@ -94,8 +94,9 @@
|
||||||
(and (:onboarding-viewed props)
|
(and (:onboarding-viewed props)
|
||||||
(not= (:release-notes-viewed props) (:main @cf/version))
|
(not= (:release-notes-viewed props) (:main @cf/version))
|
||||||
(not= "0.0" (:main @cf/version)))
|
(not= "0.0" (:main @cf/version)))
|
||||||
[:& app.main.ui.releases/release-notes-modal {}])
|
[:& app.main.ui.releases/release-notes-modal {}]))
|
||||||
[:& dashboard {:route route}]]))
|
|
||||||
|
[:& dashboard {:route route :profile profile}]]
|
||||||
|
|
||||||
:viewer
|
:viewer
|
||||||
(let [{:keys [query-params path-params]} route
|
(let [{:keys [query-params path-params]} route
|
||||||
|
|
|
@ -74,9 +74,8 @@
|
||||||
nil)])
|
nil)])
|
||||||
|
|
||||||
(mf/defc dashboard
|
(mf/defc dashboard
|
||||||
[{:keys [route] :as props}]
|
[{:keys [route profile] :as props}]
|
||||||
(let [profile (mf/deref refs/profile)
|
(let [section (get-in route [:data :name])
|
||||||
section (get-in route [:data :name])
|
|
||||||
params (parse-params route)
|
params (parse-params route)
|
||||||
|
|
||||||
project-id (:project-id params)
|
project-id (:project-id params)
|
||||||
|
|
|
@ -514,7 +514,7 @@
|
||||||
[:li {:on-click (partial on-click :settings-password)}
|
[:li {:on-click (partial on-click :settings-password)}
|
||||||
[:span.icon i/lock]
|
[:span.icon i/lock]
|
||||||
[:span.text (tr "labels.password")]]
|
[:span.text (tr "labels.password")]]
|
||||||
[:li {:on-click (partial on-click (du/logout))}
|
[:li {:on-click #(on-click (du/logout) %)}
|
||||||
[:span.icon i/exit]
|
[:span.icon i/exit]
|
||||||
[:span.text (tr "labels.logout")]]
|
[:span.text (tr "labels.logout")]]
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
(defn load-arengu-sdk
|
(defn load-arengu-sdk
|
||||||
[container-ref email form-id]
|
[container-ref email form-id]
|
||||||
(letfn [(on-init []
|
(letfn [(on-init []
|
||||||
(let [container (mf/ref-val container-ref)]
|
(when-let [container (mf/ref-val container-ref)]
|
||||||
(-> (.embed js/ArenguForms form-id container)
|
(-> (.embed js/ArenguForms form-id container)
|
||||||
(p/then (fn [form] (.setHiddenField ^js form "email" email))))))
|
(p/then (fn [form] (.setHiddenField ^js form "email" email))))))
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
:credentials credentials
|
:credentials credentials
|
||||||
:referrerPolicy "no-referrer"
|
:referrerPolicy "no-referrer"
|
||||||
:signal signal}]
|
:signal signal}]
|
||||||
|
|
||||||
(-> (js/fetch (str uri) params)
|
(-> (js/fetch (str uri) params)
|
||||||
(p/then (fn [response]
|
(p/then (fn [response]
|
||||||
(vreset! abortable? false)
|
(vreset! abortable? false)
|
||||||
|
|
|
@ -3255,3 +3255,6 @@ msgstr "Owner can't leave team, you must reassign the owner role."
|
||||||
|
|
||||||
msgid "errors.team-leave.insufficient-members"
|
msgid "errors.team-leave.insufficient-members"
|
||||||
msgstr "Insufficient members to leave team, you probably want to delete it."
|
msgstr "Insufficient members to leave team, you probably want to delete it."
|
||||||
|
|
||||||
|
msgid "errors.auth.unable-to-login"
|
||||||
|
msgstr "Unable to login, looks like you are not authenticated."
|
||||||
|
|
Loading…
Add table
Reference in a new issue