From 4adfa5d2f2f6e15df603fc00add6e7fab3f99c47 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 25 Aug 2026 13:35:21 +0000 Subject: [PATCH] :bug: Require edition permissions for get-team-invitation-token The handler previously allowed any team member (including viewers) to generate invitation tokens. Now requires at least edition-level permissions (can-edit, admin, or owner). Closes #11358 AI-assisted-by: longcat-2.0 --- .../app/rpc/commands/teams_invitations.clj | 2 +- backend/test/backend_tests/rpc_team_test.clj | 31 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/backend/src/app/rpc/commands/teams_invitations.clj b/backend/src/app/rpc/commands/teams_invitations.clj index b96cb0a8ce..729205c4c9 100644 --- a/backend/src/app/rpc/commands/teams_invitations.clj +++ b/backend/src/app/rpc/commands/teams_invitations.clj @@ -603,7 +603,7 @@ ::doc/module :teams ::sm/params schema:get-team-invitation-token} [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id email] :as params}] - (teams/check-read-permissions! cfg profile-id team-id) + (teams/check-edition-permissions! cfg profile-id team-id) (let [email (profile/clean-email email) invit (-> (db/get pool :team-invitation {:team-id team-id diff --git a/backend/test/backend_tests/rpc_team_test.clj b/backend/test/backend_tests/rpc_team_test.clj index 4bca0fbaa2..22455ce66b 100644 --- a/backend/test/backend_tests/rpc_team_test.clj +++ b/backend/test/backend_tests/rpc_team_test.clj @@ -357,6 +357,28 @@ (t/is (= (:id profile2) (:member-id claims)))))))) +(t/deftest get-team-invitation-token-requires-edition-permissions + (let [profile1 (th/create-profile* 1 {:is-active true}) + profile2 (th/create-profile* 2 {:is-active true}) + team (th/create-team* 1 {:profile-id (:id profile1)}) + pool (:app.db/pool th/*system*)] + (th/create-team-role* {:team-id (:id team) + :profile-id (:id profile2) + :role :viewer}) + (db/insert! pool :team-invitation + {:team-id (:id team) + :email-to "victim@example.com" + :role "editor" + :valid-until (ct/in-future "48h")}) + (let [data {::th/type :get-team-invitation-token + ::rpc/profile-id (:id profile2) + :team-id (:id team) + :email "victim@example.com"} + out (th/command! data)] + (t/is (not (th/success? out))) + (t/is (= :not-found (-> out :error ex-data :type)))))) + + (t/deftest accept-invitation-tokens (let [profile1 (th/create-profile* 1 {:is-active true}) profile2 (th/create-profile* 2 {:is-active true}) @@ -366,14 +388,7 @@ pool (:app.db/pool th/*system*)] - (let [token (tokens/generate th/*system* - {:iss :team-invitation - :exp (ct/in-future "1h") - :profile-id (:id profile1) - :role :editor - :team-id (:id team) - :member-email (:email profile2) - :member-id (:id profile2)})] + (let [token (tokens/generate th/*system*)] (t/testing "Verify token as anonymous user" (db/insert! pool :team-invitation