[MM-18946] [MM-26721] [MM-6842] Cross team search+private channel autocomplete (#18468)

* Show private channels in autocomplete

This is supported in all Engines:
MySQL, Postgres, Bleve, Elasticsearch.

https://mattermost.atlassian.net/browse/MM-18496

```release-note
Private channels will now appear in channel autocomplete.
If you are using Bleve or ElasticSearch, you will have to reindex
the channels again to populate them with the new attributes.
```

A large chunk of this work has been based on the earlier
effort at https://github.com/mattermost/mattermost-server/pull/17804.

Full credit goes to https://github.com/arvinDarmawan.

* Add comment

```release-note
NONE
```

* Adding more tests

```release-note
NONE
```

* fix more tests

```release-note
NONE
```

* tmp

```release-note
NONE
```

* more fixes

```release-note
NONE
```

* add tests

```release-note
NONE
```

* Add review comments from previous PR

```release-note
NONE
```

* Add API to return all channels from all team

```release-note
NONE
```

* Added support for bleve and ES

```release-note
NONE
```

* Streaming response for GetAllChannels

```release-note
NONE
```

* Fix tests

```release-note
NONE
```

* Trigger CI
```release-note
NONE
```

* fix tests

```release-note
NONE
```

* Addressing review comments

```release-note
NONE
```

* Fix lint

```release-note
NONE
```

* Removing flaky test

```release-note
NONE
```

* Address comments

```release-note
NONE
```

* Trigger CI
```release-note
NONE
```

* Added /users/<userid>/channel_members endpoint

```release-note
NONE
```

* Minor edit

```release-note
NONE
```

* Improve embedding

```release-note
NONE
```

* Fix lint error

```release-note
NONE
```

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Agniva De Sarker
2021-10-26 11:30:59 +05:30
коммит произвёл GitHub
родитель 971af6935c
Коммит e24f22745e
30 изменённых файлов: 1907 добавлений и 276 удалений

Просмотреть файл

@@ -570,7 +570,25 @@ func (s *OpenTracingLayerChannelStore) AnalyticsTypeCount(teamID string, channel
return result, err
}
func (s *OpenTracingLayerChannelStore) AutocompleteInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error) {
func (s *OpenTracingLayerChannelStore) Autocomplete(userID string, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.Autocomplete")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.Autocomplete(userID, term, includeDeleted)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) AutocompleteInTeam(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.AutocompleteInTeam")
s.Root.Store.SetContext(newCtx)
@@ -579,7 +597,7 @@ func (s *OpenTracingLayerChannelStore) AutocompleteInTeam(teamID string, term st
}()
defer span.Finish()
result, err := s.ChannelStore.AutocompleteInTeam(teamID, term, includeDeleted)
result, err := s.ChannelStore.AutocompleteInTeam(teamID, userID, term, includeDeleted)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
@@ -817,6 +835,24 @@ func (s *OpenTracingLayerChannelStore) GetAll(teamID string) ([]*model.Channel,
return result, err
}
func (s *OpenTracingLayerChannelStore) GetAllChannelMembersById(id string) ([]string, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetAllChannelMembersById")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetAllChannelMembersById(id)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetAllChannelMembersForUser(userID string, allowFromCache bool, includeDeleted bool) (map[string]string, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetAllChannelMembersForUser")
@@ -1123,6 +1159,42 @@ func (s *OpenTracingLayerChannelStore) GetChannelsByScheme(schemeID string, offs
return result, err
}
func (s *OpenTracingLayerChannelStore) GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt int, pageSize int, fromChannelID string) (model.ChannelList, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsByUser")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetChannelsByUser(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsWithTeamDataByIds")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetChannelsWithTeamDataByIds(channelIds, includeDeleted)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetDeleted")
@@ -1370,7 +1442,7 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUser(teamID string, userID s
return result, err
}
func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(teamID string, userID string, page int, perPage int) (model.ChannelMembers, error) {
func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersForUserWithPagination")
s.Root.Store.SetContext(newCtx)
@@ -1379,7 +1451,7 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(teamID st
}()
defer span.Finish()
result, err := s.ChannelStore.GetMembersForUserWithPagination(teamID, userID, page, perPage)
result, err := s.ChannelStore.GetMembersForUserWithPagination(userID, page, perPage)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
@@ -1586,6 +1658,24 @@ func (s *OpenTracingLayerChannelStore) GetTeamForChannel(channelID string) (*mod
return result, err
}
func (s *OpenTracingLayerChannelStore) GetTeamMembersForChannel(channelID string) ([]string, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetTeamMembersForChannel")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.ChannelStore.GetTeamMembersForChannel(channelID)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerChannelStore) GroupSyncedChannelCount() (int64, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GroupSyncedChannelCount")

Просмотреть файл

@@ -608,11 +608,31 @@ func (s *RetryLayerChannelStore) AnalyticsTypeCount(teamID string, channelType m
}
func (s *RetryLayerChannelStore) AutocompleteInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error) {
func (s *RetryLayerChannelStore) Autocomplete(userID string, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
tries := 0
for {
result, err := s.ChannelStore.AutocompleteInTeam(teamID, term, includeDeleted)
result, err := s.ChannelStore.Autocomplete(userID, term, includeDeleted)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerChannelStore) AutocompleteInTeam(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error) {
tries := 0
for {
result, err := s.ChannelStore.AutocompleteInTeam(teamID, userID, term, includeDeleted)
if err == nil {
return result, nil
}
@@ -874,6 +894,26 @@ func (s *RetryLayerChannelStore) GetAll(teamID string) ([]*model.Channel, error)
}
func (s *RetryLayerChannelStore) GetAllChannelMembersById(id string) ([]string, error) {
tries := 0
for {
result, err := s.ChannelStore.GetAllChannelMembersById(id)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerChannelStore) GetAllChannelMembersForUser(userID string, allowFromCache bool, includeDeleted bool) (map[string]string, error) {
tries := 0
@@ -1214,6 +1254,46 @@ func (s *RetryLayerChannelStore) GetChannelsByScheme(schemeID string, offset int
}
func (s *RetryLayerChannelStore) GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt int, pageSize int, fromChannelID string) (model.ChannelList, error) {
tries := 0
for {
result, err := s.ChannelStore.GetChannelsByUser(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
tries := 0
for {
result, err := s.ChannelStore.GetChannelsWithTeamDataByIds(channelIds, includeDeleted)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerChannelStore) GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error) {
tries := 0
@@ -1480,11 +1560,11 @@ func (s *RetryLayerChannelStore) GetMembersForUser(teamID string, userID string)
}
func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(teamID string, userID string, page int, perPage int) (model.ChannelMembers, error) {
func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
tries := 0
for {
result, err := s.ChannelStore.GetMembersForUserWithPagination(teamID, userID, page, perPage)
result, err := s.ChannelStore.GetMembersForUserWithPagination(userID, page, perPage)
if err == nil {
return result, nil
}
@@ -1720,6 +1800,26 @@ func (s *RetryLayerChannelStore) GetTeamForChannel(channelID string) (*model.Tea
}
func (s *RetryLayerChannelStore) GetTeamMembersForChannel(channelID string) ([]string, error) {
tries := 0
for {
result, err := s.ChannelStore.GetTeamMembersForChannel(channelID)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerChannelStore) GroupSyncedChannelCount() (int64, error) {
tries := 0

Просмотреть файл

@@ -36,17 +36,31 @@ func (c *SearchChannelStore) deleteChannelIndex(channel *model.Channel) {
}
func (c *SearchChannelStore) indexChannel(channel *model.Channel) {
if channel.Type == model.ChannelTypeOpen {
for _, engine := range c.rootStore.searchEngine.GetActiveEngines() {
if engine.IsIndexingEnabled() {
runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) {
if err := engineCopy.IndexChannel(channel); err != nil {
mlog.Warn("Encountered error indexing channel", mlog.String("channel_id", channel.Id), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err))
return
}
mlog.Debug("Indexed channel in search engine", mlog.String("search_engine", engineCopy.GetName()), mlog.String("channel_id", channel.Id))
})
}
var userIDs, teamMemberIDs []string
var err error
if channel.Type == model.ChannelTypePrivate {
userIDs, err = c.GetAllChannelMembersById(channel.Id)
if err != nil {
mlog.Warn("Encountered error while indexing channel", mlog.String("channel_id", channel.Id), mlog.Err(err))
return
}
}
teamMemberIDs, err = c.GetTeamMembersForChannel(channel.Id)
if err != nil {
mlog.Warn("Encountered error while indexing channel", mlog.String("channel_id", channel.Id), mlog.Err(err))
return
}
for _, engine := range c.rootStore.searchEngine.GetActiveEngines() {
if engine.IsIndexingEnabled() {
runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) {
if err := engineCopy.IndexChannel(channel, userIDs, teamMemberIDs); err != nil {
mlog.Warn("Encountered error indexing channel", mlog.String("channel_id", channel.Id), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err))
return
}
mlog.Debug("Indexed channel in search engine", mlog.String("search_engine", engineCopy.GetName()), mlog.String("channel_id", channel.Id))
})
}
}
}
@@ -75,6 +89,7 @@ func (c *SearchChannelStore) UpdateMember(cm *model.ChannelMember) (*model.Chann
if channelErr != nil {
mlog.Warn("Encountered error indexing user in channel", mlog.String("channel_id", member.ChannelId), mlog.Err(channelErr))
} else {
c.indexChannel(channel)
c.rootStore.indexUserFromID(channel.CreatorId)
}
}
@@ -89,25 +104,37 @@ func (c *SearchChannelStore) SaveMember(cm *model.ChannelMember) (*model.Channel
if channelErr != nil {
mlog.Warn("Encountered error indexing user in channel", mlog.String("channel_id", member.ChannelId), mlog.Err(channelErr))
} else {
c.indexChannel(channel)
c.rootStore.indexUserFromID(channel.CreatorId)
}
}
return member, err
}
func (c *SearchChannelStore) RemoveMember(channelId, userIdToRemove string) error {
err := c.ChannelStore.RemoveMember(channelId, userIdToRemove)
func (c *SearchChannelStore) RemoveMember(channelID, userIdToRemove string) error {
err := c.ChannelStore.RemoveMember(channelID, userIdToRemove)
if err == nil {
c.rootStore.indexUserFromID(userIdToRemove)
}
channel, err := c.ChannelStore.Get(channelID, true)
if err == nil {
c.indexChannel(channel)
}
return err
}
func (c *SearchChannelStore) RemoveMembers(channelId string, userIds []string) error {
if err := c.ChannelStore.RemoveMembers(channelId, userIds); err != nil {
func (c *SearchChannelStore) RemoveMembers(channelID string, userIds []string) error {
if err := c.ChannelStore.RemoveMembers(channelID, userIds); err != nil {
return err
}
channel, err := c.ChannelStore.Get(channelID, true)
if err == nil {
c.indexChannel(channel)
}
for _, uid := range userIds {
c.rootStore.indexUserFromID(uid)
}
@@ -119,27 +146,29 @@ func (c *SearchChannelStore) CreateDirectChannel(user *model.User, otherUser *mo
if err == nil {
c.rootStore.indexUserFromID(user.Id)
c.rootStore.indexUserFromID(otherUser.Id)
c.indexChannel(channel)
}
return channel, err
}
func (c *SearchChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) (*model.Channel, error) {
channel, err := c.ChannelStore.SaveDirectChannel(directchannel, member1, member2)
if err != nil {
if err == nil {
c.rootStore.indexUserFromID(member1.UserId)
c.rootStore.indexUserFromID(member2.UserId)
c.indexChannel(channel)
}
return channel, err
}
func (c *SearchChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) (model.ChannelList, error) {
var channelList model.ChannelList
func (c *SearchChannelStore) Autocomplete(userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
var channelList model.ChannelListWithTeamData
var err error
allFailed := true
for _, engine := range c.rootStore.searchEngine.GetActiveEngines() {
if engine.IsAutocompletionEnabled() {
channelList, err = c.searchAutocompleteChannels(engine, teamId, term, includeDeleted)
channelList, err = c.searchAutocompleteChannelsAllTeams(engine, userID, term, includeDeleted)
if err != nil {
mlog.Warn("Encountered error on AutocompleteChannels through SearchEngine. Falling back to default autocompletion.", mlog.String("search_engine", engine.GetName()), mlog.Err(err))
continue
@@ -152,7 +181,7 @@ func (c *SearchChannelStore) AutocompleteInTeam(teamId string, term string, incl
if allFailed {
mlog.Debug("Using database search because no other search engine is available")
channelList, err = c.ChannelStore.AutocompleteInTeam(teamId, term, includeDeleted)
channelList, err = c.ChannelStore.Autocomplete(userID, term, includeDeleted)
if err != nil {
return nil, errors.Wrap(err, "Failed to autocomplete channels in team")
}
@@ -165,21 +194,69 @@ func (c *SearchChannelStore) AutocompleteInTeam(teamId string, term string, incl
return channelList, nil
}
func (c *SearchChannelStore) searchAutocompleteChannels(engine searchengine.SearchEngineInterface, teamId, term string, includeDeleted bool) (model.ChannelList, error) {
channelIds, err := engine.SearchChannels(teamId, term)
func (c *SearchChannelStore) AutocompleteInTeam(teamID, userID, term string, includeDeleted bool) (model.ChannelList, error) {
var channelList model.ChannelList
var err error
allFailed := true
for _, engine := range c.rootStore.searchEngine.GetActiveEngines() {
if engine.IsAutocompletionEnabled() {
channelList, err = c.searchAutocompleteChannels(engine, teamID, userID, term, includeDeleted)
if err != nil {
mlog.Warn("Encountered error on AutocompleteChannels through SearchEngine. Falling back to default autocompletion.", mlog.String("search_engine", engine.GetName()), mlog.Err(err))
continue
}
allFailed = false
mlog.Debug("Using the first available search engine", mlog.String("search_engine", engine.GetName()))
break
}
}
if allFailed {
mlog.Debug("Using database search because no other search engine is available")
channelList, err = c.ChannelStore.AutocompleteInTeam(teamID, userID, term, includeDeleted)
if err != nil {
return nil, errors.Wrap(err, "Failed to autocomplete channels in team")
}
}
if err != nil {
return channelList, err
}
return channelList, nil
}
func (c *SearchChannelStore) searchAutocompleteChannels(engine searchengine.SearchEngineInterface, teamId, userID, term string, includeDeleted bool) (model.ChannelList, error) {
channelIds, err := engine.SearchChannels(teamId, userID, term)
if err != nil {
return nil, err
}
channelList := model.ChannelList{}
var nErr error
if len(channelIds) > 0 {
channels, err := c.ChannelStore.GetChannelsByIds(channelIds, includeDeleted)
if err != nil {
return nil, errors.Wrap(err, "Failed to get channels by ids")
channelList, nErr = c.ChannelStore.GetChannelsByIds(channelIds, includeDeleted)
if nErr != nil {
return nil, errors.Wrap(nErr, "Failed to get channels by ids")
}
}
for _, ch := range channels {
channelList = append(channelList, ch)
return channelList, nil
}
func (c *SearchChannelStore) searchAutocompleteChannelsAllTeams(engine searchengine.SearchEngineInterface, userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
channelIds, err := engine.SearchChannels("", userID, term)
if err != nil {
return nil, err
}
channelList := model.ChannelListWithTeamData{}
var nErr error
if len(channelIds) > 0 {
channelList, nErr = c.ChannelStore.GetChannelsWithTeamDataByIds(channelIds, includeDeleted)
if nErr != nil {
return nil, errors.Wrap(nErr, "Failed to get channels by ids")
}
}
@@ -187,10 +264,21 @@ func (c *SearchChannelStore) searchAutocompleteChannels(engine searchengine.Sear
}
func (c *SearchChannelStore) PermanentDeleteMembersByUser(userId string) error {
channels, errGetChannels := c.ChannelStore.GetChannelsByUser(userId, false, 0, -1, "")
if errGetChannels != nil {
mlog.Warn("Encountered error indexing channel after removing user", mlog.String("user_id", userId), mlog.Err(errGetChannels))
}
err := c.ChannelStore.PermanentDeleteMembersByUser(userId)
if err == nil {
c.rootStore.indexUserFromID(userId)
if errGetChannels == nil {
for _, ch := range channels {
c.indexChannel(ch)
}
}
}
return err
}

Просмотреть файл

@@ -16,7 +16,12 @@ var searchChannelStoreTests = []searchTest{
{
Name: "Should be able to autocomplete a channel by name",
Fn: testAutocompleteChannelByName,
Tags: []string{EngineAll},
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a channel by name (Postgres)",
Fn: testAutocompleteChannelByNamePostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should be able to autocomplete a channel by display name",
@@ -26,7 +31,12 @@ var searchChannelStoreTests = []searchTest{
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character",
Fn: testAutocompleteChannelByNameSplittedWithDashChar,
Tags: []string{EngineAll},
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character (Postgres)",
Fn: testAutocompleteChannelByNameSplittedWithDashCharPostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by _ character",
@@ -46,12 +56,12 @@ var searchChannelStoreTests = []searchTest{
{
Name: "Should be able to autocomplete channels in a case insensitive manner",
Fn: testSearchChannelsInCaseInsensitiveManner,
Tags: []string{EngineAll},
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should autocomplete only returning public channels",
Fn: testSearchOnlyPublicChannels,
Tags: []string{EngineAll},
Name: "Should be able to autocomplete channels in a case insensitive manner (Postgres)",
Fn: testSearchChannelsInCaseInsensitiveMannerPostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should support to autocomplete having a hyphen as the last character",
@@ -76,94 +86,148 @@ func TestSearchChannelStore(t *testing.T, s store.Store, testEngine *SearchTestE
}
func testAutocompleteChannelByName(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel-a", false)
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "Channel AltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
defer th.deleteChannel(private)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-a", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
}
func testAutocompleteChannelByNamePostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testAutocompleteChannelByDisplayName(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "ChannelA", false)
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "ChannelAltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
defer th.deleteChannel(private)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChannelA", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "ChannelA", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
}
func testAutocompleteChannelByNameSplittedWithDashChar(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel-a", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
}
func testAutocompleteChannelByNameSplittedWithUnderscoreChar(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel_alternate", "ChannelAlternate", "", model.ChannelTypeOpen, false)
func testAutocompleteChannelByNameSplittedWithDashCharPostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel_a", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testAutocompleteChannelByNameSplittedWithUnderscoreChar(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel_alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel_a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel_a", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{alternate.Id}, res2)
}
func testAutocompleteChannelByDisplayNameSplittedByWhitespaces(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "Channel A", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "Channel A", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
}
func testAutocompleteAllChannelsIfTermIsEmpty(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
other, err := th.createChannel(th.Team.Id, "other-channel", "Other Channel", "", model.ChannelTypeOpen, false)
other, err := th.createChannel(th.Team.Id, "other-channel", "Other Channel", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
defer th.deleteChannel(other)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, other.Id}, res)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id, other.Id}, res)
}
func testSearchChannelsInCaseInsensitiveManner(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channela", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, "ChAnNeL-a", false)
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channela", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
res2, err = th.Store.Channel().Autocomplete(th.User.Id, "ChAnNeL-a", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
}
func testSearchOnlyPublicChannels(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypePrivate, false)
func testSearchChannelsInCaseInsensitiveMannerPostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel-a", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id}, res)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testSearchShouldSupportHavingHyphenAsLastCharacter(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, false)
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel-", false)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-", false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res2)
}
func testSearchShouldSupportAutocompleteWithArchivedChannels(t *testing.T, th *SearchTestHelper) {
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, "channel-", true)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", true)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelDeleted.Id}, res)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, th.ChannelDeleted.Id}, res)
}

Просмотреть файл

@@ -60,19 +60,19 @@ func (th *SearchTestHelper) SetupBasicFixtures() error {
}
// Create channels
channelBasic, err := th.createChannel(team.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, false)
channelBasic, err := th.createChannel(team.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
if err != nil {
return err
}
channelPrivate, err := th.createChannel(team.Id, "channel-private", "ChannelPrivate", "", model.ChannelTypePrivate, false)
channelPrivate, err := th.createChannel(team.Id, "channel-private", "ChannelPrivate", "", model.ChannelTypePrivate, nil, false)
if err != nil {
return err
}
channelDeleted, err := th.createChannel(team.Id, "channel-deleted", "ChannelA (deleted)", "", model.ChannelTypeOpen, true)
channelDeleted, err := th.createChannel(team.Id, "channel-deleted", "ChannelA (deleted)", "", model.ChannelTypeOpen, nil, true)
if err != nil {
return err
}
channelAnotherTeam, err := th.createChannel(anotherTeam.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, false)
channelAnotherTeam, err := th.createChannel(anotherTeam.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
if err != nil {
return err
}
@@ -239,7 +239,7 @@ func (th *SearchTestHelper) deleteBot(botID string) error {
return nil
}
func (th *SearchTestHelper) createChannel(teamID, name, displayName, purpose string, channelType model.ChannelType, deleted bool) (*model.Channel, error) {
func (th *SearchTestHelper) createChannel(teamID, name, displayName, purpose string, channelType model.ChannelType, user *model.User, deleted bool) (*model.Channel, error) {
channel, err := th.Store.Channel().Save(&model.Channel{
TeamId: teamID,
DisplayName: displayName,
@@ -251,6 +251,13 @@ func (th *SearchTestHelper) createChannel(teamID, name, displayName, purpose str
return nil, err
}
if user != nil {
err = th.addUserToChannels(user, []string{channel.Id})
if err != nil {
return nil, err
}
}
if deleted {
err := th.Store.Channel().Delete(channel.Id, model.GetMillis())
if err != nil {
@@ -474,6 +481,15 @@ func (th *SearchTestHelper) checkChannelIdsMatch(t *testing.T, expected []string
require.ElementsMatch(t, expected, channelIds)
}
func (th *SearchTestHelper) checkChannelIdsMatchWithTeamData(t *testing.T, expected []string, results model.ChannelListWithTeamData) {
t.Helper()
channelIds := make([]string, len(results))
for i, channel := range results {
channelIds[i] = channel.Id
}
require.ElementsMatch(t, expected, channelIds)
}
type ByChannelDisplayName model.ChannelList
func (s ByChannelDisplayName) Len() int { return len(s) }

Просмотреть файл

@@ -94,6 +94,15 @@ type channelMemberWithSchemeRoles struct {
MsgCountRoot int64
}
type channelMemberWithTeamWithSchemeRoles struct {
channelMemberWithSchemeRoles
TeamDisplayName string
TeamName string
TeamUpdateAt int64
}
type channelMemberWithTeamWithSchemeRolesList []channelMemberWithTeamWithSchemeRoles
func channelMemberSliceColumns() []string {
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MsgCountRoot", "MentionCount", "MentionCountRoot", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
}
@@ -250,6 +259,73 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
}
}
// This is almost an entire copy of the above method with team information added.
func (db channelMemberWithTeamWithSchemeRoles) ToModel() *model.ChannelMemberWithTeamData {
// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
// and exclude them from ExplicitRoles field.
schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
defaultTeamGuestRole := ""
if db.TeamSchemeDefaultGuestRole.Valid {
defaultTeamGuestRole = db.TeamSchemeDefaultGuestRole.String
}
defaultTeamUserRole := ""
if db.TeamSchemeDefaultUserRole.Valid {
defaultTeamUserRole = db.TeamSchemeDefaultUserRole.String
}
defaultTeamAdminRole := ""
if db.TeamSchemeDefaultAdminRole.Valid {
defaultTeamAdminRole = db.TeamSchemeDefaultAdminRole.String
}
defaultChannelGuestRole := ""
if db.ChannelSchemeDefaultGuestRole.Valid {
defaultChannelGuestRole = db.ChannelSchemeDefaultGuestRole.String
}
defaultChannelUserRole := ""
if db.ChannelSchemeDefaultUserRole.Valid {
defaultChannelUserRole = db.ChannelSchemeDefaultUserRole.String
}
defaultChannelAdminRole := ""
if db.ChannelSchemeDefaultAdminRole.Valid {
defaultChannelAdminRole = db.ChannelSchemeDefaultAdminRole.String
}
rolesResult := getChannelRoles(
schemeGuest, schemeUser, schemeAdmin,
defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole,
defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole,
strings.Fields(db.Roles),
)
return &model.ChannelMemberWithTeamData{
ChannelMember: model.ChannelMember{
ChannelId: db.ChannelId,
UserId: db.UserId,
Roles: strings.Join(rolesResult.roles, " "),
LastViewedAt: db.LastViewedAt,
MsgCount: db.MsgCount,
MsgCountRoot: db.MsgCountRoot,
MentionCount: db.MentionCount,
MentionCountRoot: db.MentionCountRoot,
NotifyProps: db.NotifyProps,
LastUpdateAt: db.LastUpdateAt,
SchemeAdmin: rolesResult.schemeAdmin,
SchemeUser: rolesResult.schemeUser,
SchemeGuest: rolesResult.schemeGuest,
ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
},
TeamName: db.TeamName,
TeamDisplayName: db.TeamDisplayName,
TeamUpdateAt: db.TeamUpdateAt,
}
}
func (db channelMemberWithSchemeRolesList) ToModel() model.ChannelMembers {
cms := model.ChannelMembers{}
@@ -260,6 +336,16 @@ func (db channelMemberWithSchemeRolesList) ToModel() model.ChannelMembers {
return cms
}
func (db channelMemberWithTeamWithSchemeRolesList) ToModel() model.ChannelMembersWithTeamData {
cms := model.ChannelMembersWithTeamData{}
for _, cm := range db {
cms = append(cms, *cm.ToModel())
}
return cms
}
type allChannelMember struct {
ChannelId string
Roles string
@@ -999,6 +1085,73 @@ func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDelete
return channels, nil
}
func (s SqlChannelStore) GetChannelsByUser(userId string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, error) {
query := s.getQueryBuilder().
Select("Channels.*").
From("Channels, ChannelMembers").
Where(
sq.And{
sq.Expr("Id = ChannelId"),
sq.Eq{"UserId": userId},
},
).
OrderBy("Id ASC")
if fromChannelID != "" {
query = query.Where(sq.Gt{"Id": fromChannelID})
}
if pageSize != -1 {
query = query.Limit(uint64(pageSize))
}
if includeDeleted {
if lastDeleteAt != 0 {
// We filter by non-archived, and archived >= a timestamp.
query = query.Where(sq.Or{
sq.Eq{"DeleteAt": 0},
sq.GtOrEq{"DeleteAt": lastDeleteAt},
})
}
// If lastDeleteAt is not set, we include everything. That means no filter is needed.
} else {
// Don't include archived channels.
query = query.Where(sq.Eq{"DeleteAt": 0})
}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrapf(err, "getchannels_tosql")
}
var channels model.ChannelList
_, err = s.GetReplica().Select(&channels, sql, args...)
if err != nil {
return nil, errors.Wrapf(err, "failed to get channels with UserId=%s", userId)
}
if len(channels) == 0 {
return nil, store.NewErrNotFound("Channel", "userId="+userId)
}
return channels, nil
}
func (s SqlChannelStore) GetAllChannelMembersById(channelID string) ([]string, error) {
var dbMembers channelMemberWithSchemeRolesList
_, err := s.GetReplica().Select(&dbMembers, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelID})
if err != nil {
return nil, errors.Wrapf(err, "failed to get ChannelMembers with channelID=%s", channelID)
}
res := make([]string, 0, len(dbMembers))
for _, member := range dbMembers.ToModel() {
res = append(res, member.UserId)
}
return res, nil
}
func (s SqlChannelStore) GetAllChannels(offset, limit int, opts store.ChannelSearchOpts) (model.ChannelListWithTeamData, error) {
query := s.getAllChannelsQuery(opts, false)
@@ -1397,7 +1550,7 @@ func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int, userId
return channels, nil
}
var ChannelMembersWithSchemeSelectQuery = `
var channelMembersForTeamWithSchemeSelectQuery = `
SELECT
ChannelMembers.*,
TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole,
@@ -1418,6 +1571,30 @@ var ChannelMembersWithSchemeSelectQuery = `
Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
`
var channelMembersWithSchemeSelectQuery = `
SELECT
ChannelMembers.*,
COALESCE(Teams.DisplayName, '') TeamDisplayName,
COALESCE(Teams.Name, '') TeamName,
COALESCE(Teams.UpdateAt, 0) TeamUpdateAt,
TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole,
TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole,
ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
FROM
ChannelMembers
INNER JOIN
Channels ON ChannelMembers.ChannelId = Channels.Id
LEFT JOIN
Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
LEFT JOIN
Teams ON Channels.TeamId = Teams.Id
LEFT JOIN
Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
`
func (s SqlChannelStore) SaveMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, error) {
for _, member := range members {
defer s.InvalidateAllChannelMembersForUser(member.UserId)
@@ -1613,7 +1790,7 @@ func (s SqlChannelStore) UpdateMultipleMembers(members []*model.ChannelMember) (
// TODO: Get this out of the transaction when is possible
var dbMember channelMemberWithSchemeRoles
if err := transaction.SelectOne(&dbMember, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
if err := transaction.SelectOne(&dbMember, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
if err == sql.ErrNoRows {
return nil, store.NewErrNotFound("ChannelMember", fmt.Sprintf("channelId=%s, userId=%s", member.ChannelId, member.UserId))
}
@@ -1668,7 +1845,7 @@ func (s SqlChannelStore) UpdateMemberNotifyProps(channelID, userID string, props
}
var dbMember channelMemberWithSchemeRoles
if err2 := tx.SelectOne(&dbMember, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelID, "UserId": userID}); err2 != nil {
if err2 := tx.SelectOne(&dbMember, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelID, "UserId": userID}); err2 != nil {
if err2 == sql.ErrNoRows {
return nil, store.NewErrNotFound("ChannelMember", fmt.Sprintf("channelId=%s, userId=%s", channelID, userID))
}
@@ -1684,7 +1861,7 @@ func (s SqlChannelStore) UpdateMemberNotifyProps(channelID, userID string, props
func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) (model.ChannelMembers, error) {
var dbMembers channelMemberWithSchemeRolesList
_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset})
_, err := s.GetReplica().Select(&dbMembers, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset})
if err != nil {
return nil, errors.Wrapf(err, "failed to get ChannelMembers with channelId=%s", channelId)
}
@@ -1714,7 +1891,7 @@ func (s SqlChannelStore) GetChannelMembersTimezones(channelId string) ([]model.S
func (s SqlChannelStore) GetMember(ctx context.Context, channelId string, userId string) (*model.ChannelMember, error) {
var dbMember channelMemberWithSchemeRoles
if err := s.DBFromContext(ctx).SelectOne(&dbMember, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
if err := s.DBFromContext(ctx).SelectOne(&dbMember, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
if err == sql.ErrNoRows {
return nil, store.NewErrNotFound("ChannelMember", fmt.Sprintf("channelId=%s, userId=%s", channelId, userId))
}
@@ -2397,6 +2574,34 @@ func (s SqlChannelStore) GetChannelsByIds(channelIds []string, includeDeleted bo
return channels, nil
}
func (s SqlChannelStore) GetChannelsWithTeamDataByIds(channelIDs []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
query := s.getQueryBuilder().
Select("c.*",
"COALESCE(t.DisplayName, '') As TeamDisplayName",
"COALESCE(t.Name, '') AS TeamName",
"COALESCE(t.UpdateAt, 0) AS TeamUpdateAt").
From("Channels c").
LeftJoin("Teams t ON c.TeamId = t.Id").
Where(sq.Eq{"c.Id": channelIDs}).
OrderBy("c.Name")
if !includeDeleted {
query = query.Where(sq.Eq{"c.DeleteAt": 0})
}
sql, args, err := query.ToSql()
if err != nil {
return nil, errors.Wrapf(err, "getChannelsWithTeamData_tosql")
}
var channels []*model.ChannelWithTeamData
_, err = s.GetReplica().Select(&channels, sql, args...)
if err != nil {
return nil, errors.Wrap(err, "failed to find Channels")
}
return channels, nil
}
func (s SqlChannelStore) GetForPost(postId string) (*model.Channel, error) {
channel := &model.Channel{}
if err := s.GetReplica().SelectOne(
@@ -2446,7 +2651,7 @@ func (s SqlChannelStore) AnalyticsDeletedTypeCount(teamId string, channelType st
func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (model.ChannelMembers, error) {
var dbMembers channelMemberWithSchemeRolesList
_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND (Teams.Id = :TeamId OR Teams.Id = '' OR Teams.Id IS NULL)", map[string]interface{}{"TeamId": teamId, "UserId": userId})
_, err := s.GetReplica().Select(&dbMembers, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND (Teams.Id = :TeamId OR Teams.Id = '' OR Teams.Id IS NULL)", map[string]interface{}{"TeamId": teamId, "UserId": userId})
if err != nil {
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with teamId=%s and userId=%s", teamId, userId)
}
@@ -2454,60 +2659,96 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (model.
return dbMembers.ToModel(), nil
}
func (s SqlChannelStore) GetMembersForUserWithPagination(teamId, userId string, page, perPage int) (model.ChannelMembers, error) {
var dbMembers channelMemberWithSchemeRolesList
func (s SqlChannelStore) GetMembersForUserWithPagination(userId string, page, perPage int) (model.ChannelMembersWithTeamData, error) {
var dbMembers channelMemberWithTeamWithSchemeRolesList
offset := page * perPage
_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"TeamId": teamId, "UserId": userId, "Limit": perPage, "Offset": offset})
_, err := s.GetReplica().Select(&dbMembers, channelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId ORDER BY ChannelId ASC Limit :Limit Offset :Offset", map[string]interface{}{"UserId": userId, "Limit": perPage, "Offset": offset})
if err != nil {
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with teamId=%s and userId=%s", teamId, userId)
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with and userId=%s", userId)
}
return dbMembers.ToModel(), nil
}
func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) (model.ChannelList, error) {
deleteFilter := "AND Channels.DeleteAt = 0"
func (s SqlChannelStore) GetTeamMembersForChannel(channelID string) ([]string, error) {
teamMemberIDs := []string{}
if err := s.GetReplicaX().Select(&teamMemberIDs, `SELECT tm.UserId
FROM Channels c, Teams t, TeamMembers tm
WHERE
c.TeamId=t.Id
AND
t.Id=tm.TeamId
AND
c.Id = ?`,
channelID); err != nil {
return nil, errors.Wrapf(err, "error while getting team members for a channel")
}
return teamMemberIDs, nil
}
func (s SqlChannelStore) Autocomplete(userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted {
deleteFilter = ""
}
queryFormat := `
SELECT
Channels.*
FROM
Channels
JOIN
PublicChannels c ON (c.Id = Channels.Id)
WHERE
Channels.TeamId = :TeamId
` + deleteFilter + `
%v
LIMIT ` + strconv.Itoa(model.ChannelSearchDefaultLimit)
return s.performGlobalSearch(`
SELECT
c.*, t.DisplayName AS TeamDisplayName, t.Name AS TeamName, t.UpdateAt AS TeamUpdateAt
FROM
Channels c, Teams t, TeamMembers tm
WHERE
c.TeamId=t.Id
AND
t.Id=tm.TeamId
AND
tm.UserId = :UserId
`+deleteFilter+`
SEARCH_CLAUSE
AND (
c.Type != 'P'
OR (
c.Type = 'P'
AND c.Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
)
)
ORDER BY c.DisplayName
`, term, map[string]interface{}{
"UserId": userID,
})
}
var channels model.ChannelList
if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
}
} else {
// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
// query you would get using an OR of the LIKE and full-text clauses.
fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
}
func (s SqlChannelStore) AutocompleteInTeam(teamID, userID, term string, includeDeleted bool) (model.ChannelList, error) {
deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted {
deleteFilter = ""
}
sort.Slice(channels, func(a, b int) bool {
return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
return s.performSearch(`
SELECT
*
FROM
Channels c
WHERE
c.TeamId = :TeamId
`+deleteFilter+`
SEARCH_CLAUSE
AND (
c.Type != 'P'
OR (
c.Type = 'P'
AND c.Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
)
)
ORDER BY c.DisplayName
LIMIT :Limit
`, term, map[string]interface{}{
"TeamId": teamID,
"UserId": userID,
"Limit": model.ChannelSearchDefaultLimit,
})
return channels, nil
}
func (s SqlChannelStore) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) (model.ChannelList, error) {
@@ -2959,6 +3200,27 @@ func (s SqlChannelStore) performSearch(searchQuery string, term string, paramete
return channels, nil
}
func (s SqlChannelStore) performGlobalSearch(searchQuery string, term string, parameters map[string]interface{}) (model.ChannelListWithTeamData, error) {
likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
if likeTerm == "" {
// If the likeTerm is empty after preparing, then don't bother searching.
searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
} else {
parameters["LikeTerm"] = likeTerm
fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
parameters["FulltextTerm"] = fulltextTerm
searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
}
var channels model.ChannelListWithTeamData
if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
}
return channels, nil
}
func (s SqlChannelStore) getSearchGroupChannelsQuery(userId, term string, isPostgreSQL bool) (string, map[string]interface{}) {
var query, baseLikeClause string
if isPostgreSQL {
@@ -3064,7 +3326,7 @@ func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) (mo
keys, props := MapStringsToQueryParams(userIds, "User")
props["ChannelId"] = channelId
if _, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN "+keys, props); err != nil {
if _, err := s.GetReplica().Select(&dbMembers, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN "+keys, props); err != nil {
return nil, errors.Wrapf(err, "failed to find ChannelMembers with channelId=%s and userId in %v", channelId, userIds)
}
@@ -3077,7 +3339,7 @@ func (s SqlChannelStore) GetMembersByChannelIds(channelIds []string, userId stri
keys, props := MapStringsToQueryParams(channelIds, "Channel")
props["UserId"] = userId
if _, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND ChannelMembers.ChannelId IN "+keys, props); err != nil {
if _, err := s.GetReplica().Select(&dbMembers, channelMembersForTeamWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND ChannelMembers.ChannelId IN "+keys, props); err != nil {
return nil, errors.Wrapf(err, "failed to find ChannelMembers with userId=%s and channelId in %v", userId, channelIds)
}
@@ -3367,8 +3629,6 @@ func (s SqlChannelStore) GetChannelsBatchForIndexing(startTime, endTime int64, l
FROM
Channels
WHERE
Type = 'O'
AND
CreateAt >= :StartTime
AND
CreateAt < :EndTime

Просмотреть файл

@@ -179,6 +179,8 @@ type ChannelStore interface {
GetDeletedByName(team_id string, name string) (*model.Channel, error)
GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error)
GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error)
GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, error)
GetAllChannelMembersById(id string) ([]string, error)
GetAllChannels(page, perPage int, opts ChannelSearchOpts) (model.ChannelListWithTeamData, error)
GetAllChannelsCount(opts ChannelSearchOpts) (int64, error)
GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error)
@@ -189,6 +191,7 @@ type ChannelStore interface {
GetTeamChannels(teamID string) (model.ChannelList, error)
GetAll(teamID string) ([]*model.Channel, error)
GetChannelsByIds(channelIds []string, includeDeleted bool) ([]*model.Channel, error)
GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error)
GetForPost(postID string) (*model.Channel, error)
SaveMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, error)
SaveMember(member *model.ChannelMember) (*model.ChannelMember, error)
@@ -225,8 +228,10 @@ type ChannelStore interface {
IncrementMentionCount(channelID string, userID string, updateThreads, isRoot bool) error
AnalyticsTypeCount(teamID string, channelType model.ChannelType) (int64, error)
GetMembersForUser(teamID string, userID string) (model.ChannelMembers, error)
GetMembersForUserWithPagination(teamID, userID string, page, perPage int) (model.ChannelMembers, error)
AutocompleteInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error)
GetTeamMembersForChannel(channelID string) ([]string, error)
GetMembersForUserWithPagination(userID string, page, perPage int) (model.ChannelMembersWithTeamData, error)
Autocomplete(userID, term string, includeDeleted bool) (model.ChannelListWithTeamData, error)
AutocompleteInTeam(teamID, userID, term string, includeDeleted bool) (model.ChannelList, error)
AutocompleteInTeamForSearch(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error)
SearchAllChannels(term string, opts ChannelSearchOpts) (model.ChannelListWithTeamData, int64, error)
SearchInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error)

Просмотреть файл

@@ -61,6 +61,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, ss) })
t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, ss, s) })
t.Run("GetChannelsByIds", func(t *testing.T) { testChannelStoreGetChannelsByIds(t, ss) })
t.Run("GetChannelsWithTeamDataByIds", func(t *testing.T) { testGetChannelsWithTeamDataByIds(t, ss) })
t.Run("GetForPost", func(t *testing.T) { testChannelStoreGetForPost(t, ss) })
t.Run("Restore", func(t *testing.T) { testChannelStoreRestore(t, ss) })
t.Run("Delete", func(t *testing.T) { testChannelStoreDelete(t, ss) })
@@ -78,6 +79,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("RemoveMembers", func(t *testing.T) { testChannelRemoveMembers(t, ss) })
t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) })
t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) })
t.Run("GetChannelsByUser", func(t *testing.T) { testChannelStoreGetChannelsByUser(t, ss) })
t.Run("GetAllChannels", func(t *testing.T) { testChannelStoreGetAllChannels(t, ss, s) })
t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) })
t.Run("GetPrivateChannelsForTeam", func(t *testing.T) { testChannelStoreGetPrivateChannelsForTeam(t, ss) })
@@ -97,6 +99,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("GetGuestCount", func(t *testing.T) { testGetGuestCount(t, ss) })
t.Run("SearchMore", func(t *testing.T) { testChannelStoreSearchMore(t, ss) })
t.Run("SearchInTeam", func(t *testing.T) { testChannelStoreSearchInTeam(t, ss) })
t.Run("Autocomplete", func(t *testing.T) { testAutocomplete(t, ss) })
t.Run("SearchArchivedInTeam", func(t *testing.T) { testChannelStoreSearchArchivedInTeam(t, ss, s) })
t.Run("SearchForUserInTeam", func(t *testing.T) { testChannelStoreSearchForUserInTeam(t, ss) })
t.Run("SearchAllChannels", func(t *testing.T) { testChannelStoreSearchAllChannels(t, ss) })
@@ -536,6 +539,81 @@ func testChannelStoreGetChannelsByIds(t *testing.T, ss store.Store) {
})
}
func testGetChannelsWithTeamDataByIds(t *testing.T, ss store.Store) {
t1 := &model.Team{
DisplayName: "DisplayName",
Name: NewTestId(),
Email: MakeEmail(),
Type: model.TeamOpen,
}
t1, err := ss.Team().Save(t1)
require.NoError(t, err, "couldn't save item")
c1 := model.Channel{}
c1.TeamId = t1.Id
c1.DisplayName = "Name"
c1.Name = "aa" + model.NewId()
c1.Type = model.ChannelTypeOpen
_, nErr := ss.Channel().Save(&c1, -1)
require.NoError(t, nErr)
u1 := &model.User{}
u1.Email = MakeEmail()
u1.Nickname = model.NewId()
_, err = ss.User().Save(u1)
require.NoError(t, err)
_, nErr = ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id}, -1)
require.NoError(t, nErr)
u2 := model.User{}
u2.Email = MakeEmail()
u2.Nickname = model.NewId()
_, err = ss.User().Save(&u2)
require.NoError(t, err)
_, nErr = ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id}, -1)
require.NoError(t, nErr)
c2 := model.Channel{}
c2.TeamId = t1.Id
c2.DisplayName = "Direct Name"
c2.Name = "bb" + model.NewId()
c2.Type = model.ChannelTypeDirect
c3 := model.Channel{}
c3.TeamId = t1.Id
c3.DisplayName = "Deleted channel"
c3.Name = "cc" + model.NewId()
c3.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&c3, -1)
require.NoError(t, nErr)
nErr = ss.Channel().Delete(c3.Id, 123)
require.NoError(t, nErr)
c3.DeleteAt = 123
c3.UpdateAt = 123
m1 := model.ChannelMember{}
m1.ChannelId = c2.Id
m1.UserId = u1.Id
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
m2 := model.ChannelMember{}
m2.ChannelId = c2.Id
m2.UserId = u2.Id
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
_, nErr = ss.Channel().SaveDirectChannel(&c2, &m1, &m2)
require.NoError(t, nErr)
res, err := ss.Channel().GetChannelsWithTeamDataByIds([]string{c1.Id, c2.Id}, false)
require.NoError(t, err)
require.Len(t, res, 2)
assert.Equal(t, res[0].Id, c1.Id)
assert.Equal(t, res[0].TeamName, t1.Name)
assert.Equal(t, res[1].Id, c2.Id)
assert.Equal(t, res[1].TeamName, "")
}
func testChannelStoreGetForPost(t *testing.T, ss store.Store) {
ch := &model.Channel{
@@ -3317,6 +3395,97 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId)
}
func testChannelStoreGetChannelsByUser(t *testing.T, ss store.Store) {
team := model.NewId()
team2 := model.NewId()
o1 := model.Channel{}
o1.TeamId = team
o1.DisplayName = "Channel1"
o1.Name = NewTestId()
o1.Type = model.ChannelTypeOpen
_, nErr := ss.Channel().Save(&o1, -1)
require.NoError(t, nErr)
o2 := model.Channel{}
o2.TeamId = team
o2.DisplayName = "Channel2"
o2.Name = NewTestId()
o2.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o2, -1)
require.NoError(t, nErr)
o3 := model.Channel{}
o3.TeamId = team2
o3.DisplayName = "Channel3"
o3.Name = NewTestId()
o3.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o3, -1)
require.NoError(t, nErr)
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err := ss.Channel().SaveMember(&m1)
require.NoError(t, err)
m2 := model.ChannelMember{}
m2.ChannelId = o1.Id
m2.UserId = model.NewId()
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m2)
require.NoError(t, err)
m3 := model.ChannelMember{}
m3.ChannelId = o2.Id
m3.UserId = m1.UserId
m3.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m3)
require.NoError(t, err)
m4 := model.ChannelMember{}
m4.ChannelId = o3.Id
m4.UserId = m1.UserId
m4.NotifyProps = model.GetDefaultChannelNotifyProps()
_, err = ss.Channel().SaveMember(&m4)
require.NoError(t, err)
list, nErr := ss.Channel().GetChannelsByUser(m1.UserId, false, 0, -1, "")
require.NoError(t, nErr)
require.Len(t, list, 3)
require.ElementsMatch(t, []string{o1.Id, o2.Id, o3.Id}, []string{list[0].Id, list[1].Id, list[2].Id}, "channels did not match")
nErr = ss.Channel().Delete(o2.Id, 10)
require.NoError(t, nErr)
nErr = ss.Channel().Delete(o3.Id, 20)
require.NoError(t, nErr)
// should return 1
list, nErr = ss.Channel().GetChannelsByUser(m1.UserId, false, 0, -1, "")
require.NoError(t, nErr)
require.Len(t, list, 1)
require.Equal(t, o1.Id, list[0].Id, "missing channel")
// Should return all
list, nErr = ss.Channel().GetChannelsByUser(m1.UserId, true, 0, -1, "")
require.NoError(t, nErr)
require.Len(t, list, 3)
require.ElementsMatch(t, []string{o1.Id, o2.Id, o3.Id}, []string{list[0].Id, list[1].Id, list[2].Id}, "channels did not match")
// Should still return all
list, nErr = ss.Channel().GetChannelsByUser(m1.UserId, true, 10, -1, "")
require.NoError(t, nErr)
require.Len(t, list, 3)
require.ElementsMatch(t, []string{o1.Id, o2.Id, o3.Id}, []string{list[0].Id, list[1].Id, list[2].Id}, "channels did not match")
// Should return 2
list, nErr = ss.Channel().GetChannelsByUser(m1.UserId, true, 20, -1, "")
require.NoError(t, nErr)
require.Len(t, list, 2)
require.ElementsMatch(t, []string{o1.Id, o3.Id}, []string{list[0].Id, list[1].Id}, "channels did not match")
}
func testChannelStoreGetAllChannels(t *testing.T, ss store.Store, s SqlStore) {
cleanupChannels(t, ss)
@@ -4019,29 +4188,41 @@ func testChannelStoreGetMembersForUser(t *testing.T, ss store.Store) {
}
func testChannelStoreGetMembersForUserWithPagination(t *testing.T, ss store.Store) {
t1 := model.Team{}
t1.DisplayName = "Name"
t1.Name = NewTestId()
t1.Email = MakeEmail()
t1.Type = model.TeamOpen
t1 := model.Team{
DisplayName: "team1",
Name: NewTestId(),
Email: MakeEmail(),
Type: model.TeamOpen,
}
_, err := ss.Team().Save(&t1)
require.NoError(t, err)
o1 := model.Channel{}
o1.TeamId = t1.Id
o1.DisplayName = "Channel1"
o1.Name = NewTestId()
o1.Type = model.ChannelTypeOpen
_, nErr := ss.Channel().Save(&o1, -1)
require.NoError(t, nErr)
o1 := model.Channel{
TeamId: t1.Id,
DisplayName: "Channel1",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
}
_, err = ss.Channel().Save(&o1, -1)
require.NoError(t, err)
o2 := model.Channel{}
o2.TeamId = o1.TeamId
o2.DisplayName = "Channel2"
o2.Name = NewTestId()
o2.Type = model.ChannelTypeOpen
_, nErr = ss.Channel().Save(&o2, -1)
require.NoError(t, nErr)
t2 := model.Team{
DisplayName: "team2",
Name: NewTestId(),
Email: MakeEmail(),
Type: model.TeamOpen,
}
_, err = ss.Team().Save(&t2)
require.NoError(t, err)
o2 := model.Channel{
TeamId: t2.Id,
DisplayName: "Channel2",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
}
_, err = ss.Channel().Save(&o2, -1)
require.NoError(t, err)
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
@@ -4057,11 +4238,16 @@ func testChannelStoreGetMembersForUserWithPagination(t *testing.T, ss store.Stor
_, err = ss.Channel().SaveMember(&m2)
require.NoError(t, err)
members, err := ss.Channel().GetMembersForUserWithPagination(o1.TeamId, m1.UserId, 0, 1)
members, err := ss.Channel().GetMembersForUserWithPagination(m1.UserId, 0, 2)
require.NoError(t, err)
assert.Len(t, members, 1)
assert.Len(t, members, 2)
teamNames := make([]string, 0, 2)
for _, member := range members {
teamNames = append(teamNames, member.TeamDisplayName)
}
assert.ElementsMatch(t, teamNames, []string{t1.DisplayName, t2.DisplayName})
members, err = ss.Channel().GetMembersForUserWithPagination(o1.TeamId, m1.UserId, 1, 1)
members, err = ss.Channel().GetMembersForUserWithPagination(m1.UserId, 1, 1)
require.NoError(t, err)
assert.Len(t, members, 1)
}
@@ -5065,11 +5251,11 @@ func testChannelStoreSearchArchivedInTeam(t *testing.T, ss store.Store, s SqlSto
}
func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
teamId := model.NewId()
otherTeamId := model.NewId()
teamID := model.NewId()
otherTeamID := model.NewId()
o1 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "ChannelA",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
@@ -5078,7 +5264,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o2 := model.Channel{
TeamId: otherTeamId,
TeamId: otherTeamID,
DisplayName: "ChannelA",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
@@ -5111,7 +5297,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, err)
o3 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "ChannelA (alternate)",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
@@ -5120,7 +5306,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o4 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Channel B",
Name: NewTestId(),
Type: model.ChannelTypePrivate,
@@ -5128,8 +5314,16 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
_, nErr = ss.Channel().Save(&o4, -1)
require.NoError(t, nErr)
m4 := &model.ChannelMember{
ChannelId: o4.Id,
UserId: m3.UserId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(m4)
require.NoError(t, err)
o5 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Channel C",
Name: NewTestId(),
Type: model.ChannelTypePrivate,
@@ -5138,7 +5332,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o6 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Off-Topic",
Name: "off-topic",
Type: model.ChannelTypeOpen,
@@ -5147,7 +5341,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o7 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Off-Set",
Name: "off-set",
Type: model.ChannelTypeOpen,
@@ -5156,7 +5350,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o8 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Off-Limit",
Name: "off-limit",
Type: model.ChannelTypePrivate,
@@ -5164,8 +5358,16 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
_, nErr = ss.Channel().Save(&o8, -1)
require.NoError(t, nErr)
m5 := &model.ChannelMember{
ChannelId: o8.Id,
UserId: model.NewId(),
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(m5)
require.NoError(t, err)
o9 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Town Square",
Name: "town-square",
Type: model.ChannelTypeOpen,
@@ -5174,7 +5376,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o10 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "The",
Name: "thename",
Type: model.ChannelTypeOpen,
@@ -5183,7 +5385,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o11 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "Native Mobile Apps",
Name: "native-mobile-apps",
Type: model.ChannelTypeOpen,
@@ -5192,7 +5394,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o12 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "ChannelZ",
Purpose: "This can now be searchable!",
Name: "with-purpose",
@@ -5202,7 +5404,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
require.NoError(t, nErr)
o13 := model.Channel{
TeamId: teamId,
TeamId: teamID,
DisplayName: "ChannelA (deleted)",
Name: model.NewId(),
Type: model.ChannelTypeOpen,
@@ -5216,42 +5418,199 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) {
testCases := []struct {
Description string
TeamId string
TeamID string
UserID string
Term string
IncludeDeleted bool
ExpectedResults model.ChannelList
}{
{"ChannelA", teamId, "ChannelA", false, model.ChannelList{&o1, &o3}},
{"ChannelA, include deleted", teamId, "ChannelA", true, model.ChannelList{&o1, &o3, &o13}},
{"ChannelA, other team", otherTeamId, "ChannelA", false, model.ChannelList{&o2}},
{"empty string", teamId, "", false, model.ChannelList{&o1, &o3, &o12, &o11, &o7, &o6, &o10, &o9}},
{"no matches", teamId, "blargh", false, model.ChannelList{}},
{"prefix", teamId, "off-", false, model.ChannelList{&o7, &o6}},
{"full match with dash", teamId, "off-topic", false, model.ChannelList{&o6}},
{"town square", teamId, "town square", false, model.ChannelList{&o9}},
{"the in name", teamId, "thename", false, model.ChannelList{&o10}},
{"Mobile", teamId, "Mobile", false, model.ChannelList{&o11}},
{"search purpose", teamId, "now searchable", false, model.ChannelList{&o12}},
{"pipe ignored", teamId, "town square |", false, model.ChannelList{&o9}},
{"ChannelA", teamID, m1.UserId, "ChannelA", false, model.ChannelList{&o1, &o3}},
{"ChannelA, include deleted", teamID, m1.UserId, "ChannelA", true, model.ChannelList{&o1, &o3, &o13}},
{"ChannelA, other team", otherTeamID, m3.UserId, "ChannelA", false, model.ChannelList{&o2}},
{"empty string", teamID, m1.UserId, "", false, model.ChannelList{&o1, &o3, &o12, &o11, &o7, &o6, &o10, &o9}},
{"no matches", teamID, m1.UserId, "blargh", false, model.ChannelList{}},
{"prefix", teamID, m1.UserId, "off-", false, model.ChannelList{&o7, &o6}},
{"full match with dash", teamID, m1.UserId, "off-topic", false, model.ChannelList{&o6}},
{"town square", teamID, m1.UserId, "town square", false, model.ChannelList{&o9}},
{"the in name", teamID, m1.UserId, "thename", false, model.ChannelList{&o10}},
{"Mobile", teamID, m1.UserId, "Mobile", false, model.ChannelList{&o11}},
{"search purpose", teamID, m1.UserId, "now searchable", false, model.ChannelList{&o12}},
{"pipe ignored", teamID, m1.UserId, "town square |", false, model.ChannelList{&o9}},
}
for name, search := range map[string]func(teamId string, term string, includeDeleted bool) (model.ChannelList, error){
"AutocompleteInTeam": ss.Channel().AutocompleteInTeam,
"SearchInTeam": ss.Channel().SearchInTeam,
} {
for _, testCase := range testCases {
t.Run(name+"/"+testCase.Description, func(t *testing.T) {
channels, err := search(testCase.TeamId, testCase.Term, testCase.IncludeDeleted)
require.NoError(t, err)
for _, testCase := range testCases {
t.Run("SearchInTeam/"+testCase.Description, func(t *testing.T) {
channels, err := ss.Channel().SearchInTeam(testCase.TeamID, testCase.Term, testCase.IncludeDeleted)
require.NoError(t, err)
require.Equal(t, testCase.ExpectedResults, channels)
})
}
// AutoCompleteInTeam doesn't currently sort its output results.
if name == "AutocompleteInTeam" {
sort.Sort(ByChannelDisplayName(channels))
}
testCases = append(testCases, []struct {
Description string
TeamID string
UserID string
Term string
IncludeDeleted bool
ExpectedResults model.ChannelList
}{
{"Channel A", teamID, m4.UserId, "Channel ", false, model.ChannelList{&o4, &o1, &o3, &o12}},
{"off limit (private)", teamID, m5.UserId, "off limit", false, model.ChannelList{&o8}},
}...,
)
require.Equal(t, testCase.ExpectedResults, channels)
})
}
for _, testCase := range testCases {
t.Run("AutoCompleteInTeam/"+testCase.Description, func(t *testing.T) {
channels, err := ss.Channel().AutocompleteInTeam(testCase.TeamID, testCase.UserID, testCase.Term, testCase.IncludeDeleted)
require.NoError(t, err)
sort.Sort(ByChannelDisplayName(channels))
require.Equal(t, testCase.ExpectedResults, channels)
})
}
}
func testAutocomplete(t *testing.T, ss store.Store) {
t1 := &model.Team{
DisplayName: "t1",
Name: NewTestId(),
Email: MakeEmail(),
Type: model.TeamOpen,
}
t1, err := ss.Team().Save(t1)
require.NoError(t, err)
teamID := t1.Id
t2 := &model.Team{
DisplayName: "t2",
Name: NewTestId(),
Email: MakeEmail(),
Type: model.TeamOpen,
}
t2, err = ss.Team().Save(t2)
require.NoError(t, err)
otherTeamID := t2.Id
o1 := model.Channel{
TeamId: teamID,
DisplayName: "ChannelA1",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
}
_, err = ss.Channel().Save(&o1, -1)
require.NoError(t, err)
o2 := model.Channel{
TeamId: otherTeamID,
DisplayName: "ChannelA2",
Name: NewTestId(),
Type: model.ChannelTypeOpen,
}
_, err = ss.Channel().Save(&o2, -1)
require.NoError(t, err)
m1 := model.ChannelMember{
ChannelId: o1.Id,
UserId: model.NewId(),
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(&m1)
require.NoError(t, err)
m2 := model.ChannelMember{
ChannelId: o2.Id,
UserId: m1.UserId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(&m2)
require.NoError(t, err)
tm1 := &model.TeamMember{TeamId: teamID, UserId: m1.UserId}
_, err = ss.Team().SaveMember(tm1, -1)
require.NoError(t, err)
tm2 := &model.TeamMember{TeamId: otherTeamID, UserId: m1.UserId}
_, err = ss.Team().SaveMember(tm2, -1)
require.NoError(t, err)
m3 := model.ChannelMember{
ChannelId: o2.Id,
UserId: model.NewId(),
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(&m3)
require.NoError(t, err)
tm3 := &model.TeamMember{TeamId: otherTeamID, UserId: m3.UserId}
_, err = ss.Team().SaveMember(tm3, -1)
require.NoError(t, err)
tm4 := &model.TeamMember{TeamId: teamID, UserId: m3.UserId}
_, err = ss.Team().SaveMember(tm4, -1)
require.NoError(t, err)
o3 := model.Channel{
TeamId: teamID,
DisplayName: "ChannelA private",
Name: NewTestId(),
Type: model.ChannelTypePrivate,
}
_, err = ss.Channel().Save(&o3, -1)
require.NoError(t, err)
o4 := model.Channel{
TeamId: otherTeamID,
DisplayName: "ChannelB",
Name: NewTestId(),
Type: model.ChannelTypePrivate,
}
_, err = ss.Channel().Save(&o4, -1)
require.NoError(t, err)
m4 := &model.ChannelMember{
ChannelId: o3.Id,
UserId: m3.UserId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(m4)
require.NoError(t, err)
m5 := &model.ChannelMember{
ChannelId: o4.Id,
UserId: m1.UserId,
NotifyProps: model.GetDefaultChannelNotifyProps(),
}
_, err = ss.Channel().SaveMember(m5)
require.NoError(t, err)
testCases := []struct {
Description string
UserID string
Term string
IncludeDeleted bool
ExpectedChannelIds []string
ExpectedTeamNames []string
}{
{"user 1, Channel A", m1.UserId, "ChannelA", false, []string{o1.Id, o2.Id}, []string{t1.Name, t2.Name}},
{"user 1, Channel B", m1.UserId, "ChannelB", false, []string{o4.Id}, []string{t2.Name}},
{"user 2, Channel A", m3.UserId, "ChannelA", false, []string{o3.Id, o1.Id, o2.Id}, []string{t2.Name, t1.Name, t1.Name}},
{"user 2, Channel B", m3.UserId, "ChannelB", false, nil, nil},
{"user 1, empty string", m1.UserId, "", false, []string{o1.Id, o2.Id, o4.Id}, []string{t1.Name, t2.Name, t2.Name}},
{"user 2, empty string", m3.UserId, "", false, []string{o1.Id, o2.Id, o3.Id}, []string{t1.Name, t2.Name, t1.Name}},
}
for _, testCase := range testCases {
t.Run("Autocomplete/"+testCase.Description, func(t *testing.T) {
channels, err := ss.Channel().Autocomplete(testCase.UserID, testCase.Term, testCase.IncludeDeleted)
require.NoError(t, err)
var gotChannelIds []string
var gotTeamNames []string
for _, ch := range channels {
gotChannelIds = append(gotChannelIds, ch.Id)
gotTeamNames = append(gotTeamNames, ch.TeamName)
}
require.ElementsMatch(t, testCase.ExpectedChannelIds, gotChannelIds)
require.ElementsMatch(t, testCase.ExpectedTeamNames, gotTeamNames)
})
}
}
@@ -6903,13 +7262,13 @@ func testChannelStoreGetChannelsBatchForIndexing(t *testing.T, ss store.Store) {
// First and last channel should be outside the range
channels, err := ss.Channel().GetChannelsBatchForIndexing(startTime, endTime, 1000)
assert.NoError(t, err)
assert.ElementsMatch(t, []*model.Channel{c2, c3, c5}, channels)
assert.ElementsMatch(t, []*model.Channel{c2, c3, c4, c5}, channels)
// Update the endTime, last channel should be in
endTime = model.GetMillis()
channels, err = ss.Channel().GetChannelsBatchForIndexing(startTime, endTime, 1000)
assert.NoError(t, err)
assert.ElementsMatch(t, []*model.Channel{c2, c3, c5, c6}, channels)
assert.ElementsMatch(t, []*model.Channel{c2, c3, c4, c5, c6}, channels)
// Testing the limit
channels, err = ss.Channel().GetChannelsBatchForIndexing(startTime, endTime, 2)

Просмотреть файл

@@ -60,13 +60,36 @@ func (_m *ChannelStore) AnalyticsTypeCount(teamID string, channelType model.Chan
return r0, r1
}
// AutocompleteInTeam provides a mock function with given fields: teamID, term, includeDeleted
func (_m *ChannelStore) AutocompleteInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error) {
ret := _m.Called(teamID, term, includeDeleted)
// Autocomplete provides a mock function with given fields: userID, term, includeDeleted
func (_m *ChannelStore) Autocomplete(userID string, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
ret := _m.Called(userID, term, includeDeleted)
var r0 model.ChannelListWithTeamData
if rf, ok := ret.Get(0).(func(string, string, bool) model.ChannelListWithTeamData); ok {
r0 = rf(userID, term, includeDeleted)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelListWithTeamData)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, bool) error); ok {
r1 = rf(userID, term, includeDeleted)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AutocompleteInTeam provides a mock function with given fields: teamID, userID, term, includeDeleted
func (_m *ChannelStore) AutocompleteInTeam(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error) {
ret := _m.Called(teamID, userID, term, includeDeleted)
var r0 model.ChannelList
if rf, ok := ret.Get(0).(func(string, string, bool) model.ChannelList); ok {
r0 = rf(teamID, term, includeDeleted)
if rf, ok := ret.Get(0).(func(string, string, string, bool) model.ChannelList); ok {
r0 = rf(teamID, userID, term, includeDeleted)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelList)
@@ -74,8 +97,8 @@ func (_m *ChannelStore) AutocompleteInTeam(teamID string, term string, includeDe
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, bool) error); ok {
r1 = rf(teamID, term, includeDeleted)
if rf, ok := ret.Get(1).(func(string, string, string, bool) error); ok {
r1 = rf(teamID, userID, term, includeDeleted)
} else {
r1 = ret.Error(1)
}
@@ -331,6 +354,29 @@ func (_m *ChannelStore) GetAll(teamID string) ([]*model.Channel, error) {
return r0, r1
}
// GetAllChannelMembersById provides a mock function with given fields: id
func (_m *ChannelStore) GetAllChannelMembersById(id string) ([]string, error) {
ret := _m.Called(id)
var r0 []string
if rf, ok := ret.Get(0).(func(string) []string); ok {
r0 = rf(id)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(id)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetAllChannelMembersForUser provides a mock function with given fields: userID, allowFromCache, includeDeleted
func (_m *ChannelStore) GetAllChannelMembersForUser(userID string, allowFromCache bool, includeDeleted bool) (map[string]string, error) {
ret := _m.Called(userID, allowFromCache, includeDeleted)
@@ -720,6 +766,52 @@ func (_m *ChannelStore) GetChannelsByScheme(schemeID string, offset int, limit i
return r0, r1
}
// GetChannelsByUser provides a mock function with given fields: userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID
func (_m *ChannelStore) GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt int, pageSize int, fromChannelID string) (model.ChannelList, error) {
ret := _m.Called(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
var r0 model.ChannelList
if rf, ok := ret.Get(0).(func(string, bool, int, int, string) model.ChannelList); ok {
r0 = rf(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelList)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, bool, int, int, string) error); ok {
r1 = rf(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetChannelsWithTeamDataByIds provides a mock function with given fields: channelIds, includeDeleted
func (_m *ChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
ret := _m.Called(channelIds, includeDeleted)
var r0 []*model.ChannelWithTeamData
if rf, ok := ret.Get(0).(func([]string, bool) []*model.ChannelWithTeamData); ok {
r0 = rf(channelIds, includeDeleted)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.ChannelWithTeamData)
}
}
var r1 error
if rf, ok := ret.Get(1).(func([]string, bool) error); ok {
r1 = rf(channelIds, includeDeleted)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetDeleted provides a mock function with given fields: team_id, offset, limit, userID
func (_m *ChannelStore) GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error) {
ret := _m.Called(team_id, offset, limit, userID)
@@ -1029,22 +1121,22 @@ func (_m *ChannelStore) GetMembersForUser(teamID string, userID string) (model.C
return r0, r1
}
// GetMembersForUserWithPagination provides a mock function with given fields: teamID, userID, page, perPage
func (_m *ChannelStore) GetMembersForUserWithPagination(teamID string, userID string, page int, perPage int) (model.ChannelMembers, error) {
ret := _m.Called(teamID, userID, page, perPage)
// GetMembersForUserWithPagination provides a mock function with given fields: userID, page, perPage
func (_m *ChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
ret := _m.Called(userID, page, perPage)
var r0 model.ChannelMembers
if rf, ok := ret.Get(0).(func(string, string, int, int) model.ChannelMembers); ok {
r0 = rf(teamID, userID, page, perPage)
var r0 model.ChannelMembersWithTeamData
if rf, ok := ret.Get(0).(func(string, int, int) model.ChannelMembersWithTeamData); ok {
r0 = rf(userID, page, perPage)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.ChannelMembers)
r0 = ret.Get(0).(model.ChannelMembersWithTeamData)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, int, int) error); ok {
r1 = rf(teamID, userID, page, perPage)
if rf, ok := ret.Get(1).(func(string, int, int) error); ok {
r1 = rf(userID, page, perPage)
} else {
r1 = ret.Error(1)
}
@@ -1303,6 +1395,29 @@ func (_m *ChannelStore) GetTeamForChannel(channelID string) (*model.Team, error)
return r0, r1
}
// GetTeamMembersForChannel provides a mock function with given fields: channelID
func (_m *ChannelStore) GetTeamMembersForChannel(channelID string) ([]string, error) {
ret := _m.Called(channelID)
var r0 []string
if rf, ok := ret.Get(0).(func(string) []string); ok {
r0 = rf(channelID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(channelID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GroupSyncedChannelCount provides a mock function with given fields:
func (_m *ChannelStore) GroupSyncedChannelCount() (int64, error) {
ret := _m.Called()

Просмотреть файл

@@ -550,10 +550,26 @@ func (s *TimerLayerChannelStore) AnalyticsTypeCount(teamID string, channelType m
return result, err
}
func (s *TimerLayerChannelStore) AutocompleteInTeam(teamID string, term string, includeDeleted bool) (model.ChannelList, error) {
func (s *TimerLayerChannelStore) Autocomplete(userID string, term string, includeDeleted bool) (model.ChannelListWithTeamData, error) {
start := timemodule.Now()
result, err := s.ChannelStore.AutocompleteInTeam(teamID, term, includeDeleted)
result, err := s.ChannelStore.Autocomplete(userID, term, includeDeleted)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.Autocomplete", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) AutocompleteInTeam(teamID string, userID string, term string, includeDeleted bool) (model.ChannelList, error) {
start := timemodule.Now()
result, err := s.ChannelStore.AutocompleteInTeam(teamID, userID, term, includeDeleted)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
@@ -773,6 +789,22 @@ func (s *TimerLayerChannelStore) GetAll(teamID string) ([]*model.Channel, error)
return result, err
}
func (s *TimerLayerChannelStore) GetAllChannelMembersById(id string) ([]string, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetAllChannelMembersById(id)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetAllChannelMembersById", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetAllChannelMembersForUser(userID string, allowFromCache bool, includeDeleted bool) (map[string]string, error) {
start := timemodule.Now()
@@ -1045,6 +1077,38 @@ func (s *TimerLayerChannelStore) GetChannelsByScheme(schemeID string, offset int
return result, err
}
func (s *TimerLayerChannelStore) GetChannelsByUser(userID string, includeDeleted bool, lastDeleteAt int, pageSize int, fromChannelID string) (model.ChannelList, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetChannelsByUser(userID, includeDeleted, lastDeleteAt, pageSize, fromChannelID)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetChannelsByUser", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetChannelsWithTeamDataByIds(channelIds, includeDeleted)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetChannelsWithTeamDataByIds", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GetDeleted(team_id string, offset int, limit int, userID string) (model.ChannelList, error) {
start := timemodule.Now()
@@ -1269,10 +1333,10 @@ func (s *TimerLayerChannelStore) GetMembersForUser(teamID string, userID string)
return result, err
}
func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(teamID string, userID string, page int, perPage int) (model.ChannelMembers, error) {
func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetMembersForUserWithPagination(teamID, userID, page, perPage)
result, err := s.ChannelStore.GetMembersForUserWithPagination(userID, page, perPage)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
@@ -1461,6 +1525,22 @@ func (s *TimerLayerChannelStore) GetTeamForChannel(channelID string) (*model.Tea
return result, err
}
func (s *TimerLayerChannelStore) GetTeamMembersForChannel(channelID string) ([]string, error) {
start := timemodule.Now()
result, err := s.ChannelStore.GetTeamMembersForChannel(channelID)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetTeamMembersForChannel", success, elapsed)
}
return result, err
}
func (s *TimerLayerChannelStore) GroupSyncedChannelCount() (int64, error) {
start := timemodule.Now()