Files
team/server/channels/api4/outgoing_oauth_connection_test.go
0be13193c0 Fix missing return after c.Err in two api4 handlers (#37281)
* Fix missing return after c.Err in api4 handlers

Two handlers set c.Err but omitted a return, allowing subsequent code
to execute with an error already signalled:

- getJobs: invalid status passed to GetJobsByTypesAndStatuses DB query
- validateOutgoingOAuthConnectionCredentials: auditRec.Success() and
  ReturnStatusOK called even when token retrieval failed

* Drop redundant w.WriteHeader in error branch

c.Err being set is sufficient; the framework writes the error response
after the handler returns. Calling w.WriteHeader explicitly would cause
a double-write.

* Remove unused resultStatusCode variable

* Add integration test for getJobs with invalid status param

* Fix inconsistent error assertion in validate test

The invalid-credentials test was the only error-path check in the file
using httpRecorder.Code. All other error cases check c.Err.StatusCode,
which is consistent with the framework pattern (c.Err drives the HTTP
response; handlers do not write it directly).

* Add API-layer assertion to invalid validate test

The test previously only checked c.Err.StatusCode (internal handler
state). A regression that sets c.Err but fails to write the HTTP error
response would go undetected. Now the test also calls the endpoint
through the full API layer and asserts the HTTP response is not 200.

Mock matchers changed to mock.Anything so the expectation matches both
the direct handler call and the API-layer call.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 09:12:46 +02:00

1466 lines
48 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"
"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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
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(t)
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(t, 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(t)
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(t, 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(t)
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(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
canRead := checkOutgoingOAuthConnectionReadPermissions(c, th.BasicTeam.Id)
require.True(t, canRead)
})
}
func TestCheckOutgoingOAuthConnectionWritePermissions(t *testing.T) {
t.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
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(t)
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(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
canWrite := checkOutgoingOAuthConnectionWritePermissions(c)
require.True(t, canWrite)
})
}
// Client tests
func TestClientOutgoingOAuthConnectionGet(t *testing.T) {
t.Run("No license returns 501", func(t *testing.T) {
th := Setup(t).InitBasic(t)
th.AddPermissionToRole(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
th.LoginTeamAdmin(t)
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(t)
th.AddPermissionToRole(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.TeamAdminRoleId)
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(false)
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(t)
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(t, 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{}
outgoingOauthIface.Mock.On("GetConnectionForAudience", mock.Anything, "knowhere.com").Return(conn, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, model.PermissionManageOwnOutgoingWebhooks.Id, model.SystemUserRoleId)
th.AddPermissionToRole(t, 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{}
outgoingOauthIface.Mock.On("GetConnections", mock.Anything, mock.Anything).Return([]*model.OutgoingOAuthConnection{conn}, nil)
outgoingOauthIface.Mock.On("SanitizeConnections", mock.Anything)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, 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)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, 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)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, 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)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.AddPermissionToRole(t, 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)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
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.Run("no feature flag, no interface, no license", func(t *testing.T) {
th := Setup(t).InitBasic(t)
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(t)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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(t)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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(t)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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.Run("getOutgoingOAuthConnection", func(t *testing.T) {
th := Setup(t).InitBasic(t)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
conn := newOutgoingOAuthConnection()
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(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
req, err := http.NewRequest("GET", "/", nil)
require.NoError(t, err)
c.Params = &web.Params{
OutgoingOAuthConnectionID: conn.Id,
}
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())
})
t.Run("listOutgoingOAuthConnections", func(t *testing.T) {
th := Setup(t).InitBasic(t)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
conn := newOutgoingOAuthConnection()
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(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
req, err := http.NewRequest("GET", "/", nil)
require.NoError(t, err)
conns := []*model.OutgoingOAuthConnection{conn}
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())
})
t.Run("listOutgoingOAuthConnections with limit", func(t *testing.T) {
th := Setup(t).InitBasic(t)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
conn := newOutgoingOAuthConnection()
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(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
req, err := http.NewRequest("GET", "/?limit=2", nil)
require.NoError(t, err)
conns := []*model.OutgoingOAuthConnection{conn}
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())
})
}
func TestHandlerOutgoingOAuthConnectionListReadOnly(t *testing.T) {
t.Run("listOutgoingOAuthConnections", func(t *testing.T) {
th := Setup(t).InitBasic(t)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
conn := newOutgoingOAuthConnection()
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(t, model.PermissionManageOthersOutgoingWebhooks.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
req, err := http.NewRequest("GET", "/?team_id="+th.BasicTeam.Id, nil)
require.NoError(t, err)
conns := []*model.OutgoingOAuthConnection{conn}
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())
})
t.Run("listOutgoingOAuthConnections with limit", func(t *testing.T) {
th := Setup(t).InitBasic(t)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
conn := newOutgoingOAuthConnection()
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(t, model.PermissionManageOthersOutgoingWebhooks.Id, model.TeamAdminRoleId)
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
req, err := http.NewRequest("GET", "/?limit=2&team_id="+th.BasicTeam.Id, nil)
require.NoError(t, err)
conns := []*model.OutgoingOAuthConnection{conn}
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())
})
}
func TestHandlerOutgoingOAuthConnectionUpdate(t *testing.T) {
t.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.WriteString(`{/}`)
req, err := http.NewRequest("PUT", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.WriteString(`{"Id": "` + model.NewId() + `", "name": "changed name"}`)
req, err := http.NewRequest("PUT", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
conn.Id = model.NewId() // Faking an ID for the connection
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{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
body := &bytes.Buffer{}
body.WriteString(`{/}`)
req, err := http.NewRequest("POST", "/", body)
if err != nil {
t.Error(err)
}
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, 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{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
// Helper to create a fake OAuth server for validation tests
newFakeOAuthServer := func(t *testing.T) *httptest.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()
})
return server
}
t.Run("no permissions", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
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)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
server := newFakeOAuthServer(t)
conn := newOutgoingOAuthConnection()
conn.CreatorId = model.NewId()
conn.OAuthTokenURL = server.URL + "/invalid"
outgoingOauthIface := &mocks.OutgoingOAuthConnectionInterface{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
th.App.Srv().OutgoingOAuthConnection = outgoingOauthIface
// Use mock.Anything matchers so the expectation matches both the
// direct handler call below and the API-layer call that follows.
outgoingOauthIface.Mock.On("RetrieveTokenForConnection", mock.Anything, mock.Anything).Return(
&model.OutgoingOAuthConnectionToken{},
model.NewAppError(whereOutgoingOAuthConnection, "api.context.outgoing_oauth_connection.validate_connection_credentials.input_error", nil, "error", http.StatusBadRequest),
)
th.AddPermissionToRole(t, model.PermissionManageOutgoingOAuthConnections.Id, model.SystemUserRoleId)
// Direct handler call: verify c.Err is populated with the correct status.
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)
body := &bytes.Buffer{}
require.NoError(t, json.NewEncoder(body).Encode(conn))
req, err := http.NewRequest("POST", "/", body)
require.NoError(t, err)
httpRecorder := httptest.NewRecorder()
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
validateOutgoingOAuthConnectionCredentials(c, w, r)
}).ServeHTTP(httpRecorder, req)
require.Equal(t, http.StatusBadRequest, c.Err.StatusCode)
// API-layer call: verify the framework translates c.Err into a non-200
// HTTP response, catching any regression where the error is set but not
// written to the response.
apiResp, apiErr := th.SystemAdminClient.DoAPIPostJSON(context.Background(), "/oauth/outgoing_connections/validate", conn)
require.Error(t, apiErr)
require.Equal(t, http.StatusBadRequest, apiResp.StatusCode)
apiResp.Body.Close()
})
t.Run("success", func(t *testing.T) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
server := newFakeOAuthServer(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)
th.AddPermissionToRole(t, 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{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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) {
th := Setup(t).InitBasic(t)
defer outgoingOauthConnectionsCleanup(t, th)
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise, "outgoing_oauth_connections")
license.Id = "test-license-id"
th.App.Srv().SetLicense(license)
server := newFakeOAuthServer(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,
}
th.AddPermissionToRole(t, 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{}
th.App.Config().ServiceSettings.EnableOutgoingOAuthConnections = new(true)
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)
})
}