mattermost-community-enterp.../channels/store/storetest/shared_channel_store.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

1460 lines
49 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package storetest
import (
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/request"
"github.com/mattermost/mattermost/server/v8/channels/store"
)
func TestSharedChannelStore(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore) {
t.Run("SaveSharedChannel", func(t *testing.T) { testSaveSharedChannel(t, rctx, ss) })
t.Run("GetSharedChannel", func(t *testing.T) { testGetSharedChannel(t, rctx, ss) })
t.Run("HasSharedChannel", func(t *testing.T) { testHasSharedChannel(t, rctx, ss) })
t.Run("GetSharedChannels", func(t *testing.T) { testGetSharedChannels(t, rctx, ss) })
t.Run("UpdateSharedChannel", func(t *testing.T) { testUpdateSharedChannel(t, rctx, ss) })
t.Run("DeleteSharedChannel", func(t *testing.T) { testDeleteSharedChannel(t, rctx, ss) })
t.Run("SaveSharedChannelRemote", func(t *testing.T) { testSaveSharedChannelRemote(t, rctx, ss) })
t.Run("UpdateSharedChannelRemote", func(t *testing.T) { testUpdateSharedChannelRemote(t, rctx, ss) })
t.Run("GetSharedChannelRemote", func(t *testing.T) { testGetSharedChannelRemote(t, rctx, ss) })
t.Run("GetSharedChannelRemoteByIds", func(t *testing.T) { testGetSharedChannelRemoteByIds(t, rctx, ss) })
t.Run("GetSharedChannelRemotes", func(t *testing.T) { testGetSharedChannelRemotes(t, rctx, ss) })
t.Run("HasRemote", func(t *testing.T) { testHasRemote(t, rctx, ss) })
t.Run("GetRemoteForUser", func(t *testing.T) { testGetRemoteForUser(t, rctx, ss) })
t.Run("UpdateSharedChannelRemoteNextSyncAt", func(t *testing.T) { testUpdateSharedChannelRemoteCursor(t, rctx, ss) })
t.Run("UpdateGlobalUserSyncCursor", func(t *testing.T) { testUpdateGlobalUserSyncCursor(t, rctx, ss) })
t.Run("DeleteSharedChannelRemote", func(t *testing.T) { testDeleteSharedChannelRemote(t, rctx, ss) })
t.Run("SaveSharedChannelUser", func(t *testing.T) { testSaveSharedChannelUser(t, rctx, ss) })
t.Run("GetSharedChannelSingleUser", func(t *testing.T) { testGetSingleSharedChannelUser(t, rctx, ss) })
t.Run("GetSharedChannelUser", func(t *testing.T) { testGetSharedChannelUser(t, rctx, ss) })
t.Run("GetSharedChannelUsersForSync", func(t *testing.T) { testGetSharedChannelUsersForSync(t, rctx, ss) })
t.Run("UpdateSharedChannelUserLastSyncAt", func(t *testing.T) { testUpdateSharedChannelUserLastSyncAt(t, rctx, ss) })
t.Run("SaveSharedChannelAttachment", func(t *testing.T) { testSaveSharedChannelAttachment(t, rctx, ss) })
t.Run("UpsertSharedChannelAttachment", func(t *testing.T) { testUpsertSharedChannelAttachment(t, rctx, ss) })
t.Run("GetSharedChannelAttachment", func(t *testing.T) { testGetSharedChannelAttachment(t, rctx, ss) })
t.Run("UpdateSharedChannelAttachmentLastSyncAt", func(t *testing.T) { testUpdateSharedChannelAttachmentLastSyncAt(t, rctx, ss) })
}
func testSaveSharedChannel(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save shared channel (home)", func(t *testing.T) {
channel, err := createTestChannel(ss, rctx, "test_save")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
Home: true,
}
scSaved, err := ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel")
require.Equal(t, sc.ChannelId, scSaved.ChannelId)
require.Equal(t, sc.TeamId, scSaved.TeamId)
require.Equal(t, sc.CreatorId, scSaved.CreatorId)
// ensure channel's Shared flag is set
channelMod, err := ss.Channel().Get(channel.Id, false)
require.NoError(t, err)
require.True(t, channelMod.IsShared())
})
t.Run("Save shared channel (remote)", func(t *testing.T) {
channel, err := createTestChannel(ss, rctx, "test_save2")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
RemoteId: model.NewId(),
}
scSaved, err := ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel", err)
require.Equal(t, sc.ChannelId, scSaved.ChannelId)
require.Equal(t, sc.TeamId, scSaved.TeamId)
require.Equal(t, sc.CreatorId, scSaved.CreatorId)
// ensure channel's Shared flag is set
channelMod, err := ss.Channel().Get(channel.Id, false)
require.NoError(t, err)
require.True(t, channelMod.IsShared())
})
t.Run("Save invalid shared channel", func(t *testing.T) {
sc := &model.SharedChannel{
ChannelId: "",
TeamId: model.NewId(),
CreatorId: model.NewId(),
ShareName: "testshare",
Home: true,
}
_, err := ss.SharedChannel().Save(sc)
require.Error(t, err, "should error saving invalid shared channel", err)
})
t.Run("Save with invalid channel id", func(t *testing.T) {
sc := &model.SharedChannel{
ChannelId: model.NewId(),
TeamId: model.NewId(),
CreatorId: model.NewId(),
ShareName: "testshare",
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().Save(sc)
require.Error(t, err, "expected error for invalid channel id")
})
}
func testGetSharedChannel(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_get")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
Home: true,
}
scSaved, err := ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel", err)
t.Run("Get existing shared channel", func(t *testing.T) {
sc, err := ss.SharedChannel().Get(scSaved.ChannelId)
require.NoError(t, err, "couldn't get shared channel", err)
require.Equal(t, sc.ChannelId, scSaved.ChannelId)
require.Equal(t, sc.TeamId, scSaved.TeamId)
require.Equal(t, sc.CreatorId, scSaved.CreatorId)
})
t.Run("Get non-existent shared channel", func(t *testing.T) {
sc, err := ss.SharedChannel().Get(model.NewId())
require.Error(t, err)
require.Nil(t, sc)
})
}
func testHasSharedChannel(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_get")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
Home: true,
}
scSaved, err := ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel", err)
t.Run("Get existing shared channel", func(t *testing.T) {
exists, err := ss.SharedChannel().HasChannel(scSaved.ChannelId)
require.NoError(t, err, "couldn't get shared channel", err)
assert.True(t, exists)
})
t.Run("Get non-existent shared channel", func(t *testing.T) {
exists, err := ss.SharedChannel().HasChannel(model.NewId())
require.NoError(t, err)
assert.False(t, exists)
})
}
func testGetSharedChannels(t *testing.T, rctx request.CTX, ss store.Store) {
require.NoError(t, clearSharedChannels(ss))
user, err := createTestUser(rctx, ss, "gary.goodspeed")
require.NoError(t, err)
creator := model.NewId()
team1 := model.NewId()
team2 := model.NewId()
rid1 := model.NewId()
rid2 := model.NewId()
data := []model.SharedChannel{
{CreatorId: creator, TeamId: team1, ShareName: "test1", Home: true},
{CreatorId: creator, TeamId: team1, ShareName: "test2", Home: false, RemoteId: rid1},
{CreatorId: creator, TeamId: team1, ShareName: "test3", Home: false, RemoteId: rid2},
{CreatorId: creator, TeamId: team1, ShareName: "test4", Home: true},
{CreatorId: creator, TeamId: team2, ShareName: "test5", Home: true},
{CreatorId: creator, TeamId: team2, ShareName: "test6", Home: false, RemoteId: rid1},
{CreatorId: creator, TeamId: team2, ShareName: "test7", Home: false, RemoteId: rid2},
{CreatorId: creator, TeamId: team2, ShareName: "test8", Home: true},
{CreatorId: creator, TeamId: team2, ShareName: "test9", Home: true},
}
for i, sc := range data {
channel, err := createTestChannelWithUser(ss, rctx, "test_get2_"+strconv.Itoa(i), user)
require.NoError(t, err)
sc.ChannelId = channel.Id
_, err = ss.SharedChannel().Save(&sc)
require.NoError(t, err, "error saving shared channel")
}
t.Run("Get shared channels home only", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
ExcludeRemote: true,
CreatorId: creator,
}
count, err := ss.SharedChannel().GetAllCount(opts)
require.NoError(t, err, "error getting shared channels count")
home, err := ss.SharedChannel().GetAll(0, 100, opts)
require.NoError(t, err, "error getting shared channels")
require.Equal(t, int(count), len(home))
require.Len(t, home, 5, "should be 5 home channels")
for _, sc := range home {
require.True(t, sc.Home, "should be home channel")
}
})
t.Run("Get shared channels remote only", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
ExcludeHome: true,
}
count, err := ss.SharedChannel().GetAllCount(opts)
require.NoError(t, err, "error getting shared channels count")
remotes, err := ss.SharedChannel().GetAll(0, 100, opts)
require.NoError(t, err, "error getting shared channels")
require.Equal(t, int(count), len(remotes))
require.Len(t, remotes, 4, "should be 4 remote channels")
for _, sc := range remotes {
require.False(t, sc.Home, "should be remote channel")
}
})
t.Run("Get shared channels bad opts", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
ExcludeHome: true,
ExcludeRemote: true,
}
_, err := ss.SharedChannel().GetAll(0, 100, opts)
require.Error(t, err, "error expected")
})
t.Run("Get shared channels by team", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
TeamId: team1,
}
count, err := ss.SharedChannel().GetAllCount(opts)
require.NoError(t, err, "error getting shared channels count")
remotes, err := ss.SharedChannel().GetAll(0, 100, opts)
require.NoError(t, err, "error getting shared channels")
require.Equal(t, int(count), len(remotes))
require.Len(t, remotes, 4, "should be 4 matching channels")
for _, sc := range remotes {
require.Equal(t, team1, sc.TeamId)
}
})
t.Run("Get shared channels invalid pagination", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
TeamId: team1,
}
_, err := ss.SharedChannel().GetAll(-1, 100, opts)
require.Error(t, err)
_, err = ss.SharedChannel().GetAll(0, -100, opts)
require.Error(t, err)
})
t.Run("Get shared channels for member", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
TeamId: team1,
MemberId: user.Id,
}
count, err := ss.SharedChannel().GetAllCount(opts)
require.NoError(t, err, "error getting shared channels count")
remotes, err := ss.SharedChannel().GetAll(0, 100, opts)
require.NoError(t, err, "error getting shared channels")
require.Equal(t, int(count), len(remotes))
require.Len(t, remotes, 4, "should be 4 matching channels")
for _, sc := range remotes {
require.Equal(t, team1, sc.TeamId)
}
})
t.Run("Get shared channels for non-member", func(t *testing.T) {
opts := model.SharedChannelFilterOpts{
TeamId: team1,
MemberId: model.NewId(),
}
count, err := ss.SharedChannel().GetAllCount(opts)
require.NoError(t, err, "error getting shared channels count")
remotes, err := ss.SharedChannel().GetAll(0, 100, opts)
require.NoError(t, err, "error getting shared channels")
require.Equal(t, int(count), len(remotes))
require.Len(t, remotes, 0, "should be 0 matching channels")
})
}
func testUpdateSharedChannel(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_update")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
Home: true,
}
scSaved, err := ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel", err)
t.Run("Update existing shared channel", func(t *testing.T) {
id := model.NewId()
scMod := scSaved // copy struct (contains basic types only)
scMod.ShareName = "newname"
scMod.ShareDisplayName = "For testing"
scMod.ShareHeader = "This is a header."
scMod.RemoteId = id
scUpdated, err := ss.SharedChannel().Update(scMod)
require.NoError(t, err, "couldn't update shared channel", err)
require.Equal(t, "newname", scUpdated.ShareName)
require.Equal(t, "For testing", scUpdated.ShareDisplayName)
require.Equal(t, "This is a header.", scUpdated.ShareHeader)
require.Equal(t, id, scUpdated.RemoteId)
})
t.Run("Update non-existent shared channel", func(t *testing.T) {
sc := &model.SharedChannel{
ChannelId: model.NewId(),
TeamId: model.NewId(),
CreatorId: model.NewId(),
ShareName: "missingshare",
}
_, err := ss.SharedChannel().Update(sc)
require.Error(t, err, "should error when updating non-existent shared channel", err)
})
}
func testDeleteSharedChannel(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_delete")
require.NoError(t, err)
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: model.NewId(),
ShareName: "testshare",
RemoteId: model.NewId(),
}
_, err = ss.SharedChannel().Save(sc)
require.NoError(t, err, "couldn't save shared channel", err)
// add some remotes
for range 10 {
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
IsInviteConfirmed: true, // to avoid adding the IncludeUnconfirmed filter
}
_, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't add remote", err)
}
t.Run("Delete existing shared channel", func(t *testing.T) {
deleted, err := ss.SharedChannel().Delete(channel.Id)
require.NoError(t, err, "delete existing shared channel should not error", err)
require.True(t, deleted, "expected true from delete shared channel")
sc, err := ss.SharedChannel().Get(channel.Id)
require.Error(t, err)
require.Nil(t, sc)
// make sure the remotes were marked as deleted.
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, model.SharedChannelRemoteFilterOpts{ChannelId: channel.Id})
require.NoError(t, err)
require.Len(t, remotes, 0)
deletedRemotes, err := ss.SharedChannel().GetRemotes(0, 999999, model.SharedChannelRemoteFilterOpts{ChannelId: channel.Id, IncludeDeleted: true})
require.NoError(t, err)
require.Len(t, deletedRemotes, 10)
// ensure channel's Shared flag is unset
channelMod, err := ss.Channel().Get(channel.Id, false)
require.NoError(t, err)
require.False(t, channelMod.IsShared())
})
t.Run("Delete non-existent shared channel", func(t *testing.T) {
deleted, err := ss.SharedChannel().Delete(model.NewId())
require.NoError(t, err, "delete non-existent shared channel should not error", err)
require.False(t, deleted, "expected false from delete shared channel")
})
}
func testSaveSharedChannelRemote(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save shared channel remote", func(t *testing.T) {
channel, err := createTestChannel(ss, rctx, "test_save_remote")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save shared channel remote", err)
require.Equal(t, remote.ChannelId, remoteSaved.ChannelId)
require.Equal(t, remote.CreatorId, remoteSaved.CreatorId)
})
t.Run("Save invalid shared channel remote", func(t *testing.T) {
remote := &model.SharedChannelRemote{
ChannelId: "",
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().SaveRemote(remote)
require.Error(t, err, "should error saving invalid remote", err)
})
t.Run("Save shared channel remote with invalid channel id", func(t *testing.T) {
remote := &model.SharedChannelRemote{
ChannelId: model.NewId(),
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().SaveRemote(remote)
require.Error(t, err, "expected error for invalid channel id")
})
}
func testUpdateSharedChannelRemote(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Update shared channel remote", func(t *testing.T) {
channel, err := createTestChannel(ss, rctx, "test_update_remote")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save shared channel remote", err)
remoteSaved.IsInviteAccepted = true
remoteSaved.IsInviteConfirmed = true
remoteUpdated, err := ss.SharedChannel().UpdateRemote(remoteSaved)
require.NoError(t, err, "couldn't update shared channel remote", err)
require.Equal(t, true, remoteUpdated.IsInviteAccepted)
require.Equal(t, true, remoteUpdated.IsInviteConfirmed)
})
t.Run("Update invalid shared channel remote", func(t *testing.T) {
remote := &model.SharedChannelRemote{
ChannelId: "",
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().UpdateRemote(remote)
require.Error(t, err, "should error updating invalid remote", err)
})
t.Run("Update shared channel remote with invalid channel id", func(t *testing.T) {
remote := &model.SharedChannelRemote{
ChannelId: model.NewId(),
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().UpdateRemote(remote)
require.Error(t, err, "expected error for invalid channel id")
})
}
func testGetSharedChannelRemote(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remote_get")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save remote", err)
t.Run("Get existing shared channel remote", func(t *testing.T) {
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err, "could not get shared channel remote", err)
require.Equal(t, remoteSaved.Id, r.Id)
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
})
t.Run("Get non-existent shared channel remote", func(t *testing.T) {
r, err := ss.SharedChannel().GetRemote(model.NewId())
require.Error(t, err)
require.Nil(t, r)
})
}
func testGetSharedChannelRemoteByIds(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remote_get_by_ids")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "could not save remote", err)
t.Run("Get existing shared channel remote by ids", func(t *testing.T) {
r, err := ss.SharedChannel().GetRemoteByIds(remoteSaved.ChannelId, remoteSaved.RemoteId)
require.NoError(t, err, "couldn't get shared channel remote by ids", err)
require.Equal(t, remoteSaved.Id, r.Id)
require.Equal(t, remoteSaved.ChannelId, r.ChannelId)
require.Equal(t, remoteSaved.CreatorId, r.CreatorId)
require.Equal(t, remoteSaved.RemoteId, r.RemoteId)
})
t.Run("Get non-existent shared channel remote by ids", func(t *testing.T) {
r, err := ss.SharedChannel().GetRemoteByIds(model.NewId(), model.NewId())
require.Error(t, err)
require.Nil(t, r)
})
t.Run("Get deleted shared channel remote by ids", func(t *testing.T) {
deleted, err := ss.SharedChannel().DeleteRemote(remoteSaved.Id)
require.NoError(t, err)
require.True(t, deleted)
r, err := ss.SharedChannel().GetRemoteByIds(remoteSaved.ChannelId, remoteSaved.RemoteId)
require.NoError(t, err)
require.Equal(t, remoteSaved.Id, r.Id)
require.NotZero(t, r.DeleteAt)
})
}
func testGetSharedChannelRemotes(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remotes_get2")
require.NoError(t, err)
creator := model.NewId()
remoteId := model.NewId()
remoteId2 := model.NewId()
data := []model.SharedChannelRemote{
{ChannelId: channel.Id, CreatorId: creator, RemoteId: model.NewId(), IsInviteConfirmed: true},
{ChannelId: channel.Id, CreatorId: creator, RemoteId: model.NewId(), IsInviteConfirmed: true},
{ChannelId: channel.Id, CreatorId: creator, RemoteId: remoteId2, IsInviteConfirmed: true},
{CreatorId: creator, RemoteId: remoteId, IsInviteConfirmed: true},
{CreatorId: creator, RemoteId: remoteId, IsInviteConfirmed: true},
{CreatorId: creator, RemoteId: remoteId, IsInviteConfirmed: true, DeleteAt: 123},
{CreatorId: creator, RemoteId: remoteId},
}
// first three remotes are homed locally
_, scErr := shareChannel(ss, channel, true, "")
require.NoError(t, scErr)
for i, r := range data {
if r.ChannelId == "" {
c, err := createTestChannel(ss, rctx, "test_remotes_get2_"+strconv.Itoa(i))
require.NoError(t, err)
r.ChannelId = c.Id
// next three remotes are homed outside
shareChannel(ss, c, false, r.RemoteId)
}
_, err := ss.SharedChannel().SaveRemote(&r)
require.NoError(t, err, "error saving shared channel remote")
}
t.Run("Get shared channel remotes by channel_id", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ChannelId: channel.Id,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 3)
for _, r := range remotes {
require.Equal(t, channel.Id, r.ChannelId)
}
})
t.Run("Get shared channel remotes by invalid channel_id", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ChannelId: model.NewId(),
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 0)
})
t.Run("Get shared channel remotes by remote_id", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
RemoteId: remoteId,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 2) // only confirmed invitations
for _, r := range remotes {
require.Equal(t, remoteId, r.RemoteId)
require.True(t, r.IsInviteConfirmed)
}
})
t.Run("Get shared channel remotes by remote_id including deleted", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
RemoteId: remoteId,
IncludeDeleted: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 3) // only confirmed invitations
deletedCount := 0
for _, r := range remotes {
require.Equal(t, remoteId, r.RemoteId)
require.True(t, r.IsInviteConfirmed)
if r.DeleteAt != 0 {
deletedCount++
}
}
require.Equal(t, 1, deletedCount)
})
t.Run("Get shared channel remotes by invalid remote_id", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
RemoteId: model.NewId(),
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 0)
})
t.Run("Get shared channel remotes by remote_id including unconfirmed", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
RemoteId: remoteId,
IncludeUnconfirmed: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 3)
for _, r := range remotes {
require.Equal(t, remoteId, r.RemoteId)
}
})
t.Run("Get only unconfirmed shared channel remotes for remote", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
RemoteId: remoteId,
ExcludeConfirmed: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 1)
for _, r := range remotes {
require.False(t, r.IsInviteConfirmed)
}
})
t.Run("Get shared channel remotes with bad options", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ExcludeHome: true,
ExcludeRemote: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.Error(t, err, "error expected")
require.Empty(t, remotes)
})
t.Run("Get shared channel remotes excluding shared from outside", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ExcludeRemote: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 3)
})
t.Run("Get shared channel remotes excluding shared from home", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ExcludeHome: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 2)
})
t.Run("Get shared channel remotes excluding shared from outside and by remote_id", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ExcludeRemote: true,
RemoteId: remoteId2,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 1)
})
t.Run("Get shared channel remotes excluding shared from home including unconfirmed", func(t *testing.T) {
opts := model.SharedChannelRemoteFilterOpts{
ExcludeHome: true,
IncludeUnconfirmed: true,
}
remotes, err := ss.SharedChannel().GetRemotes(0, 999999, opts)
require.NoError(t, err, "should not error", err)
require.Len(t, remotes, 3)
})
}
func testHasRemote(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remotes_get2")
require.NoError(t, err)
remote1 := model.NewId()
remote2 := model.NewId()
creator := model.NewId()
data := []model.SharedChannelRemote{
{ChannelId: channel.Id, CreatorId: creator, RemoteId: remote1},
{ChannelId: channel.Id, CreatorId: creator, RemoteId: remote2},
}
for _, r := range data {
_, err := ss.SharedChannel().SaveRemote(&r)
require.NoError(t, err, "error saving shared channel remote")
}
t.Run("has remote", func(t *testing.T) {
has, err := ss.SharedChannel().HasRemote(channel.Id, remote1)
require.NoError(t, err)
assert.True(t, has)
has, err = ss.SharedChannel().HasRemote(channel.Id, remote2)
require.NoError(t, err)
assert.True(t, has)
})
t.Run("wrong channel id ", func(t *testing.T) {
has, err := ss.SharedChannel().HasRemote(model.NewId(), remote1)
require.NoError(t, err)
assert.False(t, has)
})
t.Run("wrong remote id", func(t *testing.T) {
has, err := ss.SharedChannel().HasRemote(channel.Id, model.NewId())
require.NoError(t, err)
assert.False(t, has)
})
t.Run("deleted remote", func(t *testing.T) {
scr, err := ss.SharedChannel().GetRemoteByIds(channel.Id, remote1)
require.NoError(t, err)
require.NotEmpty(t, scr.Id)
deleted, err := ss.SharedChannel().DeleteRemote(scr.Id)
require.NoError(t, err)
require.True(t, deleted)
has, err := ss.SharedChannel().HasRemote(channel.Id, remote1)
require.NoError(t, err)
assert.False(t, has)
})
}
func testGetRemoteForUser(t *testing.T, rctx request.CTX, ss store.Store) {
// add remotes, and users to simulated shared channels.
channel, err := createSharedTestChannel(ss, rctx, "share_test_channel", true, nil)
require.NoError(t, err)
remotes := []*model.RemoteCluster{
{RemoteId: model.NewId(), SiteURL: model.NewId(), CreatorId: model.NewId(), Name: "Test_Remote_1"},
{RemoteId: model.NewId(), SiteURL: model.NewId(), CreatorId: model.NewId(), Name: "Test_Remote_2"},
{RemoteId: model.NewId(), SiteURL: model.NewId(), CreatorId: model.NewId(), Name: "Test_Remote_3"},
}
for _, rc := range remotes {
_, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err)
scr := &model.SharedChannelRemote{Id: model.NewId(), CreatorId: rc.CreatorId, ChannelId: channel.Id, RemoteId: rc.RemoteId}
_, err = ss.SharedChannel().SaveRemote(scr)
require.NoError(t, err)
}
users := []string{model.NewId(), model.NewId(), model.NewId()}
for _, id := range users {
member := &model.ChannelMember{
ChannelId: channel.Id,
UserId: id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
SchemeGuest: false,
SchemeUser: true,
}
_, err := ss.Channel().SaveMember(rctx, member)
require.NoError(t, err)
}
t.Run("user is member", func(t *testing.T) {
for _, rc := range remotes {
for _, userId := range users {
rcFound, err := ss.SharedChannel().GetRemoteForUser(rc.RemoteId, userId)
assert.NoError(t, err, "remote should be found for user")
assert.Equal(t, rc.RemoteId, rcFound.RemoteId, "remoteIds should match")
}
}
})
t.Run("user is not a member", func(t *testing.T) {
for _, rc := range remotes {
rcFound, err := ss.SharedChannel().GetRemoteForUser(rc.RemoteId, model.NewId())
assert.Error(t, err, "remote should not be found for user")
assert.Nil(t, rcFound)
}
})
t.Run("unknown remote id", func(t *testing.T) {
rcFound, err := ss.SharedChannel().GetRemoteForUser(model.NewId(), users[0])
assert.Error(t, err, "remote should not be found for unknown remote id")
assert.Nil(t, rcFound)
})
}
func testUpdateSharedChannelRemoteCursor(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remote_update_next_sync_at")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save remote", err)
futureCreateAt := model.GetMillis() + 3600000 // 1 hour in the future
postCreateID := model.NewId()
futureUpdateAt := model.GetMillis() + (3600000 * 2) // 2 hours in the future
postUpdateID := model.NewId()
cursorCreate := model.GetPostsSinceForSyncCursor{
LastPostCreateAt: futureCreateAt,
LastPostCreateID: postCreateID,
}
cursorUpdate := model.GetPostsSinceForSyncCursor{
LastPostUpdateAt: futureUpdateAt,
LastPostUpdateID: postUpdateID,
}
t.Run("Update cursor CreateAt for remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, cursorCreate)
require.NoError(t, err, "update cursor should not error", err)
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err)
require.Equal(t, futureCreateAt, r.LastPostCreateAt)
require.Equal(t, postCreateID, r.LastPostCreateID)
})
t.Run("Update cursor UpdateAt for remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, cursorUpdate)
require.NoError(t, err, "update cursor should not error", err)
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err)
require.Equal(t, futureUpdateAt, r.LastPostUpdateAt)
require.Equal(t, postUpdateID, r.LastPostUpdateID)
})
t.Run("Update cursor for non-existent shared channel remote", func(t *testing.T) {
err := ss.SharedChannel().UpdateRemoteCursor(model.NewId(), cursorUpdate)
require.Error(t, err, "update non-existent remote should error", err)
})
t.Run("Update with empty cursor", func(t *testing.T) {
emptyCursor := model.GetPostsSinceForSyncCursor{}
err := ss.SharedChannel().UpdateRemoteCursor(remoteSaved.Id, emptyCursor)
require.Error(t, err, "update with empty cursor should error", err)
})
}
func testUpdateGlobalUserSyncCursor(t *testing.T, rctx request.CTX, ss store.Store) {
// Create a remote cluster first
rc := &model.RemoteCluster{
RemoteId: model.NewId(),
SiteURL: "http://example.com",
CreatorId: model.NewId(),
Name: "test",
}
rcSaved, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err, "couldn't save remote cluster", err)
futureTimestamp := model.GetMillis() + 3600000 // 1 hour in the future
t.Run("Update global user sync cursor for remote", func(t *testing.T) {
err := ss.RemoteCluster().UpdateLastGlobalUserSyncAt(rcSaved.RemoteId, futureTimestamp)
require.NoError(t, err, "update global user sync cursor should not error", err)
// Verify that the LastGlobalUserSyncAt field was updated in the RemoteCluster table
// Small sleep to ensure the transaction is committed
time.Sleep(10 * time.Millisecond)
updatedRC, err := ss.RemoteCluster().Get(rcSaved.RemoteId, false)
require.NoError(t, err)
require.NotZero(t, updatedRC.LastGlobalUserSyncAt, "LastGlobalUserSyncAt should not be zero")
require.Equal(t, futureTimestamp, updatedRC.LastGlobalUserSyncAt)
})
t.Run("Update global user sync cursor for non-existent remote", func(t *testing.T) {
err := ss.RemoteCluster().UpdateLastGlobalUserSyncAt(model.NewId(), futureTimestamp)
require.Error(t, err, "update non-existent remote should error", err)
})
}
func testDeleteSharedChannelRemote(t *testing.T, rctx request.CTX, ss store.Store) {
channel, err := createTestChannel(ss, rctx, "test_remote_delete")
require.NoError(t, err)
remote := &model.SharedChannelRemote{
ChannelId: channel.Id,
CreatorId: model.NewId(),
RemoteId: model.NewId(),
}
remoteSaved, err := ss.SharedChannel().SaveRemote(remote)
require.NoError(t, err, "couldn't save remote", err)
t.Run("Delete existing shared channel remote", func(t *testing.T) {
deleted, err := ss.SharedChannel().DeleteRemote(remoteSaved.Id)
require.NoError(t, err, "delete existing remote should not error", err)
require.True(t, deleted, "expected true from delete remote")
r, err := ss.SharedChannel().GetRemote(remoteSaved.Id)
require.NoError(t, err)
require.NotZero(t, r.DeleteAt)
})
t.Run("Delete non-existent shared channel remote", func(t *testing.T) {
deleted, err := ss.SharedChannel().DeleteRemote(model.NewId())
require.NoError(t, err, "delete non-existent remote should not error", err)
require.False(t, deleted, "expected false from delete remote")
})
}
func createTestUser(rctx request.CTX, ss store.Store, username string) (*model.User, error) {
user := &model.User{
Username: username,
Email: "gary@example.com",
}
return ss.User().Save(rctx, user)
}
func createTestChannel(ss store.Store, rctx request.CTX, name string) (*model.Channel, error) {
channel, err := createSharedTestChannel(ss, rctx, name, false, nil)
return channel, err
}
func createTestChannelWithUser(ss store.Store, rctx request.CTX, name string, member *model.User) (*model.Channel, error) {
channel, err := createSharedTestChannel(ss, rctx, name, false, member)
return channel, err
}
func createSharedTestChannel(ss store.Store, rctx request.CTX, name string, shared bool, member *model.User) (*model.Channel, error) {
channel := &model.Channel{
TeamId: model.NewId(),
Type: model.ChannelTypeOpen,
Name: name,
DisplayName: name + " display name",
Header: name + " header",
Purpose: name + "purpose",
CreatorId: model.NewId(),
Shared: model.NewPointer(shared),
}
channel, err := ss.Channel().Save(rctx, channel, 10000)
if err != nil {
return nil, err
}
if member != nil {
newMember := &model.ChannelMember{
ChannelId: channel.Id,
UserId: member.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
SchemeGuest: member.IsGuest(),
SchemeUser: !member.IsGuest(),
}
_, err = ss.Channel().SaveMember(rctx, newMember)
if err != nil {
return nil, err
}
}
if shared {
if _, err := shareChannel(ss, channel, true, ""); err != nil {
return nil, err
}
}
return channel, nil
}
func shareChannel(ss store.Store, channel *model.Channel, home bool, remoteId string) (*model.SharedChannel, error) {
sc := &model.SharedChannel{
ChannelId: channel.Id,
TeamId: channel.TeamId,
CreatorId: channel.CreatorId,
ShareName: channel.Name,
Home: home,
RemoteId: remoteId,
}
return ss.SharedChannel().Save(sc)
}
func clearSharedChannels(ss store.Store) error {
opts := model.SharedChannelFilterOpts{}
all, err := ss.SharedChannel().GetAll(0, 1000, opts)
if err != nil {
return err
}
for _, sc := range all {
if _, err := ss.SharedChannel().Delete(sc.ChannelId); err != nil {
return err
}
}
return nil
}
func testSaveSharedChannelUser(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save shared channel user", func(t *testing.T) {
scUser := &model.SharedChannelUser{
UserId: model.NewId(),
RemoteId: model.NewId(),
ChannelId: model.NewId(),
}
userSaved, err := ss.SharedChannel().SaveUser(scUser)
require.NoError(t, err, "couldn't save shared channel user", err)
require.Equal(t, scUser.UserId, userSaved.UserId)
require.Equal(t, scUser.RemoteId, userSaved.RemoteId)
})
t.Run("Save invalid shared channel user", func(t *testing.T) {
scUser := &model.SharedChannelUser{
UserId: "",
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().SaveUser(scUser)
require.Error(t, err, "should error saving invalid user", err)
})
t.Run("Save shared channel user with invalid remote id", func(t *testing.T) {
scUser := &model.SharedChannelUser{
UserId: model.NewId(),
RemoteId: "bogus",
}
_, err := ss.SharedChannel().SaveUser(scUser)
require.Error(t, err, "expected error for invalid remote id")
})
}
func testGetSingleSharedChannelUser(t *testing.T, rctx request.CTX, ss store.Store) {
scUser := &model.SharedChannelUser{
UserId: model.NewId(),
RemoteId: model.NewId(),
ChannelId: model.NewId(),
}
userSaved, err := ss.SharedChannel().SaveUser(scUser)
require.NoError(t, err, "could not save user", err)
t.Run("Get existing shared channel user", func(t *testing.T) {
r, err := ss.SharedChannel().GetSingleUser(userSaved.UserId, userSaved.ChannelId, userSaved.RemoteId)
require.NoError(t, err, "couldn't get shared channel user", err)
require.Equal(t, userSaved.Id, r.Id)
require.Equal(t, userSaved.UserId, r.UserId)
require.Equal(t, userSaved.RemoteId, r.RemoteId)
require.Equal(t, userSaved.CreateAt, r.CreateAt)
})
t.Run("Get non-existent shared channel user", func(t *testing.T) {
u, err := ss.SharedChannel().GetSingleUser(model.NewId(), model.NewId(), model.NewId())
require.Error(t, err)
require.Nil(t, u)
})
}
func testGetSharedChannelUser(t *testing.T, rctx request.CTX, ss store.Store) {
userId := model.NewId()
for range 10 {
scUser := &model.SharedChannelUser{
UserId: userId,
RemoteId: model.NewId(),
ChannelId: model.NewId(),
}
_, err := ss.SharedChannel().SaveUser(scUser)
require.NoError(t, err, "could not save user", err)
}
t.Run("Get existing shared channel user", func(t *testing.T) {
scus, err := ss.SharedChannel().GetUsersForUser(userId)
require.NoError(t, err, "couldn't get shared channel user", err)
require.Len(t, scus, 10, "should be 10 shared channel user records")
require.Equal(t, userId, scus[0].UserId)
})
t.Run("Get non-existent shared channel user", func(t *testing.T) {
scus, err := ss.SharedChannel().GetUsersForUser(model.NewId())
require.NoError(t, err, "should not error when not found")
require.Empty(t, scus, "should be empty")
})
}
func testGetSharedChannelUsersForSync(t *testing.T, rctx request.CTX, ss store.Store) {
channelID := model.NewId()
remoteID := model.NewId()
earlier := model.GetMillis() - 300000
later := model.GetMillis() + 300000
var users []*model.User
for range 10 { // need real users
u := &model.User{
Username: model.NewUsername(),
Email: model.NewId() + "@example.com",
LastPictureUpdate: model.GetMillis(),
}
u, err := ss.User().Save(rctx, u)
require.NoError(t, err)
users = append(users, u)
}
data := []model.SharedChannelUser{
{UserId: users[0].Id, ChannelId: model.NewId(), RemoteId: model.NewId(), LastSyncAt: later},
{UserId: users[1].Id, ChannelId: model.NewId(), RemoteId: model.NewId(), LastSyncAt: earlier},
{UserId: users[1].Id, ChannelId: model.NewId(), RemoteId: model.NewId(), LastSyncAt: earlier},
{UserId: users[1].Id, ChannelId: channelID, RemoteId: remoteID, LastSyncAt: later},
{UserId: users[2].Id, ChannelId: channelID, RemoteId: model.NewId(), LastSyncAt: later},
{UserId: users[3].Id, ChannelId: channelID, RemoteId: model.NewId(), LastSyncAt: earlier},
{UserId: users[4].Id, ChannelId: channelID, RemoteId: model.NewId(), LastSyncAt: later},
{UserId: users[5].Id, ChannelId: channelID, RemoteId: remoteID, LastSyncAt: earlier},
{UserId: users[6].Id, ChannelId: channelID, RemoteId: remoteID, LastSyncAt: later},
}
for i, u := range data {
scu := &model.SharedChannelUser{
UserId: u.UserId,
ChannelId: u.ChannelId,
RemoteId: u.RemoteId,
LastSyncAt: u.LastSyncAt,
}
_, err := ss.SharedChannel().SaveUser(scu)
require.NoError(t, err, "could not save user #", i, err)
}
t.Run("Filter by channelId", func(t *testing.T) {
filter := model.GetUsersForSyncFilter{
CheckProfileImage: false,
ChannelID: channelID,
}
usersFound, err := ss.SharedChannel().GetUsersForSync(filter)
require.NoError(t, err, "shouldn't error getting users", err)
require.Len(t, usersFound, 2)
for _, user := range usersFound {
require.Contains(t, []string{users[3].Id, users[5].Id}, user.Id)
}
})
t.Run("Filter by channelId for profile image", func(t *testing.T) {
filter := model.GetUsersForSyncFilter{
CheckProfileImage: true,
ChannelID: channelID,
}
usersFound, err := ss.SharedChannel().GetUsersForSync(filter)
require.NoError(t, err, "shouldn't error getting users", err)
require.Len(t, usersFound, 2)
for _, user := range usersFound {
require.Contains(t, []string{users[3].Id, users[5].Id}, user.Id)
}
})
t.Run("Filter by channelId with Limit", func(t *testing.T) {
filter := model.GetUsersForSyncFilter{
CheckProfileImage: true,
ChannelID: channelID,
Limit: 1,
}
usersFound, err := ss.SharedChannel().GetUsersForSync(filter)
require.NoError(t, err, "shouldn't error getting users", err)
require.Len(t, usersFound, 1)
})
}
func testUpdateSharedChannelUserLastSyncAt(t *testing.T, rctx request.CTX, ss store.Store) {
u1 := &model.User{
Username: model.NewUsername(),
Email: model.NewId() + "@example.com",
LastPictureUpdate: model.GetMillis() - 300000, // 5 mins
}
u1, err := ss.User().Save(rctx, u1)
require.NoError(t, err)
u2 := &model.User{
Username: model.NewUsername(),
Email: model.NewId() + "@example.com",
LastPictureUpdate: model.GetMillis() + 300000,
}
u2, err = ss.User().Save(rctx, u2)
require.NoError(t, err)
channelID := model.NewId()
remoteID := model.NewId()
scUser1 := &model.SharedChannelUser{
UserId: u1.Id,
RemoteId: remoteID,
ChannelId: channelID,
}
_, err = ss.SharedChannel().SaveUser(scUser1)
require.NoError(t, err, "couldn't save user", err)
scUser2 := &model.SharedChannelUser{
UserId: u2.Id,
RemoteId: remoteID,
ChannelId: channelID,
}
_, err = ss.SharedChannel().SaveUser(scUser2)
require.NoError(t, err, "couldn't save user", err)
t.Run("Update LastSyncAt for user via UpdateAt", func(t *testing.T) {
err := ss.SharedChannel().UpdateUserLastSyncAt(u1.Id, channelID, remoteID)
require.NoError(t, err, "updateLastSyncAt should not error", err)
scu, err := ss.SharedChannel().GetSingleUser(u1.Id, channelID, remoteID)
require.NoError(t, err)
require.Equal(t, u1.UpdateAt, scu.LastSyncAt)
})
t.Run("Update LastSyncAt for user via LastPictureUpdate", func(t *testing.T) {
err := ss.SharedChannel().UpdateUserLastSyncAt(u2.Id, channelID, remoteID)
require.NoError(t, err, "updateLastSyncAt should not error", err)
scu, err := ss.SharedChannel().GetSingleUser(u2.Id, channelID, remoteID)
require.NoError(t, err)
require.Equal(t, u2.LastPictureUpdate, scu.LastSyncAt)
})
t.Run("Update LastSyncAt for non-existent shared channel user", func(t *testing.T) {
err := ss.SharedChannel().UpdateUserLastSyncAt(model.NewId(), channelID, remoteID)
require.Error(t, err, "update non-existent user should error", err)
})
}
func testSaveSharedChannelAttachment(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save shared channel attachment", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: model.NewId(),
}
saved, err := ss.SharedChannel().SaveAttachment(attachment)
require.NoError(t, err, "couldn't save shared channel attachment", err)
require.Equal(t, attachment.FileId, saved.FileId)
require.Equal(t, attachment.RemoteId, saved.RemoteId)
})
t.Run("Save invalid shared channel attachment", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: "",
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().SaveAttachment(attachment)
require.Error(t, err, "should error saving invalid attachment", err)
})
t.Run("Save shared channel attachment with invalid remote id", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: "bogus",
}
_, err := ss.SharedChannel().SaveAttachment(attachment)
require.Error(t, err, "expected error for invalid remote id")
})
}
func testUpsertSharedChannelAttachment(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Upsert new shared channel attachment", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: model.NewId(),
}
_, err := ss.SharedChannel().UpsertAttachment(attachment)
require.NoError(t, err, "couldn't upsert shared channel attachment", err)
saved, err := ss.SharedChannel().GetAttachment(attachment.FileId, attachment.RemoteId)
require.NoError(t, err, "couldn't get shared channel attachment", err)
require.NotZero(t, saved.CreateAt)
require.Equal(t, saved.CreateAt, saved.LastSyncAt)
})
t.Run("Upsert existing shared channel attachment", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: model.NewId(),
}
saved, err := ss.SharedChannel().SaveAttachment(attachment)
require.NoError(t, err, "couldn't save shared channel attachment", err)
// make sure enough time passed that GetMillis returns a different value
time.Sleep(2 * time.Millisecond)
_, err = ss.SharedChannel().UpsertAttachment(saved)
require.NoError(t, err, "couldn't upsert shared channel attachment", err)
updated, err := ss.SharedChannel().GetAttachment(attachment.FileId, attachment.RemoteId)
require.NoError(t, err, "couldn't get shared channel attachment", err)
require.NotZero(t, updated.CreateAt)
require.Greater(t, updated.LastSyncAt, updated.CreateAt)
})
t.Run("Upsert invalid shared channel attachment", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: "",
RemoteId: model.NewId(),
}
id, err := ss.SharedChannel().UpsertAttachment(attachment)
require.Error(t, err, "should error upserting invalid attachment", err)
require.Empty(t, id)
})
t.Run("Upsert shared channel attachment with invalid remote id", func(t *testing.T) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: "bogus",
}
id, err := ss.SharedChannel().UpsertAttachment(attachment)
require.Error(t, err, "expected error for invalid remote id")
require.Empty(t, id)
})
}
func testGetSharedChannelAttachment(t *testing.T, rctx request.CTX, ss store.Store) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: model.NewId(),
}
saved, err := ss.SharedChannel().SaveAttachment(attachment)
require.NoError(t, err, "could not save attachment", err)
t.Run("Get existing shared channel attachment", func(t *testing.T) {
r, err := ss.SharedChannel().GetAttachment(saved.FileId, saved.RemoteId)
require.NoError(t, err, "couldn't get shared channel attachment", err)
require.Equal(t, saved.Id, r.Id)
require.Equal(t, saved.FileId, r.FileId)
require.Equal(t, saved.RemoteId, r.RemoteId)
require.Equal(t, saved.CreateAt, r.CreateAt)
})
t.Run("Get non-existent shared channel attachment", func(t *testing.T) {
u, err := ss.SharedChannel().GetAttachment(model.NewId(), model.NewId())
require.Error(t, err)
require.Nil(t, u)
})
}
func testUpdateSharedChannelAttachmentLastSyncAt(t *testing.T, rctx request.CTX, ss store.Store) {
attachment := &model.SharedChannelAttachment{
FileId: model.NewId(),
RemoteId: model.NewId(),
}
saved, err := ss.SharedChannel().SaveAttachment(attachment)
require.NoError(t, err, "couldn't save attachment", err)
future := model.GetMillis() + 3600000 // 1 hour in the future
t.Run("Update LastSyncAt for attachment", func(t *testing.T) {
err := ss.SharedChannel().UpdateAttachmentLastSyncAt(saved.Id, future)
require.NoError(t, err, "updateLastSyncAt should not error", err)
f, err := ss.SharedChannel().GetAttachment(saved.FileId, saved.RemoteId)
require.NoError(t, err)
require.Equal(t, future, f.LastSyncAt)
})
t.Run("Update LastSyncAt for non-existent shared channel attachment", func(t *testing.T) {
err := ss.SharedChannel().UpdateAttachmentLastSyncAt(model.NewId(), future)
require.Error(t, err, "update non-existent attachment should error", err)
})
}