diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/channel.go | 64 | ||||
-rw-r--r-- | app/channel_test.go | 206 |
2 files changed, 270 insertions, 0 deletions
diff --git a/app/channel.go b/app/channel.go index 7394d813b..eee27a6de 100644 --- a/app/channel.go +++ b/app/channel.go @@ -1591,3 +1591,67 @@ func (a *App) ToggleMuteChannel(channelId string, userId string) *model.ChannelM a.Srv.Store.Channel().UpdateMember(member) return member } + +func (a *App) FillInChannelProps(channel *model.Channel) *model.AppError { + return a.FillInChannelsProps(&model.ChannelList{channel}) +} + +func (a *App) FillInChannelsProps(channelList *model.ChannelList) *model.AppError { + // Group the channels by team and call GetChannelsByNames just once per team. + channelsByTeam := make(map[string]model.ChannelList) + for _, channel := range *channelList { + channelsByTeam[channel.TeamId] = append(channelsByTeam[channel.TeamId], channel) + } + + for teamId, channelList := range channelsByTeam { + allChannelMentions := make(map[string]bool) + channelMentions := make(map[*model.Channel][]string, len(channelList)) + + // Collect mentions across the channels so as to query just once for this team. + for _, channel := range channelList { + channelMentions[channel] = model.ChannelMentions(channel.Header) + + for _, channelMention := range channelMentions[channel] { + allChannelMentions[channelMention] = true + } + } + + allChannelMentionNames := make([]string, 0, len(allChannelMentions)) + for channelName := range allChannelMentions { + allChannelMentionNames = append(allChannelMentionNames, channelName) + } + + if len(allChannelMentionNames) > 0 { + mentionedChannels, err := a.GetChannelsByNames(allChannelMentionNames, teamId) + if err != nil { + return err + } + + mentionedChannelsByName := make(map[string]*model.Channel) + for _, channel := range mentionedChannels { + mentionedChannelsByName[channel.Name] = channel + } + + for _, channel := range channelList { + channelMentionsProp := make(map[string]interface{}, len(channelMentions[channel])) + for _, channelMention := range channelMentions[channel] { + if mentioned, ok := mentionedChannelsByName[channelMention]; ok { + if mentioned.Type == model.CHANNEL_OPEN { + channelMentionsProp[mentioned.Name] = map[string]interface{}{ + "display_name": mentioned.DisplayName, + } + } + } + } + + if len(channelMentionsProp) > 0 { + channel.AddProp("channel_mentions", channelMentionsProp) + } else if channel.Props != nil { + delete(channel.Props, "channel_mentions") + } + } + } + } + + return nil +} diff --git a/app/channel_test.go b/app/channel_test.go index 336d9b25b..4e6aaaf52 100644 --- a/app/channel_test.go +++ b/app/channel_test.go @@ -9,6 +9,7 @@ import ( "github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/store" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestPermanentDeleteChannel(t *testing.T) { @@ -399,3 +400,208 @@ func TestAppUpdateChannelScheme(t *testing.T) { t.Fatal("Wrong Channel SchemeId") } } + +func TestFillInChannelProps(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + channelPublic1, err := th.App.CreateChannel(&model.Channel{DisplayName: "Public 1", Name: "public1", Type: model.CHANNEL_OPEN, TeamId: th.BasicTeam.Id}, false) + require.Nil(t, err) + defer th.App.PermanentDeleteChannel(channelPublic1) + + channelPublic2, err := th.App.CreateChannel(&model.Channel{DisplayName: "Public 2", Name: "public2", Type: model.CHANNEL_OPEN, TeamId: th.BasicTeam.Id}, false) + require.Nil(t, err) + defer th.App.PermanentDeleteChannel(channelPublic2) + + channelPrivate, err := th.App.CreateChannel(&model.Channel{DisplayName: "Private", Name: "private", Type: model.CHANNEL_PRIVATE, TeamId: th.BasicTeam.Id}, false) + require.Nil(t, err) + defer th.App.PermanentDeleteChannel(channelPrivate) + + otherTeamId := model.NewId() + otherTeam := &model.Team{ + DisplayName: "dn_" + otherTeamId, + Name: "name" + otherTeamId, + Email: "success+" + otherTeamId + "@simulator.amazonses.com", + Type: model.TEAM_OPEN, + } + otherTeam, err = th.App.CreateTeam(otherTeam) + require.Nil(t, err) + defer th.App.PermanentDeleteTeam(otherTeam) + + channelOtherTeam, err := th.App.CreateChannel(&model.Channel{DisplayName: "Other Team Channel", Name: "other-team", Type: model.CHANNEL_OPEN, TeamId: otherTeam.Id}, false) + require.Nil(t, err) + defer th.App.PermanentDeleteChannel(channelOtherTeam) + + // Note that purpose is intentionally plaintext below. + + t.Run("single channels", func(t *testing.T) { + testCases := []struct { + Description string + Channel *model.Channel + ExpectedChannelProps map[string]interface{} + }{ + { + "channel on basic team without references", + &model.Channel{ + TeamId: th.BasicTeam.Id, + Header: "No references", + Purpose: "No references", + }, + nil, + }, + { + "channel on basic team", + &model.Channel{ + TeamId: th.BasicTeam.Id, + Header: "~public1, ~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "public1": map[string]interface{}{ + "display_name": "Public 1", + }, + }, + }, + }, + { + "channel on other team", + &model.Channel{ + TeamId: otherTeam.Id, + Header: "~public1, ~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "other-team": map[string]interface{}{ + "display_name": "Other Team Channel", + }, + }, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Description, func(t *testing.T) { + err = th.App.FillInChannelProps(testCase.Channel) + require.Nil(t, err) + + assert.Equal(t, testCase.ExpectedChannelProps, testCase.Channel.Props) + }) + } + }) + + t.Run("multiple channels", func(t *testing.T) { + testCases := []struct { + Description string + Channels *model.ChannelList + ExpectedChannelProps map[string]interface{} + }{ + { + "single channel on basic team", + &model.ChannelList{ + { + Name: "test", + TeamId: th.BasicTeam.Id, + Header: "~public1, ~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + }, + map[string]interface{}{ + "test": map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "public1": map[string]interface{}{ + "display_name": "Public 1", + }, + }, + }, + }, + }, + { + "multiple channels on basic team", + &model.ChannelList{ + { + Name: "test", + TeamId: th.BasicTeam.Id, + Header: "~public1, ~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + { + Name: "test2", + TeamId: th.BasicTeam.Id, + Header: "~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + { + Name: "test3", + TeamId: th.BasicTeam.Id, + Header: "No references", + Purpose: "No references", + }, + }, + map[string]interface{}{ + "test": map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "public1": map[string]interface{}{ + "display_name": "Public 1", + }, + }, + }, + "test2": map[string]interface{}(nil), + "test3": map[string]interface{}(nil), + }, + }, + { + "multiple channels across teams", + &model.ChannelList{ + { + Name: "test", + TeamId: th.BasicTeam.Id, + Header: "~public1, ~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + { + Name: "test2", + TeamId: otherTeam.Id, + Header: "~private, ~other-team", + Purpose: "~public2, ~private, ~other-team", + }, + { + Name: "test3", + TeamId: th.BasicTeam.Id, + Header: "No references", + Purpose: "No references", + }, + }, + map[string]interface{}{ + "test": map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "public1": map[string]interface{}{ + "display_name": "Public 1", + }, + }, + }, + "test2": map[string]interface{}{ + "channel_mentions": map[string]interface{}{ + "other-team": map[string]interface{}{ + "display_name": "Other Team Channel", + }, + }, + }, + "test3": map[string]interface{}(nil), + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Description, func(t *testing.T) { + err = th.App.FillInChannelsProps(testCase.Channels) + require.Nil(t, err) + + for _, channel := range *testCase.Channels { + assert.Equal(t, testCase.ExpectedChannelProps[channel.Name], channel.Props) + } + }) + } + }) +} |