Skip to content

Commit ea0039b

Browse files
authored
WPB-5695 Enforce group conversation permission for external partner role (#3788)
1 parent 874308c commit ea0039b

File tree

16 files changed

+281
-161
lines changed

16 files changed

+281
-161
lines changed

changelog.d/3-bug-fixes/WPB-5695

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enforce external partner permissions on the backend

integration/integration.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ library
117117
Test.Conversation
118118
Test.Demo
119119
Test.Errors
120+
Test.ExternalPartner
120121
Test.Federation
121122
Test.Federator
122123
Test.MessageTimer

integration/test/API/Galley.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ getConversationCode user conv mbZHost = do
416416
& maybe id zHost mbZHost
417417
)
418418

419+
-- https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/put_conversations__cnv_domain___cnv__name
419420
changeConversationName ::
420421
(HasCallStack, MakesValue user, MakesValue conv, MakesValue name) =>
421422
user ->

integration/test/SetupHelpers.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ deleteUser :: (HasCallStack, MakesValue user) => user -> App ()
2929
deleteUser user = bindResponse (API.Brig.deleteUser user) $ \resp -> do
3030
resp.status `shouldMatchInt` 200
3131

32-
-- | returns (user, team id)
32+
-- | returns (owner, team id, members)
3333
createTeam :: (HasCallStack, MakesValue domain) => domain -> Int -> App (Value, String, [Value])
3434
createTeam domain memberCount = do
3535
res <- createUser domain def {team = True}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{-# OPTIONS_GHC -Wno-ambiguous-fields #-}
2+
3+
-- This file is part of the Wire Server implementation.
4+
--
5+
-- Copyright (C) 2023 Wire Swiss GmbH <opensource@wire.com>
6+
--
7+
-- This program is free software: you can redistribute it and/or modify it under
8+
-- the terms of the GNU Affero General Public License as published by the Free
9+
-- Software Foundation, either version 3 of the License, or (at your option) any
10+
-- later version.
11+
--
12+
-- This program is distributed in the hope that it will be useful, but WITHOUT
13+
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14+
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
15+
-- details.
16+
--
17+
-- You should have received a copy of the GNU Affero General Public License along
18+
-- with this program. If not, see <https://www.gnu.org/licenses/>.
19+
20+
module Test.ExternalPartner where
21+
22+
import API.Galley
23+
import GHC.Stack
24+
import MLS.Util
25+
import SetupHelpers
26+
import Testlib.Prelude
27+
28+
testExternalPartnerPermissions :: HasCallStack => App ()
29+
testExternalPartnerPermissions = do
30+
(owner, tid, u1 : u2 : u3 : _) <- createTeam OwnDomain 4
31+
32+
partner <- createTeamMemberWithRole owner tid "partner"
33+
34+
-- a partner should not be able to create conversation with 2 additional users or more
35+
void $ postConversation partner (defProteus {team = Just tid, qualifiedUsers = [u1, u2]}) >>= getJSON 403
36+
37+
do
38+
-- a partner can create a one to one conversation with a user from the same team
39+
conv <- postConversation partner (defProteus {team = Just tid, qualifiedUsers = [u1]}) >>= getJSON 201
40+
41+
-- they should not be able to add another team member to the one to one conversation
42+
bindResponse (addMembers partner conv def {users = [u2]}) $ \resp -> do
43+
resp.status `shouldMatchInt` 403
44+
45+
-- the other member in the conversation gets deleted
46+
deleteUser u1
47+
48+
-- now they still should not be able to add another member
49+
bindResponse (addMembers partner conv def {users = [u2]}) $ \resp -> do
50+
resp.status `shouldMatchInt` 403
51+
52+
do
53+
-- also an external partner cannot add someone to a conversation, even if it is empty
54+
conv <- postConversation partner (defProteus {team = Just tid}) >>= getJSON 201
55+
bindResponse (addMembers partner conv def {users = [u3]}) $ \resp -> do
56+
resp.status `shouldMatchInt` 403
57+
58+
testExternalPartnerPermissionsMls :: HasCallStack => App ()
59+
testExternalPartnerPermissionsMls = do
60+
-- external partners should not be able to create (MLS) conversations
61+
(owner, tid, _) <- createTeam OwnDomain 2
62+
bobExt <- createTeamMemberWithRole owner tid "partner"
63+
bobExtClient <- createMLSClient def bobExt
64+
bindResponse (postConversation bobExtClient defMLS) $ \resp -> do
65+
resp.status `shouldMatchInt` 403
66+
67+
testExternalPartnerPermissionMlsOne2One :: HasCallStack => App ()
68+
testExternalPartnerPermissionMlsOne2One = do
69+
(owner, tid, alice : _) <- createTeam OwnDomain 2
70+
bobExternal <- createTeamMemberWithRole owner tid "partner"
71+
void $ getMLSOne2OneConversation alice bobExternal >>= getJSON 200
72+
73+
testExternalPartnerPermissionsConvName :: HasCallStack => App ()
74+
testExternalPartnerPermissionsConvName = do
75+
(owner, tid, u1 : _) <- createTeam OwnDomain 2
76+
77+
partner <- createTeamMemberWithRole owner tid "partner"
78+
79+
conv <- postConversation partner (defProteus {team = Just tid, qualifiedUsers = [u1]}) >>= getJSON 201
80+
81+
bindResponse (changeConversationName partner conv "new name") $ \resp -> do
82+
resp.status `shouldMatchInt` 403

libs/galley-types/src/Galley/Types/Teams.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ rolePerms RoleAdmin =
134134
rolePerms RoleMember =
135135
rolePerms RoleExternalPartner
136136
<> Set.fromList
137-
[ DoNotUseDeprecatedDeleteConversation,
138-
DoNotUseDeprecatedAddRemoveConvMember,
139-
DoNotUseDeprecatedModifyConvName,
137+
[ DeleteConversation,
138+
AddRemoveConvMember,
139+
ModifyConvName,
140140
GetMemberPermissions
141141
]
142142
rolePerms RoleExternalPartner =

libs/wire-api/src/Wire/API/Team/Permission.hs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ serviceWhitelistPermissions =
117117
Set.fromList
118118
[ AddTeamMember,
119119
RemoveTeamMember,
120-
DoNotUseDeprecatedAddRemoveConvMember,
120+
AddRemoveConvMember,
121121
SetTeamData
122122
]
123123

@@ -127,11 +127,20 @@ serviceWhitelistPermissions =
127127
-- | Team-level permission. Analog to conversation-level 'Action'.
128128
data Perm
129129
= CreateConversation
130-
| DoNotUseDeprecatedDeleteConversation -- NOTE: This gets now overruled by conv level checks
130+
| -- NOTE: This may get overruled by conv level checks in case those are more restrictive
131+
-- We currently cannot get rid of this team-level permission in favor of the conv-level action
132+
-- because it is used for e.g. for the team role 'RoleExternalPartner'
133+
DeleteConversation
131134
| AddTeamMember
132135
| RemoveTeamMember
133-
| DoNotUseDeprecatedAddRemoveConvMember -- NOTE: This gets now overruled by conv level checks
134-
| DoNotUseDeprecatedModifyConvName -- NOTE: This gets now overruled by conv level checks
136+
| -- NOTE: This may get overruled by conv level checks in case those are more restrictive
137+
-- We currently cannot get rid of this team-level permission in favor of the conv-level action
138+
-- because it is used for e.g. for the team role 'RoleExternalPartner'
139+
AddRemoveConvMember
140+
| -- NOTE: This may get overruled by conv level checks in case those are more restrictive
141+
-- We currently cannot get rid of this team-level permission in favor of the conv-level action
142+
-- because it is used for e.g. for the team role 'RoleExternalPartner'
143+
ModifyConvName
135144
| GetBilling
136145
| SetBilling
137146
| SetTeamData
@@ -159,11 +168,11 @@ intToPerms n =
159168

160169
permToInt :: Perm -> Word64
161170
permToInt CreateConversation = 0x0001
162-
permToInt DoNotUseDeprecatedDeleteConversation = 0x0002
171+
permToInt DeleteConversation = 0x0002
163172
permToInt AddTeamMember = 0x0004
164173
permToInt RemoveTeamMember = 0x0008
165-
permToInt DoNotUseDeprecatedAddRemoveConvMember = 0x0010
166-
permToInt DoNotUseDeprecatedModifyConvName = 0x0020
174+
permToInt AddRemoveConvMember = 0x0010
175+
permToInt ModifyConvName = 0x0020
167176
permToInt GetBilling = 0x0040
168177
permToInt SetBilling = 0x0080
169178
permToInt SetTeamData = 0x0100
@@ -174,11 +183,11 @@ permToInt SetMemberPermissions = 0x1000
174183

175184
intToPerm :: Word64 -> Maybe Perm
176185
intToPerm 0x0001 = Just CreateConversation
177-
intToPerm 0x0002 = Just DoNotUseDeprecatedDeleteConversation
186+
intToPerm 0x0002 = Just DeleteConversation
178187
intToPerm 0x0004 = Just AddTeamMember
179188
intToPerm 0x0008 = Just RemoveTeamMember
180-
intToPerm 0x0010 = Just DoNotUseDeprecatedAddRemoveConvMember
181-
intToPerm 0x0020 = Just DoNotUseDeprecatedModifyConvName
189+
intToPerm 0x0010 = Just AddRemoveConvMember
190+
intToPerm 0x0020 = Just ModifyConvName
182191
intToPerm 0x0040 = Just GetBilling
183192
intToPerm 0x0080 = Just SetBilling
184193
intToPerm 0x0100 = Just SetTeamData

libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/Event_team.hs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,11 @@ testObject_Event_team_18 =
233233
{ _self =
234234
fromList
235235
[ CreateConversation,
236-
DoNotUseDeprecatedDeleteConversation,
236+
DeleteConversation,
237237
AddTeamMember,
238238
RemoveTeamMember,
239-
DoNotUseDeprecatedAddRemoveConvMember,
240-
DoNotUseDeprecatedModifyConvName,
239+
AddRemoveConvMember,
240+
ModifyConvName,
241241
GetBilling,
242242
SetBilling,
243243
SetTeamData,
@@ -249,11 +249,11 @@ testObject_Event_team_18 =
249249
_copy =
250250
fromList
251251
[ CreateConversation,
252-
DoNotUseDeprecatedDeleteConversation,
252+
DeleteConversation,
253253
AddTeamMember,
254254
RemoveTeamMember,
255-
DoNotUseDeprecatedAddRemoveConvMember,
256-
DoNotUseDeprecatedModifyConvName,
255+
AddRemoveConvMember,
256+
ModifyConvName,
257257
GetBilling,
258258
GetMemberPermissions,
259259
SetMemberPermissions,
@@ -275,20 +275,20 @@ testObject_Event_team_19 =
275275
( Permissions
276276
{ _self =
277277
fromList
278-
[ DoNotUseDeprecatedDeleteConversation,
278+
[ DeleteConversation,
279279
RemoveTeamMember,
280-
DoNotUseDeprecatedAddRemoveConvMember,
281-
DoNotUseDeprecatedModifyConvName,
280+
AddRemoveConvMember,
281+
ModifyConvName,
282282
GetBilling,
283283
SetBilling,
284284
GetMemberPermissions,
285285
GetTeamConversations
286286
],
287287
_copy =
288288
fromList
289-
[ DoNotUseDeprecatedDeleteConversation,
289+
[ DeleteConversation,
290290
RemoveTeamMember,
291-
DoNotUseDeprecatedAddRemoveConvMember,
291+
AddRemoveConvMember,
292292
GetBilling,
293293
SetBilling,
294294
GetMemberPermissions,

libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/NewTeamMember_team.hs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ import Imports (Maybe (Just, Nothing), fromJust)
2727
import Wire.API.Team.Member (NewTeamMember, mkNewTeamMember)
2828
import Wire.API.Team.Permission
2929
( Perm
30-
( AddTeamMember,
30+
( AddRemoveConvMember,
31+
AddTeamMember,
3132
CreateConversation,
33+
DeleteConversation,
3234
DeleteTeam,
33-
DoNotUseDeprecatedAddRemoveConvMember,
34-
DoNotUseDeprecatedDeleteConversation,
35-
DoNotUseDeprecatedModifyConvName,
3635
GetBilling,
3736
GetMemberPermissions,
3837
GetTeamConversations,
38+
ModifyConvName,
3939
RemoveTeamMember,
4040
SetBilling,
4141
SetMemberPermissions,
@@ -63,13 +63,13 @@ testObject_NewTeamMember_team_2 =
6363
{ _self =
6464
fromList
6565
[ CreateConversation,
66-
DoNotUseDeprecatedDeleteConversation,
66+
DeleteConversation,
6767
AddTeamMember,
6868
RemoveTeamMember,
69-
DoNotUseDeprecatedAddRemoveConvMember,
70-
DoNotUseDeprecatedModifyConvName
69+
AddRemoveConvMember,
70+
ModifyConvName
7171
],
72-
_copy = fromList [DoNotUseDeprecatedDeleteConversation, DoNotUseDeprecatedAddRemoveConvMember]
72+
_copy = fromList [DeleteConversation, AddRemoveConvMember]
7373
}
7474
)
7575
( Just
@@ -85,8 +85,8 @@ testObject_NewTeamMember_team_3 =
8585
( Permissions
8686
{ _self =
8787
fromList
88-
[CreateConversation, DoNotUseDeprecatedDeleteConversation, RemoveTeamMember, GetBilling, DeleteTeam],
89-
_copy = fromList [CreateConversation, DoNotUseDeprecatedDeleteConversation, GetBilling]
88+
[CreateConversation, DeleteConversation, RemoveTeamMember, GetBilling, DeleteTeam],
89+
_copy = fromList [CreateConversation, DeleteConversation, GetBilling]
9090
}
9191
)
9292
( Just
@@ -124,7 +124,7 @@ testObject_NewTeamMember_team_6 =
124124
( Permissions
125125
{ _self =
126126
fromList
127-
[CreateConversation, DoNotUseDeprecatedDeleteConversation, GetBilling, SetTeamData, SetMemberPermissions],
127+
[CreateConversation, DeleteConversation, GetBilling, SetTeamData, SetMemberPermissions],
128128
_copy = fromList [CreateConversation, GetBilling]
129129
}
130130
)
@@ -141,7 +141,7 @@ testObject_NewTeamMember_team_7 =
141141
( Permissions
142142
{ _self =
143143
fromList
144-
[AddTeamMember, RemoveTeamMember, DoNotUseDeprecatedModifyConvName, GetTeamConversations, DeleteTeam],
144+
[AddTeamMember, RemoveTeamMember, ModifyConvName, GetTeamConversations, DeleteTeam],
145145
_copy = fromList [AddTeamMember]
146146
}
147147
)
@@ -156,8 +156,8 @@ testObject_NewTeamMember_team_8 =
156156
mkNewTeamMember
157157
(Id (fromJust (UUID.fromString "00000008-0000-0003-0000-000200000003")))
158158
( Permissions
159-
{ _self = fromList [DoNotUseDeprecatedModifyConvName],
160-
_copy = fromList [DoNotUseDeprecatedModifyConvName]
159+
{ _self = fromList [ModifyConvName],
160+
_copy = fromList [ModifyConvName]
161161
}
162162
)
163163
( Just
@@ -193,7 +193,7 @@ testObject_NewTeamMember_team_11 =
193193
mkNewTeamMember
194194
(Id (fromJust (UUID.fromString "00000006-0000-0005-0000-000000000002")))
195195
( Permissions
196-
{ _self = fromList [CreateConversation, DoNotUseDeprecatedModifyConvName, SetTeamData],
196+
{ _self = fromList [CreateConversation, ModifyConvName, SetTeamData],
197197
_copy = fromList []
198198
}
199199
)
@@ -215,8 +215,8 @@ testObject_NewTeamMember_team_13 =
215215
mkNewTeamMember
216216
(Id (fromJust (UUID.fromString "00000002-0000-0004-0000-000600000001")))
217217
( Permissions
218-
{ _self = fromList [AddTeamMember, DoNotUseDeprecatedAddRemoveConvMember, SetTeamData, GetTeamConversations],
219-
_copy = fromList [AddTeamMember, DoNotUseDeprecatedAddRemoveConvMember, GetTeamConversations]
218+
{ _self = fromList [AddTeamMember, AddRemoveConvMember, SetTeamData, GetTeamConversations],
219+
_copy = fromList [AddTeamMember, AddRemoveConvMember, GetTeamConversations]
220220
}
221221
)
222222
Nothing
@@ -228,7 +228,7 @@ testObject_NewTeamMember_team_14 =
228228
( Permissions
229229
{ _self =
230230
fromList
231-
[CreateConversation, DoNotUseDeprecatedDeleteConversation, DoNotUseDeprecatedModifyConvName, GetBilling],
231+
[CreateConversation, DeleteConversation, ModifyConvName, GetBilling],
232232
_copy = fromList []
233233
}
234234
)
@@ -291,8 +291,8 @@ testObject_NewTeamMember_team_19 =
291291
mkNewTeamMember
292292
(Id (fromJust (UUID.fromString "00000004-0000-0005-0000-000100000008")))
293293
( Permissions
294-
{ _self = fromList [DoNotUseDeprecatedDeleteConversation, RemoveTeamMember, SetBilling, SetMemberPermissions],
295-
_copy = fromList [DoNotUseDeprecatedDeleteConversation, SetBilling]
294+
{ _self = fromList [DeleteConversation, RemoveTeamMember, SetBilling, SetMemberPermissions],
295+
_copy = fromList [DeleteConversation, SetBilling]
296296
}
297297
)
298298
Nothing
@@ -305,8 +305,8 @@ testObject_NewTeamMember_team_20 =
305305
{ _self =
306306
fromList
307307
[ AddTeamMember,
308-
DoNotUseDeprecatedAddRemoveConvMember,
309-
DoNotUseDeprecatedModifyConvName,
308+
AddRemoveConvMember,
309+
ModifyConvName,
310310
SetBilling,
311311
GetMemberPermissions,
312312
GetTeamConversations

0 commit comments

Comments
 (0)