mattermost-community-enterp.../channels/api4/outgoing_oauth_connection_test.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

1719 lines
59 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package api4
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin/plugintest/mock"
"github.com/mattermost/mattermost/server/v8/channels/web"
"github.com/mattermost/mattermost/server/v8/einterfaces/mocks"
"github.com/stretchr/testify/require"
)
func newOutgoingOAuthConnection() *model.OutgoingOAuthConnection {
return &model.OutgoingOAuthConnection{
Name: "test",
ClientId: "test",
ClientSecret: "test",
OAuthTokenURL: "http://localhost:9999/oauth/token",
GrantType: model.OutgoingOAuthConnectionGrantTypeClientCredentials,
Audiences: []string{"http://example.com"},
}
}
func outgoingOauthConnectionsCleanup(t *testing.T, th *TestHelper) {
t.Helper()
// Remove all connections
conns, errCleanup := th.App.Srv().Store().OutgoingOAuthConnection().GetConnections(th.Context, model.OutgoingOAuthConnectionGetConnectionsFilter{})
require.NoError(t, errCleanup)
for _, c := range conns {
require.NoError(t, th.App.Srv().Store().OutgoingOAuthConnection().DeleteConnection(th.Context, c.Id))
}
}
// Helper tests
func TestCheckOutgoingOAuthConnectionReadPermissions(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
t.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
canRead := checkOutgoingOAuthConnectionReadPermissions(c, th.BasicTeam.Id)
require.False(t, canRead)
})
t.Run("with management permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
canReadWithTeam := checkOutgoingOAuthConnectionReadPermissions(c, th.BasicTeam.Id)
require.True(t, canReadWithTeam)
canReadWithoutTeam := checkOutgoingOAuthConnectionReadPermissions(c, "")
require.True(t, canReadWithoutTeam)
})
t.Run("with slash command management permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.TeamAdminRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.TeamAdminRoleId)
canRead := checkOutgoingOAuthConnectionReadPermissions(c, th.BasicTeam.Id)
require.True(t, canRead)
})
t.Run("with outgoing webhooks management permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.TeamAdminRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
canRead := checkOutgoingOAuthConnectionReadPermissions(c, th.BasicTeam.Id)
require.True(t, canRead)
})
}
func TestCheckOutgoingOAuthConnectionWritePermissions(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
t.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
canWrite := checkOutgoingOAuthConnectionWritePermissions(c)
require.False(t, canWrite)
})
t.Run("with permissions", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c := &Context{}
c.AppContext = th.Context.WithSession(&session)
c.App = th.App
c.Logger = th.App.Srv().Log()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
canWrite := checkOutgoingOAuthConnectionWritePermissions(c)
require.True(t, canWrite)
})
}
// Client tests
func TestClientOutgoingOAuthConnectionGet(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
t.Run("No license returns 501", func(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTION", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTION")
th := Setup(t).InitBasic()
defer th.TearDown()
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
defer func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
}()
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
// th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
th.LoginTeamAdmin()
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
TeamId: th.BasicTeam.Id,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.Error(t, err)
require.Nil(t, connections)
require.Equal(t, 501, response.StatusCode)
})
t.Run("license but no config enabled returns 501", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(false)
defer func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
}()
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
th.LoginTeamAdmin()
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
TeamId: th.BasicTeam.Id,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.Error(t, err)
require.Nil(t, connections)
require.Equal(t, 501, response.StatusCode)
})
}
func TestClientListOutgoingOAuthConnection(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
t.Run("no permissions", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err := th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
TeamId: th.BasicTeam.Id,
}
connection, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.Error(t, err)
require.Nil(t, connection)
require.Equal(t, http.StatusForbidden, response.StatusCode)
})
t.Run("manager do not require team id", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err := th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.NoError(t, err)
require.Equal(t, 200, response.StatusCode)
require.Equal(t, 0, len(connections))
})
t.Run("empty", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err := th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
TeamId: th.BasicTeam.Id,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.NoError(t, err)
require.Equal(t, 200, response.StatusCode)
require.Equal(t, 0, len(connections))
})
t.Run("filter by audience", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.Audiences = []string{"http://knowhere.com"}
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnectionForAudience", mock.Anything, "knowhere.com").Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err = th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 1,
Audience: "knowhere.com",
TeamId: th.BasicTeam.Id,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.NoError(t, err)
require.Equal(t, 200, response.StatusCode)
require.Equal(t, 1, len(connections))
require.Equal(t, conn, connections[0])
})
t.Run("return result", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(model.PermissionManageOwnSlashCommands.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{conn}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err = th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
filters := model.OutgoingOAuthConnectionGetConnectionsFilter{
Limit: 10,
TeamId: th.BasicTeam.Id,
}
connections, response, err := th.Client.GetOutgoingOAuthConnections(context.Background(), filters)
require.NoError(t, err)
require.Equal(t, 200, response.StatusCode)
require.Equal(t, 1, len(connections))
require.Equal(t, conn, connections[0])
})
}
func TestClientGetOutgoingOAuthConnection(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
t.Run("no permissions", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
_, _, err := th.Client.Login(context.Background(), th.BasicUser.Email, th.BasicUser.Password)
require.NoError(t, err)
connection, response, err := th.Client.GetOutgoingOAuthConnection(context.Background(), "test")
require.Error(t, err)
require.Nil(t, connection)
require.Equal(t, http.StatusForbidden, response.StatusCode)
})
t.Run("return result (management permissions)", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("GetConnection", mock.Anything, mock.Anything).Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
connection, response, err := th.Client.GetOutgoingOAuthConnection(context.Background(), conn.Id)
require.NoError(t, err)
require.Equal(t, 200, response.StatusCode)
require.NotNil(t, connection)
require.Equal(t, conn.Id, connection.Id)
require.Equal(t, conn, connection)
})
}
func TestClientCreateOutgoingOAuthConnection(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
t.Run("no permissions", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("SaveConnection", mock.Anything, mock.Anything).Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
connection, response, err := th.Client.CreateOutgoingOAuthConnection(context.Background(), conn)
require.Error(t, err)
require.Nil(t, connection)
require.Equal(t, http.StatusForbidden, response.StatusCode)
})
t.Run("ok", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("SaveConnection", mock.Anything, mock.Anything).Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
connection, response, err := th.Client.CreateOutgoingOAuthConnection(context.Background(), conn)
require.NoError(t, err)
require.NotNil(t, connection)
require.Equal(t, http.StatusCreated, response.StatusCode)
require.Equal(t, conn, connection)
})
}
func TestClientUpdateOutgoingOAuthConnection(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
t.Run("no permissions", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
connection, response, err := th.Client.UpdateOutgoingOAuthConnection(context.Background(), conn)
require.Error(t, err)
require.Nil(t, connection)
require.Equal(t, http.StatusForbidden, response.StatusCode)
})
t.Run("ok", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("GetConnection", mock.Anything, conn.Id).Return(conn, nil)
outgoingOauthIface.Mock.On("UpdateConnection", mock.Anything, conn).Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
updatedConn := conn
updatedConn.Name = "updated name"
connection, response, err := th.Client.UpdateOutgoingOAuthConnection(context.Background(), conn)
require.NoError(t, err)
require.NotNil(t, connection)
require.Equal(t, http.StatusOK, response.StatusCode)
require.Equal(t, updatedConn, connection)
})
}
func TestClientDeleteOutgoingOAuthConnection(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
t.Run("no permissions", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
response, err := th.Client.DeleteOutgoingOAuthConnection(context.Background(), conn.Id)
require.Error(t, err)
require.Equal(t, http.StatusForbidden, response.StatusCode)
})
t.Run("ok", func(t *testing.T) {
defer outgoingOauthConnectionsCleanup(t, th)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn, err := th.App.Srv().Store().OutgoingOAuthConnection().SaveConnection(th.Context, conn)
require.NoError(t, err)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("GetConnection", mock.Anything, conn.Id).Return(conn, nil)
outgoingOauthIface.Mock.On("DeleteConnection", mock.Anything, conn.Id).Return(nil)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginSystemAdmin()
response, err := th.Client.DeleteOutgoingOAuthConnection(context.Background(), conn.Id)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
})
}
// Handler tests
func TestEnsureOutgoingOAuthConnectionInterface(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
t.Run("no feature flag, no interface, no license", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
th.App.Srv().OutgoingOAuthConnection = nil
_, valid := ensureOutgoingOAuthConnectionInterface(c, "api")
require.False(t, valid)
})
t.Run("config, no interface, no license", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
th.App.Srv().OutgoingOAuthConnection = nil
_, valid := ensureOutgoingOAuthConnectionInterface(c, "api")
require.False(t, valid)
})
t.Run("feature flag, interface defined, no license", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
_, valid := ensureOutgoingOAuthConnectionInterface(c, "api")
require.False(t, valid)
})
t.Run("feature flag, interface defined, valid license", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
svc, valid := ensureOutgoingOAuthConnectionInterface(c, "api")
require.True(t, valid)
require.NotNil(t, svc)
})
}
func TestHandlerOutgoingOAuthConnectionListGet(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
conn := newOutgoingOAuthConnection()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
t.Run("getOutgoingOAuthConnection", func(t *testing.T) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Error(err)
}
c.Params = &web.Params{
OutgoingOAuthConnectionID: conn.Id,
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnection", c.AppContext, c.Params.OutgoingOAuthConnectionID).Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
getOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
var buf bytes.Buffer
require.NoError(t, json.NewEncoder(&buf).Encode(conn))
})
t.Run("listOutgoingOAuthConnections", func(t *testing.T) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Error(err)
}
conns := []*model.OutgoingOAuthConnection{conn}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", c.AppContext, mock.Anything).Return(conns, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
listOutgoingOAuthConnections(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
var buf bytes.Buffer
require.NoError(t, json.NewEncoder(&buf).Encode(conn))
})
t.Run("listOutgoingOAuthConnections with limit", func(t *testing.T) {
req, err := http.NewRequest("GET", "/?limit=2", nil)
if err != nil {
t.Error(err)
}
conns := []*model.OutgoingOAuthConnection{conn}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", c.AppContext, model.OutgoingOAuthConnectionGetConnectionsFilter{Limit: 2}).Return(conns, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
listOutgoingOAuthConnections(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
var buf bytes.Buffer
require.NoError(t, json.NewEncoder(&buf).Encode(conn))
})
}
func TestHandlerOutgoingOAuthConnectionListReadOnly(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
conn := newOutgoingOAuthConnection()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.TeamAdminRoleId,
}
c.AppContext = th.Context.WithSession(&session)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOthersOutgoingWebhooks.Id, model.TeamAdminRoleId)
t.Run("listOutgoingOAuthConnections", func(t *testing.T) {
req, err := http.NewRequest("GET", "/?team_id="+th.BasicTeam.Id, nil)
if err != nil {
t.Error(err)
}
conns := []*model.OutgoingOAuthConnection{conn}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", c.AppContext, mock.Anything).Return(conns, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
listOutgoingOAuthConnections(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
var buf bytes.Buffer
require.NoError(t, json.NewEncoder(&buf).Encode(conn))
})
t.Run("listOutgoingOAuthConnections with limit", func(t *testing.T) {
req, err := http.NewRequest("GET", "/?limit=2&team_id="+th.BasicTeam.Id, nil)
if err != nil {
t.Error(err)
}
conns := []*model.OutgoingOAuthConnection{conn}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnections", c.AppContext, model.OutgoingOAuthConnectionGetConnectionsFilter{Limit: 2}).Return(conns, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
listOutgoingOAuthConnections(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
var buf bytes.Buffer
require.NoError(t, json.NewEncoder(&buf).Encode(conn))
})
}
func TestHandlerOutgoingOAuthConnectionUpdate(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
t.Run("no permissions", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
req, err := http.NewRequest("PUT", "/", nil)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
c.Params = &web.Params{
OutgoingOAuthConnectionID: model.NewId(),
}
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
updateOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusForbidden, c.Err.StatusCode)
})
t.Run("bad json", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.Write([]byte(`{/}`))
req, err := http.NewRequest("PUT", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
c.Params = &web.Params{
OutgoingOAuthConnectionID: model.NewId(),
}
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
updateOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusBadRequest, c.Err.StatusCode)
})
t.Run("wrong id", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.Write([]byte(`{"Id": "` + model.NewId() + `", "name": "changed name"}`))
req, err := http.NewRequest("PUT", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
c.Params = &web.Params{
OutgoingOAuthConnectionID: model.NewId(),
}
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
updateOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusBadRequest, c.Err.StatusCode)
})
t.Run("ok", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
conn := newOutgoingOAuthConnection()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn.Id = model.NewId() // Faking an ID for the connection
t.Cleanup(func() {
conn.Id = ""
})
body := &bytes.Buffer{}
inputConnection := conn
inputConnection.Name = "changed name"
require.NoError(t, json.NewEncoder(body).Encode(inputConnection))
req, err := http.NewRequest("PUT", "/"+conn.Id, body)
if err != nil {
t.Error(err)
}
c.Params = &web.Params{
OutgoingOAuthConnectionID: conn.Id,
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnection", c.AppContext, c.Params.OutgoingOAuthConnectionID).Return(conn, nil)
outgoingOauthIface.Mock.On("UpdateConnection", c.AppContext, inputConnection).Return(inputConnection, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
updateOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
})
}
func TestHandlerOutgoingOAuthConnectionHandlerCreate(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
t.Run("no permissions", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
createOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusForbidden, c.Err.StatusCode)
})
t.Run("bad json", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.Write([]byte(`{/}`))
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
createOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusBadRequest, c.Err.StatusCode)
})
t.Run("ok", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
conn := newOutgoingOAuthConnection()
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
require.NoError(t, json.NewEncoder(body).Encode(conn))
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
// Handler sets the connection creator ID to the session user ID
handlerConn := conn
handlerConn.CreatorId = session.UserId
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("SaveConnection", c.AppContext, handlerConn).Return(handlerConn, nil)
outgoingOauthIface.Mock.On("SanitizeConnection", mock.Anything)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
createOutgoingOAuthConnection(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusCreated, httpRecorder.Code)
require.NotEmpty(t, httpRecorder.Body.String())
})
}
func TestHandlerOutgoingOAuthConnectionHandlerValidate(t *testing.T) {
t.Skip("https://mattermost.atlassian.net/browse/MM-61690")
os.Setenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_OUTGOINGOAUTHCONNECTIONS")
th := Setup(t).InitBasic()
defer th.TearDown()
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
defer func() {
appErr := th.App.Srv().RemoveLicense()
require.Nil(t, appErr)
}()
// Run a server to fake the valid and invalid requests made to the oauth server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch strings.TrimSpace(r.URL.Path) {
case "/valid":
w.WriteHeader(http.StatusOK)
case "/invalid":
w.WriteHeader(http.StatusBadRequest)
default:
http.NotFoundHandler().ServeHTTP(w, r)
}
}))
t.Cleanup(func() {
server.Close()
})
t.Run("no permissions", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusForbidden, c.Err.StatusCode)
})
t.Run("no interface", func(t *testing.T) {
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Error(err)
}
session := model.Session{
Id: model.NewId(),
UserId: model.NewId(),
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
defer func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
}()
th.App.Srv().OutgoingOAuthConnection = nil
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusNotImplemented, c.Err.StatusCode)
})
t.Run("invalid", func(t *testing.T) {
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn.OAuthTokenURL = server.URL + "/invalid"
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: conn.CreatorId,
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
require.NoError(t, json.NewEncoder(body).Encode(conn))
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("RetrieveTokenForConnection", c.AppContext, conn).Return(&model.OutgoingOAuthConnectionToken{}, model.NewAppError(whereOutgoingOAuthConnection, "api.context.outgoing_oauth_connection.validate_connection_credentials.input_error", nil, "error", http.StatusBadRequest))
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusBadRequest, httpRecorder.Code)
})
t.Run("success", func(t *testing.T) {
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn.OAuthTokenURL = server.URL + "/valid"
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: conn.CreatorId,
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
require.NoError(t, json.NewEncoder(body).Encode(conn))
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("RetrieveTokenForConnection", c.AppContext, conn).Return(&model.OutgoingOAuthConnectionToken{}, nil)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
})
t.Run("success (stored connection)", func(t *testing.T) {
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn.OAuthTokenURL = server.URL + "/valid"
c := &Context{}
c.AppContext = th.Context
c.App = th.App
c.Logger = th.App.Srv().Log()
session := model.Session{
Id: model.NewId(),
UserId: conn.CreatorId,
Roles: model.SystemUserRoleId,
}
c.AppContext = th.Context.WithSession(&session)
c.Params = &web.Params{
OutgoingOAuthConnectionID: conn.Id,
}
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
require.NoError(t, json.NewEncoder(body).Encode(conn))
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthImpl := th.App.Srv().OutgoingOAuthConnection
outgoingOAuthConnectionConfig := th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = model.NewPointer(true)
t.Cleanup(func() {
th.App.Srv().OutgoingOAuthConnection = outgoingOauthImpl
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = outgoingOAuthConnectionConfig
})
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
outgoingOauthIface.Mock.On("GetConnection", c.AppContext, conn.Id).Return(conn, nil)
outgoingOauthIface.Mock.On("RetrieveTokenForConnection", c.AppContext, conn).Return(&model.OutgoingOAuthConnectionToken{}, nil)
httpRecorder := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
})
handler.ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusOK, httpRecorder.Code)
})
}