mirror of
https://github.com/penpot/penpot.git
synced 2025-03-11 07:11:32 -05:00
✨ Relax transaction requeriments for team invitation creation
This commit is contained in:
parent
c6917bb0cf
commit
45f3a67950
1 changed files with 100 additions and 65 deletions
|
@ -82,10 +82,8 @@
|
||||||
(cond-> row
|
(cond-> row
|
||||||
(some? features) (assoc :features (db/decode-pgarray features #{}))))
|
(some? features) (assoc :features (db/decode-pgarray features #{}))))
|
||||||
|
|
||||||
|
(defn- check-profile-muted
|
||||||
|
"Check if the member's email is part of the global bounce report"
|
||||||
(defn- check-valid-email-muted
|
|
||||||
"Check if the member's email is part of the global bounce report."
|
|
||||||
[conn member]
|
[conn member]
|
||||||
(let [email (profile/clean-email (:email member))]
|
(let [email (profile/clean-email (:email member))]
|
||||||
(when (and member (not (eml/allow-send-emails? conn member)))
|
(when (and member (not (eml/allow-send-emails? conn member)))
|
||||||
|
@ -94,7 +92,7 @@
|
||||||
:email email
|
:email email
|
||||||
:hint "the profile has reported repeatedly as spam or has bounces"))))
|
:hint "the profile has reported repeatedly as spam or has bounces"))))
|
||||||
|
|
||||||
(defn- check-valid-email-bounce
|
(defn- check-email-bounce
|
||||||
"Check if the email is part of the global complain report"
|
"Check if the email is part of the global complain report"
|
||||||
[conn email show?]
|
[conn email show?]
|
||||||
(when (eml/has-bounce-reports? conn email)
|
(when (eml/has-bounce-reports? conn email)
|
||||||
|
@ -103,7 +101,7 @@
|
||||||
:email (if show? email "private")
|
:email (if show? email "private")
|
||||||
:hint "this email has been repeatedly reported as bounce")))
|
:hint "this email has been repeatedly reported as bounce")))
|
||||||
|
|
||||||
(defn- check-valid-email-spam
|
(defn- check-email-spam
|
||||||
"Check if the member email is part of the global complain report"
|
"Check if the member email is part of the global complain report"
|
||||||
[conn email show?]
|
[conn email show?]
|
||||||
(when (eml/has-complaint-reports? conn email)
|
(when (eml/has-complaint-reports? conn email)
|
||||||
|
@ -227,16 +225,16 @@
|
||||||
;; --- Query: Team Members
|
;; --- Query: Team Members
|
||||||
|
|
||||||
(def sql:team-members
|
(def sql:team-members
|
||||||
"select tp.*,
|
"SELECT tp.*,
|
||||||
p.id,
|
p.id,
|
||||||
p.email,
|
p.email,
|
||||||
p.fullname as name,
|
p.fullname AS name,
|
||||||
p.fullname as fullname,
|
p.fullname AS fullname,
|
||||||
p.photo_id,
|
p.photo_id,
|
||||||
p.is_active
|
p.is_active
|
||||||
from team_profile_rel as tp
|
FROM team_profile_rel AS tp
|
||||||
join profile as p on (p.id = tp.profile_id)
|
JOIN profile AS p ON (p.id = tp.profile_id)
|
||||||
where tp.team_id = ?")
|
WHERE tp.team_id = ?")
|
||||||
|
|
||||||
(defn get-team-members
|
(defn get-team-members
|
||||||
[conn team-id]
|
[conn team-id]
|
||||||
|
@ -769,21 +767,50 @@
|
||||||
:member-id member-id}))
|
:member-id member-id}))
|
||||||
|
|
||||||
(defn- create-profile-identity-token
|
(defn- create-profile-identity-token
|
||||||
[cfg profile]
|
[cfg profile-id]
|
||||||
|
|
||||||
|
(dm/assert!
|
||||||
|
"expected valid uuid for profile-id"
|
||||||
|
(uuid? profile-id))
|
||||||
|
|
||||||
(tokens/generate (::setup/props cfg)
|
(tokens/generate (::setup/props cfg)
|
||||||
{:iss :profile-identity
|
{:iss :profile-identity
|
||||||
:profile-id (:id profile)
|
:profile-id profile-id
|
||||||
:exp (dt/in-future {:days 30})}))
|
:exp (dt/in-future {:days 30})}))
|
||||||
|
|
||||||
|
(def ^:private schema:create-invitation
|
||||||
|
[:map {:title "params:create-invitation"}
|
||||||
|
[:team
|
||||||
|
[:map
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:name :string]]]
|
||||||
|
[:profile
|
||||||
|
[:map
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:fullname :string]]]
|
||||||
|
[:role [::sm/one-of valid-roles]]
|
||||||
|
[:email ::sm/email]])
|
||||||
|
|
||||||
|
(def ^:private check-create-invitation-params!
|
||||||
|
(sm/check-fn schema:create-invitation))
|
||||||
|
|
||||||
(defn- create-invitation
|
(defn- create-invitation
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [team profile role email] :as params}]
|
[{:keys [::db/conn] :as cfg} {:keys [team profile role email] :as params}]
|
||||||
|
|
||||||
|
(dm/assert!
|
||||||
|
"expected valid connection on cfg parameter"
|
||||||
|
(db/connection? conn))
|
||||||
|
|
||||||
|
(dm/assert!
|
||||||
|
"expected valid params for `create-invitation` fn"
|
||||||
|
(check-create-invitation-params! params))
|
||||||
|
|
||||||
(let [email (profile/clean-email email)
|
(let [email (profile/clean-email email)
|
||||||
member (profile/get-profile-by-email conn email)]
|
member (profile/get-profile-by-email conn email)]
|
||||||
|
|
||||||
(check-valid-email-muted conn member)
|
(check-profile-muted conn member)
|
||||||
(check-valid-email-bounce conn email true)
|
(check-email-bounce conn email true)
|
||||||
(check-valid-email-spam conn email true)
|
(check-email-spam conn email true)
|
||||||
|
|
||||||
|
|
||||||
;; When we have email verification disabled and invitation user is
|
;; When we have email verification disabled and invitation user is
|
||||||
;; already present in the database, we proceed to add it to the
|
;; already present in the database, we proceed to add it to the
|
||||||
|
@ -817,7 +844,8 @@
|
||||||
(name role) expire
|
(name role) expire
|
||||||
(name role) expire])
|
(name role) expire])
|
||||||
updated? (not= id (:id invitation))
|
updated? (not= id (:id invitation))
|
||||||
tprops {:profile-id (:id profile)
|
profile-id (:id profile)
|
||||||
|
tprops {:profile-id profile-id
|
||||||
:invitation-id (:id invitation)
|
:invitation-id (:id invitation)
|
||||||
:valid-until expire
|
:valid-until expire
|
||||||
:team-id (:id team)
|
:team-id (:id team)
|
||||||
|
@ -825,12 +853,11 @@
|
||||||
:member-id (:id member)
|
:member-id (:id member)
|
||||||
:role role}
|
:role role}
|
||||||
itoken (create-invitation-token cfg tprops)
|
itoken (create-invitation-token cfg tprops)
|
||||||
ptoken (create-profile-identity-token cfg profile)]
|
ptoken (create-profile-identity-token cfg profile-id)]
|
||||||
|
|
||||||
(when (contains? cf/flags :log-invitation-tokens)
|
(when (contains? cf/flags :log-invitation-tokens)
|
||||||
(l/info :hint "invitation token" :token itoken))
|
(l/info :hint "invitation token" :token itoken))
|
||||||
|
|
||||||
|
|
||||||
(let [props (-> (dissoc tprops :profile-id)
|
(let [props (-> (dissoc tprops :profile-id)
|
||||||
(audit/clean-props))
|
(audit/clean-props))
|
||||||
evname (if updated?
|
evname (if updated?
|
||||||
|
@ -853,7 +880,7 @@
|
||||||
itoken))))
|
itoken))))
|
||||||
|
|
||||||
(defn- add-user-to-team
|
(defn- add-user-to-team
|
||||||
[conn profile team email role]
|
[conn profile team role email]
|
||||||
|
|
||||||
(let [team-id (:id team)
|
(let [team-id (:id team)
|
||||||
member (db/get* conn :profile
|
member (db/get* conn :profile
|
||||||
|
@ -905,6 +932,39 @@
|
||||||
[conn team-id]
|
[conn team-id]
|
||||||
(db/exec! conn [sql:valid-requests-email team-id]))
|
(db/exec! conn [sql:valid-requests-email team-id]))
|
||||||
|
|
||||||
|
(def ^:private xf:map-email
|
||||||
|
(map :email))
|
||||||
|
|
||||||
|
(defn- create-team-invitations
|
||||||
|
[{:keys [::db/conn] :as cfg} profile team role emails]
|
||||||
|
(let [join-requests (into #{} xf:map-email
|
||||||
|
(get-valid-requests-email conn (:id team)))
|
||||||
|
team-members (into #{} xf:map-email
|
||||||
|
(get-team-members conn (:id team)))
|
||||||
|
|
||||||
|
invitations (into #{}
|
||||||
|
(comp
|
||||||
|
;; We don't re-send inviation to
|
||||||
|
;; already existing members
|
||||||
|
(remove team-members)
|
||||||
|
;; We don't send invitations to
|
||||||
|
;; join-requested members
|
||||||
|
(remove join-requests)
|
||||||
|
(map (fn [email]
|
||||||
|
{:email email
|
||||||
|
:team team
|
||||||
|
:profile profile
|
||||||
|
:role role}))
|
||||||
|
(keep (partial create-invitation cfg)))
|
||||||
|
emails)]
|
||||||
|
|
||||||
|
;; For requested invitations, do not send invitation emails, add
|
||||||
|
;; the user directly to the team
|
||||||
|
(->> (filter join-requests emails)
|
||||||
|
(run! (partial add-user-to-team conn profile team role)))
|
||||||
|
|
||||||
|
invitations))
|
||||||
|
|
||||||
(def ^:private schema:create-team-invitations
|
(def ^:private schema:create-team-invitations
|
||||||
[:map {:title "create-team-invitations"}
|
[:map {:title "create-team-invitations"}
|
||||||
[:team-id ::sm/uuid]
|
[:team-id ::sm/uuid]
|
||||||
|
@ -919,12 +979,10 @@
|
||||||
"A rpc call that allow to send a single or multiple invitations to
|
"A rpc call that allow to send a single or multiple invitations to
|
||||||
join the team."
|
join the team."
|
||||||
{::doc/added "1.17"
|
{::doc/added "1.17"
|
||||||
::sm/params schema:create-team-invitations
|
::sm/params schema:create-team-invitations}
|
||||||
::db/transaction true}
|
[cfg {:keys [::rpc/profile-id team-id emails role] :as params}]
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id team-id emails role] :as params}]
|
(let [perms (get-permissions cfg profile-id team-id)
|
||||||
(let [perms (get-permissions conn profile-id team-id)
|
profile (db/get-by-id cfg :profile profile-id)
|
||||||
profile (db/get-by-id conn :profile profile-id)
|
|
||||||
team (db/get-by-id conn :team team-id)
|
|
||||||
emails (into #{} (map profile/clean-email) emails)]
|
emails (into #{} (map profile/clean-email) emails)]
|
||||||
|
|
||||||
(when-not (:is-admin perms)
|
(when-not (:is-admin perms)
|
||||||
|
@ -945,33 +1003,10 @@
|
||||||
{::quotes/id ::quotes/profiles-per-team}))
|
{::quotes/id ::quotes/profiles-per-team}))
|
||||||
|
|
||||||
;; Check if the current profile is allowed to send emails
|
;; Check if the current profile is allowed to send emails
|
||||||
(check-valid-email-muted conn profile)
|
(check-profile-muted cfg profile)
|
||||||
|
|
||||||
(let [requested (into #{} (map :email) (get-valid-requests-email conn team-id))
|
|
||||||
emails-to-add (filter #(contains? requested %) emails)
|
|
||||||
emails (remove #(contains? requested %) emails)
|
|
||||||
cfg (assoc cfg ::db/conn conn)
|
|
||||||
members (->> (db/exec! conn [sql:team-members team-id])
|
|
||||||
(into #{} (map :email)))
|
|
||||||
|
|
||||||
invitations (into #{}
|
|
||||||
(comp
|
|
||||||
;; We don't re-send inviation to already existing members
|
|
||||||
(remove (partial contains? members))
|
|
||||||
(map (fn [email]
|
|
||||||
(-> params
|
|
||||||
(assoc :email email)
|
|
||||||
(assoc :team team)
|
|
||||||
(assoc :profile profile)
|
|
||||||
(assoc :role role))))
|
|
||||||
(keep (partial create-invitation cfg)))
|
|
||||||
emails)]
|
|
||||||
;; For requested invitations, do not send
|
|
||||||
;; invitation emails, add the user directly to
|
|
||||||
;; the team
|
|
||||||
(doseq [email emails-to-add]
|
|
||||||
(add-user-to-team conn profile team email role))
|
|
||||||
|
|
||||||
|
(let [team (db/get-by-id cfg :team team-id)
|
||||||
|
invitations (db/tx-run! cfg create-team-invitations profile team role emails)]
|
||||||
(with-meta {:total (count invitations)
|
(with-meta {:total (count invitations)
|
||||||
:invitations invitations}
|
:invitations invitations}
|
||||||
{::audit/props {:invitations (count invitations)}}))))
|
{::audit/props {:invitations (count invitations)}}))))
|
||||||
|
@ -1225,11 +1260,11 @@
|
||||||
:code :invalid-parameters))
|
:code :invalid-parameters))
|
||||||
|
|
||||||
;; Check that the requester is not muted
|
;; Check that the requester is not muted
|
||||||
(check-valid-email-muted conn requester)
|
(check-profile-muted conn requester)
|
||||||
|
|
||||||
;; Check that the owner is not marked as bounce nor spam
|
;; Check that the owner is not marked as bounce nor spam
|
||||||
(check-valid-email-bounce conn (:email team-owner) false)
|
(check-email-bounce conn (:email team-owner) false)
|
||||||
(check-valid-email-spam conn (:email team-owner) true)
|
(check-email-spam conn (:email team-owner) true)
|
||||||
|
|
||||||
(let [request (create-team-access-request
|
(let [request (create-team-access-request
|
||||||
cfg {:team team :requester requester :team-owner team-owner :file file :is-viewer is-viewer})]
|
cfg {:team team :requester requester :team-owner team-owner :file file :is-viewer is-viewer})]
|
||||||
|
|
Loading…
Add table
Reference in a new issue