mirror of
https://github.com/penpot/penpot.git
synced 2025-02-12 18:18:24 -05:00
🐛 Fix incorrect message on sending invitation to a member
This commit is contained in:
parent
ea753da0ae
commit
23c8043f34
4 changed files with 52 additions and 49 deletions
|
@ -57,6 +57,7 @@
|
|||
- Fix focus handling on comments edition [Taiga #5560](https://tree.taiga.io/project/penpot/issue/5560)
|
||||
- Fix incorrect fullname use on registring user after OIDC authentication [Taiga #5517](https://tree.taiga.io/project/penpot/issue/5517)
|
||||
- Fix incorrect modified-at on project after import file [Taiga #5268](https://tree.taiga.io/project/penpot/issue/5268)
|
||||
- Fix incorrect message after sending invitation to already member [Taiga 5599](https://tree.taiga.io/project/penpot/issue/5599)
|
||||
|
||||
### :arrow_up: Deps updates
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
|
@ -719,29 +720,22 @@
|
|||
|
||||
itoken))))
|
||||
|
||||
(s/def ::email ::us/email)
|
||||
(s/def ::emails ::us/set-of-valid-emails)
|
||||
(s/def ::create-team-invitations
|
||||
(s/keys :req [::rpc/profile-id]
|
||||
:req-un [::team-id ::role]
|
||||
:opt-un [::email ::emails]))
|
||||
(def ^:private schema:create-team-invitations
|
||||
[:map {:title "create-team-invitations"}
|
||||
[:team-id ::sm/uuid]
|
||||
[:role [::sm/one-of #{:owner :admin :editor}]]
|
||||
[:emails ::sm/set-of-emails]])
|
||||
|
||||
(sv/defmethod ::create-team-invitations
|
||||
"A rpc call that allow to send a single or multiple invitations to
|
||||
join the team."
|
||||
{::doc/added "1.17"}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id email emails role] :as params}]
|
||||
{::doc/added "1.17"
|
||||
::sm/params schema:create-team-invitations}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id emails role] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [perms (get-permissions conn profile-id team-id)
|
||||
profile (db/get-by-id conn :profile profile-id)
|
||||
team (db/get-by-id conn :team team-id)
|
||||
|
||||
;; Members emails. We don't re-send inviation to already existing members
|
||||
member? (into #{}
|
||||
(map :email)
|
||||
(db/exec! conn [sql:team-members team-id]))
|
||||
|
||||
emails (cond-> (or emails #{}) (string? email) (conj email))]
|
||||
team (db/get-by-id conn :team team-id)]
|
||||
|
||||
(run! (partial quotes/check-quote! conn)
|
||||
(list {::quotes/id ::quotes/invitations-per-team
|
||||
|
@ -764,9 +758,13 @@
|
|||
:hint "looks like the profile has reported repeatedly as spam or has permanent bounces"))
|
||||
|
||||
(let [cfg (assoc cfg ::db/conn conn)
|
||||
invitations (into []
|
||||
members (->> (db/exec! conn [sql:team-members team-id])
|
||||
(into #{} (map :email)))
|
||||
|
||||
invitations (into #{}
|
||||
(comp
|
||||
(remove member?)
|
||||
;; We don't re-send inviation to already existing members
|
||||
(remove (partial contains? members))
|
||||
(map (fn [email]
|
||||
{:email (str/lower email)
|
||||
:team team
|
||||
|
@ -774,7 +772,8 @@
|
|||
:role role}))
|
||||
(keep (partial create-invitation cfg)))
|
||||
emails)]
|
||||
(with-meta invitations
|
||||
(with-meta {:total (count invitations)
|
||||
:invitations invitations}
|
||||
{::audit/props {:invitations (count invitations)}})))))
|
||||
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
:role :editor}]
|
||||
|
||||
;; invite external user without complaints
|
||||
(let [data (assoc data :email "foo@bar.com")
|
||||
(let [data (assoc data :emails ["foo@bar.com"])
|
||||
out (th/command! data)
|
||||
;; retrieve the value from the database and check its content
|
||||
invitation (db/exec-one!
|
||||
|
@ -52,7 +52,7 @@
|
|||
|
||||
;; invite internal user without complaints
|
||||
(th/reset-mock! mock)
|
||||
(let [data (assoc data :email (:email profile2))
|
||||
(let [data (assoc data :emails [(:email profile2)])
|
||||
out (th/command! data)]
|
||||
(t/is (th/success? out))
|
||||
(t/is (= 1 (:call-count (deref mock)))))
|
||||
|
@ -60,7 +60,7 @@
|
|||
;; invite user with complaint
|
||||
(th/create-global-complaint-for pool {:type :complaint :email "foo@bar.com"})
|
||||
(th/reset-mock! mock)
|
||||
(let [data (assoc data :email "foo@bar.com")
|
||||
(let [data (assoc data :emails ["foo@bar.com"])
|
||||
out (th/command! data)]
|
||||
(t/is (th/success? out))
|
||||
(t/is (= 1 (:call-count (deref mock)))))
|
||||
|
@ -79,7 +79,7 @@
|
|||
(th/reset-mock! mock)
|
||||
|
||||
(th/create-global-complaint-for pool {:type :bounce :email "foo@bar.com"})
|
||||
(let [data (assoc data :email "foo@bar.com")
|
||||
(let [data (assoc data :emails ["foo@bar.com"])
|
||||
out (th/command! data)]
|
||||
|
||||
(t/is (not (th/success? out)))
|
||||
|
@ -92,7 +92,7 @@
|
|||
;; invite internal user that is muted
|
||||
(th/reset-mock! mock)
|
||||
|
||||
(let [data (assoc data :email (:email profile3))
|
||||
(let [data (assoc data :emails [(:email profile3)])
|
||||
out (th/command! data)]
|
||||
|
||||
(t/is (not (th/success? out)))
|
||||
|
@ -118,7 +118,7 @@
|
|||
;; Try to invite a not existing user
|
||||
(let [data {::th/type :create-team-invitations
|
||||
::rpc/profile-id (:id profile1)
|
||||
:email "notexisting@example.com"
|
||||
:emails ["notexisting@example.com"]
|
||||
:team-id (:id team)
|
||||
:role :editor}
|
||||
out (th/command! data)]
|
||||
|
@ -126,15 +126,15 @@
|
|||
;; (th/print-result! out)
|
||||
(t/is (th/success? out))
|
||||
(t/is (= 1 (:call-count @mock)))
|
||||
(t/is (= 1 (-> out :result count)))
|
||||
(t/is (= 1 (-> out :result :total)))
|
||||
|
||||
(let [token (-> out :result first)
|
||||
(let [token (-> out :result :invitations first)
|
||||
claims (tokens/decode sprops token)]
|
||||
(t/is (= :team-invitation (:iss claims)))
|
||||
(t/is (= (:id profile1) (:profile-id claims)))
|
||||
(t/is (= :editor (:role claims)))
|
||||
(t/is (= (:id team) (:team-id claims)))
|
||||
(t/is (= (:email data) (:member-email claims)))
|
||||
(t/is (= (first (:emails data)) (:member-email claims)))
|
||||
(t/is (nil? (:member-id claims)))))
|
||||
|
||||
(th/reset-mock! mock)
|
||||
|
@ -142,7 +142,7 @@
|
|||
;; Try to invite existing user
|
||||
(let [data {::th/type :create-team-invitations
|
||||
::rpc/profile-id (:id profile1)
|
||||
:email (:email profile2)
|
||||
:emails [(:email profile2)]
|
||||
:team-id (:id team)
|
||||
:role :editor}
|
||||
out (th/command! data)]
|
||||
|
@ -150,15 +150,15 @@
|
|||
;; (th/print-result! out)
|
||||
(t/is (th/success? out))
|
||||
(t/is (= 1 (:call-count @mock)))
|
||||
(t/is (= 1 (-> out :result count)))
|
||||
(t/is (= 1 (-> out :result :total)))
|
||||
|
||||
(let [token (-> out :result first)
|
||||
(let [token (-> out :result :invitations first)
|
||||
claims (tokens/decode sprops token)]
|
||||
(t/is (= :team-invitation (:iss claims)))
|
||||
(t/is (= (:id profile1) (:profile-id claims)))
|
||||
(t/is (= :editor (:role claims)))
|
||||
(t/is (= (:id team) (:team-id claims)))
|
||||
(t/is (= (:email data) (:member-email claims)))
|
||||
(t/is (= (first (:emails data)) (:member-email claims)))
|
||||
(t/is (= (:id profile2) (:member-id claims)))))
|
||||
|
||||
)))
|
||||
|
@ -264,7 +264,7 @@
|
|||
;; invite internal user without complaints
|
||||
(with-redefs [app.config/flags #{}]
|
||||
(th/reset-mock! mock)
|
||||
(let [data (assoc data :email (:email profile2))
|
||||
(let [data (assoc data :emails [(:email profile2)])
|
||||
out (th/command! data)]
|
||||
(t/is (th/success? out))
|
||||
(t/is (= 0 (:call-count (deref mock)))))
|
||||
|
|
|
@ -31,8 +31,9 @@
|
|||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc header
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [section team] :as props}]
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[{:keys [section team]}]
|
||||
(let [go-members (mf/use-fn #(st/emit! (dd/go-to-team-members)))
|
||||
go-settings (mf/use-fn #(st/emit! (dd/go-to-team-settings)))
|
||||
go-invitations (mf/use-fn #(st/emit! (dd/go-to-team-invitations)))
|
||||
|
@ -98,27 +99,29 @@
|
|||
|
||||
(mf/defc invite-members-modal
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :invite-members}
|
||||
::mf/register-as :invite-members
|
||||
::mf/wrap-props false}
|
||||
[{:keys [team origin]}]
|
||||
(let [members-map (mf/deref refs/dashboard-team-members)
|
||||
perms (:permissions team)
|
||||
|
||||
perms (:permissions team)
|
||||
|
||||
roles (mf/use-memo (mf/deps perms) #(get-available-roles perms))
|
||||
initial (mf/use-memo (constantly {:role "editor" :team-id (:id team)}))
|
||||
form (fm/use-form :spec ::invite-member-form
|
||||
:initial initial)
|
||||
error-text (mf/use-state "")
|
||||
|
||||
on-success
|
||||
(fn []
|
||||
(st/emit! (msg/success (tr "notifications.invitation-email-sent"))
|
||||
(modal/hide)
|
||||
(dd/fetch-team-invitations)))
|
||||
roles (mf/use-memo (mf/deps perms) #(get-available-roles perms))
|
||||
initial (mf/use-memo (constantly {:role "editor" :team-id (:id team)}))
|
||||
form (fm/use-form :spec ::invite-member-form
|
||||
:initial initial)
|
||||
error-text (mf/use-state "")
|
||||
|
||||
current-data-emails (into #{} (dm/get-in @form [:clean-data :emails]))
|
||||
current-members-emails (into #{} (map (comp :email second)) members-map)
|
||||
|
||||
on-success
|
||||
(fn [form {:keys [total]}]
|
||||
(when (pos? total)
|
||||
(st/emit! (msg/success (tr "notifications.invitation-email-sent"))))
|
||||
|
||||
(st/emit! (modal/hide)
|
||||
(dd/fetch-team-invitations)))
|
||||
|
||||
on-error
|
||||
(fn [{:keys [type code] :as error}]
|
||||
(cond
|
||||
|
|
Loading…
Add table
Reference in a new issue