Files
mostlymatter/api4/system_test.go
Agniva De Sarker ab8de49f0a MM-40818: Refactor product initialization to happen late (#19658)
This is more of a general refactor of the initialization
process which should allow us to pass services more
easily.

The changes are minimal to keep the scope limited.
For now, the objective is to pass the file service
to the Channels product. For that, it was required
to move some of the enterprise interfaces under Channels
from Server.

We also create a filestore field in the server to
avoid creating filestore reference every time
we make a filestore operation. This will be later
passed on to the Channels product.

Also removed an unnecessary test. 
The test was working so far because we were creating
the filebackend every time for every request. But
we should go via UpdateConfig call which would fail,
were we to assign an invalid filestore name.

So we were actually testing for a different thing.
Therefore, removed the test.

```release-note
NONE
```
2022-03-03 12:22:10 +05:30

898 строки
26 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package api4
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/utils/fileutils"
)
func TestGetPing(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
t.Run("healthy", func(t *testing.T) {
status, _, err := client.GetPing()
require.NoError(t, err)
assert.Equal(t, model.StatusOk, status)
})
t.Run("unhealthy", func(t *testing.T) {
goRoutineHealthThreshold := *th.App.Config().ServiceSettings.GoroutineHealthThreshold
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.GoroutineHealthThreshold = goRoutineHealthThreshold })
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.GoroutineHealthThreshold = 10 })
status, resp, err := client.GetPing()
require.Error(t, err)
CheckInternalErrorStatus(t, resp)
assert.Equal(t, model.StatusUnhealthy, status)
})
}, "basic ping")
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
t.Run("healthy", func(t *testing.T) {
status, _, err := client.GetPingWithServerStatus()
require.NoError(t, err)
assert.Equal(t, model.StatusOk, status)
})
}, "with server status")
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
th.App.ReloadConfig()
resp, err := client.DoAPIGet("/system/ping", "")
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
respBytes, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
respString := string(respBytes)
require.NotContains(t, respString, "TestFeatureFlag")
// Run the environment variable override code to test
os.Setenv("MM_FEATUREFLAGS_TESTFEATURE", "testvalueunique")
defer os.Unsetenv("MM_FEATUREFLAGS_TESTFEATURE")
th.App.ReloadConfig()
resp, err = client.DoAPIGet("/system/ping", "")
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
respBytes, err = ioutil.ReadAll(resp.Body)
require.NoError(t, err)
respString = string(respBytes)
require.Contains(t, respString, "testvalue")
}, "ping feature flag test")
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
th.App.ReloadConfig()
resp, err := client.DoAPIGet("/system/ping?device_id=platform:id", "")
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
var respMap map[string]string
err = json.NewDecoder(resp.Body).Decode(&respMap)
require.NoError(t, err)
assert.Equal(t, "unknown", respMap["CanReceiveNotifications"]) // Unrecognized platform
}, "ping and test push notification")
}
func TestGetAudits(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
audits, _, err := th.SystemAdminClient.GetAudits(0, 100, "")
require.NoError(t, err)
require.NotEmpty(t, audits, "should not be empty")
audits, _, err = th.SystemAdminClient.GetAudits(0, 1, "")
require.NoError(t, err)
require.Len(t, audits, 1, "should only be 1")
audits, _, err = th.SystemAdminClient.GetAudits(1, 1, "")
require.NoError(t, err)
require.Len(t, audits, 1, "should only be 1")
_, _, err = th.SystemAdminClient.GetAudits(-1, -1, "")
require.NoError(t, err)
_, resp, err := client.GetAudits(0, 100, "")
require.Error(t, err)
CheckForbiddenStatus(t, resp)
client.Logout()
_, resp, err = client.GetAudits(0, 100, "")
require.Error(t, err)
CheckUnauthorizedStatus(t, resp)
}
func TestEmailTest(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
defer os.RemoveAll(dir)
config := model.Config{
ServiceSettings: model.ServiceSettings{
SiteURL: model.NewString(""),
},
EmailSettings: model.EmailSettings{
SMTPServer: model.NewString(""),
SMTPPort: model.NewString(""),
SMTPPassword: model.NewString(""),
FeedbackName: model.NewString(""),
FeedbackEmail: model.NewString("some-addr@test.com"),
ReplyToAddress: model.NewString("some-addr@test.com"),
ConnectionSecurity: model.NewString(""),
SMTPUsername: model.NewString(""),
EnableSMTPAuth: model.NewBool(false),
SkipServerCertificateVerification: model.NewBool(true),
SendEmailNotifications: model.NewBool(false),
SMTPServerTimeout: model.NewInt(15),
},
FileSettings: model.FileSettings{
DriverName: model.NewString(model.ImageDriverLocal),
Directory: model.NewString(dir),
},
}
t.Run("as system user", func(t *testing.T) {
resp, err := client.TestEmail(&config)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as system admin", func(t *testing.T) {
resp, err := th.SystemAdminClient.TestEmail(&config)
CheckErrorID(t, err, "api.admin.test_email.missing_server")
CheckBadRequestStatus(t, resp)
inbucket_host := os.Getenv("CI_INBUCKET_HOST")
if inbucket_host == "" {
inbucket_host = "localhost"
}
inbucket_port := os.Getenv("CI_INBUCKET_SMTP_PORT")
if inbucket_port == "" {
inbucket_port = "10025"
}
*config.EmailSettings.SMTPServer = inbucket_host
*config.EmailSettings.SMTPPort = inbucket_port
resp, err = th.SystemAdminClient.TestEmail(&config)
require.NoError(t, err)
CheckOKStatus(t, resp)
})
t.Run("as restricted system admin", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
resp, err := th.SystemAdminClient.TestEmail(&config)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestGenerateSupportPacket(t *testing.T) {
th := Setup(t)
defer th.TearDown()
t.Run("As a System Administrator", func(t *testing.T) {
l := model.NewTestLicense()
th.App.Srv().SetLicense(l)
file, _, err := th.SystemAdminClient.GenerateSupportPacket()
require.NoError(t, err)
require.NotZero(t, len(file))
})
t.Run("As a Regular User", func(t *testing.T) {
_, resp, err := th.Client.GenerateSupportPacket()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("Server with no License", func(t *testing.T) {
_, err := th.SystemAdminClient.RemoveLicenseFile()
require.NoError(t, err)
_, resp, err := th.SystemAdminClient.GenerateSupportPacket()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestSiteURLTest(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(r.URL.Path, "/valid/api/v4/system/ping") {
w.WriteHeader(200)
} else {
w.WriteHeader(400)
}
}))
defer ts.Close()
validSiteURL := ts.URL + "/valid"
invalidSiteURL := ts.URL + "/invalid"
t.Run("as system admin", func(t *testing.T) {
resp, err := th.SystemAdminClient.TestSiteURL("")
require.Error(t, err)
CheckBadRequestStatus(t, resp)
resp, err = th.SystemAdminClient.TestSiteURL(invalidSiteURL)
require.Error(t, err)
CheckBadRequestStatus(t, resp)
resp, err = th.SystemAdminClient.TestSiteURL(validSiteURL)
require.NoError(t, err)
CheckOKStatus(t, resp)
})
t.Run("as system user", func(t *testing.T) {
resp, err := client.TestSiteURL(validSiteURL)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as restricted system admin", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
resp, err := client.TestSiteURL(validSiteURL)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestDatabaseRecycle(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
t.Run("as system user", func(t *testing.T) {
resp, err := client.DatabaseRecycle()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as system admin", func(t *testing.T) {
_, err := th.SystemAdminClient.DatabaseRecycle()
require.NoError(t, err)
})
t.Run("as restricted system admin", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
resp, err := th.SystemAdminClient.DatabaseRecycle()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestInvalidateCaches(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
t.Run("as system user", func(t *testing.T) {
resp, err := client.InvalidateCaches()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as system admin", func(t *testing.T) {
_, err := th.SystemAdminClient.InvalidateCaches()
require.NoError(t, err)
})
t.Run("as restricted system admin", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
resp, err := th.SystemAdminClient.InvalidateCaches()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestGetLogs(t *testing.T) {
th := Setup(t)
defer th.TearDown()
for i := 0; i < 20; i++ {
mlog.Info(strconv.Itoa(i))
}
err := th.TestLogger.Flush()
require.NoError(t, err, "failed to flush log")
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
logs, _, err2 := c.GetLogs(0, 10)
require.NoError(t, err2)
require.Len(t, logs, 10)
for i := 10; i < 20; i++ {
assert.Containsf(t, logs[i-10], fmt.Sprintf(`"msg":"%d"`, i), "Log line doesn't contain correct message")
}
logs, _, err = c.GetLogs(1, 10)
require.NoError(t, err)
require.Len(t, logs, 10)
logs, _, err = c.GetLogs(-1, -1)
require.NoError(t, err)
require.NotEmpty(t, logs, "should not be empty")
})
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
_, resp, err2 := th.Client.GetLogs(0, 10)
require.Error(t, err2)
CheckForbiddenStatus(t, resp)
})
_, resp, err := th.Client.GetLogs(0, 10)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
th.Client.Logout()
_, resp, err = th.Client.GetLogs(0, 10)
require.Error(t, err)
CheckUnauthorizedStatus(t, resp)
}
func TestPostLog(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
enableDev := *th.App.Config().ServiceSettings.EnableDeveloper
defer func() {
*th.App.Config().ServiceSettings.EnableDeveloper = enableDev
}()
*th.App.Config().ServiceSettings.EnableDeveloper = true
message := make(map[string]string)
message["level"] = "ERROR"
message["message"] = "this is a test"
_, _, err := client.PostLog(message)
require.NoError(t, err)
*th.App.Config().ServiceSettings.EnableDeveloper = false
_, _, err = client.PostLog(message)
require.NoError(t, err)
*th.App.Config().ServiceSettings.EnableDeveloper = true
client.Logout()
_, _, err = client.PostLog(message)
require.NoError(t, err)
*th.App.Config().ServiceSettings.EnableDeveloper = false
_, resp, err := client.PostLog(message)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
logMessage, _, err := th.SystemAdminClient.PostLog(message)
require.NoError(t, err)
require.NotEmpty(t, logMessage, "should return the log message")
}
func TestGetAnalyticsOld(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
client := th.Client
rows, resp, err := client.GetAnalyticsOld("", "")
require.Error(t, err)
CheckForbiddenStatus(t, resp)
require.Nil(t, rows, "should be nil")
rows, _, err = th.SystemAdminClient.GetAnalyticsOld("", "")
require.NoError(t, err)
found := false
found2 := false
for _, row := range rows {
if row.Name == "unique_user_count" {
found = true
} else if row.Name == "inactive_user_count" {
found2 = true
assert.True(t, row.Value >= 0)
}
}
assert.True(t, found, "should return unique user count")
assert.True(t, found2, "should return inactive user count")
_, _, err = th.SystemAdminClient.GetAnalyticsOld("post_counts_day", "")
require.NoError(t, err)
_, _, err = th.SystemAdminClient.GetAnalyticsOld("user_counts_with_posts_day", "")
require.NoError(t, err)
_, _, err = th.SystemAdminClient.GetAnalyticsOld("extra_counts", "")
require.NoError(t, err)
rows, _, err = th.SystemAdminClient.GetAnalyticsOld("", th.BasicTeam.Id)
require.NoError(t, err)
for _, row := range rows {
if row.Name == "inactive_user_count" {
assert.Equal(t, float64(-1), row.Value, "inactive user count should be -1 when team specified")
}
}
rows2, _, err := th.SystemAdminClient.GetAnalyticsOld("standard", "")
require.NoError(t, err)
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
assert.Equal(t, float64(0), rows2[5].Value)
WebSocketClient, err := th.CreateWebSocketClient()
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
rows2, _, err = th.SystemAdminClient.GetAnalyticsOld("standard", "")
require.NoError(t, err)
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
assert.Equal(t, float64(1), rows2[5].Value)
WebSocketClient.Close()
rows2, _, err = th.SystemAdminClient.GetAnalyticsOld("standard", "")
require.NoError(t, err)
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
assert.Equal(t, float64(0), rows2[5].Value)
client.Logout()
_, resp, err = client.GetAnalyticsOld("", th.BasicTeam.Id)
require.Error(t, err)
CheckUnauthorizedStatus(t, resp)
}
func TestS3TestConnection(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
s3Host := os.Getenv("CI_MINIO_HOST")
if s3Host == "" {
s3Host = "localhost"
}
s3Port := os.Getenv("CI_MINIO_PORT")
if s3Port == "" {
s3Port = "9000"
}
s3Endpoint := fmt.Sprintf("%s:%s", s3Host, s3Port)
config := model.Config{
FileSettings: model.FileSettings{
DriverName: model.NewString(model.ImageDriverS3),
AmazonS3AccessKeyId: model.NewString(model.MinioAccessKey),
AmazonS3SecretAccessKey: model.NewString(model.MinioSecretKey),
AmazonS3Bucket: model.NewString(""),
AmazonS3Endpoint: model.NewString(s3Endpoint),
AmazonS3Region: model.NewString(""),
AmazonS3PathPrefix: model.NewString(""),
AmazonS3SSL: model.NewBool(false),
},
}
t.Run("as system user", func(t *testing.T) {
resp, err := client.TestS3Connection(&config)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as system admin", func(t *testing.T) {
resp, err := th.SystemAdminClient.TestS3Connection(&config)
CheckBadRequestStatus(t, resp)
CheckErrorMessage(t, err, "S3 Bucket is required")
// If this fails, check the test configuration to ensure minio is setup with the
// `mattermost-test` bucket defined by model.MINIO_BUCKET.
*config.FileSettings.AmazonS3Bucket = model.MinioBucket
config.FileSettings.AmazonS3PathPrefix = model.NewString("")
*config.FileSettings.AmazonS3Region = "us-east-1"
resp, err = th.SystemAdminClient.TestS3Connection(&config)
require.NoError(t, err)
CheckOKStatus(t, resp)
config.FileSettings.AmazonS3Region = model.NewString("")
resp, err = th.SystemAdminClient.TestS3Connection(&config)
require.NoError(t, err)
CheckOKStatus(t, resp)
config.FileSettings.AmazonS3Bucket = model.NewString("Wrong_bucket")
resp, err = th.SystemAdminClient.TestS3Connection(&config)
CheckInternalErrorStatus(t, resp)
CheckErrorID(t, err, "api.file.test_connection_s3_bucket_does_not_exist.app_error")
*config.FileSettings.AmazonS3Bucket = "shouldnotcreatenewbucket"
resp, err = th.SystemAdminClient.TestS3Connection(&config)
CheckInternalErrorStatus(t, resp)
CheckErrorID(t, err, "api.file.test_connection_s3_bucket_does_not_exist.app_error")
})
t.Run("with incorrect credentials", func(t *testing.T) {
configCopy := config
*configCopy.FileSettings.AmazonS3AccessKeyId = "invalidaccesskey"
resp, err := th.SystemAdminClient.TestS3Connection(&configCopy)
CheckInternalErrorStatus(t, resp)
CheckErrorID(t, err, "api.file.test_connection_s3_auth.app_error")
})
t.Run("as restricted system admin", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
resp, err := th.SystemAdminClient.TestS3Connection(&config)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
}
func TestSupportedTimezones(t *testing.T) {
th := Setup(t)
defer th.TearDown()
client := th.Client
supportedTimezonesFromConfig := th.App.Timezones().GetSupported()
supportedTimezones, _, err := client.GetSupportedTimezone()
require.NoError(t, err)
assert.Equal(t, supportedTimezonesFromConfig, supportedTimezones)
}
func TestRedirectLocation(t *testing.T) {
expected := "https://mattermost.com/wp-content/themes/mattermostv2/img/logo-light.svg"
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Location", expected)
res.WriteHeader(http.StatusFound)
res.Write([]byte("body"))
}))
defer func() { testServer.Close() }()
mockBitlyLink := testServer.URL
th := Setup(t)
defer th.TearDown()
client := th.Client
enableLinkPreviews := *th.App.Config().ServiceSettings.EnableLinkPreviews
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableLinkPreviews = enableLinkPreviews })
}()
*th.App.Config().ServiceSettings.EnableLinkPreviews = true
*th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.1"
_, _, err := th.SystemAdminClient.GetRedirectLocation("https://mattermost.com/", "")
require.NoError(t, err)
_, resp, err := th.SystemAdminClient.GetRedirectLocation("", "")
require.Error(t, err)
CheckBadRequestStatus(t, resp)
actual, _, err := th.SystemAdminClient.GetRedirectLocation(mockBitlyLink, "")
require.NoError(t, err)
assert.Equal(t, expected, actual)
// Check cached value
actual, _, err = th.SystemAdminClient.GetRedirectLocation(mockBitlyLink, "")
require.NoError(t, err)
assert.Equal(t, expected, actual)
*th.App.Config().ServiceSettings.EnableLinkPreviews = false
actual, _, err = th.SystemAdminClient.GetRedirectLocation("https://mattermost.com/", "")
require.NoError(t, err)
assert.Equal(t, actual, "")
actual, _, err = th.SystemAdminClient.GetRedirectLocation("", "")
require.NoError(t, err)
assert.Equal(t, actual, "")
actual, _, err = th.SystemAdminClient.GetRedirectLocation(mockBitlyLink, "")
require.NoError(t, err)
assert.Equal(t, actual, "")
client.Logout()
_, resp, err = client.GetRedirectLocation("", "")
require.Error(t, err)
CheckUnauthorizedStatus(t, resp)
}
func TestSetServerBusy(t *testing.T) {
th := Setup(t)
defer th.TearDown()
const secs = 30
t.Run("as system user", func(t *testing.T) {
resp, err := th.Client.SetServerBusy(secs)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
require.False(t, th.App.Srv().Busy.IsBusy(), "server should not be marked busy")
})
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
_, err := c.SetServerBusy(secs)
require.NoError(t, err)
require.True(t, th.App.Srv().Busy.IsBusy(), "server should be marked busy")
}, "as system admin")
}
func TestSetServerBusyInvalidParam(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
params := []int{-1, 0, MaxServerBusySeconds + 1}
for _, p := range params {
resp, err := c.SetServerBusy(p)
require.Error(t, err)
CheckBadRequestStatus(t, resp)
require.False(t, th.App.Srv().Busy.IsBusy(), "server should not be marked busy due to invalid param ", p)
}
}, "as system admin, invalid param")
}
func TestClearServerBusy(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.App.Srv().Busy.Set(time.Second * 30)
t.Run("as system user", func(t *testing.T) {
resp, err := th.Client.ClearServerBusy()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
require.True(t, th.App.Srv().Busy.IsBusy(), "server should be marked busy")
})
th.App.Srv().Busy.Set(time.Second * 30)
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
_, err := c.ClearServerBusy()
require.NoError(t, err)
require.False(t, th.App.Srv().Busy.IsBusy(), "server should not be marked busy")
}, "as system admin")
}
func TestGetServerBusy(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.App.Srv().Busy.Set(time.Second * 30)
t.Run("as system user", func(t *testing.T) {
_, resp, err := th.Client.GetServerBusy()
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
sbs, _, err := c.GetServerBusy()
expires := time.Unix(sbs.Expires, 0)
require.NoError(t, err)
require.Greater(t, expires.Unix(), time.Now().Unix())
}, "as system admin")
}
func TestServerBusy503(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.App.Srv().Busy.Set(time.Second * 30)
t.Run("search users while busy", func(t *testing.T) {
us := &model.UserSearch{Term: "test"}
_, resp, err := th.SystemAdminClient.SearchUsers(us)
require.Error(t, err)
CheckServiceUnavailableStatus(t, resp)
})
t.Run("search teams while busy", func(t *testing.T) {
ts := &model.TeamSearch{}
_, resp, err := th.SystemAdminClient.SearchTeams(ts)
require.Error(t, err)
CheckServiceUnavailableStatus(t, resp)
})
t.Run("search channels while busy", func(t *testing.T) {
cs := &model.ChannelSearch{}
_, resp, err := th.SystemAdminClient.SearchChannels("foo", cs)
require.Error(t, err)
CheckServiceUnavailableStatus(t, resp)
})
t.Run("search archived channels while busy", func(t *testing.T) {
cs := &model.ChannelSearch{}
_, resp, err := th.SystemAdminClient.SearchArchivedChannels("foo", cs)
require.Error(t, err)
CheckServiceUnavailableStatus(t, resp)
})
th.App.Srv().Busy.Clear()
t.Run("search users while not busy", func(t *testing.T) {
us := &model.UserSearch{Term: "test"}
_, _, err := th.SystemAdminClient.SearchUsers(us)
require.NoError(t, err)
})
}
func TestPushNotificationAck(t *testing.T) {
th := Setup(t).InitBasic()
api, err := Init(th.Server)
require.NoError(t, err)
session, _ := th.App.GetSession(th.Client.AuthToken)
defer th.TearDown()
t.Run("should return error when the ack body is not passed", func(t *testing.T) {
handler := api.APIHandler(pushNotificationAck)
resp := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/api/v4/notifications/ack", nil)
req.Header.Set(model.HeaderAuth, "Bearer "+session.Token)
handler.ServeHTTP(resp, req)
assert.Equal(t, http.StatusBadRequest, resp.Code)
assert.NotNil(t, resp.Body)
})
t.Run("should return error when the ack post is not authorized for the user", func(t *testing.T) {
privateChannel := th.CreateChannelWithClient(th.SystemAdminClient, model.ChannelTypePrivate)
privatePost := th.CreatePostWithClient(th.SystemAdminClient, privateChannel)
handler := api.APIHandler(pushNotificationAck)
resp := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/api/v4/notifications/ack", nil)
req.Header.Set(model.HeaderAuth, "Bearer "+session.Token)
req.Body = ioutil.NopCloser(bytes.NewBufferString(fmt.Sprintf(`{"id":"123", "is_id_loaded":true, "post_id":"%s", "type": "%s"}`, privatePost.Id, model.PushTypeMessage)))
handler.ServeHTTP(resp, req)
assert.Equal(t, http.StatusForbidden, resp.Code)
assert.NotNil(t, resp.Body)
})
}
func TestCompleteOnboarding(t *testing.T) {
th := Setup(t)
defer th.TearDown()
path, _ := fileutils.FindDir("tests")
signatureFilename := "testplugin2.tar.gz.sig"
signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename))
require.NoError(t, err)
sigFile, err := ioutil.ReadAll(signatureFileReader)
require.NoError(t, err)
pluginSignature := base64.StdEncoding.EncodeToString(sigFile)
tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz"))
require.NoError(t, err)
pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.WriteHeader(http.StatusOK)
res.Write(tarData)
}))
defer pluginServer.Close()
samplePlugins := []*model.MarketplacePlugin{{
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps",
IconData: "https://example.com/icon.svg",
DownloadURL: pluginServer.URL,
Manifest: &model.Manifest{
Id: "testplugin2",
Name: "testplugin2",
Description: "a second plugin",
Version: "1.2.3",
MinServerVersion: "",
},
Signature: pluginSignature,
},
InstalledVersion: "",
}}
marketplaceServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.WriteHeader(http.StatusOK)
var data []byte
data, err = json.Marshal(samplePlugins)
require.NoError(t, err)
res.Write(data)
}))
defer marketplaceServer.Close()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.PluginSettings.Enable = true
*cfg.PluginSettings.EnableMarketplace = false
*cfg.PluginSettings.EnableRemoteMarketplace = true
*cfg.PluginSettings.MarketplaceURL = marketplaceServer.URL
*cfg.PluginSettings.AllowInsecureDownloadURL = true
})
key, err := os.Open(filepath.Join(path, "development-private-key.asc"))
require.NoError(t, err)
appErr := th.App.AddPublicKey("pub_key", key)
require.Nil(t, appErr)
t.Cleanup(func() {
appErr = th.App.DeletePublicKey("pub_key")
require.Nil(t, appErr)
})
req := &model.CompleteOnboardingRequest{
InstallPlugins: []string{"testplugin2"},
}
t.Run("as a regular user", func(t *testing.T) {
resp, err := th.Client.CompleteOnboarding(req)
require.Error(t, err)
CheckForbiddenStatus(t, resp)
})
t.Run("as a system admin", func(t *testing.T) {
resp, err := th.SystemAdminClient.CompleteOnboarding(req)
require.NoError(t, err)
CheckOKStatus(t, resp)
t.Cleanup(func() {
resp, err = th.SystemAdminClient.RemovePlugin("testplugin2")
require.NoError(t, err)
CheckOKStatus(t, resp)
})
received := make(chan struct{})
go func() {
for {
installedPlugins, resp, err := th.SystemAdminClient.GetPlugins()
if err != nil || resp.StatusCode != http.StatusOK {
time.Sleep(500 * time.Millisecond)
continue
}
for _, p := range installedPlugins.Active {
if p.Id == "testplugin2" {
received <- struct{}{}
return
}
}
time.Sleep(500 * time.Millisecond)
}
}()
select {
case <-received:
break
case <-time.After(15 * time.Second):
require.Fail(t, "timed out waiting testplugin2 to be installed and enabled ")
}
})
}