Shared channels plugin APIs for MS Teams plugin (#25805)

New plugin APIs and hooks for accessing Shared Channels service via plugin. 

- RegisterPluginForSharedChannels(opts model.RegisterPluginOpts) (remoteID string, err error)
- UnregisterPluginForSharedChannels(pluginID string) error
- ShareChannel(sc *model.SharedChannel) (*model.SharedChannel, error)
- UpdateSharedChannel(sc *model.SharedChannel) (*model.SharedChannel, error)
- UnshareChannel(channelID string) (unshared bool, err error)
- UpdateSharedChannelCursor(channelID, remoteID string, cusror model.GetPostsSinceForSyncCursor) error
- SyncSharedChannel(channelID string) error
- InviteRemoteToChannel(channelID string, remoteID string, userID string) error
- UninviteRemoteFromChannel(channelID string, remoteID string) error

Hooks
- OnSharedChannelsSyncMsg(msg *model.SyncMsg, rc *model.RemoteCluster) (model.SyncResponse, error)
- OnSharedChannelsPing(rc *model.RemoteCluster) bool
Этот коммит содержится в:
Doug Lauder
2023-12-22 17:00:27 -05:00
коммит произвёл GitHub
родитель 0f3553c8ab
Коммит 2d1135ca46
40 изменённых файлов: 1725 добавлений и 168 удалений

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

@@ -90,6 +90,32 @@ func (_m *RemoteClusterStore) GetAll(filter model.RemoteClusterQueryFilter) ([]*
return r0, r1
}
// GetByPluginID provides a mock function with given fields: pluginID
func (_m *RemoteClusterStore) GetByPluginID(pluginID string) (*model.RemoteCluster, error) {
ret := _m.Called(pluginID)
var r0 *model.RemoteCluster
var r1 error
if rf, ok := ret.Get(0).(func(string) (*model.RemoteCluster, error)); ok {
return rf(pluginID)
}
if rf, ok := ret.Get(0).(func(string) *model.RemoteCluster); ok {
r0 = rf(pluginID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.RemoteCluster)
}
}
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(pluginID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Save provides a mock function with given fields: rc
func (_m *RemoteClusterStore) Save(rc *model.RemoteCluster) (*model.RemoteCluster, error) {
ret := _m.Called(rc)

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

@@ -15,10 +15,6 @@ import (
"github.com/stretchr/testify/require"
)
const (
testPluginID = "com.sample.blap"
)
func TestRemoteClusterStore(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("RemoteClusterGetAllInChannel", func(t *testing.T) { testRemoteClusterGetAllInChannel(t, rctx, ss) })
t.Run("RemoteClusterGetAllNotInChannel", func(t *testing.T) { testRemoteClusterGetAllNotInChannel(t, rctx, ss) })
@@ -30,12 +26,17 @@ func TestRemoteClusterStore(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("RemoteClusterUpdateTopics", func(t *testing.T) { testRemoteClusterUpdateTopics(t, rctx, ss) })
}
func makeSiteURL() string {
return "www.example.com/" + model.NewId()
}
func testRemoteClusterSave(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: "some_remote",
SiteURL: "somewhere.com",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
PluginID: model.NewId(),
}
rcSaved, err := ss.RemoteCluster().Save(rc)
@@ -44,12 +45,13 @@ func testRemoteClusterSave(t *testing.T, rctx request.CTX, ss store.Store) {
require.Equal(t, rc.SiteURL, rcSaved.SiteURL)
require.Greater(t, rc.CreateAt, int64(0))
require.Equal(t, rc.LastPingAt, int64(0))
require.Equal(t, rc.PluginID, rcSaved.PluginID)
require.Equal(t, rc.Options, model.Bitmask(0))
})
t.Run("Save missing display name", func(t *testing.T) {
rc := &model.RemoteCluster{
SiteURL: "somewhere.com",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
}
_, err := ss.RemoteCluster().Save(rc)
@@ -59,34 +61,84 @@ func testRemoteClusterSave(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Save missing creator id", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: "some_remote_2",
SiteURL: "somewhere.com",
SiteURL: makeSiteURL(),
}
_, err := ss.RemoteCluster().Save(rc)
require.Error(t, err)
})
t.Run("Save pluginID collision", func(t *testing.T) {
const testPluginID = "com.example.collision"
rc := &model.RemoteCluster{
Name: "some_remote",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
PluginID: testPluginID,
}
_, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err)
rc2 := &model.RemoteCluster{
Name: "another_remote",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
PluginID: testPluginID,
}
rcSaved, err := ss.RemoteCluster().Save(rc2)
require.NoError(t, err)
require.NotNil(t, rcSaved)
// original remotecluster should be returned
require.Equal(t, rc.Name, rcSaved.Name)
require.Equal(t, rc.SiteURL, rcSaved.SiteURL)
require.Greater(t, rc.CreateAt, int64(0))
require.Equal(t, rc.PluginID, rcSaved.PluginID)
})
t.Run("Save multiple with blank pluginID", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: model.NewId(),
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
}
_, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err)
rc2 := &model.RemoteCluster{
Name: model.NewId(),
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
}
_, err = ss.RemoteCluster().Save(rc2)
require.NoError(t, err)
})
t.Run("Save for plugin with options", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: "plugin_remote",
SiteURL: "plugin.example.com",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
PluginID: testPluginID,
PluginID: model.NewId(),
Options: model.BitflagOptionAutoShareDMs,
}
rcSaved, err := ss.RemoteCluster().Save(rc)
require.NoError(t, err)
require.Equal(t, testPluginID, rcSaved.PluginID)
require.Equal(t, rc.PluginID, rcSaved.PluginID)
require.Equal(t, model.BitflagOptionAutoShareDMs, rcSaved.Options)
require.True(t, rcSaved.IsOptionFlagSet(model.BitflagOptionAutoShareDMs))
rc.Name = "plugin_remote_2"
rc.SiteURL = makeSiteURL()
rc.PluginID = model.NewId()
rc.SiteURL = "plugin2.example.com"
rc.UnsetOptionFlag(model.BitflagOptionAutoShareDMs)
rcSaved, err = ss.RemoteCluster().Save(rc)
require.NoError(t, err)
require.Equal(t, testPluginID, rcSaved.PluginID)
require.Equal(t, rc.PluginID, rcSaved.PluginID)
require.Equal(t, model.Bitmask(0), rcSaved.Options)
require.False(t, rcSaved.IsOptionFlagSet(model.BitflagOptionAutoShareDMs))
})
@@ -96,7 +148,7 @@ func testRemoteClusterDelete(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Delete", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: "shortlived_remote",
SiteURL: "nowhere.com",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
}
rcSaved, err := ss.RemoteCluster().Save(rc)
@@ -118,9 +170,9 @@ func testRemoteClusterGet(t *testing.T, rctx request.CTX, ss store.Store) {
t.Run("Get", func(t *testing.T) {
rc := &model.RemoteCluster{
Name: "shortlived_remote_2",
SiteURL: "nowhere.com",
SiteURL: makeSiteURL(),
CreatorId: model.NewId(),
PluginID: testPluginID,
PluginID: model.NewId(),
}
rc.SetOptionFlag(model.BitflagOptionAutoShareDMs)
rcSaved, err := ss.RemoteCluster().Save(rc)
@@ -129,7 +181,7 @@ func testRemoteClusterGet(t *testing.T, rctx request.CTX, ss store.Store) {
rcGet, err := ss.RemoteCluster().Get(rcSaved.RemoteId)
require.NoError(t, err)
require.Equal(t, rcSaved.RemoteId, rcGet.RemoteId)
require.Equal(t, testPluginID, rcGet.PluginID)
require.Equal(t, rcSaved.PluginID, rcGet.PluginID)
require.True(t, rcGet.IsOptionFlagSet(model.BitflagOptionAutoShareDMs))
})
@@ -147,10 +199,10 @@ func testRemoteClusterGetAll(t *testing.T, rctx request.CTX, ss store.Store) {
pingLongAgo := model.GetMillis() - (model.RemoteOfflineAfterMillis * 3)
data := []*model.RemoteCluster{
{Name: "offline_remote", CreatorId: userId, SiteURL: "somewhere.com", LastPingAt: pingLongAgo, Topics: " shared incident "},
{Name: "some_online_remote", CreatorId: userId, SiteURL: "nowhere.com", LastPingAt: now, Topics: " shared incident "},
{Name: "another_online_remote", CreatorId: model.NewId(), SiteURL: "underwhere.com", LastPingAt: now, Topics: ""},
{Name: "another_offline_remote", CreatorId: model.NewId(), SiteURL: "knowhere.com", LastPingAt: pingLongAgo, Topics: " shared "},
{Name: "offline_remote", CreatorId: userId, SiteURL: makeSiteURL(), LastPingAt: pingLongAgo, Topics: " shared incident "},
{Name: "some_online_remote", CreatorId: userId, SiteURL: makeSiteURL(), LastPingAt: now, Topics: " shared incident "},
{Name: "another_online_remote", CreatorId: model.NewId(), SiteURL: makeSiteURL(), LastPingAt: now, Topics: ""},
{Name: "another_offline_remote", CreatorId: model.NewId(), SiteURL: makeSiteURL(), LastPingAt: pingLongAgo, Topics: " shared "},
{Name: "brand_new_offline_remote", CreatorId: userId, SiteURL: "", LastPingAt: 0, Topics: " bogus shared stuff "},
}
@@ -245,6 +297,11 @@ func testRemoteClusterGetAll(t *testing.T, rctx request.CTX, ss store.Store) {
}
func testRemoteClusterGetAllInChannel(t *testing.T, rctx request.CTX, ss store.Store) {
const (
testPluginID_1 = "com.sample.blap"
testPluginID_2 = "com.sample.bloop"
)
require.NoError(t, clearRemoteClusters(ss))
now := model.GetMillis()
@@ -272,8 +329,8 @@ func testRemoteClusterGetAllInChannel(t *testing.T, rctx request.CTX, ss store.S
// Create some remote clusters
rcData := []*model.RemoteCluster{
{Name: "AAAA_Inc", CreatorId: userId, SiteURL: "aaaa.com", RemoteId: model.NewId(), LastPingAt: now, PluginID: testPluginID},
{Name: "BBBB_Inc", CreatorId: userId, SiteURL: "bbbb.com", RemoteId: model.NewId(), LastPingAt: 0, PluginID: testPluginID},
{Name: "AAAA_Inc", CreatorId: userId, SiteURL: "aaaa.com", RemoteId: model.NewId(), LastPingAt: now, PluginID: testPluginID_1},
{Name: "BBBB_Inc", CreatorId: userId, SiteURL: "bbbb.com", RemoteId: model.NewId(), LastPingAt: 0, PluginID: testPluginID_2},
{Name: "CCCC_Inc", CreatorId: userId, SiteURL: "cccc.com", RemoteId: model.NewId(), LastPingAt: now},
{Name: "DDDD_Inc", CreatorId: userId, SiteURL: "dddd.com", RemoteId: model.NewId(), LastPingAt: now},
{Name: "EEEE_Inc", CreatorId: userId, SiteURL: "eeee.com", RemoteId: model.NewId(), LastPingAt: 0},
@@ -305,8 +362,8 @@ func testRemoteClusterGetAllInChannel(t *testing.T, rctx request.CTX, ss store.S
require.Len(t, list, 2, "channel 1 should have 2 remote clusters")
ids := getIds(list)
require.ElementsMatch(t, []string{rcData[0].RemoteId, rcData[1].RemoteId}, ids)
require.Equal(t, testPluginID, rcData[0].PluginID)
require.Equal(t, testPluginID, rcData[1].PluginID)
require.Equal(t, testPluginID_1, rcData[0].PluginID)
require.Equal(t, testPluginID_2, rcData[1].PluginID)
})
t.Run("Channel 1 online only", func(t *testing.T) {