Skip to content

Commit b42e024

Browse files
committed
WPB-18191: Add route to collaborator permissions from team
1 parent 8e873f3 commit b42e024

File tree

12 files changed

+145
-0
lines changed

12 files changed

+145
-0
lines changed

changelog.d/2-features/WPB-18191

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow member permissions to be updated in a team.

integration/test/API/Brig.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,14 @@ getAllTeamCollaborators owner tid = do
10981098
req <- baseRequest owner Brig Versioned $ joinHttpPath ["teams", tid, "collaborators"]
10991099
submit "GET" req
11001100

1101+
updateTeamCollaborator :: (MakesValue owner, MakesValue collaborator, HasCallStack) => owner -> String -> collaborator -> [String] -> App Response
1102+
updateTeamCollaborator owner tid collaborator permissions = do
1103+
(_, collabId) <- objQid collaborator
1104+
req <- baseRequest owner Brig Versioned $ joinHttpPath ["teams", tid, "collaborators", collabId]
1105+
submit "PUT" $
1106+
req
1107+
& addJSON permissions
1108+
11011109
removeTeamCollaborator :: (MakesValue owner, MakesValue collaborator, HasCallStack) => owner -> String -> collaborator -> App Response
11021110
removeTeamCollaborator owner tid collaborator = do
11031111
(_, collabId) <- objQid collaborator

integration/test/Test/TeamCollaborators.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,33 @@ testRemoveMember = do
157157
removeTeamCollaborator owner team bob >>= assertSuccess
158158

159159
postOne2OneConversation bob alice team "chit-chat" >>= assertLabel 403 "no-team-member"
160+
161+
testUpdateMember :: (HasCallStack) => App ()
162+
testUpdateMember = do
163+
(owner, team, [alice]) <- createTeam OwnDomain 2
164+
165+
-- At the time of writing, it wasn't clear if this should be a bot instead.
166+
bob <- randomUser OwnDomain def
167+
addTeamCollaborator
168+
owner
169+
team
170+
bob
171+
["implicit_connection"]
172+
>>= assertSuccess
173+
postOne2OneConversation bob alice team "chit-chat" >>= assertSuccess
174+
175+
updateTeamCollaborator
176+
owner
177+
team
178+
bob
179+
["create_team_conversation", "implicit_connection"]
180+
>>= assertSuccess
181+
postOne2OneConversation bob alice team "chit-chat" >>= assertSuccess
182+
183+
updateTeamCollaborator
184+
owner
185+
team
186+
bob
187+
[]
188+
>>= assertSuccess
189+
postOne2OneConversation bob alice team "chit-chat" >>= assertLabel 403 "operation-denied"

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ data EventType
124124
| ConvCreate
125125
| ConvDelete
126126
| CollaboratorAdd
127+
| CollaboratorUpdate
127128
| CollaboratorRemove
128129
deriving stock (Eq, Show, Generic)
129130
deriving (Arbitrary) via (GenericUniform EventType)
@@ -142,6 +143,7 @@ instance ToSchema EventType where
142143
element "team.conversation-create" ConvCreate,
143144
element "team.conversation-delete" ConvDelete,
144145
element "team.collaborator-add" CollaboratorAdd,
146+
element "team.collaborator-update" CollaboratorUpdate,
145147
element "team.collaborator-remove" CollaboratorRemove
146148
]
147149

@@ -158,6 +160,7 @@ data EventData
158160
| EdConvCreate ConvId
159161
| EdConvDelete ConvId
160162
| EdCollaboratorAdd UserId [CollaboratorPermission]
163+
| EdCollaboratorUpdate UserId [CollaboratorPermission]
161164
| EdCollaboratorRemove UserId
162165
deriving stock (Eq, Show, Generic)
163166

@@ -188,6 +191,11 @@ instance ToJSON EventData where
188191
[ "user" A..= usr,
189192
"permissions" A..= perms
190193
]
194+
toJSON (EdCollaboratorUpdate usr perms) =
195+
A.object
196+
[ "user" A..= usr,
197+
"permissions" A..= perms
198+
]
191199
toJSON (EdCollaboratorRemove usr) = A.object ["user" A..= usr]
192200

193201
eventDataType :: EventData -> EventType
@@ -200,6 +208,7 @@ eventDataType (EdMemberUpdate _ _) = MemberUpdate
200208
eventDataType (EdConvCreate _) = ConvCreate
201209
eventDataType (EdConvDelete _) = ConvDelete
202210
eventDataType (EdCollaboratorAdd _ _) = CollaboratorAdd
211+
eventDataType (EdCollaboratorUpdate _ _) = CollaboratorUpdate
203212
eventDataType (EdCollaboratorRemove _) = CollaboratorRemove
204213

