Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/3-bug-fixes/WPB-5133
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Only allow team member search with SearchContacts permission
6 changes: 6 additions & 0 deletions integration/test/API/Galley.hs
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,9 @@ updateMessageTimer user qcnv update = do
let path = joinHttpPath ["conversations", cnvDomain, cnvId, "message-timer"]
req <- baseRequest user Galley Versioned path
submit "PUT" (addJSONObject ["message_timer" .= updateReq] req)

getTeamMembers :: (HasCallStack, MakesValue user, MakesValue tid) => user -> tid -> App Response
getTeamMembers user tid = do
tidStr <- asString tid
req <- baseRequest user Galley Versioned (joinHttpPath ["teams", tidStr, "members"])
submit "GET" req
12 changes: 10 additions & 2 deletions integration/test/SetupHelpers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,17 @@ createTeamMember ::
inviter ->
String ->
App Value
createTeamMember inviter tid = do
createTeamMember inviter tid = createTeamMemberWithRole inviter tid "member"

createTeamMemberWithRole ::
(HasCallStack, MakesValue inviter) =>
inviter ->
String ->
String ->
App Value
createTeamMemberWithRole inviter tid role = do
newUserEmail <- randomEmail
let invitationJSON = ["role" .= "member", "email" .= newUserEmail]
let invitationJSON = ["role" .= role, "email" .= newUserEmail]
invitationReq <-
baseRequest inviter Brig Versioned $
joinHttpPath ["teams", tid, "invitations"]
Expand Down
19 changes: 16 additions & 3 deletions integration/test/Test/Brig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Test.Brig where
import API.Brig qualified as BrigP
import API.BrigInternal qualified as BrigI
import API.Common qualified as API
import API.GalleyInternal qualified as GalleyI
import API.Galley qualified as Galley
import Control.Concurrent (threadDelay)
import Data.Aeson.Types hiding ((.=))
import Data.Set qualified as Set
Expand All @@ -18,14 +18,27 @@ import Testlib.Prelude
testSearchContactForExternalUsers :: HasCallStack => App ()
testSearchContactForExternalUsers = do
owner <- randomUser OwnDomain def {BrigI.team = True}
partner <- randomUser OwnDomain def {BrigI.team = True}
tid <- owner %. "team" & asString

bindResponse (GalleyI.putTeamMember partner (partner %. "team") (API.teamRole "partner")) $ \resp ->
partner <- createTeamMemberWithRole owner tid "partner"
teamMember <- createTeamMember owner tid

bindResponse (BrigP.searchContacts teamMember (owner %. "name") OwnDomain) $ \resp ->
resp.status `shouldMatchInt` 200

bindResponse (BrigP.searchContacts partner (owner %. "name") OwnDomain) $ \resp ->
resp.status `shouldMatchInt` 403

bindResponse (Galley.getTeamMembers teamMember tid) $ \resp -> do
members <- resp.json %. "members" & asList
userIds <- for members (\m -> m %. "user")
expected <- for [owner, teamMember, partner] objId
userIds `shouldMatchSet` expected
resp.status `shouldMatchInt` 200

bindResponse (Galley.getTeamMembers partner tid) $ \resp -> do
resp.status `shouldMatchInt` 403

testCrudFederationRemotes :: HasCallStack => App ()
testCrudFederationRemotes = do
otherDomain <- asString OtherDomain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type TeamMemberAPI =
"get-team-members"
( Summary "Get team members"
:> CanThrow 'NotATeamMember
:> CanThrow 'InvalidPermissions
:> ZLocalUser
:> "teams"
:> Capture "tid" TeamId
Expand Down
2 changes: 2 additions & 0 deletions services/galley/src/Galley/API/Teams.hs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ getTeamConversationRoles zusr tid = do

getTeamMembers ::
( Member (ErrorS 'NotATeamMember) r,
Member (ErrorS 'InvalidPermissions) r,
Member TeamStore r,
Member (TeamMemberStore CassandraPaging) r
) =>
Expand All @@ -494,6 +495,7 @@ getTeamMembers ::
Sem r TeamMembersPage
getTeamMembers lzusr tid mbMaxResults mbPagingState = do
member <- E.getTeamMember tid (tUnqualified lzusr) >>= noteS @'NotATeamMember
unless (member `hasPermission` SearchContacts) $ throwS @'InvalidPermissions
let mState = C.PagingState . LBS.fromStrict <$> (mbPagingState >>= mtpsState)
let mLimit = fromMaybe (unsafeRange Public.hardTruncationLimit) mbMaxResults
E.listTeamMembers @CassandraPaging tid mState mLimit <&> toTeamMembersPage member
Expand Down