Skip to content

Commit 2ce94ca

Browse files
committed
Revert "Do not send member updates to all (#3431)"
This reverts commit e124b2c, but keeps the schema and data migrations in place.
1 parent 6db29bb commit 2ce94ca

File tree

13 files changed

+233
-120
lines changed

13 files changed

+233
-120
lines changed

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ module Galley.Types.Teams
5656
rolePermissions,
5757
roleHiddenPermissions,
5858
permissionsRole,
59-
isAdminOrOwner,
6059
HiddenPerm (..),
6160
IsPerm (..),
6261
)
@@ -102,15 +101,6 @@ permissionsRole (Permissions p p') =
102101
rolePerms role `Set.isSubsetOf` perms
103102
]
104103

105-
isAdminOrOwner :: Permissions -> Bool
106-
isAdminOrOwner perms =
107-
case permissionsRole perms of
108-
Just RoleOwner -> True
109-
Just RoleAdmin -> True
110-
Just RoleMember -> False
111-
Just RoleExternalPartner -> False
112-
Nothing -> False
113-
114104
-- | Internal function for 'rolePermissions'. (It works iff the two sets in 'Permissions' are
115105
-- identical for every 'Role', otherwise it'll need to be specialized for the resp. sides.)
116106
rolePerms :: Role -> Set Perm

libs/wire-api/src/Wire/API/Error/Galley.hs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ data GalleyError
5959
| UserBindingExists
6060
| NoAddToBinding
6161
| TooManyTeamMembers
62-
| TooManyTeamAdmins
6362
| -- FUTUREWORK: possibly make MissingPermission take a list of Perm
6463
MissingPermission (Maybe Perm)
6564
| ActionDenied Action
@@ -169,8 +168,6 @@ type instance MapError 'NoAddToBinding = 'StaticError 403 "binding-team" "Cannot
169168

170169
type instance MapError 'TooManyTeamMembers = 'StaticError 403 "too-many-team-members" "Maximum number of members per team reached"
171170

172-
type instance MapError 'TooManyTeamAdmins = 'StaticError 403 "too-many-team-admins" "Maximum number of admins per team reached"
173-
174171
type instance MapError ('MissingPermission mperm) = 'StaticError 403 "operation-denied" (MissingPermissionMessage mperm)
175172

176173
type instance MapError ('ActionDenied action) = 'StaticError 403 "action-denied" ("Insufficient authorization (missing " `AppendSymbol` ActionName action `AppendSymbol` ")")

libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ type ITeamsAPIBase =
294294
"unchecked-add-team-member"
295295
( CanThrow 'TooManyTeamMembers
296296
:> CanThrow 'TooManyTeamMembersOnTeamWithLegalhold
297-
:> CanThrow 'TooManyTeamAdmins
298297
:> ReqBody '[Servant.JSON] NewTeamMember
299298
:> MultiVerb1 'POST '[Servant.JSON] (RespondEmpty 200 "OK")
300299
)
@@ -321,7 +320,6 @@ type ITeamsAPIBase =
321320
:> CanThrow 'InvalidPermissions
322321
:> CanThrow 'TeamNotFound
323322
:> CanThrow 'TeamMemberNotFound
324-
:> CanThrow 'TooManyTeamAdmins
325323
:> CanThrow 'NotATeamMember
326324
:> CanThrow OperationDenied
327325
:> ReqBody '[Servant.JSON] NewTeamMember

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ type TeamMemberAPI =
105105
:> CanThrow OperationDenied
106106
:> CanThrow 'TeamNotFound
107107
:> CanThrow 'TooManyTeamMembers
108-
:> CanThrow 'TooManyTeamAdmins
109108
:> CanThrow 'UserBindingExists
110109
:> CanThrow 'TooManyTeamMembersOnTeamWithLegalhold
111110
:> ZLocalUser
@@ -170,7 +169,6 @@ type TeamMemberAPI =
170169
:> CanThrow 'InvalidPermissions
171170
:> CanThrow 'TeamNotFound
172171
:> CanThrow 'TeamMemberNotFound
173-
:> CanThrow 'TooManyTeamAdmins
174172
:> CanThrow 'NotATeamMember
175173
:> CanThrow OperationDenied
176174
:> ZLocalUser

services/brig/test/integration/API/Federation.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ testRemoteUserGetsDeleted opts brig cannon fedBrigClient = do
389389
runFedClient @"on-user-deleted-connections" fedBrigClient (qDomain remoteUser) $
390390
UserDeletedConnectionsNotification (qUnqualified remoteUser) (unsafeRange localUsers)
391391

392-
WS.assertMatchN_ (60 # Second) [cc] $ matchDeleteUserNotification remoteUser
392+
WS.assertMatchN_ (5 # Second) [cc] $ matchDeleteUserNotification remoteUser
393393
WS.assertNoEvent (1 # Second) [pc, bc, uc]
394394

395395
for_ localUsers $ \u ->

services/galley/src/Galley/API/Internal.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ import Galley.Effects.MemberStore
7373
import qualified Galley.Effects.MemberStore as E
7474
import Galley.Effects.ProposalStore
7575
import Galley.Effects.TeamStore
76-
import qualified Galley.Effects.TeamStore as E
7776
import qualified Galley.Intra.Push as Intra
7877
import Galley.Monad
7978
import Galley.Options
@@ -377,8 +376,8 @@ rmUser lusr conn = do
377376
goConvPages range newCids
378377

379378
leaveTeams page = for_ (pageItems page) $ \tid -> do
380-
admins <- E.getTeamAdmins tid
381-
uncheckedDeleteTeamMember lusr conn tid (tUnqualified lusr) admins
379+
mems <- getTeamMembersForFanout tid
380+
uncheckedDeleteTeamMember lusr conn tid (tUnqualified lusr) mems
382381
page' <- listTeams @p2 (tUnqualified lusr) (Just (pageState page)) maxBound
383382
leaveTeams page'
384383

services/galley/src/Galley/API/Teams.hs

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ import Wire.API.Team.Conversation
138138
import qualified Wire.API.Team.Conversation as Public
139139
import Wire.API.Team.Export (TeamExportUser (..))
140140
import Wire.API.Team.Member
141-
import qualified Wire.API.Team.Member as M
142141
import qualified Wire.API.Team.Member as Public
143142
import Wire.API.Team.Permission (Perm (..), Permissions (..), SPerm (..), copy, fullPermissions, self)
144143
import Wire.API.Team.Role
@@ -329,13 +328,17 @@ updateTeamH ::
329328
Sem r ()
330329
updateTeamH zusr zcon tid updateData = do
331330
zusrMembership <- E.getTeamMember tid zusr
331+
-- let zothers = map (view userId) membs
332+
-- Log.debug $
333+
-- Log.field "targets" (toByteString . show $ toByteString <$> zothers)
334+
-- . Log.field "action" (Log.val "Teams.updateTeam")
332335
void $ permissionCheckS SSetTeamData zusrMembership
333336
E.setTeamData tid updateData
334337
now <- input
335-
admins <- E.getTeamAdmins tid
338+
memList <- getTeamMembersForFanout tid
336339
let e = newEvent tid now (EdTeamUpdate updateData)
337-
let r = list1 (userRecipient zusr) (map userRecipient (filter (/= zusr) admins))
338-
E.push1 $ newPushLocal1 ListComplete zusr (TeamEvent e) r & pushConn ?~ zcon & pushTransient .~ True
340+
let r = list1 (userRecipient zusr) (membersToRecipients (Just zusr) (memList ^. teamMembers))
341+
E.push1 $ newPushLocal1 (memList ^. teamMemberListType) zusr (TeamEvent e) r & pushConn ?~ zcon
339342

340343
deleteTeam ::
341344
forall r.
@@ -704,7 +707,6 @@ addTeamMember ::
704707
Member (ErrorS OperationDenied) r,
705708
Member (ErrorS 'TeamNotFound) r,
706709
Member (ErrorS 'TooManyTeamMembers) r,
707-
Member (ErrorS 'TooManyTeamAdmins) r,
708710
Member (ErrorS 'UserBindingExists) r,
709711
Member (ErrorS 'TooManyTeamMembersOnTeamWithLegalhold) r,
710712
Member (Input Opts) r,
@@ -737,15 +739,15 @@ addTeamMember lzusr zcon tid nmem = do
737739
ensureConnectedToLocals zusr [uid]
738740
(TeamSize sizeBeforeJoin) <- E.getSize tid
739741
ensureNotTooLargeForLegalHold tid (fromIntegral sizeBeforeJoin + 1)
740-
void $ addTeamMemberInternal tid (Just zusr) (Just zcon) nmem
742+
memList <- getTeamMembersForFanout tid
743+
void $ addTeamMemberInternal tid (Just zusr) (Just zcon) nmem memList
741744

742745
-- This function is "unchecked" because there is no need to check for user binding (invite only).
743746
uncheckedAddTeamMember ::
744747
forall r.
745748
( Member BrigAccess r,
746749
Member GundeckAccess r,
747750
Member (ErrorS 'TooManyTeamMembers) r,
748-
Member (ErrorS 'TooManyTeamAdmins) r,
749751
Member (ErrorS 'TooManyTeamMembersOnTeamWithLegalhold) r,
750752
Member (Input Opts) r,
751753
Member (Input UTCTime) r,
@@ -759,18 +761,18 @@ uncheckedAddTeamMember ::
759761
NewTeamMember ->
760762
Sem r ()
761763
uncheckedAddTeamMember tid nmem = do
764+
mems <- getTeamMembersForFanout tid
762765
(TeamSize sizeBeforeJoin) <- E.getSize tid
763766
ensureNotTooLargeForLegalHold tid (fromIntegral sizeBeforeJoin + 1)
764-
(TeamSize sizeBeforeAdd) <- addTeamMemberInternal tid Nothing Nothing nmem
765-
owners <- E.getBillingTeamMembers tid
766-
Journal.teamUpdate tid (sizeBeforeAdd + 1) owners
767+
(TeamSize sizeBeforeAdd) <- addTeamMemberInternal tid Nothing Nothing nmem mems
768+
billingUserIds <- E.getBillingTeamMembers tid
769+
Journal.teamUpdate tid (sizeBeforeAdd + 1) billingUserIds
767770

768771
uncheckedUpdateTeamMember ::
769772
forall r.
770773
( Member BrigAccess r,
771774
Member (ErrorS 'TeamNotFound) r,
772775
Member (ErrorS 'TeamMemberNotFound) r,
773-
Member (ErrorS 'TooManyTeamAdmins) r,
774776
Member GundeckAccess r,
775777
Member (Input UTCTime) r,
776778
Member P.TinyLog r,
@@ -795,22 +797,33 @@ uncheckedUpdateTeamMember mlzusr mZcon tid newMember = do
795797
previousMember <-
796798
E.getTeamMember tid targetId >>= noteS @'TeamMemberNotFound
797799

798-
admins <- E.getTeamAdmins tid
799-
let admins' = [targetId | isAdminOrOwner targetPermissions] <> filter (/= targetId) admins
800-
checkAdminLimit (length admins')
801-
802800
-- update target in Cassandra
803801
E.setTeamMemberPermissions (previousMember ^. permissions) tid targetId targetPermissions
804802

805-
when (team ^. teamBinding == Binding) $ do
806-
(TeamSize size) <- E.getSize tid
807-
owners <- E.getBillingTeamMembers tid
808-
Journal.teamUpdate tid size owners
809-
810-
now <- input
811-
let event = newEvent tid now (EdMemberUpdate targetId (Just targetPermissions))
812-
let pushPriv = newPush ListComplete mZusr (TeamEvent event) (map userRecipient admins')
813-
for_ pushPriv (\p -> E.push1 (p & pushConn .~ mZcon & pushTransient .~ True))
803+
updatedMembers <- getTeamMembersForFanout tid
804+
updateJournal team
805+
updatePeers mZusr targetId targetMember targetPermissions updatedMembers
806+
where
807+
updateJournal :: Team -> Sem r ()
808+
updateJournal team = do
809+
when (team ^. teamBinding == Binding) $ do
810+
(TeamSize size) <- E.getSize tid
811+
owners <- E.getBillingTeamMembers tid
812+
Journal.teamUpdate tid size owners
813+
814+
updatePeers :: Maybe UserId -> UserId -> TeamMember -> Permissions -> TeamMemberList -> Sem r ()
815+
updatePeers zusr targetId targetMember targetPermissions updatedMembers = do
816+
-- inform members of the team about the change
817+
-- some (privileged) users will be informed about which change was applied
818+
let privileged = filter (`canSeePermsOf` targetMember) (updatedMembers ^. teamMembers)
819+
mkUpdate = EdMemberUpdate targetId
820+
privilegedUpdate = mkUpdate $ Just targetPermissions
821+
privilegedRecipients = membersToRecipients Nothing privileged
822+
now <- input
823+
let ePriv = newEvent tid now privilegedUpdate
824+
-- push to all members (user is privileged)
825+
let pushPriv = newPush (updatedMembers ^. teamMemberListType) zusr (TeamEvent ePriv) $ privilegedRecipients
826+
for_ pushPriv (\p -> E.push1 (p & pushConn .~ mZcon))
814827

815828
updateTeamMember ::
816829
forall r.
@@ -819,7 +832,6 @@ updateTeamMember ::
819832
Member (ErrorS 'InvalidPermissions) r,
820833
Member (ErrorS 'TeamNotFound) r,
821834
Member (ErrorS 'TeamMemberNotFound) r,
822-
Member (ErrorS 'TooManyTeamAdmins) r,
823835
Member (ErrorS 'NotATeamMember) r,
824836
Member (ErrorS OperationDenied) r,
825837
Member GundeckAccess r,
@@ -950,6 +962,7 @@ deleteTeamMember' lusr zcon tid remove mBody = do
950962
tm <- noteS @'TeamMemberNotFound targetMember
951963
unless (canDeleteMember dm tm) $ throwS @'AccessDenied
952964
team <- fmap tdTeam $ E.getTeam tid >>= noteS @'TeamNotFound
965+
mems <- getTeamMembersForFanout tid
953966
if team ^. teamBinding == Binding && isJust targetMember
954967
then do
955968
body <- mBody & note (InvalidPayload "missing request body")
@@ -967,8 +980,7 @@ deleteTeamMember' lusr zcon tid remove mBody = do
967980
Journal.teamUpdate tid sizeAfterDelete $ filter (/= remove) owners
968981
pure TeamMemberDeleteAccepted
969982
else do
970-
admins <- E.getTeamAdmins tid
971-
uncheckedDeleteTeamMember lusr (Just zcon) tid remove admins
983+
uncheckedDeleteTeamMember lusr (Just zcon) tid remove mems
972984
pure TeamMemberDeleteCompleted
973985

974986
-- This function is "unchecked" because it does not validate that the user has the `RemoveTeamMember` permission.
@@ -985,43 +997,47 @@ uncheckedDeleteTeamMember ::
985997
Maybe ConnId ->
986998
TeamId ->
987999
UserId ->
988-
[UserId] ->
1000+
TeamMemberList ->
9891001
Sem r ()
990-
uncheckedDeleteTeamMember lusr zcon tid remove admins = do
1002+
uncheckedDeleteTeamMember lusr zcon tid remove mems = do
9911003
now <- input
9921004
pushMemberLeaveEvent now
9931005
E.deleteTeamMember tid remove
9941006
removeFromConvsAndPushConvLeaveEvent now
9951007
where
996-
-- notify team admins
1008+
-- notify all team members.
9971009
pushMemberLeaveEvent :: UTCTime -> Sem r ()
9981010
pushMemberLeaveEvent now = do
9991011
let e = newEvent tid now (EdMemberLeave remove)
10001012
let r =
1001-
userRecipient
1002-
<$> list1
1003-
(tUnqualified lusr)
1004-
(filter (/= (tUnqualified lusr)) admins)
1013+
list1
1014+
(userRecipient (tUnqualified lusr))
1015+
(membersToRecipients (Just (tUnqualified lusr)) (mems ^. teamMembers))
10051016
E.push1 $
1006-
newPushLocal1 ListComplete (tUnqualified lusr) (TeamEvent e) r & pushConn .~ zcon & pushTransient .~ True
1017+
newPushLocal1 (mems ^. teamMemberListType) (tUnqualified lusr) (TeamEvent e) r & pushConn .~ zcon
10071018
-- notify all conversation members not in this team.
10081019
removeFromConvsAndPushConvLeaveEvent :: UTCTime -> Sem r ()
10091020
removeFromConvsAndPushConvLeaveEvent now = do
1010-
let tmids = Set.fromList admins
1021+
-- This may not make sense if that list has been truncated. In such cases, we still want to
1022+
-- remove the user from conversations but never send out any events. We assume that clients
1023+
-- handle nicely these missing events, regardless of whether they are in the same team or not
1024+
let tmids = Set.fromList $ map (view userId) (mems ^. teamMembers)
10111025
let edata = Conv.EdMembersLeave (Conv.QualifiedUserIdList [tUntagged (qualifyAs lusr remove)])
10121026
cc <- E.getTeamConversations tid
10131027
for_ cc $ \c ->
10141028
E.getConversation (c ^. conversationId) >>= \conv ->
10151029
for_ conv $ \dc -> when (remove `isMember` Data.convLocalMembers dc) $ do
10161030
E.deleteMembers (c ^. conversationId) (UserList [remove] [])
1017-
pushEvent tmids edata now dc
1031+
-- If the list was truncated, then the tmids list is incomplete so we simply drop these events
1032+
unless (mems ^. teamMemberListType == ListTruncated) $
1033+
pushEvent tmids edata now dc
10181034
pushEvent :: Set UserId -> Conv.EventData -> UTCTime -> Data.Conversation -> Sem r ()
10191035
pushEvent exceptTo edata now dc = do
10201036
let qconvId = tUntagged $ qualifyAs lusr (Data.convId dc)
10211037
let (bots, users) = localBotsAndUsers (Data.convLocalMembers dc)
10221038
let x = filter (\m -> not (Conv.lmId m `Set.member` exceptTo)) users
10231039
let y = Conv.Event qconvId Nothing (tUntagged lusr) now edata
1024-
for_ (newPushLocal ListComplete (tUnqualified lusr) (ConvEvent y) (recipient <$> x)) $ \p ->
1040+
for_ (newPushLocal (mems ^. teamMemberListType) (tUnqualified lusr) (ConvEvent y) (recipient <$> x)) $ \p ->
10251041
E.push1 $ p & pushConn .~ zcon
10261042
E.deliverAsync (bots `zip` repeat y)
10271043

@@ -1226,7 +1242,6 @@ ensureNotTooLargeForLegalHold tid teamSize =
12261242
addTeamMemberInternal ::
12271243
( Member BrigAccess r,
12281244
Member (ErrorS 'TooManyTeamMembers) r,
1229-
Member (ErrorS 'TooManyTeamAdmins) r,
12301245
Member GundeckAccess r,
12311246
Member (Input Opts) r,
12321247
Member (Input UTCTime) r,
@@ -1238,29 +1253,29 @@ addTeamMemberInternal ::
12381253
Maybe UserId ->
12391254
Maybe ConnId ->
12401255
NewTeamMember ->
1256+
TeamMemberList ->
12411257
Sem r TeamSize
1242-
addTeamMemberInternal tid origin originConn (ntmNewTeamMember -> new) = do
1258+
addTeamMemberInternal tid origin originConn (ntmNewTeamMember -> new) memList = do
12431259
P.debug $
12441260
Log.field "targets" (toByteString (new ^. userId))
12451261
. Log.field "action" (Log.val "Teams.addTeamMemberInternal")
12461262
sizeBeforeAdd <- ensureNotTooLarge tid
1247-
1248-
admins <- E.getTeamAdmins tid
1249-
let admins' = [new ^. userId | isAdminOrOwner (new ^. M.permissions)] <> admins
1250-
checkAdminLimit (length admins')
1251-
12521263
E.createTeamMember tid new
1253-
12541264
now <- input
12551265
let e = newEvent tid now (EdMemberJoin (new ^. userId))
1256-
let rs = case origin of
1257-
Just o -> userRecipient <$> list1 o (filter (/= o) ((new ^. userId) : admins'))
1258-
Nothing -> userRecipient <$> list1 (new ^. userId) (admins')
12591266
E.push1 $
1260-
newPushLocal1 ListComplete (new ^. userId) (TeamEvent e) rs & pushConn .~ originConn & pushTransient .~ True
1261-
1267+
newPushLocal1 (memList ^. teamMemberListType) (new ^. userId) (TeamEvent e) (recipients origin new) & pushConn .~ originConn
12621268
APITeamQueue.pushTeamEvent tid e
12631269
pure sizeBeforeAdd
1270+
where
1271+
recipients (Just o) n =
1272+
list1
1273+
(userRecipient o)
1274+
(membersToRecipients (Just o) (n : memList ^. teamMembers))
1275+
recipients Nothing n =
1276+
list1
1277+
(userRecipient (n ^. userId))
1278+
(membersToRecipients Nothing (memList ^. teamMembers))
12641279

12651280
finishCreateTeam ::
12661281
( Member GundeckAccess r,
@@ -1389,8 +1404,3 @@ queueTeamDeletion ::
13891404
queueTeamDeletion tid zusr zcon = do
13901405
ok <- E.tryPush (TeamItem tid zusr zcon)
13911406
unless ok $ throwS @'DeleteQueueFull
1392-
1393-
checkAdminLimit :: Member (ErrorS 'TooManyTeamAdmins) r => Int -> Sem r ()
1394-
checkAdminLimit adminCount =
1395-
when (adminCount > 2000) $
1396-
throwS @'TooManyTeamAdmins

services/galley/src/Galley/Cassandra.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ module Galley.Cassandra (schemaVersion) where
2020
import Imports
2121

2222
schemaVersion :: Int32
23-
schemaVersion = 83
23+
schemaVersion = 81

services/galley/src/Galley/Cassandra/Queries.hs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,6 @@ deleteBillingTeamMember = "delete from billing_team_member where team = ? and us
167167
listBillingTeamMembers :: PrepQuery R (Identity TeamId) (Identity UserId)
168168
listBillingTeamMembers = "select user from billing_team_member where team = ?"
169169

170-
insertTeamAdmin :: PrepQuery W (TeamId, UserId) ()
171-
insertTeamAdmin = "insert into team_admin (team, user) values (?, ?)"
172-
173-
deleteTeamAdmin :: PrepQuery W (TeamId, UserId) ()
174-
deleteTeamAdmin = "delete from team_admin where team = ? and user = ?"
175-
176-
listTeamAdmins :: PrepQuery R (Identity TeamId) (Identity UserId)
177-
listTeamAdmins = "select user from team_admin where team = ?"
178-
179170
updatePermissions :: PrepQuery W (Permissions, TeamId, UserId) ()
180171
updatePermissions = "update team_member set perms = ? where team = ? and user = ?"
181172

0 commit comments

Comments
 (0)