mirror of
https://github.com/penpot/penpot.git
synced 2026-08-06 21:08:34 +00:00
🐛 Fix nitrate sso doesn't notify workspace on activation (#10955)
This commit is contained in:
parent
be5d9f9e9c
commit
03f9393200
@ -11,7 +11,9 @@
|
|||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.time :as ct]
|
[app.common.time :as ct]
|
||||||
|
[app.common.types.organization :as co]
|
||||||
[app.common.types.team :as ctt]
|
[app.common.types.team :as ctt]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
@ -232,6 +234,63 @@
|
|||||||
;; Delay so the navigation can finish
|
;; Delay so the navigation can finish
|
||||||
(rx/delay 250))))))))
|
(rx/delay 250))))))))
|
||||||
|
|
||||||
|
(defn- check-team-sso
|
||||||
|
[team-id]
|
||||||
|
(let [url (rt/get-current-href)]
|
||||||
|
(->> (rp/cmd! :check-nitrate-sso {:team-id team-id :url url})
|
||||||
|
(rx/mapcat (fn [{:keys [authorized redirect-uri]}]
|
||||||
|
(if authorized
|
||||||
|
(rx/empty)
|
||||||
|
(if redirect-uri
|
||||||
|
(rx/of (rt/nav-raw :uri (str redirect-uri)))
|
||||||
|
(rx/empty))))))))
|
||||||
|
|
||||||
|
(defn handle-change-team-org
|
||||||
|
"Handle :team-org-change websocket messages on dashboard and workspace.
|
||||||
|
Updates local team org data and redirects to SSO when required."
|
||||||
|
[{:keys [team notification]}]
|
||||||
|
(ptk/reify ::handle-change-team-org
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [current-team-id (:current-team-id state)
|
||||||
|
organization (:organization team)
|
||||||
|
current-team? (= (:id team) current-team-id)]
|
||||||
|
(when (and (contains? cf/flags :nitrate)
|
||||||
|
current-team?)
|
||||||
|
(rx/concat
|
||||||
|
(when notification
|
||||||
|
(rx/of (ntf/show {:content (tr notification (:name organization))
|
||||||
|
:type :toast
|
||||||
|
:level :info
|
||||||
|
:timeout nil})))
|
||||||
|
(when (:id organization)
|
||||||
|
(check-team-sso current-team-id))))))
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(if (contains? cf/flags :nitrate)
|
||||||
|
(let [team-id (:id team)
|
||||||
|
team-name (:name team)
|
||||||
|
organization (:organization team)]
|
||||||
|
(d/update-in-when state [:teams team-id]
|
||||||
|
(fn [team]
|
||||||
|
(cond-> (co/apply-organization team organization)
|
||||||
|
team-name (assoc :name team-name)))))
|
||||||
|
state))))
|
||||||
|
|
||||||
|
(defn handle-organization-change-sso
|
||||||
|
"Handle :organization-change-sso websocket messages on dashboard and workspace.
|
||||||
|
Redirects to the org SSO login when the current team belongs to that org."
|
||||||
|
[{:keys [organization-id]}]
|
||||||
|
(ptk/reify ::handle-organization-change-sso
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(when (contains? cf/flags :nitrate)
|
||||||
|
(let [team-id (:current-team-id state)
|
||||||
|
team (dm/get-in state [:teams team-id])
|
||||||
|
org-id (dm/get-in team [:organization :id])]
|
||||||
|
(when (= organization-id org-id)
|
||||||
|
(check-team-sso team-id)))))))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; PROGRESS EVENTS
|
;; PROGRESS EVENTS
|
||||||
|
|||||||
@ -13,7 +13,6 @@
|
|||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.time :as ct]
|
[app.common.time :as ct]
|
||||||
[app.common.types.organization :as co]
|
|
||||||
[app.common.types.project :refer [valid-project?]]
|
[app.common.types.project :refer [valid-project?]]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
@ -27,7 +26,6 @@
|
|||||||
[app.main.data.team :as dtm]
|
[app.main.data.team :as dtm]
|
||||||
[app.main.data.websocket :as dws]
|
[app.main.data.websocket :as dws]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.router :as rt]
|
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.sse :as sse]
|
[app.util.sse :as sse]
|
||||||
@ -687,47 +685,6 @@
|
|||||||
(rx/of (dcm/change-team-role params)
|
(rx/of (dcm/change-team-role params)
|
||||||
(modal/hide)))))
|
(modal/hide)))))
|
||||||
|
|
||||||
(defn- check-team-sso
|
|
||||||
[team-id]
|
|
||||||
(let [url (rt/get-current-href)]
|
|
||||||
(->> (rp/cmd! :check-nitrate-sso {:team-id team-id :url url})
|
|
||||||
(rx/mapcat (fn [{:keys [authorized redirect-uri]}]
|
|
||||||
(if authorized
|
|
||||||
(rx/empty)
|
|
||||||
(if redirect-uri
|
|
||||||
(rx/of (rt/nav-raw :uri (str redirect-uri)))
|
|
||||||
(rx/empty))))))))
|
|
||||||
|
|
||||||
(defn handle-change-team-org
|
|
||||||
[{:keys [team notification]}]
|
|
||||||
(ptk/reify ::handle-change-team-org
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [current-team-id (:current-team-id state)
|
|
||||||
organization (:organization team)
|
|
||||||
current-team? (= (:id team) current-team-id)]
|
|
||||||
(when (and (contains? cf/flags :nitrate)
|
|
||||||
current-team?)
|
|
||||||
(rx/concat
|
|
||||||
(when notification
|
|
||||||
(rx/of (ntf/show {:content (tr notification (:name organization))
|
|
||||||
:type :toast
|
|
||||||
:level :info
|
|
||||||
:timeout nil})))
|
|
||||||
(when (:id organization)
|
|
||||||
(check-team-sso current-team-id))))))
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(if (contains? cf/flags :nitrate)
|
|
||||||
(let [team-id (:id team)
|
|
||||||
team-name (:name team)
|
|
||||||
organization (:organization team)]
|
|
||||||
(d/update-in-when state [:teams team-id]
|
|
||||||
(fn [team]
|
|
||||||
(cond-> (co/apply-organization team organization)
|
|
||||||
team-name (assoc :name team-name)))))
|
|
||||||
state))))
|
|
||||||
|
|
||||||
(defn- handle-user-org-change
|
(defn- handle-user-org-change
|
||||||
[{:keys [organization-id organization-name notification]}]
|
[{:keys [organization-id organization-name notification]}]
|
||||||
(ptk/reify ::handle-user-org-change
|
(ptk/reify ::handle-user-org-change
|
||||||
@ -772,28 +729,16 @@
|
|||||||
(when fetch? ;; If the user belonged to the org
|
(when fetch? ;; If the user belonged to the org
|
||||||
(rx/of (dtm/fetch-teams)))))))))
|
(rx/of (dtm/fetch-teams)))))))))
|
||||||
|
|
||||||
(defn- handle-nitrate-change-sso
|
|
||||||
[{:keys [organization-id]}]
|
|
||||||
(ptk/reify ::handle-nitrate-change-sso
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(when (contains? cf/flags :nitrate)
|
|
||||||
(let [team-id (:current-team-id state)
|
|
||||||
team (dm/get-in state [:teams team-id])
|
|
||||||
org-id (dm/get-in team [:organization :id])]
|
|
||||||
(when (= organization-id org-id)
|
|
||||||
(check-team-sso team-id)))))))
|
|
||||||
|
|
||||||
(defn- process-message
|
(defn- process-message
|
||||||
[{:keys [type] :as msg}]
|
[{:keys [type] :as msg}]
|
||||||
(case type
|
(case type
|
||||||
:notification (dcm/handle-notification msg)
|
:notification (dcm/handle-notification msg)
|
||||||
:team-role-change (handle-change-team-role msg)
|
:team-role-change (handle-change-team-role msg)
|
||||||
:team-membership-change (dcm/team-membership-change msg)
|
:team-membership-change (dcm/team-membership-change msg)
|
||||||
:team-org-change (handle-change-team-org msg)
|
:team-org-change (dcm/handle-change-team-org msg)
|
||||||
:user-org-change (handle-user-org-change msg)
|
:user-org-change (handle-user-org-change msg)
|
||||||
:organization-deleted (handle-organization-deleted msg)
|
:organization-deleted (handle-organization-deleted msg)
|
||||||
:organization-change-sso (handle-nitrate-change-sso msg)
|
:organization-change-sso (dcm/handle-organization-change-sso msg)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -125,18 +125,20 @@
|
|||||||
(defn- process-message
|
(defn- process-message
|
||||||
[{:keys [type] :as msg}]
|
[{:keys [type] :as msg}]
|
||||||
(case type
|
(case type
|
||||||
:join-file (handle-presence msg)
|
:join-file (handle-presence msg)
|
||||||
:leave-file (handle-presence msg)
|
:leave-file (handle-presence msg)
|
||||||
:presence (handle-presence msg)
|
:presence (handle-presence msg)
|
||||||
:disconnect (handle-presence msg)
|
:disconnect (handle-presence msg)
|
||||||
:pointer-update (handle-pointer-update msg)
|
:pointer-update (handle-pointer-update msg)
|
||||||
:file-change (handle-file-change msg)
|
:file-change (handle-file-change msg)
|
||||||
:file-deleted (handle-file-deleted msg)
|
:file-deleted (handle-file-deleted msg)
|
||||||
:file-restored (handle-file-restored msg)
|
:file-restored (handle-file-restored msg)
|
||||||
:library-change (handle-library-change msg)
|
:library-change (handle-library-change msg)
|
||||||
:notification (dc/handle-notification msg)
|
:notification (dc/handle-notification msg)
|
||||||
:team-role-change (handle-change-team-role msg)
|
:team-role-change (handle-change-team-role msg)
|
||||||
:team-membership-change (dc/team-membership-change msg)
|
:team-membership-change (dc/team-membership-change msg)
|
||||||
|
:team-org-change (dc/handle-change-team-org msg)
|
||||||
|
:organization-change-sso (dc/handle-organization-change-sso msg)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(defn- handle-pointer-send
|
(defn- handle-pointer-send
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.dashboard :as dd]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.router :as rt]
|
[app.main.router :as rt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
@ -23,7 +23,7 @@
|
|||||||
current-url (str "https://penpot.example.com/#/dashboard/recent?team-id=" team-id)
|
current-url (str "https://penpot.example.com/#/dashboard/recent?team-id=" team-id)
|
||||||
redirect-url "https://idp.example.com/authorize"
|
redirect-url "https://idp.example.com/authorize"
|
||||||
state {:current-team-id team-id}
|
state {:current-team-id team-id}
|
||||||
event (dd/handle-change-team-org
|
event (dcm/handle-change-team-org
|
||||||
{:team {:id team-id :organization organization}
|
{:team {:id team-id :organization organization}
|
||||||
:notification nil})]
|
:notification nil})]
|
||||||
(mock/with-mocks
|
(mock/with-mocks
|
||||||
@ -48,3 +48,37 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(done')))))
|
(done')))))
|
||||||
done))))
|
done))))
|
||||||
|
|
||||||
|
(t/deftest organization-sso-activation-redirects-current-team
|
||||||
|
(t/async done
|
||||||
|
(let [team-id (uuid/next)
|
||||||
|
org-id (uuid/next)
|
||||||
|
current-url (str "https://penpot.example.com/#/workspace?team-id=" team-id)
|
||||||
|
redirect-url "https://idp.example.com/authorize"
|
||||||
|
state {:current-team-id team-id
|
||||||
|
:teams {team-id {:id team-id
|
||||||
|
:organization {:id org-id}}}}
|
||||||
|
event (dcm/handle-organization-change-sso
|
||||||
|
{:organization-id org-id})]
|
||||||
|
(mock/with-mocks
|
||||||
|
{cf/flags (conj cf/flags :nitrate)
|
||||||
|
rp/cmd! (mock/stub
|
||||||
|
(fn [cmd params]
|
||||||
|
(if (= [:check-nitrate-sso
|
||||||
|
{:team-id team-id :url current-url}]
|
||||||
|
[cmd params])
|
||||||
|
(rx/of {:authorized false :redirect-uri redirect-url})
|
||||||
|
(rx/throw (ex-info "unexpected RPC" {:cmd cmd :params params})))))
|
||||||
|
rt/get-current-href (mock/stub (constantly current-url))}
|
||||||
|
(fn [done']
|
||||||
|
(->> (ptk/watch event state nil)
|
||||||
|
(rx/reduce conj [])
|
||||||
|
(rx/subs!
|
||||||
|
(fn [events]
|
||||||
|
(t/is (= [::rt/nav-raw] (mapv ptk/type events))))
|
||||||
|
(fn [error]
|
||||||
|
(t/is false (str "unexpected error: " error))
|
||||||
|
(done'))
|
||||||
|
(fn []
|
||||||
|
(done')))))
|
||||||
|
done))))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user