mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-03 20:40:00 -05:00
1206 lines
38 KiB
Go
1206 lines
38 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"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/public/model"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
|
)
|
|
|
|
func TestGetPing(t *testing.T) {
|
|
th := Setup(t)
|
|
|
|
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
|
|
t.Run("healthy", func(t *testing.T) {
|
|
status, _, err := client.GetPing(context.Background())
|
|
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(context.Background())
|
|
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(context.Background())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.StatusOk, status)
|
|
})
|
|
}, "with server status")
|
|
|
|
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
|
|
err := th.App.ReloadConfig()
|
|
require.NoError(t, err)
|
|
respMap, resp, err := client.GetPingWithOptions(context.Background(), model.SystemPingOptions{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
_, ok := respMap["TestFeatureFlag"]
|
|
assert.Equal(t, false, ok)
|
|
|
|
// Run the environment variable override code to test
|
|
os.Setenv("MM_FEATUREFLAGS_TESTFEATURE", "testvalueunique")
|
|
defer os.Unsetenv("MM_FEATUREFLAGS_TESTFEATURE")
|
|
err = th.App.ReloadConfig()
|
|
require.NoError(t, err)
|
|
|
|
respMap, resp, err = client.GetPingWithOptions(context.Background(), model.SystemPingOptions{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
_, ok = respMap["TestFeatureFlag"]
|
|
assert.Equal(t, true, ok)
|
|
}, "ping feature flag test")
|
|
|
|
t.Run("ping root_status test", func(t *testing.T) {
|
|
respMap, resp, err := th.SystemAdminClient.GetPingWithOptions(context.Background(), model.SystemPingOptions{FullStatus: true})
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
_, ok := respMap["root_status"]
|
|
assert.Equal(t, true, ok)
|
|
})
|
|
|
|
t.Run("ping root_status test with client user", func(t *testing.T) {
|
|
respMap, resp, err := th.Client.GetPingWithOptions(context.Background(), model.SystemPingOptions{FullStatus: true})
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
_, ok := respMap["root_status"]
|
|
assert.Equal(t, false, ok)
|
|
})
|
|
|
|
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
|
|
err := th.App.ReloadConfig()
|
|
require.NoError(t, err)
|
|
resp, err := client.DoAPIGet(context.Background(), "/system/ping?device_id=platform:id", "")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
var respMap map[string]any
|
|
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) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
audits, _, err := th.SystemAdminClient.GetAudits(context.Background(), 0, 100, "")
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, audits, "should not be empty")
|
|
|
|
audits, _, err = th.SystemAdminClient.GetAudits(context.Background(), 0, 1, "")
|
|
require.NoError(t, err)
|
|
require.Len(t, audits, 1, "should only be 1")
|
|
|
|
audits, _, err = th.SystemAdminClient.GetAudits(context.Background(), 1, 1, "")
|
|
require.NoError(t, err)
|
|
require.Len(t, audits, 1, "should only be 1")
|
|
|
|
_, _, err = th.SystemAdminClient.GetAudits(context.Background(), -1, -1, "")
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.GetAudits(context.Background(), 0, 100, "")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.GetAudits(context.Background(), 0, 100, "")
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
}
|
|
|
|
func TestEmailTest(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
dir, err := os.MkdirTemp("", "")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(dir)
|
|
|
|
es := model.EmailSettings{}
|
|
es.SetDefaults(false)
|
|
|
|
es.SMTPServer = model.NewPointer("")
|
|
es.SMTPPort = model.NewPointer("")
|
|
es.SMTPPassword = model.NewPointer("")
|
|
es.FeedbackName = model.NewPointer("")
|
|
es.FeedbackEmail = model.NewPointer("some-addr@test.com")
|
|
es.ReplyToAddress = model.NewPointer("some-addr@test.com")
|
|
es.ConnectionSecurity = model.NewPointer("")
|
|
es.SMTPUsername = model.NewPointer("")
|
|
es.EnableSMTPAuth = model.NewPointer(false)
|
|
es.SkipServerCertificateVerification = model.NewPointer(true)
|
|
es.SendEmailNotifications = model.NewPointer(false)
|
|
es.SMTPServerTimeout = model.NewPointer(15)
|
|
|
|
config := model.Config{
|
|
ServiceSettings: model.ServiceSettings{
|
|
SiteURL: model.NewPointer(""),
|
|
},
|
|
EmailSettings: es,
|
|
FileSettings: model.FileSettings{
|
|
DriverName: model.NewPointer(model.ImageDriverLocal),
|
|
Directory: model.NewPointer(dir),
|
|
},
|
|
}
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := client.TestEmail(context.Background(), &config)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as system admin", func(t *testing.T) {
|
|
resp, err := th.SystemAdminClient.TestEmail(context.Background(), &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(context.Background(), &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(context.Background(), &config)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("empty email settings", func(t *testing.T) {
|
|
config.EmailSettings = model.EmailSettings{}
|
|
resp, err := th.SystemAdminClient.TestEmail(context.Background(), &config)
|
|
require.Error(t, err)
|
|
CheckErrorID(t, err, "api.file.test_connection_email_settings_nil.app_error")
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestGenerateSupportPacket(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
th.LoginSystemManager(t)
|
|
|
|
t.Run("system admin and local client can generate Support Packet", func(t *testing.T) {
|
|
l := model.NewTestLicense()
|
|
th.App.Srv().SetLicense(l)
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
file, filename, resp, err := th.SystemAdminClient.GenerateSupportPacket(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
assert.Contains(t, filename, "mm_support_packet_My_awesome_Company_")
|
|
|
|
d, err := io.ReadAll(file)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, len(d))
|
|
|
|
// Verify that the Cache-Control header is set to prevent caching
|
|
assert.Equal(t, "no-cache, no-store, must-revalidate", resp.Header.Get("Cache-Control"))
|
|
})
|
|
})
|
|
|
|
t.Run("Using system admin and local client but with RestrictSystemAdmin true", func(t *testing.T) {
|
|
originalRestrictSystemAdminVal := *th.App.Config().ExperimentalSettings.RestrictSystemAdmin
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ExperimentalSettings.RestrictSystemAdmin = true })
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ExperimentalSettings.RestrictSystemAdmin = originalRestrictSystemAdminVal
|
|
})
|
|
}()
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
_, _, resp, err := th.SystemAdminClient.GenerateSupportPacket(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
})
|
|
|
|
t.Run("As a system role, not system admin", func(t *testing.T) {
|
|
_, _, resp, err := th.SystemManagerClient.GenerateSupportPacket(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("As a Regular User", func(t *testing.T) {
|
|
_, _, resp, err := th.Client.GenerateSupportPacket(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("Server with no License", func(t *testing.T) {
|
|
_, err := th.SystemAdminClient.RemoveLicenseFile(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, _, resp, err := th.SystemAdminClient.GenerateSupportPacket(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestSupportPacketFileName(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
tests := map[string]struct {
|
|
now time.Time
|
|
customerName string
|
|
expected string
|
|
}{
|
|
"standard case": {
|
|
now: time.Date(2023, 11, 12, 13, 14, 15, 0, time.UTC),
|
|
customerName: "TestCustomer",
|
|
expected: "mm_support_packet_TestCustomer_2023-11-12T13-14.zip",
|
|
},
|
|
"customer name with special characters": {
|
|
now: time.Date(2023, 11, 12, 13, 14, 15, 0, time.UTC),
|
|
customerName: "Test/Customer:Name",
|
|
expected: "mm_support_packet_Test_Customer_Name_2023-11-12T13-14.zip",
|
|
},
|
|
"empty customer name": {
|
|
now: time.Date(2023, 10, 10, 10, 10, 10, 0, time.UTC),
|
|
customerName: "",
|
|
expected: "mm_support_packet__2023-10-10T10-10.zip",
|
|
},
|
|
}
|
|
|
|
for name, tt := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
result := supportPacketFileName(tt.now, tt.customerName)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSiteURLTest(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
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(context.Background(), "")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
resp, err = th.SystemAdminClient.TestSiteURL(context.Background(), invalidSiteURL)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
resp, err = th.SystemAdminClient.TestSiteURL(context.Background(), validSiteURL)
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := client.TestSiteURL(context.Background(), 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(context.Background(), validSiteURL)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestDatabaseRecycle(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := client.DatabaseRecycle(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as system admin", func(t *testing.T) {
|
|
_, err := th.SystemAdminClient.DatabaseRecycle(context.Background())
|
|
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(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestInvalidateCaches(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := client.InvalidateCaches(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as system admin", func(t *testing.T) {
|
|
_, err := th.SystemAdminClient.InvalidateCaches(context.Background())
|
|
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(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestGetLogs(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
for i := range 20 {
|
|
th.TestLogger.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(context.Background(), 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(context.Background(), 1, 10)
|
|
require.NoError(t, err)
|
|
require.Len(t, logs, 10)
|
|
|
|
logs, _, err = c.GetLogs(context.Background(), -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(context.Background(), 0, 10)
|
|
require.Error(t, err2)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
_, resp, err := th.Client.GetLogs(context.Background(), 0, 10)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = th.Client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = th.Client.GetLogs(context.Background(), 0, 10)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
}
|
|
|
|
func TestDownloadLogs(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
for i := range 20 {
|
|
th.TestLogger.Info(strconv.Itoa(i))
|
|
}
|
|
err := th.TestLogger.Flush()
|
|
require.NoError(t, err, "failed to flush log")
|
|
|
|
t.Run("Download Logs as system admin", func(t *testing.T) {
|
|
resData, resp, err2 := th.SystemAdminClient.DownloadLogs(context.Background())
|
|
require.NoError(t, err2)
|
|
|
|
require.Equal(t, "text/plain", resp.Header.Get("Content-Type"))
|
|
require.Contains(t, resp.Header.Get("Content-Disposition"), "attachment;filename=\"mattermost.log\"")
|
|
|
|
bodyString := string(resData)
|
|
for i := range 20 {
|
|
assert.Contains(t, bodyString, fmt.Sprintf(`"msg":"%d"`, i))
|
|
}
|
|
})
|
|
|
|
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.DownloadLogs(context.Background())
|
|
require.Error(t, err2)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
_, resp, err := th.Client.DownloadLogs(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = th.Client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = th.Client.DownloadLogs(context.Background())
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
}
|
|
|
|
func TestPostLog(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
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(context.Background(), message)
|
|
require.NoError(t, err)
|
|
|
|
*th.App.Config().ServiceSettings.EnableDeveloper = false
|
|
|
|
_, _, err = client.PostLog(context.Background(), message)
|
|
require.NoError(t, err)
|
|
|
|
*th.App.Config().ServiceSettings.EnableDeveloper = true
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = client.PostLog(context.Background(), message)
|
|
require.NoError(t, err)
|
|
|
|
*th.App.Config().ServiceSettings.EnableDeveloper = false
|
|
|
|
_, resp, err := client.PostLog(context.Background(), message)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
logMessage, _, err := th.SystemAdminClient.PostLog(context.Background(), message)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, logMessage, "should return the log message")
|
|
}
|
|
|
|
func TestGetAnalyticsOld(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
rows, resp, err := client.GetAnalyticsOld(context.Background(), "", "")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
require.Nil(t, rows, "should be nil")
|
|
rows, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "", "")
|
|
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(context.Background(), "post_counts_day", "")
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "user_counts_with_posts_day", "")
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "extra_counts", "")
|
|
require.NoError(t, err)
|
|
|
|
rows, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "", 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(context.Background(), "standard", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
|
|
assert.Equal(t, float64(0), rows2[5].Value)
|
|
|
|
WebSocketClient := th.CreateConnectedWebSocketClient(t)
|
|
rows2, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "standard", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
|
|
assert.Equal(t, float64(1), rows2[5].Value)
|
|
WebSocketClient.Close()
|
|
|
|
// Give it a second for internal webhub counters to be updated after the client disconnects.
|
|
// Test can be flaky otherwise.
|
|
time.Sleep(time.Second)
|
|
|
|
rows2, _, err = th.SystemAdminClient.GetAnalyticsOld(context.Background(), "standard", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "total_websocket_connections", rows2[5].Name)
|
|
assert.Equal(t, float64(0), rows2[5].Value)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.GetAnalyticsOld(context.Background(), "", th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
}
|
|
|
|
func TestS3TestConnection(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
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)
|
|
|
|
fs := model.FileSettings{}
|
|
fs.SetDefaults(false)
|
|
|
|
fs.DriverName = model.NewPointer(model.ImageDriverS3)
|
|
fs.AmazonS3AccessKeyId = model.NewPointer(model.MinioAccessKey)
|
|
fs.AmazonS3SecretAccessKey = model.NewPointer(model.MinioSecretKey)
|
|
fs.AmazonS3Bucket = model.NewPointer("")
|
|
fs.AmazonS3Endpoint = model.NewPointer(s3Endpoint)
|
|
fs.AmazonS3Region = model.NewPointer("")
|
|
fs.AmazonS3PathPrefix = model.NewPointer("")
|
|
fs.AmazonS3SSL = model.NewPointer(false)
|
|
|
|
config := model.Config{
|
|
FileSettings: fs,
|
|
}
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := client.TestS3Connection(context.Background(), &config)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as system admin", func(t *testing.T) {
|
|
resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &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.NewPointer("")
|
|
*config.FileSettings.AmazonS3Region = "us-east-1"
|
|
resp, err = th.SystemAdminClient.TestS3Connection(context.Background(), &config)
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
config.FileSettings.AmazonS3Region = model.NewPointer("")
|
|
resp, err = th.SystemAdminClient.TestS3Connection(context.Background(), &config)
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
config.FileSettings.AmazonS3Bucket = model.NewPointer("Wrong_bucket")
|
|
resp, err = th.SystemAdminClient.TestS3Connection(context.Background(), &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(context.Background(), &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(context.Background(), &configCopy)
|
|
CheckInternalErrorStatus(t, resp)
|
|
CheckErrorID(t, err, "api.file.test_connection_s3_auth.app_error")
|
|
})
|
|
|
|
t.Run("empty file settings", func(t *testing.T) {
|
|
config.FileSettings = model.FileSettings{}
|
|
resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &config)
|
|
require.Error(t, err)
|
|
CheckErrorID(t, err, "api.file.test_connection_s3_settings_nil.app_error")
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestSupportedTimezones(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
supportedTimezonesFromConfig := th.App.Timezones().GetSupported()
|
|
supportedTimezones, _, err := client.GetSupportedTimezone(context.Background())
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, supportedTimezonesFromConfig, supportedTimezones)
|
|
}
|
|
|
|
func TestRedirectLocation(t *testing.T) {
|
|
mainHelper.Parallel(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)
|
|
_, err := res.Write([]byte("body"))
|
|
require.NoError(t, err)
|
|
}))
|
|
defer func() { testServer.Close() }()
|
|
|
|
mockBitlyLink := testServer.URL
|
|
|
|
th := Setup(t)
|
|
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(context.Background(), "https://mattermost.com/", "")
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := th.SystemAdminClient.GetRedirectLocation(context.Background(), "", "")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
actual, _, err := th.SystemAdminClient.GetRedirectLocation(context.Background(), mockBitlyLink, "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
|
|
// Check cached value
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), mockBitlyLink, "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expected, actual)
|
|
|
|
*th.App.Config().ServiceSettings.EnableLinkPreviews = false
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), "https://mattermost.com/", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, actual, "")
|
|
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), "", "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, actual, "")
|
|
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), mockBitlyLink, "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, actual, "")
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.GetRedirectLocation(context.Background(), "", "")
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
// Check that too-long redirect locations are ignored
|
|
*th.App.Config().ServiceSettings.EnableLinkPreviews = true
|
|
urlPrefix := "https://example.co"
|
|
almostTooLongUrl := urlPrefix + strings.Repeat("a", 2100-len(urlPrefix))
|
|
testServer2 := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
|
res.Header().Set("Location", almostTooLongUrl)
|
|
res.WriteHeader(http.StatusFound)
|
|
_, err = res.Write([]byte("body"))
|
|
require.NoError(t, err)
|
|
}))
|
|
defer func() { testServer2.Close() }()
|
|
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), testServer2.URL, "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, almostTooLongUrl, actual)
|
|
|
|
tooLongUrl := urlPrefix + strings.Repeat("a", 2101-len(urlPrefix))
|
|
testServer3 := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
|
res.Header().Set("Location", tooLongUrl)
|
|
res.WriteHeader(http.StatusFound)
|
|
_, err = res.Write([]byte("body"))
|
|
require.NoError(t, err)
|
|
}))
|
|
defer func() { testServer3.Close() }()
|
|
|
|
actual, _, err = th.SystemAdminClient.GetRedirectLocation(context.Background(), testServer3.URL, "")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "", actual)
|
|
}
|
|
|
|
func TestSetServerBusy(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
const secs = 30
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := th.Client.SetServerBusy(context.Background(), secs)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
require.False(t, th.App.Srv().Platform().Busy.IsBusy(), "server should not be marked busy")
|
|
})
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
_, err := c.SetServerBusy(context.Background(), secs)
|
|
require.NoError(t, err)
|
|
require.True(t, th.App.Srv().Platform().Busy.IsBusy(), "server should be marked busy")
|
|
}, "as system admin")
|
|
}
|
|
|
|
func TestSetServerBusyInvalidParam(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
params := []int{-1, 0, MaxServerBusySeconds + 1}
|
|
for _, p := range params {
|
|
resp, err := c.SetServerBusy(context.Background(), p)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
require.False(t, th.App.Srv().Platform().Busy.IsBusy(), "server should not be marked busy due to invalid param ", p)
|
|
}
|
|
}, "as system admin, invalid param")
|
|
}
|
|
|
|
func TestClearServerBusy(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
th.App.Srv().Platform().Busy.Set(time.Second * 30)
|
|
t.Run("as system user", func(t *testing.T) {
|
|
resp, err := th.Client.ClearServerBusy(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
require.True(t, th.App.Srv().Platform().Busy.IsBusy(), "server should be marked busy")
|
|
})
|
|
|
|
th.App.Srv().Platform().Busy.Set(time.Second * 30)
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
_, err := c.ClearServerBusy(context.Background())
|
|
require.NoError(t, err)
|
|
require.False(t, th.App.Srv().Platform().Busy.IsBusy(), "server should not be marked busy")
|
|
}, "as system admin")
|
|
}
|
|
|
|
func TestGetServerBusy(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
th.App.Srv().Platform().Busy.Set(time.Second * 30)
|
|
|
|
t.Run("as system user", func(t *testing.T) {
|
|
_, resp, err := th.Client.GetServerBusy(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
sbs, _, err := c.GetServerBusy(context.Background())
|
|
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) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
th.App.Srv().Platform().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(context.Background(), 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(context.Background(), 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(context.Background(), "foo", cs)
|
|
require.Error(t, err)
|
|
CheckServiceUnavailableStatus(t, resp)
|
|
})
|
|
|
|
th.App.Srv().Platform().Busy.Clear()
|
|
|
|
t.Run("search users while not busy", func(t *testing.T) {
|
|
us := &model.UserSearch{Term: "test"}
|
|
_, _, err := th.SystemAdminClient.SearchUsers(context.Background(), us)
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestPushNotificationAck(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
api, err := Init(th.Server)
|
|
require.NoError(t, err)
|
|
session, appErr := th.App.GetSession(th.Client.AuthToken)
|
|
require.Nil(t, appErr)
|
|
|
|
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(t, th.SystemAdminClient, model.ChannelTypePrivate)
|
|
privatePost := th.CreatePostWithClient(t, 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 = io.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)
|
|
})
|
|
|
|
ttcc := []struct {
|
|
name string
|
|
propValue string
|
|
platform string
|
|
expectedValue string
|
|
}{
|
|
{
|
|
name: "should set session prop device notification disabled to false if an ack is sent from iOS",
|
|
propValue: "true",
|
|
platform: "ios",
|
|
expectedValue: "false",
|
|
},
|
|
{
|
|
name: "no change if empty",
|
|
propValue: "",
|
|
platform: "ios",
|
|
expectedValue: "",
|
|
},
|
|
{
|
|
name: "no change if false",
|
|
propValue: "false",
|
|
platform: "ios",
|
|
expectedValue: "false",
|
|
},
|
|
{
|
|
name: "no change on Android",
|
|
propValue: "true",
|
|
platform: "android",
|
|
expectedValue: "true",
|
|
},
|
|
}
|
|
for _, tc := range ttcc {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
defer func() {
|
|
session.AddProp(model.SessionPropDeviceNotificationDisabled, "")
|
|
err = th.Server.Store().Session().UpdateProps(session)
|
|
require.NoError(t, err)
|
|
th.App.ClearSessionCacheForUser(session.UserId)
|
|
}()
|
|
|
|
session.AddProp(model.SessionPropDeviceNotificationDisabled, tc.propValue)
|
|
err := th.Server.Store().Session().UpdateProps(session)
|
|
th.App.ClearSessionCacheForUser(session.UserId)
|
|
assert.NoError(t, err)
|
|
|
|
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 = io.NopCloser(bytes.NewBufferString(fmt.Sprintf(`{"id":"123", "is_id_loaded":true, "platform": "%s", "post_id":"%s", "type": "%s"}`, tc.platform, th.BasicPost.Id, model.PushTypeMessage)))
|
|
|
|
handler.ServeHTTP(resp, req)
|
|
updatedSession, _ := th.App.GetSession(th.Client.AuthToken)
|
|
assert.Equal(t, tc.expectedValue, updatedSession.Props[model.SessionPropDeviceNotificationDisabled])
|
|
storeSession, _ := th.Server.Store().Session().Get(th.Context, session.Id)
|
|
assert.Equal(t, tc.expectedValue, storeSession.Props[model.SessionPropDeviceNotificationDisabled])
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCompleteOnboarding(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
path, _ := fileutils.FindDir("tests")
|
|
signatureFilename := "testplugin2.tar.gz.sig"
|
|
signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename))
|
|
require.NoError(t, err)
|
|
sigFile, err := io.ReadAll(signatureFileReader)
|
|
require.NoError(t, err)
|
|
pluginSignature := base64.StdEncoding.EncodeToString(sigFile)
|
|
|
|
tarData, err := os.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)
|
|
_, err = res.Write(tarData)
|
|
require.NoError(t, err)
|
|
}))
|
|
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)
|
|
_, err = res.Write(data)
|
|
require.NoError(t, err)
|
|
}))
|
|
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"},
|
|
Organization: "my-org",
|
|
}
|
|
|
|
t.Run("as a regular user", func(t *testing.T) {
|
|
resp, err := th.Client.CompleteOnboarding(context.Background(), req)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as a system admin", func(t *testing.T) {
|
|
resp, err := th.SystemAdminClient.CompleteOnboarding(context.Background(), req)
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
t.Cleanup(func() {
|
|
resp, err = th.SystemAdminClient.RemovePlugin(context.Background(), "testplugin2")
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
})
|
|
|
|
received := make(chan struct{})
|
|
|
|
go func() {
|
|
for {
|
|
installedPlugins, resp, err := th.SystemAdminClient.GetPlugins(context.Background())
|
|
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 ")
|
|
}
|
|
})
|
|
|
|
t.Run("as a system admin when plugins are disabled", func(t *testing.T) {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.PluginSettings.Enable = false
|
|
})
|
|
|
|
t.Cleanup(func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.PluginSettings.Enable = true
|
|
})
|
|
})
|
|
|
|
resp, err := th.SystemAdminClient.CompleteOnboarding(context.Background(), req)
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestGetAppliedSchemaMigrations(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
|
|
t.Run("as a regular user", func(t *testing.T) {
|
|
_, resp, err := th.Client.GetAppliedSchemaMigrations(context.Background())
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("as a system manager role", func(t *testing.T) {
|
|
_, appErr := th.App.UpdateUserRoles(th.Context, th.BasicUser2.Id, model.SystemManagerRoleId, false)
|
|
require.Nil(t, appErr)
|
|
th.LoginBasic2(t)
|
|
|
|
_, resp, err := th.Client.GetAppliedSchemaMigrations(context.Background())
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
})
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
_, resp, err := c.GetAppliedSchemaMigrations(context.Background())
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestCheckHasNilFields(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
t.Run("check if the empty struct has nil fields", func(t *testing.T) {
|
|
var s model.FileSettings
|
|
res := checkHasNilFields(&s)
|
|
require.True(t, res)
|
|
})
|
|
|
|
t.Run("check if the struct has any nil fields", func(t *testing.T) {
|
|
s := model.FileSettings{
|
|
DriverName: model.NewPointer(model.ImageDriverLocal),
|
|
}
|
|
res := checkHasNilFields(&s)
|
|
require.True(t, res)
|
|
})
|
|
|
|
t.Run("struct has all fields set", func(t *testing.T) {
|
|
var s model.FileSettings
|
|
s.SetDefaults(false)
|
|
res := checkHasNilFields(&s)
|
|
require.False(t, res)
|
|
})
|
|
|
|
t.Run("embedded struct, with nil fields", func(t *testing.T) {
|
|
type myStr struct {
|
|
Name string
|
|
Surname *string
|
|
}
|
|
s := myStr{}
|
|
res := checkHasNilFields(&s)
|
|
require.True(t, res)
|
|
})
|
|
}
|