Adds Shared Channel related API endpoints (#27436)
* Adds Shared Channel management API endpoints
New endpoints for the following routes are added:
- Get Shared Channel Remotes by Remote Cluster at `GET
/api/v4/remotecluster/{remote_id}/sharedchannelremotes`
- Invite Remote Cluster to Channel at `POST
/api/v4/remotecluster/{remote_id}/channels/invite`
- Uninvite Remote Cluster to Channel at `POST
/api/v4/remotecluster/{remote_id}/channels/uninvite`
These endpoints are planned to be used from the system console, and
gated through the `manage_secure_connections` permission.
* Adds i18n messages for API errors
* Fix pagination flaky test
* Fix linter
* Adds the posibility of filtering shared channel remotes by home
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
60ffd00d30
Коммит
3dc0e63c03
@@ -129,8 +129,10 @@ type Routes struct {
|
||||
Exports *mux.Router // 'api/v4/exports'
|
||||
Export *mux.Router // 'api/v4/exports/{export_name:.+\\.zip}'
|
||||
|
||||
RemoteCluster *mux.Router // 'api/v4/remotecluster'
|
||||
SharedChannels *mux.Router // 'api/v4/sharedchannels'
|
||||
RemoteCluster *mux.Router // 'api/v4/remotecluster'
|
||||
SharedChannels *mux.Router // 'api/v4/sharedchannels'
|
||||
ChannelForRemote *mux.Router // 'api/v4/remotecluster/{remote_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}'
|
||||
SharedChannelRemotes *mux.Router // 'api/v4/remotecluster/{remote_id:[A-Za-z0-9]+}/sharedchannelremotes'
|
||||
|
||||
Permissions *mux.Router // 'api/v4/permissions'
|
||||
|
||||
@@ -265,6 +267,8 @@ func Init(srv *app.Server) (*API, error) {
|
||||
|
||||
api.BaseRoutes.RemoteCluster = api.BaseRoutes.APIRoot.PathPrefix("/remotecluster").Subrouter()
|
||||
api.BaseRoutes.SharedChannels = api.BaseRoutes.APIRoot.PathPrefix("/sharedchannels").Subrouter()
|
||||
api.BaseRoutes.SharedChannelRemotes = api.BaseRoutes.RemoteCluster.PathPrefix("/{remote_id:[A-Za-z0-9]+}/sharedchannelremotes").Subrouter()
|
||||
api.BaseRoutes.ChannelForRemote = api.BaseRoutes.RemoteCluster.PathPrefix("/{remote_id:[A-Za-z0-9]+}/channels/{channel_id:[A-Za-z0-9]+}").Subrouter()
|
||||
|
||||
api.BaseRoutes.Permissions = api.BaseRoutes.APIRoot.PathPrefix("/permissions").Subrouter()
|
||||
|
||||
|
||||
@@ -8,11 +8,17 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/audit"
|
||||
)
|
||||
|
||||
func (api *API) InitSharedChannels() {
|
||||
api.BaseRoutes.SharedChannels.Handle("/{team_id:[A-Za-z0-9]+}", api.APISessionRequired(getSharedChannels)).Methods(http.MethodGet)
|
||||
api.BaseRoutes.SharedChannels.Handle("/remote_info/{remote_id:[A-Za-z0-9]+}", api.APISessionRequired(getRemoteClusterInfo)).Methods(http.MethodGet)
|
||||
|
||||
api.BaseRoutes.SharedChannelRemotes.Handle("", api.APISessionRequired(getSharedChannelRemotesByRemoteCluster)).Methods(http.MethodGet)
|
||||
api.BaseRoutes.ChannelForRemote.Handle("/invite", api.APISessionRequired(inviteRemoteClusterToChannel)).Methods(http.MethodPost)
|
||||
api.BaseRoutes.ChannelForRemote.Handle("/uninvite", api.APISessionRequired(uninviteRemoteClusterToChannel)).Methods(http.MethodPost)
|
||||
}
|
||||
|
||||
func getSharedChannels(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -86,3 +92,146 @@ func getRemoteClusterInfo(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func getSharedChannelRemotesByRemoteCluster(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSecureConnections) {
|
||||
c.SetPermissionError(model.PermissionManageSecureConnections)
|
||||
return
|
||||
}
|
||||
|
||||
// make sure remote cluster service is enabled.
|
||||
if _, appErr := c.App.GetRemoteClusterService(); appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
if _, appErr := c.App.GetRemoteCluster(c.Params.RemoteId); appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
filter := model.SharedChannelRemoteFilterOpts{
|
||||
RemoteId: c.Params.RemoteId,
|
||||
ExcludeHome: c.Params.ExcludeHome,
|
||||
ExcludeRemote: c.Params.ExcludeRemote,
|
||||
}
|
||||
sharedChannelRemotes, err := c.App.GetSharedChannelRemotes(c.Params.Page, c.Params.PerPage, filter)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("getSharedChannelRemotesByRemoteCluster", "api.shared_channel.get_shared_channel_remotes_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(sharedChannelRemotes); err != nil {
|
||||
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
|
||||
func inviteRemoteClusterToChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.RequireChannelId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSecureConnections) {
|
||||
c.SetPermissionError(model.PermissionManageSharedChannels)
|
||||
return
|
||||
}
|
||||
|
||||
// make sure remote cluster service is enabled.
|
||||
if _, appErr := c.App.GetRemoteClusterService(); appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
if _, appErr := c.App.GetRemoteCluster(c.Params.RemoteId); appErr != nil {
|
||||
c.SetInvalidRemoteIdError(c.Params.RemoteId)
|
||||
return
|
||||
}
|
||||
|
||||
if _, appErr := c.App.GetChannel(c.AppContext, c.Params.ChannelId); appErr != nil {
|
||||
c.SetInvalidURLParam("channel_id")
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("inviteRemoteClusterToChannel", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId)
|
||||
audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId)
|
||||
audit.AddEventParameter(auditRec, "user_id", c.AppContext.Session().UserId)
|
||||
|
||||
if err := c.App.InviteRemoteToChannel(c.Params.ChannelId, c.Params.RemoteId, c.AppContext.Session().UserId, true); err != nil {
|
||||
c.Err = model.NewAppError("inviteRemoteClusterToChannel", "api.shared_channel.invite_remote_to_channel_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func uninviteRemoteClusterToChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireRemoteId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.RequireChannelId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSecureConnections) {
|
||||
c.SetPermissionError(model.PermissionManageSharedChannels)
|
||||
return
|
||||
}
|
||||
|
||||
// make sure remote cluster service is enabled.
|
||||
if _, appErr := c.App.GetRemoteClusterService(); appErr != nil {
|
||||
c.Err = appErr
|
||||
return
|
||||
}
|
||||
|
||||
if _, appErr := c.App.GetRemoteCluster(c.Params.RemoteId); appErr != nil {
|
||||
c.SetInvalidRemoteIdError(c.Params.RemoteId)
|
||||
return
|
||||
}
|
||||
|
||||
if _, appErr := c.App.GetChannel(c.AppContext, c.Params.ChannelId); appErr != nil {
|
||||
c.SetInvalidURLParam("channel_id")
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("uninviteRemoteClusterToChannel", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId)
|
||||
audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId)
|
||||
|
||||
hasRemote, err := c.App.HasRemote(c.Params.ChannelId, c.Params.RemoteId)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("uninviteRemoteClusterToChannel", "api.shared_channel.has_remote_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
// if the channel is not shared with the remote, we return early
|
||||
if !hasRemote {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.App.UninviteRemoteFromChannel(c.Params.ChannelId, c.Params.RemoteId); err != nil {
|
||||
c.Err = model.NewAppError("uninviteRemoteClusterToChannel", "api.shared_channel.uninvite_remote_to_channel_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
return
|
||||
}
|
||||
|
||||
auditRec.Success()
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -22,10 +23,16 @@ var (
|
||||
)
|
||||
|
||||
func setupForSharedChannels(tb testing.TB) *TestHelper {
|
||||
return SetupConfig(tb, func(cfg *model.Config) {
|
||||
th := SetupConfig(tb, func(cfg *model.Config) {
|
||||
*cfg.ExperimentalSettings.EnableRemoteClusterService = true
|
||||
*cfg.ExperimentalSettings.EnableSharedChannels = true
|
||||
})
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.SiteURL = fmt.Sprintf("http://localhost:%d", th.Server.ListenAddr.Port)
|
||||
})
|
||||
|
||||
return th
|
||||
}
|
||||
|
||||
func TestGetAllSharedChannels(t *testing.T) {
|
||||
@@ -232,3 +239,278 @@ func TestCreateDirectChannelWithRemoteUser(t *testing.T) {
|
||||
require.True(t, dm.IsShared())
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetSharedChannelRemotesByRemoteCluster(t *testing.T) {
|
||||
t.Run("Should not work if the remote cluster service is not enabled", func(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
resp, err := th.SystemAdminClient.DeleteRemoteCluster(context.Background(), model.NewId())
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
th := setupForSharedChannels(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
newRC1 := &model.RemoteCluster{Name: "rc1", SiteURL: "http://example1.com", CreatorId: th.SystemAdminUser.Id}
|
||||
newRC2 := &model.RemoteCluster{Name: "rc2", SiteURL: "http://example2.com", CreatorId: th.SystemAdminUser.Id}
|
||||
|
||||
rc1, appErr := th.App.AddRemoteCluster(newRC1)
|
||||
require.Nil(t, appErr)
|
||||
rc2, appErr := th.App.AddRemoteCluster(newRC2)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
c1 := th.CreateChannelWithClientAndTeam(th.Client, model.ChannelTypeOpen, th.BasicTeam.Id)
|
||||
sc1 := &model.SharedChannel{
|
||||
ChannelId: c1.Id,
|
||||
TeamId: th.BasicTeam.Id,
|
||||
ShareName: "shared_1",
|
||||
ShareDisplayName: "Shared Channel 1", // for sorting purposes
|
||||
CreatorId: th.BasicUser.Id,
|
||||
RemoteId: rc1.RemoteId,
|
||||
Home: true,
|
||||
}
|
||||
_, err := th.App.ShareChannel(th.Context, sc1)
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := th.CreateChannelWithClientAndTeam(th.Client, model.ChannelTypeOpen, th.BasicTeam.Id)
|
||||
sc2 := &model.SharedChannel{
|
||||
ChannelId: c2.Id,
|
||||
TeamId: th.BasicTeam.Id,
|
||||
ShareName: "shared_2",
|
||||
ShareDisplayName: "Shared Channel 2",
|
||||
CreatorId: th.BasicUser.Id,
|
||||
RemoteId: rc1.RemoteId,
|
||||
Home: false,
|
||||
}
|
||||
|
||||
_, err = th.App.ShareChannel(th.Context, sc2)
|
||||
require.NoError(t, err)
|
||||
|
||||
c3 := th.CreateChannelWithClientAndTeam(th.Client, model.ChannelTypeOpen, th.BasicTeam.Id)
|
||||
sc3 := &model.SharedChannel{
|
||||
ChannelId: c3.Id,
|
||||
TeamId: th.BasicTeam.Id,
|
||||
ShareName: "shared_3",
|
||||
CreatorId: th.BasicUser.Id,
|
||||
RemoteId: rc2.RemoteId,
|
||||
}
|
||||
_, err = th.App.ShareChannel(th.Context, sc3)
|
||||
require.NoError(t, err)
|
||||
|
||||
// for the pagination test, we need to get the channelId of the
|
||||
// second SharedChannelRemote that belongs to RC1, sorted by ID,
|
||||
// so we accumulate those SharedChannelRemotes on creation and
|
||||
// later sort them to be able to get the right one for the test
|
||||
// result
|
||||
sharedChannelRemotesFromRC1 := []*model.SharedChannelRemote{}
|
||||
|
||||
// create the shared channel remotes
|
||||
for _, sc := range []*model.SharedChannel{sc1, sc2, sc3} {
|
||||
scr := &model.SharedChannelRemote{
|
||||
Id: model.NewId(),
|
||||
ChannelId: sc.ChannelId,
|
||||
CreatorId: sc.CreatorId,
|
||||
IsInviteAccepted: true,
|
||||
IsInviteConfirmed: true,
|
||||
RemoteId: sc.RemoteId,
|
||||
}
|
||||
_, err = th.App.SaveSharedChannelRemote(scr)
|
||||
require.NoError(t, err)
|
||||
|
||||
if scr.RemoteId == rc1.RemoteId {
|
||||
sharedChannelRemotesFromRC1 = append(sharedChannelRemotesFromRC1, scr)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(sharedChannelRemotesFromRC1, func(i, j int) bool {
|
||||
return sharedChannelRemotesFromRC1[i].Id < sharedChannelRemotesFromRC1[j].Id
|
||||
})
|
||||
|
||||
t.Run("should return the expected shared channels", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Client *model.Client4
|
||||
RemoteId string
|
||||
ExcludeHome bool
|
||||
ExcludeRemote bool
|
||||
Page int
|
||||
PerPage int
|
||||
ExpectedStatusCode int
|
||||
ExpectedError bool
|
||||
ExpectedIds []string
|
||||
}{
|
||||
{
|
||||
Name: "should not work if the user doesn't have the right permissions",
|
||||
Client: th.Client,
|
||||
RemoteId: rc1.RemoteId,
|
||||
Page: 0,
|
||||
PerPage: 100,
|
||||
ExpectedStatusCode: http.StatusForbidden,
|
||||
ExpectedError: true,
|
||||
},
|
||||
{
|
||||
Name: "should not work if the remote cluster is nonexistent",
|
||||
Client: th.SystemAdminClient,
|
||||
RemoteId: model.NewId(),
|
||||
Page: 0,
|
||||
PerPage: 100,
|
||||
ExpectedStatusCode: http.StatusNotFound,
|
||||
ExpectedError: true,
|
||||
},
|
||||
{
|
||||
Name: "should return the complete list of shared channel remotes for a remote cluster",
|
||||
Client: th.SystemAdminClient,
|
||||
RemoteId: rc1.RemoteId,
|
||||
Page: 0,
|
||||
PerPage: 100,
|
||||
ExpectedStatusCode: http.StatusOK,
|
||||
ExpectedError: false,
|
||||
ExpectedIds: []string{sc1.ChannelId, sc2.ChannelId},
|
||||
},
|
||||
{
|
||||
Name: "should return only the shared channel remotes homed localy",
|
||||
Client: th.SystemAdminClient,
|
||||
RemoteId: rc1.RemoteId,
|
||||
ExcludeRemote: true,
|
||||
Page: 0,
|
||||
PerPage: 100,
|
||||
ExpectedStatusCode: http.StatusOK,
|
||||
ExpectedError: false,
|
||||
ExpectedIds: []string{sc1.ChannelId},
|
||||
},
|
||||
{
|
||||
Name: "should return only the shared channel remotes homed remotely",
|
||||
Client: th.SystemAdminClient,
|
||||
RemoteId: rc1.RemoteId,
|
||||
ExcludeHome: true,
|
||||
Page: 0,
|
||||
PerPage: 100,
|
||||
ExpectedStatusCode: http.StatusOK,
|
||||
ExpectedError: false,
|
||||
ExpectedIds: []string{sc2.ChannelId},
|
||||
},
|
||||
{
|
||||
Name: "should correctly paginate the results",
|
||||
Client: th.SystemAdminClient,
|
||||
RemoteId: rc1.RemoteId,
|
||||
Page: 1,
|
||||
PerPage: 1,
|
||||
ExpectedStatusCode: http.StatusOK,
|
||||
ExpectedError: false,
|
||||
ExpectedIds: []string{sharedChannelRemotesFromRC1[1].ChannelId},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
scrs, resp, err := tc.Client.GetSharedChannelRemotesByRemoteCluster(context.Background(), tc.RemoteId, tc.ExcludeHome, tc.ExcludeRemote, tc.Page, tc.PerPage)
|
||||
checkHTTPStatus(t, resp, tc.ExpectedStatusCode)
|
||||
if tc.ExpectedError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Len(t, scrs, len(tc.ExpectedIds))
|
||||
|
||||
foundIds := []string{}
|
||||
for _, scr := range scrs {
|
||||
require.Equal(t, tc.RemoteId, scr.RemoteId)
|
||||
foundIds = append(foundIds, scr.ChannelId)
|
||||
}
|
||||
require.ElementsMatch(t, tc.ExpectedIds, foundIds)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestInviteRemoteClusterToChannel(t *testing.T) {
|
||||
t.Run("Should not work if the remote cluster service is not enabled", func(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
resp, err := th.SystemAdminClient.InviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
th := setupForSharedChannels(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
newRC := &model.RemoteCluster{Name: "rc", SiteURL: "http://example.com", CreatorId: th.SystemAdminUser.Id}
|
||||
|
||||
rc, appErr := th.App.AddRemoteCluster(newRC)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
t.Run("Should not work if the user doesn't have the right permissions", func(t *testing.T) {
|
||||
resp, err := th.Client.InviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckForbiddenStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should not work if the remote cluster is nonexistent", func(t *testing.T) {
|
||||
resp, err := th.SystemAdminClient.InviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should not work if the channel is nonexistent", func(t *testing.T) {
|
||||
resp, err := th.SystemAdminClient.InviteRemoteClusterToChannel(context.Background(), rc.RemoteId, model.NewId())
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should correctly invite the remote cluster to the channel", func(t *testing.T) {
|
||||
t.Skip("Requires server2server communication: ToBeImplemented")
|
||||
})
|
||||
|
||||
t.Run("should do nothing but return 204 if the remote cluster is already invited to the channel", func(t *testing.T) {
|
||||
t.Skip("Requires server2server communication: ToBeImplemented")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUninviteRemoteClusterToChannel(t *testing.T) {
|
||||
t.Run("Should not work if the remote cluster service is not enabled", func(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
resp, err := th.SystemAdminClient.UninviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
th := setupForSharedChannels(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
newRC := &model.RemoteCluster{Name: "rc", SiteURL: "http://example.com", CreatorId: th.SystemAdminUser.Id}
|
||||
|
||||
rc, appErr := th.App.AddRemoteCluster(newRC)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
t.Run("Should not work if the user doesn't have the right permissions", func(t *testing.T) {
|
||||
resp, err := th.Client.UninviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckForbiddenStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should not work if the remote cluster is nonexistent", func(t *testing.T) {
|
||||
resp, err := th.SystemAdminClient.UninviteRemoteClusterToChannel(context.Background(), model.NewId(), model.NewId())
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should not work if the channel is nonexistent", func(t *testing.T) {
|
||||
resp, err := th.SystemAdminClient.UninviteRemoteClusterToChannel(context.Background(), rc.RemoteId, model.NewId())
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("should correctly uninvite the remote cluster to the channel", func(t *testing.T) {
|
||||
t.Skip("Requires server2server communication: ToBeImplemented")
|
||||
})
|
||||
|
||||
t.Run("should do nothing but return 204 if the remote cluster is not sharing the channel", func(t *testing.T) {
|
||||
t.Skip("Requires server2server communication: ToBeImplemented")
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user