diff --git a/api4/team_test.go b/api4/team_test.go index c1eef6e6ac..4ffe1db335 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -2632,6 +2632,51 @@ func TestRemoveTeamMember(t *testing.T) { require.NoError(t, err) } +func TestRemoveTeamMemberEvents(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + client1 := th.CreateClient() + th.LoginBasicWithClient(client1) + WebSocketClient, err := th.CreateWebSocketClientWithClient(client1) + require.NoError(t, err) + defer WebSocketClient.Close() + WebSocketClient.Listen() + resp := <-WebSocketClient.ResponseChannel + require.Equal(t, resp.Status, model.StatusOk) + + client2 := th.CreateClient() + th.LoginBasic2WithClient(client2) + WebSocketClient2, err := th.CreateWebSocketClientWithClient(client2) + require.NoError(t, err) + defer WebSocketClient2.Close() + WebSocketClient2.Listen() + resp = <-WebSocketClient2.ResponseChannel + require.Equal(t, resp.Status, model.StatusOk) + + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + // remove second user from basic team + _, err := client.RemoveTeamMember(th.BasicTeam.Id, th.BasicUser2.Id) + require.NoError(t, err) + + assertExpectedWebsocketEvent(t, WebSocketClient, model.WebsocketEventLeaveTeam, func(event *model.WebSocketEvent) { + eventUserId, ok := event.GetData()["user_id"].(string) + require.True(t, ok, "expected user") + // assert eventUser.Id is same as th.BasicUser.Id + assert.Equal(t, eventUserId, th.BasicUser2.Id) + // assert this event doesn't go to event creator + assert.Equal(t, event.GetBroadcast().OmitUsers[eventUserId], true) + }) + assertExpectedWebsocketEvent(t, WebSocketClient2, model.WebsocketEventLeaveTeam, func(event *model.WebSocketEvent) { + eventUserId, ok := event.GetData()["user_id"].(string) + require.True(t, ok, "expected user") + // assert eventUser.Id is same as th.BasicUser.Id + assert.Equal(t, eventUserId, th.BasicUser2.Id) + }) + }) + +} + func TestGetTeamStats(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() diff --git a/app/teams/teams.go b/app/teams/teams.go index 9b6db445b3..fb0143b35a 100644 --- a/app/teams/teams.go +++ b/app/teams/teams.go @@ -191,11 +191,25 @@ func (ts *TeamService) JoinUserToTeam(team *model.Team, user *model.User) (*mode // RemoveTeamMember removes the team member from the team. This method sends // the websocket message before actually removing so the user being removed gets it. func (ts *TeamService) RemoveTeamMember(teamMember *model.TeamMember) error { - message := model.NewWebSocketEvent(model.WebsocketEventLeaveTeam, teamMember.TeamId, "", "", nil, "") - message.Add("user_id", teamMember.UserId) - message.Add("team_id", teamMember.TeamId) - ts.wh.Publish(message) + /* + MM-43850: send leave_team event to user using `ReliableClusterSend` to improve safety + */ + // message for other team members + omitUsers := make(map[string]bool, 1) + omitUsers[teamMember.UserId] = true + messageTeam := model.NewWebSocketEvent(model.WebsocketEventLeaveTeam, teamMember.TeamId, "", "", omitUsers, "") + messageTeam.Add("user_id", teamMember.UserId) + messageTeam.Add("team_id", teamMember.TeamId) + ts.wh.Publish(messageTeam) + // message for teamMember.UserId + messageUser := model.NewWebSocketEvent(model.WebsocketEventLeaveTeam, "", "", teamMember.UserId, nil, "") + messageUser.Add("user_id", teamMember.UserId) + messageUser.Add("team_id", teamMember.TeamId) + + ts.wh.Publish(messageUser) + + // delete team member teamMember.Roles = "" teamMember.DeleteAt = model.GetMillis()