205214
parseEventData :: EventType -> Maybe Value -> Parser EventData
@@ -231,6 +240,10 @@ parseEventData CollaboratorAdd Nothing = fail "missing event data for type 'team
231240
parseEventData CollaboratorAdd (Just j) = do
232241
let f o = EdCollaboratorAdd <$> o .: "user" <*> o .: "permissions"
233242
withObject "collaborator add data" f j
243+
parseEventData CollaboratorUpdate Nothing = fail "missing event data for type 'team.collaborator-update"
244+
parseEventData CollaboratorUpdate (Just j) = do
245+
let f o = EdCollaboratorUpdate <$> o .: "user" <*> o .: "permissions"
246+
withObject "collaborator update data" f j
234247
parseEventData CollaboratorRemove Nothing = fail "missing event data for type 'team.collaborator-remove"
235248
parseEventData CollaboratorRemove (Just j) = do
236249
let f o = EdCollaboratorRemove <$> o .: "user"
@@ -249,6 +262,7 @@ genEventData = \case
249262
ConvCreate -> EdConvCreate <$> arbitrary
250263
ConvDelete -> EdConvDelete <$> arbitrary
251264
CollaboratorAdd -> EdCollaboratorAdd <$> arbitrary <*> arbitrary
265+
CollaboratorUpdate -> EdCollaboratorUpdate <$> arbitrary <*> arbitrary
252266
CollaboratorRemove -> EdCollaboratorRemove <$> arbitrary
253267

254268
makeLenses ''Event

libs/wire-api/src/Wire/API/Routes/Public/Brig.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,6 +1979,18 @@ type TeamsAPI =
19791979
:> ReqBody '[JSON] NewTeamCollaborator
19801980
:> MultiVerb1 'POST '[JSON] (RespondEmpty 200 "")
19811981
)
1982+
:<|> Named
1983+
"update-team-collaborator"
1984+
( Summary "Update a collaborator permissions from the team."
1985+
:> From 'V11
1986+
:> ZLocalUser
1987+
:> "teams"
1988+
:> Capture "tid" TeamId
1989+
:> "collaborators"
1990+
:> Capture "uid" UserId
1991+
:> ReqBody '[JSON] (Set CollaboratorPermission)
1992+
:> MultiVerb1 'PUT '[JSON] (RespondEmpty 200 "")
1993+
)
19821994
:<|> Named
19831995
"remove-team-collaborator"
19841996
( Summary "Remove a collaborator from the team."

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ data HiddenPerm
478478
| ChangeTeamMemberProfiles
479479
| SearchContacts
480480
| NewTeamCollaborator
481+
| UpdateTeamCollaborator
481482
| RemoveTeamCollaborator
482483
deriving (Eq, Ord, Show)
483484

@@ -564,6 +565,7 @@ roleHiddenPermissions role = HiddenPermissions p p
564565
CreateReadDeleteScimToken,
565566
DownloadTeamMembersCsv,
566567
NewTeamCollaborator,
568+
UpdateTeamCollaborator,
567569
RemoveTeamCollaborator
568570
]
569571
roleHiddenPerms RoleMember =

libs/wire-subsystems/src/Wire/TeamCollaboratorsStore.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ data TeamCollaboratorsStore m a where
1111
CreateTeamCollaborator :: UserId -> TeamId -> Set CollaboratorPermission -> TeamCollaboratorsStore m ()
1212
GetAllTeamCollaborators :: TeamId -> TeamCollaboratorsStore m [TeamCollaborator]
1313
GetTeamCollaborator :: TeamId -> UserId -> TeamCollaboratorsStore m (Maybe TeamCollaborator)
14+
UpdateTeamCollaborator :: UserId -> TeamId -> Set CollaboratorPermission -> TeamCollaboratorsStore m ()
1415
RemoveTeamCollaborator :: UserId -> TeamId -> TeamCollaboratorsStore m ()
1516

1617
makeSem ''TeamCollaboratorsStore

libs/wire-subsystems/src/Wire/TeamCollaboratorsStore/Postgres.hs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ interpretTeamCollaboratorsStoreToPostgres =
3636
CreateTeamCollaborator userId teamId permissions -> createTeamCollaboratorImpl userId teamId permissions
3737
GetAllTeamCollaborators teamId -> getAllTeamCollaboratorsImpl teamId
3838
GetTeamCollaborator teamId userId -> getTeamCollaboratorImpl teamId userId
39+
UpdateTeamCollaborator userId teamId permissions -> updateTeamCollaboratorImpl userId teamId permissions
3940
RemoveTeamCollaborator userId teamId -> removeTeamCollaboratorImpl userId teamId
4041

4142
getTeamCollaboratorImpl ::
@@ -123,6 +124,33 @@ getAllTeamCollaboratorsImpl teamId = do
123124
select user_id :: uuid, team_id :: uuid, permissions :: int2[] from collaborators where team_id = ($1 :: uuid)
124125
|]
125126

