♻️ Rename org to organization

This commit is contained in:
Marina López 2026-07-16 15:32:02 +02:00
parent d9511db585
commit 33d478b532
6 changed files with 99 additions and 99 deletions

View File

@ -112,24 +112,24 @@
(->> (db/exec! cfg [sql:get-teams current-user-id]) (->> (db/exec! cfg [sql:get-teams current-user-id])
(map #(select-keys % [:id :name]))))) (map #(select-keys % [:id :name])))))
;; ---- API: upload-org-logo ;; ---- API: upload-organization-logo
(def ^:private schema:upload-org-logo (def ^:private schema:upload-organization-logo
[:map [:map
[:content media/schema:upload] [:content media/schema:upload]
[:organization-id ::sm/uuid] [:organization-id ::sm/uuid]
[:previous-id {:optional true} ::sm/uuid]]) [:previous-id {:optional true} ::sm/uuid]])
(def ^:private schema:upload-org-logo-result (def ^:private schema:upload-organization-logo-result
[:map [:id ::sm/uuid]]) [:map [:id ::sm/uuid]])
(sv/defmethod ::upload-org-logo (sv/defmethod ::upload-organization-logo
"Store an organization logo in penpot storage and return its ID. "Store an organization logo in penpot storage and return its ID.
Accepts an optional previous-id to mark the old logo for garbage Accepts an optional previous-id to mark the old logo for garbage
collection when replacing an existing one." collection when replacing an existing one."
{::doc/added "2.17" {::doc/added "2.17"
::sm/params schema:upload-org-logo ::sm/params schema:upload-organization-logo
::sm/result schema:upload-org-logo-result ::sm/result schema:upload-organization-logo-result
::nitrate/sso false} ::nitrate/sso false}
[{:keys [::sto/storage]} {:keys [content organization-id previous-id]}] [{:keys [::sto/storage]} {:keys [content organization-id previous-id]}]
(when previous-id (when previous-id
@ -441,9 +441,9 @@ RETURNING id, deleted_at;")
(profile-to-map profile))) (profile-to-map profile)))
;; ---- API: get-org-member-team-counts ;; ---- API: get-organization-member-team-counts
(def ^:private sql:get-org-member-team-counts (def ^:private sql:get-organization-member-team-counts
"SELECT tpr.profile_id, COUNT(DISTINCT t.id) AS team_count "SELECT tpr.profile_id, COUNT(DISTINCT t.id) AS team_count
FROM team_profile_rel AS tpr FROM team_profile_rel AS tpr
JOIN team AS t ON t.id = tpr.team_id JOIN team AS t ON t.id = tpr.team_id
@ -452,19 +452,19 @@ RETURNING id, deleted_at;")
AND t.is_default IS FALSE AND t.is_default IS FALSE
GROUP BY tpr.profile_id;") GROUP BY tpr.profile_id;")
(def ^:private schema:get-org-member-team-counts-params (def ^:private schema:get-organization-member-team-counts-params
[:map [:team-ids [:or ::sm/uuid [:vector ::sm/uuid]]]]) [:map [:team-ids [:or ::sm/uuid [:vector ::sm/uuid]]]])
(def ^:private schema:get-org-member-team-counts-result (def ^:private schema:get-organization-member-team-counts-result
[:vector [:map [:vector [:map
[:profile-id ::sm/uuid] [:profile-id ::sm/uuid]
[:team-count ::sm/int]]]) [:team-count ::sm/int]]])
(sv/defmethod ::get-org-member-team-counts (sv/defmethod ::get-organization-member-team-counts
"Get the number of non-default teams each profile belongs to within a set of teams." "Get the number of non-default teams each profile belongs to within a set of teams."
{::doc/added "2.15" {::doc/added "2.15"
::sm/params schema:get-org-member-team-counts-params ::sm/params schema:get-organization-member-team-counts-params
::sm/result schema:get-org-member-team-counts-result ::sm/result schema:get-organization-member-team-counts-result
::rpc/auth false} ::rpc/auth false}
[cfg {:keys [team-ids]}] [cfg {:keys [team-ids]}]
(let [team-ids (cond (let [team-ids (cond
@ -480,12 +480,12 @@ RETURNING id, deleted_at;")
[] []
(db/run! cfg (fn [{:keys [::db/conn]}] (db/run! cfg (fn [{:keys [::db/conn]}]
(let [ids-array (db/create-array conn "uuid" team-ids)] (let [ids-array (db/create-array conn "uuid" team-ids)]
(db/exec! conn [sql:get-org-member-team-counts ids-array]))))))) (db/exec! conn [sql:get-organization-member-team-counts ids-array])))))))
;; API: invite-to-org ;; API: invite-to-organization
(sv/defmethod ::invite-to-org (sv/defmethod ::invite-to-organization
"Invite to organization" "Invite to organization"
{::doc/added "2.15" {::doc/added "2.15"
::sm/params [:map ::sm/params [:map
@ -497,13 +497,13 @@ RETURNING id, deleted_at;")
nil) nil)
;; API: get-org-invitations ;; API: get-organization-invitations
(def ^:private schema:get-org-invitations-params (def ^:private schema:get-organization-invitations-params
[:map [:map
[:organization-id ::sm/uuid]]) [:organization-id ::sm/uuid]])
(def ^:private schema:get-org-invitations-result (def ^:private schema:get-organization-invitations-result
[:vector [:vector
[:map [:map
[:id ::sm/uuid] [:id ::sm/uuid]
@ -514,11 +514,11 @@ RETURNING id, deleted_at;")
[:profile-id {:optional true} [:maybe ::sm/uuid]] [:profile-id {:optional true} [:maybe ::sm/uuid]]
[:photo-url {:optional true} ::sm/uri]]]) [:photo-url {:optional true} ::sm/uri]]])
(sv/defmethod ::get-org-invitations (sv/defmethod ::get-organization-invitations
"Get valid invitations for an organization, returning at most one invitation per email." "Get valid invitations for an organization, returning at most one invitation per email."
{::doc/added "2.16" {::doc/added "2.16"
::sm/params schema:get-org-invitations-params ::sm/params schema:get-organization-invitations-params
::sm/result schema:get-org-invitations-result ::sm/result schema:get-organization-invitations-result
::nitrate/sso false} ::nitrate/sso false}
[cfg {:keys [organization-id]}] [cfg {:keys [organization-id]}]
(let [team-ids (noh/get-org-team-ids cfg organization-id)] (let [team-ids (noh/get-org-team-ids cfg organization-id)]
@ -530,59 +530,59 @@ RETURNING id, deleted_at;")
(assoc :photo-url (files/resolve-public-uri photo-id)))))))))) (assoc :photo-url (files/resolve-public-uri photo-id))))))))))
;; API: delete-org-invitations ;; API: delete-organization-invitations
(def ^:private sql:delete-org-invitations (def ^:private sql:delete-organization-invitations
"DELETE FROM team_invitation AS ti "DELETE FROM team_invitation AS ti
WHERE ti.email_to = ? WHERE ti.email_to = ?
AND (ti.org_id = ? OR ti.team_id = ANY(?));") AND (ti.org_id = ? OR ti.team_id = ANY(?));")
(def ^:private schema:delete-org-invitations-params (def ^:private schema:delete-organization-invitations-params
[:map [:map
[:organization-id ::sm/uuid] [:organization-id ::sm/uuid]
[:email ::sm/email]]) [:email ::sm/email]])
(sv/defmethod ::delete-org-invitations (sv/defmethod ::delete-organization-invitations
"Delete all invitations for one email in an organization scope (org + org teams)." "Delete all invitations for one email in an organization scope (org + org teams)."
{::doc/added "2.16" {::doc/added "2.16"
::sm/params schema:delete-org-invitations-params ::sm/params schema:delete-organization-invitations-params
::nitrate/sso false} ::nitrate/sso false}
[cfg {:keys [organization-id email]}] [cfg {:keys [organization-id email]}]
(let [clean-email (profile/clean-email email) (let [clean-email (profile/clean-email email)
team-ids (noh/get-org-team-ids cfg organization-id)] team-ids (noh/get-org-team-ids cfg organization-id)]
(db/run! cfg (fn [{:keys [::db/conn]}] (db/run! cfg (fn [{:keys [::db/conn]}]
(let [ids-array (db/create-array conn "uuid" team-ids)] (let [ids-array (db/create-array conn "uuid" team-ids)]
(db/exec! conn [sql:delete-org-invitations clean-email organization-id ids-array])))) (db/exec! conn [sql:delete-organization-invitations clean-email organization-id ids-array]))))
nil)) nil))
;; API: delete-all-org-invitations ;; API: delete-all-organization-invitations
(def ^:private sql:delete-all-org-invitations (def ^:private sql:delete-all-organization-invitations
"DELETE FROM team_invitation AS ti "DELETE FROM team_invitation AS ti
WHERE ti.org_id = ? WHERE ti.org_id = ?
OR ti.team_id = ANY(?);") OR ti.team_id = ANY(?);")
(def ^:private schema:delete-all-org-invitations-params (def ^:private schema:delete-all-organization-invitations-params
[:map [:map
[:organization-id ::sm/uuid]]) [:organization-id ::sm/uuid]])
(sv/defmethod ::delete-all-org-invitations (sv/defmethod ::delete-all-organization-invitations
"Delete every pending invitation associated with an organization (org-level + team-level). "Delete every pending invitation associated with an organization (org-level + team-level).
Called from Nitrate when an organization is about to be deleted, so users that click Called from Nitrate when an organization is about to be deleted, so users that click
their invitation token hit the existing invalid-token landing page." their invitation token hit the existing invalid-token landing page."
{::doc/added "2.18" {::doc/added "2.18"
::sm/params schema:delete-all-org-invitations-params ::sm/params schema:delete-all-organization-invitations-params
::rpc/auth false} ::rpc/auth false}
[cfg {:keys [organization-id]}] [cfg {:keys [organization-id]}]
(let [team-ids (noh/get-org-team-ids cfg organization-id)] (let [team-ids (noh/get-org-team-ids cfg organization-id)]
(db/run! cfg (fn [{:keys [::db/conn]}] (db/run! cfg (fn [{:keys [::db/conn]}]
(let [ids-array (db/create-array conn "uuid" team-ids)] (let [ids-array (db/create-array conn "uuid" team-ids)]
(db/exec! conn [sql:delete-all-org-invitations organization-id ids-array])))) (db/exec! conn [sql:delete-all-organization-invitations organization-id ids-array]))))
nil)) nil))
;; API: remove-from-org ;; API: remove-from-organization
(def ^:private sql:get-reassign-to (def ^:private sql:get-reassign-to
"SELECT tpr.profile_id "SELECT tpr.profile_id
@ -607,7 +607,7 @@ RETURNING id, deleted_at;")
(assoc team-to-transfer :reassign-to reassign-to))) (assoc team-to-transfer :reassign-to reassign-to)))
(sv/defmethod ::remove-from-org (sv/defmethod ::remove-from-organization
"Remove an user from an organization" "Remove an user from an organization"
{::doc/added "2.17" {::doc/added "2.17"
::sm/params [:map ::sm/params [:map
@ -635,16 +635,16 @@ RETURNING id, deleted_at;")
(notifications/notify-user-org-change cfg profile-id organization-id organization-name "dashboard.user-no-longer-belong-org") (notifications/notify-user-org-change cfg profile-id organization-id organization-name "dashboard.user-no-longer-belong-org")
nil)) nil))
;; API: get-remove-from-org-summary ;; API: get-remove-from-organization-summary
(def ^:private schema:get-remove-from-org-summary-result (def ^:private schema:get-remove-from-organization-summary-result
[:map [:map
[:teams-to-delete ::sm/int] [:teams-to-delete ::sm/int]
[:teams-to-transfer ::sm/int] [:teams-to-transfer ::sm/int]
[:teams-to-exit ::sm/int] [:teams-to-exit ::sm/int]
[:teams-to-detach ::sm/int]]) [:teams-to-detach ::sm/int]])
(sv/defmethod ::get-remove-from-org-summary (sv/defmethod ::get-remove-from-organization-summary
"Get a summary of the teams that would be deleted, transferred, or exited "Get a summary of the teams that would be deleted, transferred, or exited
if the user were removed from the organization" if the user were removed from the organization"
{::doc/added "2.17" {::doc/added "2.17"
@ -652,7 +652,7 @@ RETURNING id, deleted_at;")
[:profile-id ::sm/uuid] [:profile-id ::sm/uuid]
[:organization-id ::sm/uuid] [:organization-id ::sm/uuid]
[:default-team-id ::sm/uuid]] [:default-team-id ::sm/uuid]]
::sm/result schema:get-remove-from-org-summary-result ::sm/result schema:get-remove-from-organization-summary-result
::db/transaction true ::db/transaction true
::nitrate/sso false} ::nitrate/sso false}
[cfg {:keys [profile-id organization-id default-team-id]}] [cfg {:keys [profile-id organization-id default-team-id]}]
@ -701,8 +701,8 @@ RETURNING id, deleted_at;")
:organizations organizations})))) :organizations organizations}))))
nil) nil)
;; API: exists-org-team-invitations-for-non-members / ;; API: exists-organization-team-invitations-for-non-members /
;; delete-org-team-invitations-for-non-members ;; delete-organization-team-invitations-for-non-members
(def ^:private sql:get-profile-emails-by-ids (def ^:private sql:get-profile-emails-by-ids
"SELECT email "SELECT email
@ -729,7 +729,7 @@ RETURNING id, deleted_at;")
[:team-ids [:vector ::sm/uuid]] [:team-ids [:vector ::sm/uuid]]
[:member-ids [:vector ::sm/uuid]]]) [:member-ids [:vector ::sm/uuid]]])
(def ^:private schema:exists-org-team-invitations-for-non-members-result (def ^:private schema:exists-organization-team-invitations-for-non-members-result
[:map [:exists ::sm/boolean]]) [:map [:exists ::sm/boolean]])
(defn- org-team-invitations-for-non-members-arrays (defn- org-team-invitations-for-non-members-arrays
@ -751,17 +751,17 @@ RETURNING id, deleted_at;")
emails-array]) emails-array])
:non-member))) :non-member)))
(sv/defmethod ::exists-org-team-invitations-for-non-members (sv/defmethod ::exists-organization-team-invitations-for-non-members
"Return if there are any team invitations for emails that are not organization members." "Return if there are any team invitations for emails that are not organization members."
{::doc/added "2.18" {::doc/added "2.18"
::sm/params schema:org-team-invitations-for-non-members-params ::sm/params schema:org-team-invitations-for-non-members-params
::sm/result schema:exists-org-team-invitations-for-non-members-result ::sm/result schema:exists-organization-team-invitations-for-non-members-result
::nitrate/sso false} ::nitrate/sso false}
[cfg params] [cfg params]
(db/run! cfg (fn [{:keys [::db/conn]}] (db/run! cfg (fn [{:keys [::db/conn]}]
{:exists (boolean (non-member-org-team-invitations-exist? conn params))}))) {:exists (boolean (non-member-org-team-invitations-exist? conn params))})))
(sv/defmethod ::delete-org-team-invitations-for-non-members (sv/defmethod ::delete-organization-team-invitations-for-non-members
"Delete team invitations for emails that are not organization members." "Delete team invitations for emails that are not organization members."
{::doc/added "2.18" {::doc/added "2.18"
::sm/params schema:org-team-invitations-for-non-members-params ::sm/params schema:org-team-invitations-for-non-members-params
@ -914,8 +914,8 @@ RETURNING id, deleted_at;")
[cfg params] [cfg params]
{:valid (oidc/is-organization-sso-config-valid? cfg params)}) {:valid (oidc/is-organization-sso-config-valid? cfg params)})
;; ---- API: notify-org-sso-change ;; ---- API: notify-organization-sso-change
(sv/defmethod ::notify-org-sso-change (sv/defmethod ::notify-organization-sso-change
"Nitrate notifies that an organization sso values have changed" "Nitrate notifies that an organization sso values have changed"
{::doc/added "2.19" {::doc/added "2.19"
::sm/params [:map ::sm/params [:map

View File

@ -369,7 +369,7 @@
(t/is (= :not-found (th/ex-type (:error ko-out)))) (t/is (= :not-found (th/ex-type (:error ko-out))))
(t/is (= :profile-not-found (th/ex-code (:error ko-out)))))) (t/is (= :profile-not-found (th/ex-code (:error ko-out))))))
(t/deftest get-org-invitations-returns-valid-deduped-by-email (t/deftest get-organization-invitations-returns-valid-deduped-by-email
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
team-1 (th/create-team* 1 {:profile-id (:id profile)}) team-1 (th/create-team* 1 {:profile-id (:id profile)})
team-2 (th/create-team* 2 {:profile-id (:id profile)}) team-2 (th/create-team* 2 {:profile-id (:id profile)})
@ -377,7 +377,7 @@
org-summary {:id org-id org-summary {:id org-id
:teams [{:id (:id team-1)} :teams [{:id (:id team-1)}
{:id (:id team-2)}]} {:id (:id team-2)}]}
params {::th/type :get-org-invitations params {::th/type :get-organization-invitations
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id}] :organization-id org-id}]
@ -439,12 +439,12 @@
(t/is (nil? (:role dedup))) (t/is (nil? (:role dedup)))
(t/is (nil? (:valid-until dedup)))))) (t/is (nil? (:valid-until dedup))))))
(t/deftest get-org-invitations-includes-org-level-invitations-when-no-teams (t/deftest get-organization-invitations-includes-org-level-invitations-when-no-teams
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
org-id (uuid/random) org-id (uuid/random)
org-summary {:id org-id org-summary {:id org-id
:teams []} :teams []}
params {::th/type :get-org-invitations params {::th/type :get-organization-invitations
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id}] :organization-id org-id}]
@ -468,7 +468,7 @@
(t/is (= "org-only@example.com" (-> result first :email))) (t/is (= "org-only@example.com" (-> result first :email)))
(t/is (some? (-> result first :sent-at)))))) (t/is (some? (-> result first :sent-at))))))
(t/deftest get-org-invitations-returns-existing-profile-data (t/deftest get-organization-invitations-returns-existing-profile-data
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
invited (th/create-profile* 2 {:is-active true invited (th/create-profile* 2 {:is-active true
:fullname "Invited User"}) :fullname "Invited User"})
@ -479,7 +479,7 @@
org-id (uuid/random) org-id (uuid/random)
org-summary {:id org-id org-summary {:id org-id
:teams []} :teams []}
params {::th/type :get-org-invitations params {::th/type :get-organization-invitations
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id}] :organization-id org-id}]
@ -504,7 +504,7 @@
(t/is (str/ends-with? (:photo-url invitation) (t/is (str/ends-with? (:photo-url invitation)
(str "/assets/by-id/" photo-id)))))) (str "/assets/by-id/" photo-id))))))
(t/deftest delete-org-invitations-removes-org-and-org-team-invitations-for-email (t/deftest delete-organization-invitations-removes-org-and-org-team-invitations-for-email
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
team-1 (th/create-team* 1 {:profile-id (:id profile)}) team-1 (th/create-team* 1 {:profile-id (:id profile)})
team-2 (th/create-team* 2 {:profile-id (:id profile)}) team-2 (th/create-team* 2 {:profile-id (:id profile)})
@ -514,7 +514,7 @@
:teams [{:id (:id team-1)} :teams [{:id (:id team-1)}
{:id (:id team-2)}]} {:id (:id team-2)}]}
target-email "target@example.com" target-email "target@example.com"
params {::th/type :delete-org-invitations params {::th/type :delete-organization-invitations
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id :organization-id org-id
:email "TARGET@example.com"}] :email "TARGET@example.com"}]
@ -572,7 +572,7 @@
(t/is (= (:id outside-team) (:team-id (first remaining-target)))) (t/is (= (:id outside-team) (:team-id (first remaining-target))))
(t/is (= 1 (count remaining-other)))))) (t/is (= 1 (count remaining-other))))))
(t/deftest delete-all-org-invitations-removes-org-and-org-team-invitations (t/deftest delete-all-organization-invitations-removes-org-and-org-team-invitations
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
team-1 (th/create-team* 1 {:profile-id (:id profile)}) team-1 (th/create-team* 1 {:profile-id (:id profile)})
team-2 (th/create-team* 2 {:profile-id (:id profile)}) team-2 (th/create-team* 2 {:profile-id (:id profile)})
@ -581,7 +581,7 @@
org-summary {:id org-id org-summary {:id org-id
:teams [{:id (:id team-1)} :teams [{:id (:id team-1)}
{:id (:id team-2)}]} {:id (:id team-2)}]}
params {::th/type :delete-all-org-invitations params {::th/type :delete-all-organization-invitations
:organization-id org-id}] :organization-id org-id}]
;; Should be deleted: org-level invitation. ;; Should be deleted: org-level invitation.
@ -660,10 +660,10 @@
(t/is (present? "dan@example.com")) (t/is (present? "dan@example.com"))
(t/is (present? "erin@example.com"))))) (t/is (present? "erin@example.com")))))
(t/deftest delete-all-org-invitations-handles-org-with-no-teams (t/deftest delete-all-organization-invitations-handles-org-with-no-teams
(let [profile (th/create-profile* 1 {:is-active true}) (let [profile (th/create-profile* 1 {:is-active true})
org-id (uuid/random) org-id (uuid/random)
params {::th/type :delete-all-org-invitations params {::th/type :delete-all-organization-invitations
:organization-id org-id}] :organization-id org-id}]
;; Org-level invitation should still be deleted. ;; Org-level invitation should still be deleted.
@ -686,14 +686,14 @@
(t/is (nil? (:result out))) (t/is (nil? (:result out)))
(t/is (empty? remaining))))) (t/is (empty? remaining)))))
(t/deftest exists-org-team-invitations-for-non-members-reports-invitations-to-delete (t/deftest exists-organization-team-invitations-for-non-members-reports-invitations-to-delete
(let [member1 (th/create-profile* 1 {:is-active true :email "member1@example.com"}) (let [member1 (th/create-profile* 1 {:is-active true :email "member1@example.com"})
profile (th/create-profile* 4 {:is-active true}) profile (th/create-profile* 4 {:is-active true})
team-1 (th/create-team* 1 {:profile-id (:id profile)}) team-1 (th/create-team* 1 {:profile-id (:id profile)})
team-2 (th/create-team* 2 {:profile-id (:id profile)}) team-2 (th/create-team* 2 {:profile-id (:id profile)})
outside-team (th/create-team* 3 {:profile-id (:id profile)}) outside-team (th/create-team* 3 {:profile-id (:id profile)})
org-id (uuid/random) org-id (uuid/random)
base-params {::th/type :exists-org-team-invitations-for-non-members base-params {::th/type :exists-organization-team-invitations-for-non-members
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id :organization-id org-id
:team-ids [(:id team-1) (:id team-2)] :team-ids [(:id team-1) (:id team-2)]
@ -744,14 +744,14 @@
:valid-until (ct/in-future "24h")}) :valid-until (ct/in-future "24h")})
(t/is (true? (exist!))))) (t/is (true? (exist!)))))
(t/deftest delete-org-team-invitations-for-non-members-removes-non-member-invitations (t/deftest delete-organization-team-invitations-for-non-members-removes-non-member-invitations
(let [member1 (th/create-profile* 1 {:is-active true :email "member1@example.com"}) (let [member1 (th/create-profile* 1 {:is-active true :email "member1@example.com"})
profile (th/create-profile* 4 {:is-active true}) profile (th/create-profile* 4 {:is-active true})
team-1 (th/create-team* 1 {:profile-id (:id profile)}) team-1 (th/create-team* 1 {:profile-id (:id profile)})
team-2 (th/create-team* 2 {:profile-id (:id profile)}) team-2 (th/create-team* 2 {:profile-id (:id profile)})
outside-team (th/create-team* 3 {:profile-id (:id profile)}) outside-team (th/create-team* 3 {:profile-id (:id profile)})
org-id (uuid/random) org-id (uuid/random)
params {::th/type :delete-org-team-invitations-for-non-members params {::th/type :delete-organization-team-invitations-for-non-members
::rpc/profile-id (:id profile) ::rpc/profile-id (:id profile)
:organization-id org-id :organization-id org-id
:team-ids [(:id team-1) (:id team-2)] :team-ids [(:id team-1) (:id team-2)]
@ -830,7 +830,7 @@
(t/is (= 1 (count (th/db-query :team-invitation {:email-to "outsider@example.com"}))))))) (t/is (= 1 (count (th/db-query :team-invitation {:email-to "outsider@example.com"})))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: remove-from-org ;; Tests: remove-from-organization
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- make-org-summary (defn- make-org-summary
@ -853,7 +853,7 @@
:remove-profile-from-org nil :remove-profile-from-org nil
nil))) nil)))
(t/deftest remove-from-org-happy-path-no-extra-teams (t/deftest remove-from-organization-happy-path-no-extra-teams
;; User is only in its default team (which has files); it should be ;; User is only in its default team (which has files); it should be
;; kept, renamed and unset as default. A notification must be sent. ;; kept, renamed and unset as default. A notification must be sent.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
@ -875,7 +875,7 @@
mbus/pub! (fn [_bus & {:keys [topic message]}] mbus/pub! (fn [_bus & {:keys [topic message]}]
(swap! calls conj {:topic topic :message message}))] (swap! calls conj {:topic topic :message message}))]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -898,7 +898,7 @@
(t/is (= "Acme Org" (:organization-name msg))) (t/is (= "Acme Org" (:organization-name msg)))
(t/is (= "dashboard.user-no-longer-belong-org" (:notification msg)))))) (t/is (= "dashboard.user-no-longer-belong-org" (:notification msg))))))
(t/deftest remove-from-org-deletes-empty-default-team (t/deftest remove-from-organization-deletes-empty-default-team
;; When the default team has no files it should be soft-deleted. ;; When the default team has no files it should be soft-deleted.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -913,7 +913,7 @@
out (with-redefs [nitrate/call (nitrate-call-mock org-summary) out (with-redefs [nitrate/call (nitrate-call-mock org-summary)
mbus/pub! (fn [& _] nil)] mbus/pub! (fn [& _] nil)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -923,7 +923,7 @@
(let [team (th/db-get :team {:id (:id org-team)} {::db/remove-deleted false})] (let [team (th/db-get :team {:id (:id org-team)} {::db/remove-deleted false})]
(t/is (some? (:deleted-at team)))))) (t/is (some? (:deleted-at team))))))
(t/deftest remove-from-org-deletes-sole-owner-team (t/deftest remove-from-organization-deletes-sole-owner-team
;; When the user is the sole member of an org team it should be deleted. ;; When the user is the sole member of an org team it should be deleted.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -939,7 +939,7 @@
out (with-redefs [nitrate/call (nitrate-call-mock org-summary) out (with-redefs [nitrate/call (nitrate-call-mock org-summary)
mbus/pub! (fn [& _] nil)] mbus/pub! (fn [& _] nil)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -949,7 +949,7 @@
(let [team (th/db-get :team {:id (:id extra-team)} {::db/remove-deleted false})] (let [team (th/db-get :team {:id (:id extra-team)} {::db/remove-deleted false})]
(t/is (some? (:deleted-at team)))))) (t/is (some? (:deleted-at team))))))
(t/deftest remove-from-org-transfers-ownership-of-multi-member-team (t/deftest remove-from-organization-transfers-ownership-of-multi-member-team
;; When the user owns a team that has another non-owner member, ownership ;; When the user owns a team that has another non-owner member, ownership
;; is transferred to that member by the endpoint automatically. ;; is transferred to that member by the endpoint automatically.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
@ -970,7 +970,7 @@
out (with-redefs [nitrate/call (nitrate-call-mock org-summary) out (with-redefs [nitrate/call (nitrate-call-mock org-summary)
mbus/pub! (fn [& _] nil)] mbus/pub! (fn [& _] nil)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -984,7 +984,7 @@
(let [rel (th/db-get :team-profile-rel {:team-id (:id extra-team) :profile-id (:id candidate)})] (let [rel (th/db-get :team-profile-rel {:team-id (:id extra-team) :profile-id (:id candidate)})]
(t/is (true? (:is-owner rel)))))) (t/is (true? (:is-owner rel))))))
(t/deftest remove-from-org-exits-non-owned-team (t/deftest remove-from-organization-exits-non-owned-team
;; When the user is a non-owner member of an org team, they simply leave. ;; When the user is a non-owner member of an org team, they simply leave.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1003,7 +1003,7 @@
out (with-redefs [nitrate/call (nitrate-call-mock org-summary) out (with-redefs [nitrate/call (nitrate-call-mock org-summary)
mbus/pub! (fn [& _] nil)] mbus/pub! (fn [& _] nil)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1017,7 +1017,7 @@
(let [team (th/db-get :team {:id (:id extra-team)})] (let [team (th/db-get :team {:id (:id extra-team)})]
(t/is (some? team))))) (t/is (some? team)))))
(t/deftest remove-from-org-error-nobody-to-reassign (t/deftest remove-from-organization-error-nobody-to-reassign
;; When the user owns a multi-member team but every other member is ;; When the user owns a multi-member team but every other member is
;; also an owner, the auto-selection query finds nobody and raises. ;; also an owner, the auto-selection query finds nobody and raises.
(let [other-owner (th/create-profile* 1 {:is-active true}) (let [other-owner (th/create-profile* 1 {:is-active true})
@ -1041,7 +1041,7 @@
out (with-redefs [nitrate/call (nitrate-call-mock org-summary) out (with-redefs [nitrate/call (nitrate-call-mock org-summary)
mbus/pub! (fn [& _] nil)] mbus/pub! (fn [& _] nil)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :remove-from-org {::th/type :remove-from-organization
::rpc/profile-id (:id other-owner) ::rpc/profile-id (:id other-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1051,10 +1051,10 @@
(t/is (= :validation (th/ex-type (:error out)))) (t/is (= :validation (th/ex-type (:error out))))
(t/is (= :nobody-to-reassign-team (th/ex-code (:error out)))))) (t/is (= :nobody-to-reassign-team (th/ex-code (:error out))))))
;; Tests: get-remove-from-org-summary ;; Tests: get-remove-from-organization-summary
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(t/deftest get-remove-from-org-summary-no-extra-teams (t/deftest get-remove-from-organization-summary-no-extra-teams
;; User only has a default team — nothing to delete/transfer/exit. ;; User only has a default team — nothing to delete/transfer/exit.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1068,7 +1068,7 @@
:org-teams []) :org-teams [])
out (with-redefs [nitrate/call (nitrate-call-mock org-summary)] out (with-redefs [nitrate/call (nitrate-call-mock org-summary)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :get-remove-from-org-summary {::th/type :get-remove-from-organization-summary
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1080,7 +1080,7 @@
:teams-to-detach 0} :teams-to-detach 0}
(:result out))))) (:result out)))))
(t/deftest get-remove-from-org-summary-with-teams-to-delete (t/deftest get-remove-from-organization-summary-with-teams-to-delete
;; User owns a sole-member extra org team → 1 to delete. ;; User owns a sole-member extra org team → 1 to delete.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1095,7 +1095,7 @@
:org-teams [(:id extra-team)]) :org-teams [(:id extra-team)])
out (with-redefs [nitrate/call (nitrate-call-mock org-summary)] out (with-redefs [nitrate/call (nitrate-call-mock org-summary)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :get-remove-from-org-summary {::th/type :get-remove-from-organization-summary
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1107,7 +1107,7 @@
:teams-to-detach 0} :teams-to-detach 0}
(:result out))))) (:result out)))))
(t/deftest get-remove-from-org-summary-with-teams-to-transfer (t/deftest get-remove-from-organization-summary-with-teams-to-transfer
;; User owns a multi-member extra org team → 1 to transfer. ;; User owns a multi-member extra org team → 1 to transfer.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1126,7 +1126,7 @@
:org-teams [(:id extra-team)]) :org-teams [(:id extra-team)])
out (with-redefs [nitrate/call (nitrate-call-mock org-summary)] out (with-redefs [nitrate/call (nitrate-call-mock org-summary)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :get-remove-from-org-summary {::th/type :get-remove-from-organization-summary
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1138,7 +1138,7 @@
:teams-to-detach 0} :teams-to-detach 0}
(:result out))))) (:result out)))))
(t/deftest get-remove-from-org-summary-with-teams-to-exit (t/deftest get-remove-from-organization-summary-with-teams-to-exit
;; User is a non-owner member of an org team → 1 to exit. ;; User is a non-owner member of an org team → 1 to exit.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1156,7 +1156,7 @@
:org-teams [(:id extra-team)]) :org-teams [(:id extra-team)])
out (with-redefs [nitrate/call (nitrate-call-mock org-summary)] out (with-redefs [nitrate/call (nitrate-call-mock org-summary)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :get-remove-from-org-summary {::th/type :get-remove-from-organization-summary
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1168,7 +1168,7 @@
:teams-to-detach 0} :teams-to-detach 0}
(:result out))))) (:result out)))))
(t/deftest get-remove-from-org-summary-does-not-mutate (t/deftest get-remove-from-organization-summary-does-not-mutate
;; Calling the summary endpoint must not modify any teams. ;; Calling the summary endpoint must not modify any teams.
(let [org-owner (th/create-profile* 1 {:is-active true}) (let [org-owner (th/create-profile* 1 {:is-active true})
user (th/create-profile* 2 {:is-active true}) user (th/create-profile* 2 {:is-active true})
@ -1183,7 +1183,7 @@
:org-teams [(:id extra-team)]) :org-teams [(:id extra-team)])
_ (with-redefs [nitrate/call (nitrate-call-mock org-summary)] _ (with-redefs [nitrate/call (nitrate-call-mock org-summary)]
(management-command-with-nitrate! (management-command-with-nitrate!
{::th/type :get-remove-from-org-summary {::th/type :get-remove-from-organization-summary
::rpc/profile-id (:id org-owner) ::rpc/profile-id (:id org-owner)
:profile-id (:id user) :profile-id (:id user)
:organization-id organization-id :organization-id organization-id
@ -1201,7 +1201,7 @@
(let [rel2 (th/db-get :team-profile-rel {:team-id (:id extra-team) :profile-id (:id user)})] (let [rel2 (th/db-get :team-profile-rel {:team-id (:id extra-team) :profile-id (:id user)})]
(t/is (some? rel2))))) (t/is (some? rel2)))))
(t/deftest notify-org-sso-change-sends-setup-sso-email-once-per-recipient (t/deftest notify-organization-sso-change-sends-setup-sso-email-once-per-recipient
(let [owner (th/create-profile* 1 {:is-active true :fullname "Owner"}) (let [owner (th/create-profile* 1 {:is-active true :fullname "Owner"})
member (th/create-profile* 2 {:is-active true member (th/create-profile* 2 {:is-active true
:fullname "Member" :fullname "Member"
@ -1216,7 +1216,7 @@
:name org-name :name org-name
:teams [{:id (:id team)}]} :teams [{:id (:id team)}]}
sent (atom []) sent (atom [])
params {::th/type :notify-org-sso-change params {::th/type :notify-organization-sso-change
:organization-id org-id :organization-id org-id
:updated-props false :updated-props false
:became-active true}] :became-active true}]
@ -1269,9 +1269,9 @@
(t/is (= org-name (:organization-name email-params))) (t/is (= org-name (:organization-name email-params)))
(t/is (= eml/organization-setup-sso (::eml/factory email-params))))))) (t/is (= eml/organization-setup-sso (::eml/factory email-params)))))))
(t/deftest notify-org-sso-change-skips-email-when-not-active (t/deftest notify-organization-sso-change-skips-email-when-not-active
(let [sent (atom []) (let [sent (atom [])
params {::th/type :notify-org-sso-change params {::th/type :notify-organization-sso-change
:organization-id (uuid/random) :organization-id (uuid/random)
:updated-props false :updated-props false
:became-active false}] :became-active false}]

View File

@ -59,7 +59,7 @@
(st/emit! (rt/nav-raw :href "/admin-console/"))) (st/emit! (rt/nav-raw :href "/admin-console/")))
([{:keys [organization-id organization-slug]}] ([{:keys [organization-id organization-slug]}]
(if (and organization-id organization-slug) (if (and organization-id organization-slug)
(let [href (dm/str "/admin-console/org/" (let [href (dm/str "/admin-console/organization/"
(u/percent-encode organization-slug) (u/percent-encode organization-slug)
"/" "/"
(u/percent-encode (str organization-id)) (u/percent-encode (str organization-id))
@ -67,9 +67,9 @@
(st/emit! (rt/nav-raw :href href))) (st/emit! (rt/nav-raw :href href)))
(st/emit! (rt/nav-raw :href "/admin-console/"))))) (st/emit! (rt/nav-raw :href "/admin-console/")))))
(defn go-to-nitrate-ac-create-org (defn go-to-nitrate-ac-create-organization
[] []
(st/emit! (rt/nav-raw :href "/admin-console/?action=create-org"))) (st/emit! (rt/nav-raw :href "/admin-console/?action=create-organization")))
(defn can-send-invitations? (defn can-send-invitations?
[{:keys [organization profile-id team-permissions]}] [{:keys [organization profile-id team-permissions]}]

View File

@ -320,7 +320,7 @@
(st/emit! (dnt/show-nitrate-popup :nitrate-form {:show-contact-sales-option true})) (st/emit! (dnt/show-nitrate-popup :nitrate-form {:show-contact-sales-option true}))
(dnt/is-valid-license? profile) (dnt/is-valid-license? profile)
(dnt/go-to-nitrate-ac-create-org) (dnt/go-to-nitrate-ac-create-organization)
:else :else
(st/emit! (dnt/show-nitrate-popup :nitrate-form))))) (st/emit! (dnt/show-nitrate-popup :nitrate-form)))))
@ -766,7 +766,7 @@
(st/emit! (dnt/show-nitrate-popup :nitrate-form {:show-contact-sales-option true})) (st/emit! (dnt/show-nitrate-popup :nitrate-form {:show-contact-sales-option true}))
(dnt/is-valid-license? profile) (dnt/is-valid-license? profile)
(dnt/go-to-nitrate-ac-create-org) (dnt/go-to-nitrate-ac-create-organization)
:else :else
(st/emit! (dnt/show-nitrate-popup :nitrate-form)))))] (st/emit! (dnt/show-nitrate-popup :nitrate-form)))))]

View File

@ -169,7 +169,7 @@
{:show-contact-sales-option true}))))) {:show-contact-sales-option true})))))
handle-go-to-cc handle-go-to-cc
(mf/use-fn dnt/go-to-nitrate-ac-create-org) (mf/use-fn dnt/go-to-nitrate-ac-create-organization)
handle-open-renew-modal handle-open-renew-modal
(mf/use-fn #(st/emit! (modal/show :nitrate-code-activation {:renew? true})))] (mf/use-fn #(st/emit! (modal/show :nitrate-code-activation {:renew? true})))]

View File

@ -36,7 +36,7 @@
(mf/use-fn (mf/use-fn
(fn [] (fn []
(modal/hide!) (modal/hide!)
(dnt/go-to-nitrate-ac-create-org)))] (dnt/go-to-nitrate-ac-create-organization)))]
[:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-dialog)} [:div {:class (stl/css :modal-dialog)}