GraphQL (part 1): Store layer (#19465)
We add the necessary store methods to use GraphQL ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e9a777f4e2
Коммит
a733fb840d
@@ -885,7 +885,10 @@ func getChannelsForTeamForUser(c *Context, w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
channels, err := c.App.GetChannelsForTeamForUser(c.Params.TeamId, c.Params.UserId, c.Params.IncludeDeleted, lastDeleteAt)
|
||||
channels, err := c.App.GetChannelsForTeamForUser(c.Params.TeamId, c.Params.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: c.Params.IncludeDeleted,
|
||||
LastDeleteAt: lastDeleteAt,
|
||||
})
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
|
||||
@@ -210,7 +210,10 @@ func updateCategoriesForTeamForUser(c *Context, w http.ResponseWriter, r *http.R
|
||||
}
|
||||
|
||||
func validateSidebarCategory(c *Context, teamId, userId string, category *model.SidebarCategoryWithChannels) *model.AppError {
|
||||
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, true, 0)
|
||||
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
@@ -221,7 +224,10 @@ func validateSidebarCategory(c *Context, teamId, userId string, category *model.
|
||||
}
|
||||
|
||||
func validateSidebarCategories(c *Context, teamId, userId string, categories []*model.SidebarCategoryWithChannels) *model.AppError {
|
||||
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, true, 0)
|
||||
channels, err := c.App.GetChannelsForTeamForUser(teamId, userId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return model.NewAppError("validateSidebarCategory", "api.invalid_channel", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
@@ -573,7 +573,8 @@ type AppIface interface {
|
||||
GetChannelsForRetentionPolicy(policyID string, offset, limit int) (*model.ChannelsWithCount, *model.AppError)
|
||||
GetChannelsForScheme(scheme *model.Scheme, offset int, limit int) (model.ChannelList, *model.AppError)
|
||||
GetChannelsForSchemePage(scheme *model.Scheme, page int, perPage int) (model.ChannelList, *model.AppError)
|
||||
GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError)
|
||||
GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError)
|
||||
GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError)
|
||||
GetChannelsForUser(userID string, includeDeleted bool, lastDeleteAt, pageSize int, fromChannelID string) (model.ChannelList, *model.AppError)
|
||||
GetChannelsUserNotIn(teamID string, userID string, offset int, limit int) (model.ChannelList, *model.AppError)
|
||||
GetCloudSession(token string) (*model.Session, *model.AppError)
|
||||
|
||||
@@ -1767,8 +1767,23 @@ func (a *App) GetChannelByNameForTeamName(channelName, teamName string, includeD
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *App) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError) {
|
||||
list, err := a.Srv().Store.Channel().GetChannels(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
func (a *App) GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError) {
|
||||
list, err := a.Srv().Store.Channel().GetChannels(teamID, userID, opts)
|
||||
if err != nil {
|
||||
var nfErr *store.ErrNotFound
|
||||
switch {
|
||||
case errors.As(err, &nfErr):
|
||||
return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound)
|
||||
default:
|
||||
return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (a *App) GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError) {
|
||||
list, err := a.Srv().Store.Channel().GetChannelsWithCursor(teamID, userID, opts, afterChannelID)
|
||||
if err != nil {
|
||||
var nfErr *store.ErrNotFound
|
||||
switch {
|
||||
|
||||
@@ -997,19 +997,28 @@ func TestGetChannelsForUser(t *testing.T) {
|
||||
defer th.App.PermanentDeleteChannel(channel)
|
||||
defer th.TearDown()
|
||||
|
||||
channelList, err := th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, false, 0)
|
||||
channelList, err := th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelList, 4)
|
||||
|
||||
th.App.DeleteChannel(th.Context, channel, th.BasicUser.Id)
|
||||
|
||||
// Now we get all the non-archived channels for the user
|
||||
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, false, 0)
|
||||
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelList, 3)
|
||||
|
||||
// Now we get all the channels, even though are archived, for the user
|
||||
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, true, 0)
|
||||
channelList, err = th.App.GetChannelsForTeamForUser(th.BasicTeam.Id, th.BasicUser.Id, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelList, 4)
|
||||
}
|
||||
|
||||
@@ -5203,7 +5203,7 @@ func (a *OpenTracingAppLayer) GetChannelsForSchemePage(scheme *model.Scheme, pag
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, *model.AppError) {
|
||||
func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelsForTeamForUser")
|
||||
|
||||
@@ -5215,7 +5215,29 @@ func (a *OpenTracingAppLayer) GetChannelsForTeamForUser(teamID string, userID st
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetChannelsForTeamForUser(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
resultVar0, resultVar1 := a.app.GetChannelsForTeamForUser(teamID, userID, opts)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetChannelsForTeamForUserWithCursor(teamID string, userID string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelsForTeamForUserWithCursor")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store.SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetChannelsForTeamForUserWithCursor(teamID, userID, opts, afterChannelID)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
|
||||
@@ -437,7 +437,10 @@ func (api *PluginAPI) GetChannelByNameForTeamName(teamName, channelName string,
|
||||
}
|
||||
|
||||
func (api *PluginAPI) GetChannelsForTeamForUser(teamID, userID string, includeDeleted bool) ([]*model.Channel, *model.AppError) {
|
||||
channels, err := api.app.GetChannelsForTeamForUser(teamID, userID, includeDeleted, 0)
|
||||
channels, err := api.app.GetChannelsForTeamForUser(teamID, userID, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: includeDeleted,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1116,7 +1116,10 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User,
|
||||
|
||||
var channelList model.ChannelList
|
||||
var nErr error
|
||||
if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, true, 0); nErr != nil {
|
||||
if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
}); nErr != nil {
|
||||
var nfErr *store.ErrNotFound
|
||||
if errors.As(nErr, &nfErr) {
|
||||
channelList = model.ChannelList{}
|
||||
|
||||
@@ -868,7 +868,10 @@ func (a *App) invalidateUserChannelMembersCaches(userID string) *model.AppError
|
||||
}
|
||||
|
||||
for _, team := range teamsForUser {
|
||||
channelsForUser, err := a.GetChannelsForTeamForUser(team.Id, userID, false, 0)
|
||||
channelsForUser, err := a.GetChannelsForTeamForUser(team.Id, userID, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -178,7 +178,10 @@ func manualTest(c *web.Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func getChannelID(a app.AppIface, channelname string, teamid string, userid string) (string, bool) {
|
||||
// Grab all the channels
|
||||
channels, err := a.Srv().Store.Channel().GetChannels(teamid, userid, false, 0)
|
||||
channels, err := a.Srv().Store.Channel().GetChannels(teamid, userid, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err != nil {
|
||||
mlog.Debug("Unable to get channels")
|
||||
return "", false
|
||||
|
||||
@@ -141,6 +141,8 @@ type ChannelSearchOpts struct {
|
||||
Private bool
|
||||
Page *int
|
||||
PerPage *int
|
||||
LastDeleteAt int
|
||||
LastUpdateAt int
|
||||
}
|
||||
|
||||
type ChannelMemberCountByGroup struct {
|
||||
|
||||
@@ -1087,7 +1087,7 @@ func (s *OpenTracingLayerChannelStore) GetChannelUnread(channelID string, userID
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannels")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
@@ -1096,7 +1096,7 @@ func (s *OpenTracingLayerChannelStore) GetChannels(teamID string, userID string,
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
@@ -1177,6 +1177,24 @@ func (s *OpenTracingLayerChannelStore) GetChannelsByUser(userID string, includeD
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetChannelsWithCursor")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
|
||||
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")
|
||||
@@ -1442,6 +1460,24 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUser(teamID string, userID s
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersForUserWithCursor")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -1460,6 +1496,24 @@ func (s *OpenTracingLayerChannelStore) GetMembersForUserWithPagination(userID st
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMembersInfoByChannelIds")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.GetMoreChannels")
|
||||
@@ -2446,6 +2500,24 @@ func (s *OpenTracingLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelMemberHistoryStore.GetChannelsLeftSince")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelMemberHistoryStore.GetUsersInChannelDuring")
|
||||
|
||||
@@ -1213,11 +1213,11 @@ func (s *RetryLayerChannelStore) GetChannelUnread(channelID string, userID strin
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
func (s *RetryLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
@@ -1318,6 +1318,27 @@ func (s *RetryLayerChannelStore) GetChannelsByUser(userID string, includeDeleted
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
|
||||
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
|
||||
}
|
||||
timepkg.Sleep(100 * timepkg.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
|
||||
|
||||
tries := 0
|
||||
@@ -1618,6 +1639,27 @@ func (s *RetryLayerChannelStore) GetMembersForUser(teamID string, userID string)
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
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
|
||||
}
|
||||
timepkg.Sleep(100 * timepkg.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
|
||||
|
||||
tries := 0
|
||||
@@ -1639,6 +1681,27 @@ func (s *RetryLayerChannelStore) GetMembersForUserWithPagination(userID string,
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
|
||||
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
|
||||
}
|
||||
timepkg.Sleep(100 * timepkg.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
|
||||
|
||||
tries := 0
|
||||
@@ -2716,6 +2779,27 @@ func (s *RetryLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
|
||||
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
|
||||
}
|
||||
timepkg.Sleep(100 * timepkg.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
|
||||
|
||||
tries := 0
|
||||
|
||||
@@ -160,7 +160,10 @@ func (s SearchFileInfoStore) PermanentDeleteByUser(userId string) (int64, error)
|
||||
func (s SearchFileInfoStore) Search(paramsList []*model.SearchParams, userId, teamId string, page, perPage int) (*model.FileInfoList, error) {
|
||||
for _, engine := range s.rootStore.searchEngine.GetActiveEngines() {
|
||||
if engine.IsSearchEnabled() {
|
||||
userChannels, nErr := s.rootStore.Channel().GetChannels(teamId, userId, paramsList[0].IncludeDeletedChannels, 0)
|
||||
userChannels, nErr := s.rootStore.Channel().GetChannels(teamId, userId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: paramsList[0].IncludeDeletedChannels,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if nErr != nil {
|
||||
return nil, nErr
|
||||
}
|
||||
|
||||
@@ -142,7 +142,11 @@ func (s SearchPostStore) searchPostsForUserByEngine(engine searchengine.SearchEn
|
||||
}
|
||||
|
||||
// We only allow the user to search in channels they are a member of.
|
||||
userChannels, err2 := s.rootStore.Channel().GetChannels(teamId, userId, paramsList[0].IncludeDeletedChannels, 0)
|
||||
userChannels, err2 := s.rootStore.Channel().GetChannels(teamId, userId,
|
||||
&model.ChannelSearchOpts{
|
||||
IncludeDeleted: paramsList[0].IncludeDeletedChannels,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if err2 != nil {
|
||||
return nil, errors.Wrap(err2, "error getting channel for user")
|
||||
}
|
||||
|
||||
@@ -255,3 +255,24 @@ func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit
|
||||
}
|
||||
return rowsAffected, nil
|
||||
}
|
||||
|
||||
// GetChannelsLeftSince returns list of channels that the user has left after a given time,
|
||||
// but has not rejoined again.
|
||||
func (s SqlChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
query, params, err := s.getQueryBuilder().
|
||||
Select("ChannelId").
|
||||
From("ChannelMemberHistory").
|
||||
GroupBy("ChannelId").
|
||||
Where(sq.Eq{"UserId": userID}).
|
||||
Having("MAX(LeaveTime) > MAX(JoinTime) AND MAX(LeaveTime) IS NOT NULL AND MAX(LeaveTime) >= ?", since).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "channel_member_history_to_sql")
|
||||
}
|
||||
channelIds := []string{}
|
||||
err = s.GetReplicaX().Select(&channelIds, query, params...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetChannelsLeftSince userId=%s since=%d", userID, since)
|
||||
}
|
||||
|
||||
return channelIds, nil
|
||||
}
|
||||
|
||||
@@ -1084,37 +1084,105 @@ func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
func (s SqlChannelStore) GetChannels(teamId string, userId string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("Channels.*").
|
||||
From("Channels, ChannelMembers").
|
||||
Select("ch.*").
|
||||
From("Channels ch, ChannelMembers cm").
|
||||
Where(
|
||||
sq.And{
|
||||
sq.Expr("Id = ChannelId"),
|
||||
sq.Eq{"UserId": userId},
|
||||
sq.Expr("ch.Id = cm.ChannelId"),
|
||||
sq.Eq{"cm.UserId": userId},
|
||||
},
|
||||
).
|
||||
OrderBy("DisplayName")
|
||||
OrderBy("ch.DisplayName")
|
||||
|
||||
if teamId != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"TeamId": teamId},
|
||||
sq.Eq{"TeamId": ""},
|
||||
sq.Eq{"ch.TeamId": teamId},
|
||||
sq.Eq{"ch.TeamId": ""},
|
||||
})
|
||||
}
|
||||
|
||||
if includeDeleted {
|
||||
if lastDeleteAt != 0 {
|
||||
if opts.IncludeDeleted {
|
||||
if opts.LastDeleteAt != 0 {
|
||||
// We filter by non-archived, and archived >= a timestamp.
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"DeleteAt": 0},
|
||||
sq.GtOrEq{"DeleteAt": lastDeleteAt},
|
||||
sq.Eq{"ch.DeleteAt": 0},
|
||||
sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
|
||||
})
|
||||
}
|
||||
// If lastDeleteAt is not set, we include everything. That means no filter is needed.
|
||||
// If opts.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})
|
||||
query = query.Where(sq.Eq{"ch.DeleteAt": 0})
|
||||
}
|
||||
|
||||
if opts.LastUpdateAt > 0 {
|
||||
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
|
||||
}
|
||||
|
||||
channels := model.ChannelList{}
|
||||
sql, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getchannels_tosql")
|
||||
}
|
||||
|
||||
err = s.GetReplicaX().Select(&channels, sql, args...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get channels with TeamId=%s and UserId=%s", teamId, userId)
|
||||
}
|
||||
|
||||
if len(channels) == 0 {
|
||||
return nil, store.NewErrNotFound("Channel", "userId="+userId)
|
||||
}
|
||||
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("ch.*").
|
||||
From("Channels ch, ChannelMembers cm").
|
||||
Where(
|
||||
sq.And{
|
||||
sq.Expr("ch.Id = cm.ChannelId"),
|
||||
sq.Eq{"cm.UserId": userId},
|
||||
},
|
||||
).
|
||||
OrderBy("ch.Id")
|
||||
|
||||
if opts.PerPage != nil {
|
||||
// The limit is verified at the GraphQL layer.
|
||||
query = query.Limit(uint64(*opts.PerPage))
|
||||
}
|
||||
|
||||
if afterChannelID != "" {
|
||||
query = query.Where(sq.Gt{"ch.Id": afterChannelID})
|
||||
}
|
||||
|
||||
if teamId != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"ch.TeamId": teamId},
|
||||
sq.Eq{"ch.TeamId": ""},
|
||||
})
|
||||
}
|
||||
|
||||
if opts.IncludeDeleted {
|
||||
if opts.LastDeleteAt != 0 {
|
||||
// We filter by non-archived, and archived >= a timestamp.
|
||||
query = query.Where(sq.Or{
|
||||
sq.Eq{"ch.DeleteAt": 0},
|
||||
sq.GtOrEq{"ch.DeleteAt": opts.LastDeleteAt},
|
||||
})
|
||||
}
|
||||
// If opts.LastDeleteAt is not set, we include everything. That means no filter is needed.
|
||||
} else {
|
||||
// Don't include archived channels.
|
||||
query = query.Where(sq.Eq{"ch.DeleteAt": 0})
|
||||
}
|
||||
|
||||
if opts.LastUpdateAt > 0 {
|
||||
query = query.Where(sq.GtOrEq{"ch.UpdateAt": opts.LastUpdateAt})
|
||||
}
|
||||
|
||||
channels := model.ChannelList{}
|
||||
@@ -2773,6 +2841,56 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (model.
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersForUserWithCursor(userID, afterChannel, afterUser string, limit, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("ChannelMembers.*",
|
||||
"TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole",
|
||||
"TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole",
|
||||
"TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole",
|
||||
"ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole",
|
||||
"ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole",
|
||||
"ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole").
|
||||
From("ChannelMembers").
|
||||
InnerJoin("Channels ON ChannelMembers.ChannelId = Channels.Id").
|
||||
LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
|
||||
LeftJoin("Teams ON Channels.TeamId = Teams.Id").
|
||||
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
|
||||
Where(sq.Eq{
|
||||
"ChannelMembers.UserId": userID,
|
||||
"Channels.DeleteAt": 0,
|
||||
}).
|
||||
OrderBy("ChannelId, UserId ASC").
|
||||
// The limit is verified at the GraphQL layer.
|
||||
Limit(uint64(limit))
|
||||
|
||||
if afterChannel != "" && afterUser != "" {
|
||||
query = query.Where(sq.Or{
|
||||
sq.Gt{"ChannelMembers.ChannelId": afterChannel},
|
||||
sq.And{
|
||||
sq.Eq{"ChannelMembers.ChannelId": afterChannel},
|
||||
sq.Gt{"ChannelMembers.UserId": afterUser},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if lastUpdateAt != 0 {
|
||||
query = query.Where(sq.GtOrEq{"ChannelMembers.LastUpdateAt": lastUpdateAt})
|
||||
}
|
||||
|
||||
queryString, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getMembersForUserWithCursor_tosql")
|
||||
}
|
||||
|
||||
dbMembers := channelMemberWithSchemeRolesList{}
|
||||
err = s.GetReplicaX().Select(&dbMembers, queryString, args...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s", userID)
|
||||
}
|
||||
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersForUserWithPagination(userId string, page, perPage int) (model.ChannelMembersWithTeamData, error) {
|
||||
dbMembers := channelMemberWithTeamWithSchemeRolesList{}
|
||||
offset := page * perPage
|
||||
@@ -3470,6 +3588,43 @@ func (s SqlChannelStore) GetMembersByChannelIds(channelIds []string, userId stri
|
||||
return dbMembers.ToModel(), nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("Channels.Id as ChannelId, Users.Id, Users.FirstName, Users.LastName, Users.Nickname, Users.Username").
|
||||
From("ChannelMembers as cm").
|
||||
Join("Channels ON cm.ChannelId = Channels.Id").
|
||||
Join("Users ON cm.UserId = Users.Id").
|
||||
Where(sq.Eq{
|
||||
"Channels.Id": channelIDs,
|
||||
"Channels.DeleteAt": 0,
|
||||
})
|
||||
|
||||
sql, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "dm_gm_names_tosql")
|
||||
}
|
||||
|
||||
res := []*struct {
|
||||
model.User
|
||||
ChannelId string
|
||||
}{}
|
||||
|
||||
if err := s.GetReplicaX().Select(&res, sql, args...); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to find channels display name")
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
return nil, store.NewErrNotFound("User", fmt.Sprintf("%v", channelIDs))
|
||||
}
|
||||
|
||||
userInfo := make(map[string][]*model.User)
|
||||
for _, item := range res {
|
||||
userInfo[item.ChannelId] = append(userInfo[item.ChannelId], &item.User)
|
||||
}
|
||||
|
||||
return userInfo, nil
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) (model.ChannelList, error) {
|
||||
channels := model.ChannelList{}
|
||||
err := s.GetReplicaX().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = ? ORDER BY DisplayName LIMIT ? OFFSET ?", schemeId, limit, offset)
|
||||
|
||||
@@ -178,7 +178,8 @@ type ChannelStore interface {
|
||||
GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*model.Channel, error)
|
||||
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)
|
||||
GetChannels(teamID, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error)
|
||||
GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (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)
|
||||
@@ -230,6 +231,7 @@ type ChannelStore interface {
|
||||
GetMembersForUser(teamID string, userID string) (model.ChannelMembers, error)
|
||||
GetTeamMembersForChannel(channelID string) ([]string, error)
|
||||
GetMembersForUserWithPagination(userID string, page, perPage int) (model.ChannelMembersWithTeamData, error)
|
||||
GetMembersForUserWithCursor(userID, afterChannel, afterUser string, limit, lastUpdateAt int) (model.ChannelMembers, 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)
|
||||
@@ -241,6 +243,7 @@ type ChannelStore interface {
|
||||
SearchGroupChannels(userID, term string) (model.ChannelList, error)
|
||||
GetMembersByIds(channelID string, userIds []string) (model.ChannelMembers, error)
|
||||
GetMembersByChannelIds(channelIds []string, userID string) (model.ChannelMembers, error)
|
||||
GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error)
|
||||
AnalyticsDeletedTypeCount(teamID string, channelType string) (int64, error)
|
||||
GetChannelUnread(channelID, userID string) (*model.ChannelUnread, error)
|
||||
ClearCaches()
|
||||
@@ -284,6 +287,7 @@ type ChannelMemberHistoryStore interface {
|
||||
PermanentDeleteBatchForRetentionPolicies(now, globalPolicyEndTime, limit int64, cursor model.RetentionPolicyCursor) (int64, model.RetentionPolicyCursor, error)
|
||||
DeleteOrphanedRows(limit int) (deleted int64, err error)
|
||||
PermanentDeleteBatch(endTime int64, limit int64) (int64, error)
|
||||
GetChannelsLeftSince(userID string, since int64) ([]string, error)
|
||||
}
|
||||
type ThreadStore interface {
|
||||
GetThreadFollowers(threadID string, fetchOnlyActive bool) ([]string, error)
|
||||
@@ -919,6 +923,8 @@ type ChannelSearchOpts struct {
|
||||
Private bool
|
||||
Page *int
|
||||
PerPage *int
|
||||
LastDeleteAt int
|
||||
LastUpdateAt int
|
||||
}
|
||||
|
||||
func (c *ChannelSearchOpts) IsPaginated() bool {
|
||||
|
||||
@@ -22,6 +22,7 @@ func TestChannelMemberHistoryStore(t *testing.T, ss store.Store) {
|
||||
t.Run("TestGetUsersInChannelAtChannelMembers", func(t *testing.T) { testGetUsersInChannelAtChannelMembers(t, ss) })
|
||||
t.Run("TestPermanentDeleteBatch", func(t *testing.T) { testPermanentDeleteBatch(t, ss) })
|
||||
t.Run("TestPermanentDeleteBatchForRetentionPolicies", func(t *testing.T) { testPermanentDeleteBatchForRetentionPolicies(t, ss) })
|
||||
t.Run("TestGetChannelsLeftSince", func(t *testing.T) { testGetChannelsLeftSince(t, ss) })
|
||||
}
|
||||
|
||||
func testLogJoinEvent(t *testing.T, ss store.Store) {
|
||||
@@ -29,7 +30,7 @@ func testLogJoinEvent(t *testing.T, ss store.Store) {
|
||||
ch := model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: "Display " + model.NewId(),
|
||||
Name: "zz" + model.NewId() + "b",
|
||||
Name: NewTestId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}
|
||||
channel, err := ss.Channel().Save(&ch, -1)
|
||||
@@ -55,7 +56,7 @@ func testLogLeaveEvent(t *testing.T, ss store.Store) {
|
||||
ch := model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: "Display " + model.NewId(),
|
||||
Name: "zz" + model.NewId() + "b",
|
||||
Name: NewTestId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}
|
||||
channel, err := ss.Channel().Save(&ch, -1)
|
||||
@@ -84,7 +85,7 @@ func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) {
|
||||
ch := &model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: "Display " + model.NewId(),
|
||||
Name: "zz" + model.NewId() + "b",
|
||||
Name: NewTestId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}
|
||||
channel, err := ss.Channel().Save(ch, -1)
|
||||
@@ -180,7 +181,7 @@ func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) {
|
||||
channel := &model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: "Display " + model.NewId(),
|
||||
Name: "zz" + model.NewId() + "b",
|
||||
Name: NewTestId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}
|
||||
channel, err := ss.Channel().Save(channel, -1)
|
||||
@@ -292,7 +293,7 @@ func testPermanentDeleteBatch(t *testing.T, ss store.Store) {
|
||||
channel := &model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: "Display " + model.NewId(),
|
||||
Name: "zz" + model.NewId() + "b",
|
||||
Name: NewTestId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}
|
||||
channel, err := ss.Channel().Save(channel, -1)
|
||||
@@ -389,3 +390,54 @@ func testPermanentDeleteBatchForRetentionPolicies(t *testing.T, ss store.Store)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, result, "history should have been deleted by channel policy")
|
||||
}
|
||||
|
||||
func testGetChannelsLeftSince(t *testing.T, ss store.Store) {
|
||||
team, err := ss.Team().Save(&model.Team{
|
||||
DisplayName: "DisplayName",
|
||||
Name: "team" + model.NewId(),
|
||||
Email: MakeEmail(),
|
||||
Type: model.TeamOpen,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
channel, err := ss.Channel().Save(&model.Channel{
|
||||
TeamId: team.Id,
|
||||
DisplayName: "DisplayName",
|
||||
Name: "channel" + model.NewId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}, -1)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := model.NewId()
|
||||
|
||||
joinTime := int64(1000)
|
||||
err = ss.ChannelMemberHistory().LogJoinEvent(userID, channel.Id, joinTime)
|
||||
require.NoError(t, err)
|
||||
|
||||
// has not left
|
||||
ids, err := ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, ids)
|
||||
|
||||
// left
|
||||
err = ss.ChannelMemberHistory().LogLeaveEvent(userID, channel.Id, joinTime+100)
|
||||
require.NoError(t, err)
|
||||
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+100)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{channel.Id}, ids)
|
||||
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+200)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, ids)
|
||||
|
||||
// joined and left again.
|
||||
err = ss.ChannelMemberHistory().LogJoinEvent(userID, channel.Id, joinTime+200)
|
||||
require.NoError(t, err)
|
||||
err = ss.ChannelMemberHistory().LogLeaveEvent(userID, channel.Id, joinTime+300)
|
||||
require.NoError(t, err)
|
||||
// should be same for both time stamps
|
||||
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+100)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{channel.Id}, ids)
|
||||
ids, err = ss.ChannelMemberHistory().GetChannelsLeftSince(userID, joinTime+300)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{channel.Id}, ids)
|
||||
}
|
||||
|
||||
@@ -79,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("GetChannelsWithCursor", func(t *testing.T) { testChannelStoreGetChannelsWithCursor(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) })
|
||||
@@ -87,6 +88,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
|
||||
t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) })
|
||||
t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) })
|
||||
t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) })
|
||||
t.Run("GetMembersForUserWithCursor", func(t *testing.T) { testChannelStoreGetMembersForUserWithCursor(t, ss) })
|
||||
t.Run("GetMembersForUserWithPagination", func(t *testing.T) { testChannelStoreGetMembersForUserWithPagination(t, ss) })
|
||||
t.Run("CountPostsAfter", func(t *testing.T) { testCountPostsAfter(t, ss) })
|
||||
t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) })
|
||||
@@ -105,6 +107,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlStore) {
|
||||
t.Run("SearchAllChannels", func(t *testing.T) { testChannelStoreSearchAllChannels(t, ss) })
|
||||
t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) })
|
||||
t.Run("GetMembersByChannelIds", func(t *testing.T) { testChannelStoreGetMembersByChannelIds(t, ss) })
|
||||
t.Run("GetMembersInfoByChannelIds", func(t *testing.T) { testChannelStoreGetMembersInfoByChannelIds(t, ss) })
|
||||
t.Run("SearchGroupChannels", func(t *testing.T) { testChannelStoreSearchGroupChannels(t, ss) })
|
||||
t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) })
|
||||
t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) })
|
||||
@@ -719,7 +722,10 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) {
|
||||
nErr = ss.Channel().Delete(o3.Id, model.GetMillis())
|
||||
require.NoError(t, nErr, nErr)
|
||||
|
||||
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0)
|
||||
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 1, "invalid number of channels")
|
||||
|
||||
@@ -730,7 +736,10 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) {
|
||||
cresult := ss.Channel().PermanentDelete(o2.Id)
|
||||
require.NoError(t, cresult)
|
||||
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0)
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
if assert.Error(t, nErr) {
|
||||
var nfErr *store.ErrNotFound
|
||||
require.True(t, errors.As(nErr, &nfErr))
|
||||
@@ -3263,12 +3272,13 @@ func testChannelDeleteMemberStore(t *testing.T, ss store.Store) {
|
||||
|
||||
func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
team := model.NewId()
|
||||
o1 := model.Channel{}
|
||||
o1 := &model.Channel{}
|
||||
o1.TeamId = team
|
||||
o1.DisplayName = "Channel1"
|
||||
o1.Name = NewTestId()
|
||||
o1.Type = model.ChannelTypeOpen
|
||||
_, nErr := ss.Channel().Save(&o1, -1)
|
||||
var nErr error
|
||||
o1, nErr = ss.Channel().Save(o1, -1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
o2 := model.Channel{}
|
||||
@@ -3315,7 +3325,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Channel().SaveMember(&m4)
|
||||
require.NoError(t, err)
|
||||
|
||||
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0)
|
||||
list, nErr := ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 3)
|
||||
require.Equal(t, o1.Id, list[0].Id, "missing channel")
|
||||
@@ -3342,6 +3355,25 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
_, ok = ids4[o1.Id]
|
||||
require.True(t, ok, "missing channel")
|
||||
|
||||
// Sleeping to guarantee that the
|
||||
// UpdateAt is different.
|
||||
// The proper way would be to set UpdateAt during channel creation itself,
|
||||
// but the *Channel.PreSave method ignores any existing CreateAt value.
|
||||
// TODO: check if using an existing CreateAt breaks anything.
|
||||
time.Sleep(time.Millisecond)
|
||||
|
||||
now := model.GetMillis()
|
||||
_, nErr = ss.Channel().Update(o1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastUpdateAt: int(now),
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
// should return 1
|
||||
require.Len(t, list, 1)
|
||||
|
||||
nErr = ss.Channel().Delete(o2.Id, 10)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
@@ -3349,13 +3381,19 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
require.NoError(t, nErr)
|
||||
|
||||
// should return 1
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, false, 0)
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
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().GetChannels(o1.TeamId, m1.UserId, true, 0)
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 3)
|
||||
require.Equal(t, o1.Id, list[0].Id, "missing channel")
|
||||
@@ -3363,7 +3401,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, o3.Id, list[2].Id, "missing channel")
|
||||
|
||||
// Should still return all
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, true, 10)
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 10,
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 3)
|
||||
require.Equal(t, o1.Id, list[0].Id, "missing channel")
|
||||
@@ -3371,7 +3412,10 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, o3.Id, list[2].Id, "missing channel")
|
||||
|
||||
// Should return 2
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, true, 20)
|
||||
list, nErr = ss.Channel().GetChannels(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 20,
|
||||
})
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 2)
|
||||
require.Equal(t, o1.Id, list[0].Id, "missing channel")
|
||||
@@ -3399,6 +3443,147 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) {
|
||||
ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId)
|
||||
}
|
||||
|
||||
func testChannelStoreGetChannelsWithCursor(t *testing.T, ss store.Store) {
|
||||
teamID := model.NewId()
|
||||
o1 := &model.Channel{}
|
||||
o1.TeamId = teamID
|
||||
o1.DisplayName = "Channel1"
|
||||
o1.Name = NewTestId()
|
||||
o1.Type = model.ChannelTypeOpen
|
||||
var nErr error
|
||||
o1, nErr = ss.Channel().Save(o1, -1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
o2 := model.Channel{}
|
||||
o2.TeamId = teamID
|
||||
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 = teamID
|
||||
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().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
PerPage: model.NewInt(2),
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 2)
|
||||
require.Equal(t, teamID, list[0].TeamId, "incorrect teamID")
|
||||
require.Equal(t, teamID, list[1].TeamId, "incorrect teamID")
|
||||
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
PerPage: model.NewInt(2),
|
||||
}, list[1].Id)
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 1)
|
||||
require.Equal(t, teamID, list[0].TeamId, "incorrect teamID")
|
||||
|
||||
// Sleeping to guarantee that the
|
||||
// UpdateAt is different.
|
||||
// The proper way would be to set UpdateAt during channel creation itself,
|
||||
// but the *Channel.PreSave method ignores any existing CreateAt value.
|
||||
// TODO: check if using an existing CreateAt breaks anything.
|
||||
time.Sleep(time.Millisecond)
|
||||
|
||||
now := model.GetMillis()
|
||||
_, nErr = ss.Channel().Update(o1)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastUpdateAt: int(now),
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
// should return 1
|
||||
require.Len(t, list, 1)
|
||||
|
||||
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().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: false,
|
||||
LastDeleteAt: 0,
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 1)
|
||||
|
||||
// Should return all
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
PerPage: model.NewInt(2),
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 2)
|
||||
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 0,
|
||||
PerPage: model.NewInt(2),
|
||||
}, list[1].Id)
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 1)
|
||||
|
||||
// Should still return all
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 10,
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 3)
|
||||
|
||||
// Should return 2
|
||||
list, nErr = ss.Channel().GetChannelsWithCursor(o1.TeamId, m1.UserId, &model.ChannelSearchOpts{
|
||||
IncludeDeleted: true,
|
||||
LastDeleteAt: 20,
|
||||
}, "")
|
||||
require.NoError(t, nErr)
|
||||
require.Len(t, list, 2)
|
||||
}
|
||||
|
||||
func testChannelStoreGetChannelsByUser(t *testing.T, ss store.Store) {
|
||||
team := model.NewId()
|
||||
team2 := model.NewId()
|
||||
@@ -4191,6 +4376,120 @@ func testChannelStoreGetMembersForUser(t *testing.T, ss store.Store) {
|
||||
})
|
||||
}
|
||||
|
||||
func testChannelStoreGetMembersForUserWithCursor(t *testing.T, ss store.Store) {
|
||||
t1 := model.Team{}
|
||||
t1.DisplayName = "Team1"
|
||||
t1.Name = NewTestId()
|
||||
t1.Email = MakeEmail()
|
||||
t1.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)
|
||||
|
||||
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)
|
||||
|
||||
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 = o2.Id
|
||||
m2.UserId = m1.UserId
|
||||
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||
_, err = ss.Channel().SaveMember(&m2)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("with channels", func(t *testing.T) {
|
||||
var members model.ChannelMembers
|
||||
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 1, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 1)
|
||||
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 3, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 2)
|
||||
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[0].ChannelId, m1.UserId, 1, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 1)
|
||||
})
|
||||
|
||||
t.Run("with channels and direct messages", func(t *testing.T) {
|
||||
user := model.User{Id: m1.UserId}
|
||||
u1 := model.User{Id: model.NewId()}
|
||||
u2 := model.User{Id: model.NewId()}
|
||||
u3 := model.User{Id: model.NewId()}
|
||||
u4 := model.User{Id: model.NewId()}
|
||||
_, nErr = ss.Channel().CreateDirectChannel(&u1, &user)
|
||||
require.NoError(t, nErr)
|
||||
_, nErr = ss.Channel().CreateDirectChannel(&u2, &user)
|
||||
require.NoError(t, nErr)
|
||||
// other user direct message
|
||||
_, nErr = ss.Channel().CreateDirectChannel(&u3, &u4)
|
||||
require.NoError(t, nErr)
|
||||
|
||||
members, err2 := ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 10, 0)
|
||||
require.NoError(t, err2)
|
||||
assert.Len(t, members, 4)
|
||||
|
||||
members, err2 = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 2, 0)
|
||||
require.NoError(t, err2)
|
||||
assert.Len(t, members, 2)
|
||||
|
||||
members, err2 = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[1].ChannelId, m1.UserId, 2, 0)
|
||||
require.NoError(t, err2)
|
||||
assert.Len(t, members, 2)
|
||||
})
|
||||
|
||||
t.Run("with channels, direct channels and group messages", func(t *testing.T) {
|
||||
userIds := []string{model.NewId(), model.NewId(), model.NewId(), m1.UserId}
|
||||
group := &model.Channel{
|
||||
Name: model.GetGroupNameFromUserIds(userIds),
|
||||
DisplayName: "test",
|
||||
Type: model.ChannelTypeGroup,
|
||||
}
|
||||
var channel *model.Channel
|
||||
channel, nErr = ss.Channel().Save(group, 10000)
|
||||
require.NoError(t, nErr)
|
||||
for _, userId := range userIds {
|
||||
cm := &model.ChannelMember{
|
||||
UserId: userId,
|
||||
ChannelId: channel.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
SchemeUser: true,
|
||||
}
|
||||
|
||||
_, err = ss.Channel().SaveMember(cm)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
members, err := ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 10, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 5)
|
||||
|
||||
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, "", "", 2, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 2)
|
||||
|
||||
members, err = ss.Channel().GetMembersForUserWithCursor(m1.UserId, members[1].ChannelId, m1.UserId, 10, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, members, 3)
|
||||
})
|
||||
}
|
||||
|
||||
func testChannelStoreGetMembersForUserWithPagination(t *testing.T, ss store.Store) {
|
||||
t1 := model.Team{
|
||||
DisplayName: "team1",
|
||||
@@ -6072,6 +6371,62 @@ func testChannelStoreGetMembersByChannelIds(t *testing.T, ss store.Store) {
|
||||
})
|
||||
}
|
||||
|
||||
func testChannelStoreGetMembersInfoByChannelIds(t *testing.T, ss store.Store) {
|
||||
u, err := ss.User().Save(&model.User{
|
||||
Username: "user.test",
|
||||
Email: MakeEmail(),
|
||||
Nickname: model.NewId(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a couple channels and add the user to them
|
||||
channel1, err := ss.Channel().Save(&model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: model.NewId(),
|
||||
Name: model.NewId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}, -1)
|
||||
require.NoError(t, err)
|
||||
|
||||
channel2, err := ss.Channel().Save(&model.Channel{
|
||||
TeamId: model.NewId(),
|
||||
DisplayName: model.NewId(),
|
||||
Name: model.NewId(),
|
||||
Type: model.ChannelTypeOpen,
|
||||
}, -1)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||
ChannelId: channel1.Id,
|
||||
UserId: u.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||
ChannelId: channel2.Id,
|
||||
UserId: u.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("should return the user's members for the given channels", func(t *testing.T) {
|
||||
result, nErr := ss.Channel().GetMembersInfoByChannelIds([]string{channel1.Id, channel2.Id})
|
||||
require.NoError(t, nErr)
|
||||
assert.Len(t, result, 2)
|
||||
for _, item := range result {
|
||||
assert.Len(t, item, 1)
|
||||
assert.Equal(t, u.Id, item[0].Id)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("should not error or return anything for invalid channel IDs", func(t *testing.T) {
|
||||
_, err := ss.Channel().GetMembersInfoByChannelIds([]string{model.NewId(), model.NewId()})
|
||||
var nfErr *store.ErrNotFound
|
||||
require.True(t, errors.As(err, &nfErr))
|
||||
})
|
||||
}
|
||||
|
||||
func testChannelStoreSearchGroupChannels(t *testing.T, ss store.Store) {
|
||||
// Users
|
||||
u1 := &model.User{}
|
||||
|
||||
@@ -35,6 +35,29 @@ func (_m *ChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int64, error
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetChannelsLeftSince provides a mock function with given fields: userID, since
|
||||
func (_m *ChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
ret := _m.Called(userID, since)
|
||||
|
||||
var r0 []string
|
||||
if rf, ok := ret.Get(0).(func(string, int64) []string); ok {
|
||||
r0 = rf(userID, since)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]string)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, int64) error); ok {
|
||||
r1 = rf(userID, since)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetUsersInChannelDuring provides a mock function with given fields: startTime, endTime, channelID
|
||||
func (_m *ChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
|
||||
ret := _m.Called(startTime, endTime, channelID)
|
||||
|
||||
@@ -674,13 +674,13 @@ func (_m *ChannelStore) GetChannelUnread(channelID string, userID string) (*mode
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetChannels provides a mock function with given fields: teamID, userID, includeDeleted, lastDeleteAt
|
||||
func (_m *ChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
ret := _m.Called(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
// GetChannels provides a mock function with given fields: teamID, userID, opts
|
||||
func (_m *ChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
ret := _m.Called(teamID, userID, opts)
|
||||
|
||||
var r0 model.ChannelList
|
||||
if rf, ok := ret.Get(0).(func(string, string, bool, int) model.ChannelList); ok {
|
||||
r0 = rf(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.ChannelSearchOpts) model.ChannelList); ok {
|
||||
r0 = rf(teamID, userID, opts)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(model.ChannelList)
|
||||
@@ -688,8 +688,8 @@ func (_m *ChannelStore) GetChannels(teamID string, userID string, includeDeleted
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, bool, int) error); ok {
|
||||
r1 = rf(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
if rf, ok := ret.Get(1).(func(string, string, *model.ChannelSearchOpts) error); ok {
|
||||
r1 = rf(teamID, userID, opts)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
@@ -789,6 +789,29 @@ func (_m *ChannelStore) GetChannelsByUser(userID string, includeDeleted bool, la
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetChannelsWithCursor provides a mock function with given fields: teamId, userId, opts, afterChannelID
|
||||
func (_m *ChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
ret := _m.Called(teamId, userId, opts, afterChannelID)
|
||||
|
||||
var r0 model.ChannelList
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.ChannelSearchOpts, string) model.ChannelList); ok {
|
||||
r0 = rf(teamId, userId, opts, afterChannelID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(model.ChannelList)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, *model.ChannelSearchOpts, string) error); ok {
|
||||
r1 = rf(teamId, userId, opts, afterChannelID)
|
||||
} 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)
|
||||
@@ -1121,6 +1144,29 @@ func (_m *ChannelStore) GetMembersForUser(teamID string, userID string) (model.C
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetMembersForUserWithCursor provides a mock function with given fields: userID, afterChannel, afterUser, limit, lastUpdateAt
|
||||
func (_m *ChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
ret := _m.Called(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
|
||||
var r0 model.ChannelMembers
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, int, int) model.ChannelMembers); ok {
|
||||
r0 = rf(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(model.ChannelMembers)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, string, int, int) error); ok {
|
||||
r1 = rf(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -1144,6 +1190,29 @@ func (_m *ChannelStore) GetMembersForUserWithPagination(userID string, page int,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetMembersInfoByChannelIds provides a mock function with given fields: channelIDs
|
||||
func (_m *ChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
ret := _m.Called(channelIDs)
|
||||
|
||||
var r0 map[string][]*model.User
|
||||
if rf, ok := ret.Get(0).(func([]string) map[string][]*model.User); ok {
|
||||
r0 = rf(channelIDs)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(map[string][]*model.User)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func([]string) error); ok {
|
||||
r1 = rf(channelIDs)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetMoreChannels provides a mock function with given fields: teamID, userID, offset, limit
|
||||
func (_m *ChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
|
||||
ret := _m.Called(teamID, userID, offset, limit)
|
||||
|
||||
@@ -1013,10 +1013,10 @@ func (s *TimerLayerChannelStore) GetChannelUnread(channelID string, userID strin
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetChannels(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (model.ChannelList, error) {
|
||||
func (s *TimerLayerChannelStore) GetChannels(teamID string, userID string, opts *model.ChannelSearchOpts) (model.ChannelList, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, includeDeleted, lastDeleteAt)
|
||||
result, err := s.ChannelStore.GetChannels(teamID, userID, opts)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -1093,6 +1093,22 @@ func (s *TimerLayerChannelStore) GetChannelsByUser(userID string, includeDeleted
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetChannelsWithCursor(teamId string, userId string, opts *model.ChannelSearchOpts, afterChannelID string) (model.ChannelList, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetChannelsWithCursor(teamId, userId, opts, afterChannelID)
|
||||
|
||||
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.GetChannelsWithCursor", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetChannelsWithTeamDataByIds(channelIds []string, includeDeleted bool) ([]*model.ChannelWithTeamData, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
@@ -1333,6 +1349,22 @@ func (s *TimerLayerChannelStore) GetMembersForUser(teamID string, userID string)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMembersForUserWithCursor(userID string, afterChannel string, afterUser string, limit int, lastUpdateAt int) (model.ChannelMembers, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetMembersForUserWithCursor(userID, afterChannel, afterUser, limit, lastUpdateAt)
|
||||
|
||||
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.GetMembersForUserWithCursor", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string, page int, perPage int) (model.ChannelMembersWithTeamData, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
@@ -1349,6 +1381,22 @@ func (s *TimerLayerChannelStore) GetMembersForUserWithPagination(userID string,
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMembersInfoByChannelIds(channelIDs []string) (map[string][]*model.User, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetMembersInfoByChannelIds(channelIDs)
|
||||
|
||||
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.GetMembersInfoByChannelIds", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMoreChannels(teamID string, userID string, offset int, limit int) (model.ChannelList, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
@@ -2254,6 +2302,22 @@ func (s *TimerLayerChannelMemberHistoryStore) DeleteOrphanedRows(limit int) (int
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelMemberHistoryStore) GetChannelsLeftSince(userID string, since int64) ([]string, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.ChannelMemberHistoryStore.GetChannelsLeftSince(userID, since)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("ChannelMemberHistoryStore.GetChannelsLeftSince", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, endTime int64, channelID string) ([]*model.ChannelMemberHistoryResult, error) {
|
||||
start := timemodule.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user