127+
updateTeamCollaboratorImpl ::
128+
( Member (Input Pool) r,
129+
Member (Embed IO) r,
130+
Member (Error UsageError) r
131+
) =>
132+
UserId ->
133+
TeamId ->
134+
Set CollaboratorPermission ->
135+
Sem r ()
136+
updateTeamCollaboratorImpl userId teamId permissions = do
137+
pool <- input
138+
eitherErrorOrUnit <- liftIO $ use pool session
139+
either throw pure eitherErrorOrUnit
140+
where
141+
session :: Session ()
142+
session = statement (userId, teamId, permissions) updateStatement
143+
144+
updateStatement :: Statement (UserId, TeamId, Set CollaboratorPermission) ()
145+
updateStatement =
146+
lmap
147+
( \(uid, tid, pms) ->
148+
(toUUID uid, toUUID tid, collaboratorPermissionToPostgreslRep <$> (Data.Vector.fromList . toAscList) pms)
149+
)
150+
$ [resultlessStatement|
151+
update collaborators set permissions = ($3 :: smallint[]) where user_id = ($1 :: uuid) and team_id = ($2 :: uuid)
152+
|]
153+
126154
removeTeamCollaboratorImpl ::
127155
( Member (Input Pool) r,
128156
Member (Embed IO) r,

libs/wire-subsystems/src/Wire/TeamCollaboratorsSubsystem.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ data TeamCollaboratorsSubsystem m a where
1212
CreateTeamCollaborator :: Local UserId -> UserId -> TeamId -> Set CollaboratorPermission -> TeamCollaboratorsSubsystem m ()
1313
GetAllTeamCollaborators :: Local UserId -> TeamId -> TeamCollaboratorsSubsystem m [TeamCollaborator]
1414
InternalGetTeamCollaborator :: TeamId -> UserId -> TeamCollaboratorsSubsystem m (Maybe TeamCollaborator)
15+
UpdateTeamCollaborator :: Local UserId -> UserId -> TeamId -> Set CollaboratorPermission -> TeamCollaboratorsSubsystem m ()
1516
RemoveTeamCollaborator :: Local UserId -> UserId -> TeamId -> TeamCollaboratorsSubsystem m ()
1617

1718
makeSem ''TeamCollaboratorsSubsystem

libs/wire-subsystems/src/Wire/TeamCollaboratorsSubsystem/Interpreter.hs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ interpretTeamCollaboratorsSubsystem = interpret $ \case
3737
CreateTeamCollaborator zUser user team perms -> createTeamCollaboratorImpl zUser user team perms
3838
GetAllTeamCollaborators zUser team -> getAllTeamCollaboratorsImpl zUser team
3939
InternalGetTeamCollaborator team user -> internalGetTeamCollaboratorImpl team user
40+
UpdateTeamCollaborator zUser user team perms -> updateTeamCollaboratorImpl zUser user team perms
4041
RemoveTeamCollaborator zUser user team -> removeTeamCollaboratorImpl zUser user team
4142

4243
internalGetTeamCollaboratorImpl ::
@@ -96,6 +97,46 @@ getAllTeamCollaboratorsImpl zUser team = do
9697
guardPermission (tUnqualified zUser) team TeamMember.NewTeamCollaborator InsufficientRights
9798
Store.getAllTeamCollaborators team
9899

100+
updateTeamCollaboratorImpl ::
101+
( Member TeamSubsystem r,
102+
Member (Error TeamCollaboratorsError) r,
103+
Member Store.TeamCollaboratorsStore r,
104+
Member Now r,
105+
Member NotificationSubsystem r
106+
) =>
107+
Local UserId ->
108+
UserId ->
109+
TeamId ->
110+
Set CollaboratorPermission ->
111+
Sem r ()
112+
updateTeamCollaboratorImpl zUser user team perms = do
113+
guardPermission (tUnqualified zUser) team TeamMember.UpdateTeamCollaborator InsufficientRights
114+
Store.updateTeamCollaborator user team perms
115+
unless (Set.member ImplicitConnection perms) $
116+
-- TODO gdf remove O2O conversations
117+
pure ()
118+
119+
now <- get
120+
let event = newEvent team now (EdCollaboratorUpdate user $ Set.toList perms)
121+
teamMembersList <- internalGetTeamAdmins team
122+
let teamMembers :: [UserId] = view TeamMember.userId <$> (teamMembersList ^. TeamMember.teamMembers)
123+
-- TODO: Review the event's values
124+
pushNotifications
125+
[ def
126+
{ origin = Just (tUnqualified zUser),
127+
json = toJSONObject $ event,
128+
recipients =
129+
( \uid ->
130+
Recipient
131+
{ recipientUserId = uid,
132+
recipientClients = Push.RecipientClientsAll
133+
}
134+
)
135+
<$> teamMembers,
136+
transient = False
137+
}
138+
]
139+
99140
removeTeamCollaboratorImpl ::
100141
( Member TeamSubsystem r,
101142
Member (Error TeamCollaboratorsError) r,

0 commit comments

Comments
 (0)