Merge branch 'master' into mark-as-unread
Этот коммит содержится в:
4
Makefile
4
Makefile
@@ -59,7 +59,7 @@ LDFLAGS += -X "github.com/mattermost/mattermost-server/model.BuildEnterpriseRead
|
||||
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
|
||||
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
||||
MINIMUM_SUPPORTED_GO_MAJOR_VERSION = 1
|
||||
MINIMUM_SUPPORTED_GO_MINOR_VERSION = 12
|
||||
MINIMUM_SUPPORTED_GO_MINOR_VERSION = 13
|
||||
GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION).$(MINIMUM_SUPPORTED_GO_MINOR_VERSION)
|
||||
|
||||
# GOOS/GOARCH of the build host, used to determine whether we're cross-compiling or not
|
||||
@@ -81,7 +81,7 @@ TESTFLAGSEE ?= -short
|
||||
TE_PACKAGES=$(shell $(GO) list ./...)
|
||||
|
||||
# Plugins Packages
|
||||
PLUGIN_PACKAGES=mattermost-plugin-zoom-v1.1.1
|
||||
PLUGIN_PACKAGES=mattermost-plugin-zoom-v1.1.2
|
||||
PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.1.1
|
||||
PLUGIN_PACKAGES += mattermost-plugin-nps-v1.0.3
|
||||
PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.0.2
|
||||
|
||||
@@ -25,31 +25,26 @@ func TestGetConfig(t *testing.T) {
|
||||
require.NotEqual(t, "", cfg.TeamSettings.SiteName)
|
||||
|
||||
if *cfg.LdapSettings.BindPassword != model.FAKE_SETTING && len(*cfg.LdapSettings.BindPassword) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
}
|
||||
if *cfg.FileSettings.PublicLinkSalt != model.FAKE_SETTING {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
require.Equal(t, model.FAKE_SETTING, *cfg.FileSettings.PublicLinkSalt, "did not sanitize properly")
|
||||
|
||||
if *cfg.FileSettings.AmazonS3SecretAccessKey != model.FAKE_SETTING && len(*cfg.FileSettings.AmazonS3SecretAccessKey) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
if *cfg.EmailSettings.SMTPPassword != model.FAKE_SETTING && len(*cfg.EmailSettings.SMTPPassword) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
if *cfg.GitLabSettings.Secret != model.FAKE_SETTING && len(*cfg.GitLabSettings.Secret) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
}
|
||||
if *cfg.SqlSettings.DataSource != model.FAKE_SETTING {
|
||||
t.Fatal("did not sanitize properly")
|
||||
}
|
||||
if *cfg.SqlSettings.AtRestEncryptKey != model.FAKE_SETTING {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
require.Equal(t, model.FAKE_SETTING, *cfg.SqlSettings.DataSource, "did not sanitize properly")
|
||||
require.Equal(t, model.FAKE_SETTING, *cfg.SqlSettings.AtRestEncryptKey, "did not sanitize properly")
|
||||
if !strings.Contains(strings.Join(cfg.SqlSettings.DataSourceReplicas, " "), model.FAKE_SETTING) && len(cfg.SqlSettings.DataSourceReplicas) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
if !strings.Contains(strings.Join(cfg.SqlSettings.DataSourceSearchReplicas, " "), model.FAKE_SETTING) && len(cfg.SqlSettings.DataSourceSearchReplicas) != 0 {
|
||||
t.Fatal("did not sanitize properly")
|
||||
require.FailNow(t, "did not sanitize properly")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,17 +56,13 @@ func TestReloadConfig(t *testing.T) {
|
||||
t.Run("as system user", func(t *testing.T) {
|
||||
ok, resp := Client.ReloadConfig()
|
||||
CheckForbiddenStatus(t, resp)
|
||||
if ok {
|
||||
t.Fatal("should not Reload the config due no permission.")
|
||||
}
|
||||
require.False(t, ok, "should not Reload the config due no permission.")
|
||||
})
|
||||
|
||||
t.Run("as system admin", func(t *testing.T) {
|
||||
ok, resp := th.SystemAdminClient.ReloadConfig()
|
||||
CheckNoError(t, resp)
|
||||
if !ok {
|
||||
t.Fatal("should Reload the config")
|
||||
}
|
||||
require.True(t, ok, "should Reload the config")
|
||||
})
|
||||
|
||||
t.Run("as restricted system admin", func(t *testing.T) {
|
||||
@@ -79,9 +70,7 @@ func TestReloadConfig(t *testing.T) {
|
||||
|
||||
ok, resp := Client.ReloadConfig()
|
||||
CheckForbiddenStatus(t, resp)
|
||||
if ok {
|
||||
t.Fatal("should not Reload the config due no permission.")
|
||||
}
|
||||
require.False(t, ok, "should not Reload the config due no permission.")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -245,31 +234,28 @@ func TestGetEnvironmentConfig(t *testing.T) {
|
||||
envConfig, resp := SystemAdminClient.GetEnvironmentConfig()
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if serviceSettings, ok := envConfig["ServiceSettings"]; !ok {
|
||||
t.Fatal("should've returned ServiceSettings")
|
||||
} else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok {
|
||||
t.Fatal("should've returned ServiceSettings as a map")
|
||||
} else {
|
||||
if siteURL, ok := serviceSettingsAsMap["SiteURL"]; !ok {
|
||||
t.Fatal("should've returned ServiceSettings.SiteURL")
|
||||
} else if siteURLAsBool, ok := siteURL.(bool); !ok {
|
||||
t.Fatal("should've returned ServiceSettings.SiteURL as a boolean")
|
||||
} else if !siteURLAsBool {
|
||||
t.Fatal("should've returned ServiceSettings.SiteURL as true")
|
||||
}
|
||||
serviceSettings, ok := envConfig["ServiceSettings"]
|
||||
require.True(t, ok, "should've returned ServiceSettings")
|
||||
|
||||
if enableCustomEmoji, ok := serviceSettingsAsMap["EnableCustomEmoji"]; !ok {
|
||||
t.Fatal("should've returned ServiceSettings.EnableCustomEmoji")
|
||||
} else if enableCustomEmojiAsBool, ok := enableCustomEmoji.(bool); !ok {
|
||||
t.Fatal("should've returned ServiceSettings.EnableCustomEmoji as a boolean")
|
||||
} else if !enableCustomEmojiAsBool {
|
||||
t.Fatal("should've returned ServiceSettings.EnableCustomEmoji as true")
|
||||
}
|
||||
}
|
||||
serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{})
|
||||
require.True(t, ok, "should've returned ServiceSettings as a map")
|
||||
|
||||
if _, ok := envConfig["TeamSettings"]; ok {
|
||||
t.Fatal("should not have returned TeamSettings")
|
||||
}
|
||||
siteURL, ok := serviceSettingsAsMap["SiteURL"]
|
||||
require.True(t, ok, "should've returned ServiceSettings.SiteURL")
|
||||
|
||||
siteURLAsBool, ok := siteURL.(bool)
|
||||
require.True(t, ok, "should've returned ServiceSettings.SiteURL as a boolean")
|
||||
require.True(t, siteURLAsBool, "should've returned ServiceSettings.SiteURL as true")
|
||||
|
||||
enableCustomEmoji, ok := serviceSettingsAsMap["EnableCustomEmoji"]
|
||||
require.True(t, ok, "should've returned ServiceSettings.EnableCustomEmoji")
|
||||
|
||||
enableCustomEmojiAsBool, ok := enableCustomEmoji.(bool)
|
||||
require.True(t, ok, "should've returned ServiceSettings.EnableCustomEmoji as a boolean")
|
||||
require.True(t, enableCustomEmojiAsBool, "should've returned ServiceSettings.EnableCustomEmoji as true")
|
||||
|
||||
_, ok = envConfig["TeamSettings"]
|
||||
require.False(t, ok, "should not have returned TeamSettings")
|
||||
})
|
||||
|
||||
t.Run("as team admin", func(t *testing.T) {
|
||||
|
||||
@@ -21,6 +21,8 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -242,19 +244,16 @@ func (a *App) DoPostActionWithCookie(postId, actionId, userId, selectedOption st
|
||||
|
||||
// Perform an HTTP POST request to an integration's action endpoint.
|
||||
// Caller must consume and close returned http.Response as necessary.
|
||||
// For internal requests, requests are routed directly to a plugin ServerHTTP hook
|
||||
func (a *App) DoActionRequest(rawURL string, body []byte) (*http.Response, *model.AppError) {
|
||||
inURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
siteURL, _ := url.Parse(*a.Config().ServiceSettings.SiteURL)
|
||||
rawURLPath := path.Clean(rawURL)
|
||||
if siteURL != nil && (strings.HasPrefix(rawURLPath, "/plugins/") || strings.HasPrefix(rawURLPath, "plugins/")) {
|
||||
inURL.Scheme = siteURL.Scheme
|
||||
inURL.Host = siteURL.Host
|
||||
inURL.Path = path.Join("/", siteURL.Path, rawURLPath)
|
||||
rawURL = inURL.String()
|
||||
if strings.HasPrefix(rawURLPath, "/plugins/") || strings.HasPrefix(rawURLPath, "plugins/") {
|
||||
return a.DoLocalRequest(rawURLPath, body)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", rawURL, bytes.NewReader(body))
|
||||
@@ -267,6 +266,7 @@ func (a *App) DoActionRequest(rawURL string, body []byte) (*http.Response, *mode
|
||||
// Allow access to plugin routes for action buttons
|
||||
var httpClient *http.Client
|
||||
subpath, _ := utils.GetSubpathFromConfig(a.Config())
|
||||
siteURL, _ := url.Parse(*a.Config().ServiceSettings.SiteURL)
|
||||
if (inURL.Hostname() == "localhost" || inURL.Hostname() == "127.0.0.1" || inURL.Hostname() == siteURL.Hostname()) && strings.HasPrefix(inURL.Path, path.Join(subpath, "plugins")) {
|
||||
req.Header.Set(model.HEADER_AUTH, "Bearer "+a.Session.Token)
|
||||
httpClient = a.HTTPService.MakeClient(true)
|
||||
@@ -286,6 +286,74 @@ func (a *App) DoActionRequest(rawURL string, body []byte) (*http.Response, *mode
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
type LocalResponseWriter struct {
|
||||
data []byte
|
||||
headers http.Header
|
||||
status int
|
||||
}
|
||||
|
||||
func (w *LocalResponseWriter) Header() http.Header {
|
||||
if w.headers == nil {
|
||||
w.headers = make(http.Header)
|
||||
}
|
||||
return w.headers
|
||||
}
|
||||
|
||||
func (w *LocalResponseWriter) Write(bytes []byte) (int, error) {
|
||||
w.data = make([]byte, len(bytes))
|
||||
copy(w.data, bytes)
|
||||
return len(w.data), nil
|
||||
}
|
||||
|
||||
func (w *LocalResponseWriter) WriteHeader(statusCode int) {
|
||||
w.status = statusCode
|
||||
}
|
||||
|
||||
func (a *App) DoLocalRequest(rawURL string, body []byte) (*http.Response, *model.AppError) {
|
||||
rawURL = strings.TrimPrefix(rawURL, "/")
|
||||
inURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
result := strings.Split(inURL.Path, "/")
|
||||
if len(result) < 2 {
|
||||
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err=Unable to find pluginId", http.StatusBadRequest)
|
||||
}
|
||||
if result[0] != "plugins" {
|
||||
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err=plugins not in path", http.StatusBadRequest)
|
||||
}
|
||||
pluginId := result[1]
|
||||
|
||||
path := strings.TrimPrefix(inURL.Path, "plugins/"+pluginId)
|
||||
|
||||
w := &LocalResponseWriter{}
|
||||
r, err := http.NewRequest("POST", path, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
r.Header.Set("Mattermost-User-Id", a.Session.UserId)
|
||||
r.Header.Set(model.HEADER_AUTH, "Bearer "+a.Session.Token)
|
||||
params := make(map[string]string)
|
||||
params["plugin_id"] = pluginId
|
||||
r = mux.SetURLVars(r, params)
|
||||
|
||||
a.ServePluginRequest(w, r)
|
||||
|
||||
resp := &http.Response{
|
||||
StatusCode: w.status,
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Header: w.headers,
|
||||
Body: ioutil.NopCloser(bytes.NewReader(w.data)),
|
||||
}
|
||||
if resp.StatusCode == 0 {
|
||||
resp.StatusCode = http.StatusOK
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (a *App) OpenInteractiveDialog(request model.OpenDialogRequest) *model.AppError {
|
||||
clientTriggerId, userId, err := request.DecodeAndVerifyTriggerId(a.AsymmetricSigningKey())
|
||||
if err != nil {
|
||||
|
||||
@@ -443,6 +443,37 @@ func TestSubmitInteractiveDialog(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
setupPluginApiTest(t,
|
||||
`
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||
response := &model.SubmitDialogResponse{
|
||||
Errors: map[string]string{"name1": "some error"},
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(response.ToJson())
|
||||
}
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&MyPlugin{})
|
||||
}
|
||||
`, `{"id": "myplugin", "backend": {"executable": "backend.exe"}}`, "myplugin", th.App)
|
||||
|
||||
hooks, err2 := th.App.GetPluginsEnvironment().HooksForPlugin("myplugin")
|
||||
require.Nil(t, err2)
|
||||
require.NotNil(t, hooks)
|
||||
|
||||
submit.URL = ts.URL
|
||||
|
||||
resp, err := th.App.SubmitInteractiveDialog(submit)
|
||||
@@ -601,7 +632,8 @@ func TestPostActionRelativeURL(t *testing.T) {
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, err)
|
||||
|
||||
})
|
||||
|
||||
t.Run("valid (but dirty) relative URL with SiteURL set", func(t *testing.T) {
|
||||
@@ -641,7 +673,7 @@ func TestPostActionRelativeURL(t *testing.T) {
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("valid relative URL with SiteURL set and no leading slash", func(t *testing.T) {
|
||||
@@ -680,6 +712,200 @@ func TestPostActionRelativeURL(t *testing.T) {
|
||||
require.NotEmpty(t, attachments[0].Actions)
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPostActionRelativePluginURL(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
setupPluginApiTest(t,
|
||||
`
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||
response := &model.PostActionIntegrationResponse{}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(response.ToJson())
|
||||
}
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&MyPlugin{})
|
||||
}
|
||||
`, `{"id": "myplugin", "backend": {"executable": "backend.exe"}}`, "myplugin", th.App)
|
||||
|
||||
hooks, err2 := th.App.GetPluginsEnvironment().HooksForPlugin("myplugin")
|
||||
require.Nil(t, err2)
|
||||
require.NotNil(t, hooks)
|
||||
|
||||
t.Run("invalid relative URL", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = ""
|
||||
*cfg.ServiceSettings.SiteURL = ""
|
||||
})
|
||||
|
||||
interactivePost := model.Post{
|
||||
Message: "Interactive post",
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
|
||||
UserId: th.BasicUser.Id,
|
||||
Props: model.StringInterface{
|
||||
"attachments": []*model.SlackAttachment{
|
||||
{
|
||||
Text: "hello",
|
||||
Actions: []*model.PostAction{
|
||||
{
|
||||
Integration: &model.PostActionIntegration{
|
||||
URL: "/notaplugin/some/path",
|
||||
},
|
||||
Name: "action",
|
||||
Type: "some_type",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
post, err := th.App.CreatePostAsUser(&interactivePost, "")
|
||||
require.Nil(t, err)
|
||||
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
|
||||
require.True(t, ok)
|
||||
require.NotEmpty(t, attachments[0].Actions)
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("valid relative URL", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = ""
|
||||
*cfg.ServiceSettings.SiteURL = ""
|
||||
})
|
||||
|
||||
interactivePost := model.Post{
|
||||
Message: "Interactive post",
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
|
||||
UserId: th.BasicUser.Id,
|
||||
Props: model.StringInterface{
|
||||
"attachments": []*model.SlackAttachment{
|
||||
{
|
||||
Text: "hello",
|
||||
Actions: []*model.PostAction{
|
||||
{
|
||||
Integration: &model.PostActionIntegration{
|
||||
URL: "/plugins/myplugin/myaction",
|
||||
},
|
||||
Name: "action",
|
||||
Type: "some_type",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
post, err := th.App.CreatePostAsUser(&interactivePost, "")
|
||||
require.Nil(t, err)
|
||||
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
|
||||
require.True(t, ok)
|
||||
require.NotEmpty(t, attachments[0].Actions)
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("valid (but dirty) relative URL", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = ""
|
||||
*cfg.ServiceSettings.SiteURL = ""
|
||||
})
|
||||
|
||||
interactivePost := model.Post{
|
||||
Message: "Interactive post",
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
|
||||
UserId: th.BasicUser.Id,
|
||||
Props: model.StringInterface{
|
||||
"attachments": []*model.SlackAttachment{
|
||||
{
|
||||
Text: "hello",
|
||||
Actions: []*model.PostAction{
|
||||
{
|
||||
Integration: &model.PostActionIntegration{
|
||||
URL: "//plugins/myplugin///myaction",
|
||||
},
|
||||
Name: "action",
|
||||
Type: "some_type",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
post, err := th.App.CreatePostAsUser(&interactivePost, "")
|
||||
require.Nil(t, err)
|
||||
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
|
||||
require.True(t, ok)
|
||||
require.NotEmpty(t, attachments[0].Actions)
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("valid relative URL and no leading slash", func(t *testing.T) {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = ""
|
||||
*cfg.ServiceSettings.SiteURL = ""
|
||||
})
|
||||
|
||||
interactivePost := model.Post{
|
||||
Message: "Interactive post",
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
|
||||
UserId: th.BasicUser.Id,
|
||||
Props: model.StringInterface{
|
||||
"attachments": []*model.SlackAttachment{
|
||||
{
|
||||
Text: "hello",
|
||||
Actions: []*model.PostAction{
|
||||
{
|
||||
Integration: &model.PostActionIntegration{
|
||||
URL: "plugins/myplugin/myaction",
|
||||
},
|
||||
Name: "action",
|
||||
Type: "some_type",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
post, err := th.App.CreatePostAsUser(&interactivePost, "")
|
||||
require.Nil(t, err)
|
||||
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
|
||||
require.True(t, ok)
|
||||
require.NotEmpty(t, attachments[0].Actions)
|
||||
require.NotEmpty(t, attachments[0].Actions[0].Id)
|
||||
|
||||
_, err = th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -825,3 +826,29 @@ func (api *PluginAPI) DeleteBotIconImage(userId string) *model.AppError {
|
||||
|
||||
return api.app.DeleteBotIconImage(userId)
|
||||
}
|
||||
|
||||
func (api *PluginAPI) PluginHTTP(request *http.Request) *http.Response {
|
||||
split := strings.SplitN(request.URL.Path, "/", 3)
|
||||
if len(split) != 3 {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("Not enough URL. Form of URL should be /<pluginid>/*")),
|
||||
}
|
||||
}
|
||||
destinationPluginId := split[1]
|
||||
newURL, err := url.Parse("/" + split[2])
|
||||
request.URL = newURL
|
||||
if destinationPluginId == "" || err != nil {
|
||||
message := "No plugin specified. Form of URL should be /<pluginid>/*"
|
||||
if err != nil {
|
||||
message = "Form of URL should be /<pluginid>/* Error: " + err.Error()
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(message)),
|
||||
}
|
||||
}
|
||||
responseTransfer := &PluginResponseWriter{}
|
||||
api.app.ServeInterPluginRequest(responseTransfer, request, api.id, destinationPluginId)
|
||||
return responseTransfer.GenerateResponse()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupPluginApiTest(t *testing.T, pluginCode string, pluginManifest string, pluginId string, app *App) string {
|
||||
func setupMultiPluginApiTest(t *testing.T, pluginCodes []string, pluginManifests []string, pluginIds []string, app *App) string {
|
||||
pluginDir, err := ioutil.TempDir("", "")
|
||||
require.NoError(t, err)
|
||||
webappPluginDir, err := ioutil.TempDir("", "")
|
||||
@@ -37,20 +37,29 @@ func setupPluginApiTest(t *testing.T, pluginCode string, pluginManifest string,
|
||||
env, err := plugin.NewEnvironment(app.NewPluginAPI, pluginDir, webappPluginDir, app.Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
backend := filepath.Join(pluginDir, pluginId, "backend.exe")
|
||||
utils.CompileGo(t, pluginCode, backend)
|
||||
require.Equal(t, len(pluginCodes), len(pluginIds))
|
||||
require.Equal(t, len(pluginManifests), len(pluginIds))
|
||||
|
||||
ioutil.WriteFile(filepath.Join(pluginDir, pluginId, "plugin.json"), []byte(pluginManifest), 0600)
|
||||
manifest, activated, reterr := env.Activate(pluginId)
|
||||
require.Nil(t, reterr)
|
||||
require.NotNil(t, manifest)
|
||||
require.True(t, activated)
|
||||
for i, pluginId := range pluginIds {
|
||||
backend := filepath.Join(pluginDir, pluginId, "backend.exe")
|
||||
utils.CompileGo(t, pluginCodes[i], backend)
|
||||
|
||||
ioutil.WriteFile(filepath.Join(pluginDir, pluginId, "plugin.json"), []byte(pluginManifests[i]), 0600)
|
||||
manifest, activated, reterr := env.Activate(pluginId)
|
||||
require.Nil(t, reterr)
|
||||
require.NotNil(t, manifest)
|
||||
require.True(t, activated)
|
||||
}
|
||||
|
||||
app.SetPluginsEnvironment(env)
|
||||
|
||||
return pluginDir
|
||||
}
|
||||
|
||||
func setupPluginApiTest(t *testing.T, pluginCode string, pluginManifest string, pluginId string, app *App) string {
|
||||
return setupMultiPluginApiTest(t, []string{pluginCode}, []string{pluginManifest}, []string{pluginId}, app)
|
||||
}
|
||||
|
||||
func TestPublicFilesPathConfiguration(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
@@ -1462,3 +1471,98 @@ func TestPluginAddUserToChannel(t *testing.T) {
|
||||
require.Equal(t, th.BasicChannel.Id, member.ChannelId)
|
||||
require.Equal(t, th.BasicUser.Id, member.UserId)
|
||||
}
|
||||
|
||||
func TestInterpluginPluginHTTP(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
setupMultiPluginApiTest(t,
|
||||
[]string{`
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
"bytes"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func (p *MyPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/api/v2/test" {
|
||||
return
|
||||
}
|
||||
buf := bytes.Buffer{}
|
||||
buf.ReadFrom(r.Body)
|
||||
resp := "we got:" + buf.String()
|
||||
w.WriteHeader(598)
|
||||
w.Write([]byte(resp))
|
||||
}
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&MyPlugin{})
|
||||
}
|
||||
`,
|
||||
`
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"bytes"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
|
||||
buf := bytes.Buffer{}
|
||||
buf.WriteString("This is the request")
|
||||
req, err := http.NewRequest("GET", "/testplugininterserver/api/v2/test", &buf)
|
||||
if err != nil {
|
||||
return nil, err.Error()
|
||||
}
|
||||
req.Header.Add("Mattermost-User-Id", "userid")
|
||||
resp := p.API.PluginHTTP(req)
|
||||
if resp == nil {
|
||||
return nil, "Nil resp"
|
||||
}
|
||||
if resp.Body == nil {
|
||||
return nil, "Nil body"
|
||||
}
|
||||
respbody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err.Error()
|
||||
}
|
||||
if resp.StatusCode != 598 {
|
||||
return nil, "wrong status " + string(respbody)
|
||||
}
|
||||
return nil, string(respbody)
|
||||
}
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&MyPlugin{})
|
||||
}
|
||||
`,
|
||||
},
|
||||
[]string{
|
||||
`{"id": "testplugininterserver", "backend": {"executable": "backend.exe"}}`,
|
||||
`{"id": "testplugininterclient", "backend": {"executable": "backend.exe"}}`,
|
||||
},
|
||||
[]string{
|
||||
"testplugininterserver",
|
||||
"testplugininterclient",
|
||||
},
|
||||
th.App,
|
||||
)
|
||||
|
||||
hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testplugininterclient")
|
||||
require.NoError(t, err)
|
||||
_, ret := hooks.MessageWillBePosted(nil, nil)
|
||||
assert.Equal(t, "we got:This is the request", ret)
|
||||
}
|
||||
|
||||
@@ -42,6 +42,37 @@ func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) {
|
||||
a.servePluginRequest(w, r, hooks.ServeHTTP)
|
||||
}
|
||||
|
||||
func (a *App) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string) {
|
||||
pluginsEnvironment := a.GetPluginsEnvironment()
|
||||
if pluginsEnvironment == nil {
|
||||
err := model.NewAppError("ServeInterPluginRequest", "app.plugin.disabled.app_error", nil, "Plugin enviroment not found.", http.StatusNotImplemented)
|
||||
a.Log.Error(err.Error())
|
||||
w.WriteHeader(err.StatusCode)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(err.ToJson()))
|
||||
return
|
||||
}
|
||||
|
||||
hooks, err := pluginsEnvironment.HooksForPlugin(destinationPluginId)
|
||||
if err != nil {
|
||||
a.Log.Error("Access to route for non-existent plugin in inter plugin request",
|
||||
mlog.String("sourse_plugin_id", sourcePluginId),
|
||||
mlog.String("destination_plugin_id", destinationPluginId),
|
||||
mlog.Err(err),
|
||||
)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
context := &plugin.Context{
|
||||
RequestId: model.NewId(),
|
||||
UserAgent: r.UserAgent(),
|
||||
SourcePluginId: sourcePluginId,
|
||||
}
|
||||
|
||||
hooks.ServeHTTP(context, w, r)
|
||||
}
|
||||
|
||||
// ServePluginPublicRequest serves public plugin files
|
||||
// at the URL http(s)://$SITE_URL/plugins/$PLUGIN_ID/public/{anything}
|
||||
func (a *App) ServePluginPublicRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
70
app/response_transfer.go
Обычный файл
70
app/response_transfer.go
Обычный файл
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PluginResponseWriter struct {
|
||||
bytes.Buffer
|
||||
headers http.Header
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (rt *PluginResponseWriter) Header() http.Header {
|
||||
if rt.headers == nil {
|
||||
rt.headers = make(http.Header)
|
||||
}
|
||||
return rt.headers
|
||||
}
|
||||
|
||||
func (rt *PluginResponseWriter) WriteHeader(statusCode int) {
|
||||
rt.statusCode = statusCode
|
||||
}
|
||||
|
||||
// From net/http/httptest/recorder.go
|
||||
func parseContentLength(cl string) int64 {
|
||||
cl = strings.TrimSpace(cl)
|
||||
if cl == "" {
|
||||
return -1
|
||||
}
|
||||
n, err := strconv.ParseInt(cl, 10, 64)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return n
|
||||
|
||||
}
|
||||
|
||||
func (rt *PluginResponseWriter) GenerateResponse() *http.Response {
|
||||
res := &http.Response{
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
StatusCode: rt.statusCode,
|
||||
Header: rt.headers.Clone(),
|
||||
}
|
||||
|
||||
if res.StatusCode == 0 {
|
||||
res.StatusCode = http.StatusOK
|
||||
}
|
||||
|
||||
res.Status = fmt.Sprintf("%03d %s", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
|
||||
if rt.Len() > 0 {
|
||||
res.Body = ioutil.NopCloser(rt)
|
||||
} else {
|
||||
res.Body = http.NoBody
|
||||
}
|
||||
|
||||
res.ContentLength = parseContentLength(rt.headers.Get("Content-Length"))
|
||||
|
||||
return res
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func (s *Server) RunOldAppInitalization() error {
|
||||
|
||||
if s.FakeApp().Srv.newStore == nil {
|
||||
s.FakeApp().Srv.newStore = func() store.Store {
|
||||
return store.NewTimerLayer(localcachelayer.NewLocalCacheLayer(store.NewLayeredStore(sqlstore.NewSqlSupplier(s.FakeApp().Config().SqlSettings, s.Metrics), s.Metrics, s.Cluster), s.Metrics, s.Cluster), s.Metrics)
|
||||
return store.NewTimerLayer(localcachelayer.NewLocalCacheLayer(sqlstore.NewSqlSupplier(s.FakeApp().Config().SqlSettings, s.Metrics), s.Metrics, s.Cluster), s.Metrics)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/mattermost-server/mlog"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/utils"
|
||||
@@ -215,11 +213,11 @@ func (a *App) SetStatusOnline(userId string, manual bool) {
|
||||
if status.Status != oldStatus || status.Manual != oldManual || status.LastActivityAt-oldTime > model.STATUS_MIN_UPDATE_TIME {
|
||||
if broadcast {
|
||||
if err := a.Srv.Store.Status().SaveOrUpdate(status); err != nil {
|
||||
mlog.Error(fmt.Sprintf("Failed to save status for user_id=%v, err=%v", userId, err), mlog.String("user_id", userId))
|
||||
mlog.Error("Failed to save status", mlog.String("user_id", userId), mlog.Err(err), mlog.String("user_id", userId))
|
||||
}
|
||||
} else {
|
||||
if err := a.Srv.Store.Status().UpdateLastActivityAt(status.UserId, status.LastActivityAt); err != nil {
|
||||
mlog.Error(fmt.Sprintf("Failed to save status for user_id=%v, err=%v", userId, err), mlog.String("user_id", userId))
|
||||
mlog.Error("Failed to save status", mlog.String("user_id", userId), mlog.Err(err), mlog.String("user_id", userId))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,7 +302,7 @@ func (a *App) SaveAndBroadcastStatus(status *model.Status) {
|
||||
a.AddStatusCache(status)
|
||||
|
||||
if err := a.Srv.Store.Status().SaveOrUpdate(status); err != nil {
|
||||
mlog.Error(fmt.Sprintf("Failed to save status for user_id=%v, err=%v", status.UserId, err))
|
||||
mlog.Error("Failed to save status", mlog.String("user_id", status.UserId), mlog.Err(err))
|
||||
}
|
||||
|
||||
a.BroadcastStatus(status)
|
||||
|
||||
@@ -91,6 +91,9 @@ type PluginSettingsSchema struct {
|
||||
// "id": "com.mycompany.myplugin",
|
||||
// "name": "My Plugin",
|
||||
// "description": "This is my plugin",
|
||||
// "homepage_url": "https://example.com",
|
||||
// "support_url": "https://example.com/support",
|
||||
// "icon_path": "assets/logo.svg",
|
||||
// "version": "0.1.0",
|
||||
// "min_server_version": "5.6.0",
|
||||
// "server": {
|
||||
|
||||
175
plugin/api.go
175
plugin/api.go
@@ -5,6 +5,7 @@ package plugin
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
@@ -19,17 +20,20 @@ type API interface {
|
||||
// LoadPluginConfiguration loads the plugin's configuration. dest should be a pointer to a
|
||||
// struct that the configuration JSON can be unmarshalled to.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.2
|
||||
LoadPluginConfiguration(dest interface{}) error
|
||||
|
||||
// RegisterCommand registers a custom slash command. When the command is triggered, your plugin
|
||||
// can fulfill it via the ExecuteCommand hook.
|
||||
//
|
||||
// @tag Command
|
||||
// Minimum server version: 5.2
|
||||
RegisterCommand(command *model.Command) error
|
||||
|
||||
// UnregisterCommand unregisters a command previously registered via RegisterCommand.
|
||||
//
|
||||
// @tag Command
|
||||
// Minimum server version: 5.2
|
||||
UnregisterCommand(teamId, trigger string) error
|
||||
|
||||
@@ -40,139 +44,168 @@ type API interface {
|
||||
|
||||
// GetConfig fetches the currently persisted config
|
||||
//
|
||||
// @tag Configuration
|
||||
// Minimum server version: 5.2
|
||||
GetConfig() *model.Config
|
||||
|
||||
// GetUnsanitizedConfig fetches the currently persisted config without removing secrets.
|
||||
//
|
||||
// @tag Configuration
|
||||
// Minimum server version: 5.16
|
||||
GetUnsanitizedConfig() *model.Config
|
||||
|
||||
// SaveConfig sets the given config and persists the changes
|
||||
//
|
||||
// @tag Configuration
|
||||
// Minimum server version: 5.2
|
||||
SaveConfig(config *model.Config) *model.AppError
|
||||
|
||||
// GetPluginConfig fetches the currently persisted config of plugin
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
GetPluginConfig() map[string]interface{}
|
||||
|
||||
// SavePluginConfig sets the given config for plugin and persists the changes
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
SavePluginConfig(config map[string]interface{}) *model.AppError
|
||||
|
||||
// GetBundlePath returns the absolute path where the plugin's bundle was unpacked.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.10
|
||||
GetBundlePath() (string, error)
|
||||
|
||||
// GetLicense returns the current license used by the Mattermost server. Returns nil if the
|
||||
// the server does not have a license.
|
||||
//
|
||||
// @tag Server
|
||||
// Minimum server version: 5.10
|
||||
GetLicense() *model.License
|
||||
|
||||
// GetServerVersion return the current Mattermost server version
|
||||
//
|
||||
// @tag Server
|
||||
// Minimum server version: 5.4
|
||||
GetServerVersion() string
|
||||
|
||||
// GetSystemInstallDate returns the time that Mattermost was first installed and ran.
|
||||
//
|
||||
// @tag Server
|
||||
// Minimum server version: 5.10
|
||||
GetSystemInstallDate() (int64, *model.AppError)
|
||||
|
||||
// GetDiagnosticId returns a unique identifier used by the server for diagnostic reports.
|
||||
//
|
||||
// @tag Server
|
||||
// Minimum server version: 5.10
|
||||
GetDiagnosticId() string
|
||||
|
||||
// CreateUser creates a user.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
CreateUser(user *model.User) (*model.User, *model.AppError)
|
||||
|
||||
// DeleteUser deletes a user.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
DeleteUser(userId string) *model.AppError
|
||||
|
||||
// GetUsers a list of users based on search options.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.10
|
||||
GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError)
|
||||
|
||||
// GetUser gets a user.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetUser(userId string) (*model.User, *model.AppError)
|
||||
|
||||
// GetUserByEmail gets a user by their email address.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetUserByEmail(email string) (*model.User, *model.AppError)
|
||||
|
||||
// GetUserByUsername gets a user by their username.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetUserByUsername(name string) (*model.User, *model.AppError)
|
||||
|
||||
// GetUsersByUsernames gets users by their usernames.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError)
|
||||
|
||||
// GetUsersInTeam gets users in team.
|
||||
//
|
||||
// @tag User
|
||||
// @tag Team
|
||||
// Minimum server version: 5.6
|
||||
GetUsersInTeam(teamId string, page int, perPage int) ([]*model.User, *model.AppError)
|
||||
|
||||
// GetTeamIcon gets the team icon.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.6
|
||||
GetTeamIcon(teamId string) ([]byte, *model.AppError)
|
||||
|
||||
// SetTeamIcon sets the team icon.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.6
|
||||
SetTeamIcon(teamId string, data []byte) *model.AppError
|
||||
|
||||
// RemoveTeamIcon removes the team icon.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.6
|
||||
RemoveTeamIcon(teamId string) *model.AppError
|
||||
|
||||
// UpdateUser updates a user.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
UpdateUser(user *model.User) (*model.User, *model.AppError)
|
||||
|
||||
// GetUserStatus will get a user's status.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetUserStatus(userId string) (*model.Status, *model.AppError)
|
||||
|
||||
// GetUserStatusesByIds will return a list of user statuses based on the provided slice of user IDs.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetUserStatusesByIds(userIds []string) ([]*model.Status, *model.AppError)
|
||||
|
||||
// UpdateUserStatus will set a user's status until the user, or another integration/plugin, sets it back to online.
|
||||
// The status parameter can be: "online", "away", "dnd", or "offline".
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
UpdateUserStatus(userId, status string) (*model.Status, *model.AppError)
|
||||
|
||||
// UpdateUserActive deactivates or reactivates an user.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.8
|
||||
UpdateUserActive(userId string, active bool) *model.AppError
|
||||
|
||||
// GetUsersInChannel returns a page of users in a channel. Page counting starts at 0.
|
||||
// The sortBy parameter can be: "username" or "status".
|
||||
//
|
||||
// @tag User
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetUsersInChannel(channelId, sortBy string, page, perPage int) ([]*model.User, *model.AppError)
|
||||
|
||||
@@ -181,312 +214,403 @@ type API interface {
|
||||
// Returns a map with attribute names as keys and the user's attributes as values.
|
||||
// Requires an enterprise license, LDAP to be configured and for the user to use LDAP as an authentication method.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.3
|
||||
GetLDAPUserAttributes(userId string, attributes []string) (map[string]string, *model.AppError)
|
||||
|
||||
// CreateTeam creates a team.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
CreateTeam(team *model.Team) (*model.Team, *model.AppError)
|
||||
|
||||
// DeleteTeam deletes a team.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
DeleteTeam(teamId string) *model.AppError
|
||||
|
||||
// GetTeam gets all teams.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
GetTeams() ([]*model.Team, *model.AppError)
|
||||
|
||||
// GetTeam gets a team.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
GetTeam(teamId string) (*model.Team, *model.AppError)
|
||||
|
||||
// GetTeamByName gets a team by its name.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
GetTeamByName(name string) (*model.Team, *model.AppError)
|
||||
|
||||
// GetTeamsUnreadForUser gets the unread message and mention counts for each team to which the given user belongs.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetTeamsUnreadForUser(userId string) ([]*model.TeamUnread, *model.AppError)
|
||||
|
||||
// UpdateTeam updates a team.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
UpdateTeam(team *model.Team) (*model.Team, *model.AppError)
|
||||
|
||||
// SearchTeams search a team.
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.8
|
||||
SearchTeams(term string) ([]*model.Team, *model.AppError)
|
||||
|
||||
// GetTeamsForUser returns list of teams of given user ID.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetTeamsForUser(userId string) ([]*model.Team, *model.AppError)
|
||||
|
||||
// CreateTeamMember creates a team membership.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
CreateTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError)
|
||||
|
||||
// CreateTeamMember creates a team membership for all provided user ids.
|
||||
// CreateTeamMembers creates a team membership for all provided user ids.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
CreateTeamMembers(teamId string, userIds []string, requestorId string) ([]*model.TeamMember, *model.AppError)
|
||||
|
||||
// DeleteTeamMember deletes a team membership.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
DeleteTeamMember(teamId, userId, requestorId string) *model.AppError
|
||||
|
||||
// GetTeamMembers returns the memberships of a specific team.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetTeamMembers(teamId string, page, perPage int) ([]*model.TeamMember, *model.AppError)
|
||||
|
||||
// GetTeamMember returns a specific membership.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError)
|
||||
|
||||
// GetTeamMembersForUser returns all team memberships for a user.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.10
|
||||
GetTeamMembersForUser(userId string, page int, perPage int) ([]*model.TeamMember, *model.AppError)
|
||||
|
||||
// UpdateTeamMemberRoles updates the role for a team membership.
|
||||
//
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
UpdateTeamMemberRoles(teamId, userId, newRoles string) (*model.TeamMember, *model.AppError)
|
||||
|
||||
// CreateChannel creates a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.2
|
||||
CreateChannel(channel *model.Channel) (*model.Channel, *model.AppError)
|
||||
|
||||
// DeleteChannel deletes a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.2
|
||||
DeleteChannel(channelId string) *model.AppError
|
||||
|
||||
// GetPublicChannelsForTeam gets a list of all channels.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
GetPublicChannelsForTeam(teamId string, page, perPage int) ([]*model.Channel, *model.AppError)
|
||||
|
||||
// GetChannel gets a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.2
|
||||
GetChannel(channelId string) (*model.Channel, *model.AppError)
|
||||
|
||||
// GetChannelByName gets a channel by its name, given a team id.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.2
|
||||
GetChannelByName(teamId, name string, includeDeleted bool) (*model.Channel, *model.AppError)
|
||||
|
||||
// GetChannelByNameForTeamName gets a channel by its name, given a team name.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag Team
|
||||
// Minimum server version: 5.2
|
||||
GetChannelByNameForTeamName(teamName, channelName string, includeDeleted bool) (*model.Channel, *model.AppError)
|
||||
|
||||
// GetChannelsForTeamForUser gets a list of channels for given user ID in given team ID.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag Team
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetChannelsForTeamForUser(teamId, userId string, includeDeleted bool) ([]*model.Channel, *model.AppError)
|
||||
|
||||
// GetChannelStats gets statistics for a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetChannelStats(channelId string) (*model.ChannelStats, *model.AppError)
|
||||
|
||||
// GetDirectChannel gets a direct message channel.
|
||||
// If the channel does not exist it will create it.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetDirectChannel(userId1, userId2 string) (*model.Channel, *model.AppError)
|
||||
|
||||
// GetGroupChannel gets a group message channel.
|
||||
// If the channel does not exist it will create it.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetGroupChannel(userIds []string) (*model.Channel, *model.AppError)
|
||||
|
||||
// UpdateChannel updates a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.2
|
||||
UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError)
|
||||
|
||||
// SearchChannels returns the channels on a team matching the provided search term.
|
||||
//
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
SearchChannels(teamId string, term string) ([]*model.Channel, *model.AppError)
|
||||
|
||||
// SearchUsers returns a list of users based on some search criteria.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
SearchUsers(search *model.UserSearch) ([]*model.User, *model.AppError)
|
||||
|
||||
// SearchPostsInTeam returns a list of posts in a specific team that match the given params.
|
||||
//
|
||||
// @tag Post
|
||||
// @tag Team
|
||||
// Minimum server version: 5.10
|
||||
SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError)
|
||||
|
||||
// AddChannelMember joins a user to a channel (as if they joined themselves)
|
||||
// This means the user will not receive notifications for joining the channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
// AddUserToChannel adds a user to a channel as if the specified user had invited them.
|
||||
// This means the user will receive the regular notifications for being added to the channel.
|
||||
//
|
||||
// @tag User
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.18
|
||||
AddUserToChannel(channelId, userId, asUserId string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
// GetChannelMember gets a channel membership for a user.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
GetChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
// GetChannelMembers gets a channel membership for all users.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetChannelMembers(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError)
|
||||
|
||||
// GetChannelMembersByIds gets a channel membership for a particular User
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetChannelMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError)
|
||||
|
||||
// GetChannelMembersForUser returns all channel memberships on a team for a user.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.10
|
||||
GetChannelMembersForUser(teamId, userId string, page, perPage int) ([]*model.ChannelMember, *model.AppError)
|
||||
|
||||
// UpdateChannelMemberRoles updates a user's roles for a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
UpdateChannelMemberRoles(channelId, userId, newRoles string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
// UpdateChannelMemberNotifications updates a user's notification properties for a channel.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
UpdateChannelMemberNotifications(channelId, userId string, notifications map[string]string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
// GetGroup gets a group by ID.
|
||||
//
|
||||
// @tag Group
|
||||
// Minimum server version: 5.18
|
||||
GetGroup(groupId string) (*model.Group, *model.AppError)
|
||||
|
||||
// GetGroupByName gets a group by name.
|
||||
//
|
||||
// @tag Group
|
||||
// Minimum server version: 5.18
|
||||
GetGroupByName(name string) (*model.Group, *model.AppError)
|
||||
|
||||
// GetGroupsForUser gets the groups a user is in.
|
||||
//
|
||||
// @tag Group
|
||||
// @tag User
|
||||
// Minimum server version: 5.18
|
||||
GetGroupsForUser(userId string) ([]*model.Group, *model.AppError)
|
||||
|
||||
// DeleteChannelMember deletes a channel membership for a user.
|
||||
//
|
||||
// @tag Channel
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
DeleteChannelMember(channelId, userId string) *model.AppError
|
||||
|
||||
// CreatePost creates a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
CreatePost(post *model.Post) (*model.Post, *model.AppError)
|
||||
|
||||
// AddReaction add a reaction to a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.3
|
||||
AddReaction(reaction *model.Reaction) (*model.Reaction, *model.AppError)
|
||||
|
||||
// RemoveReaction remove a reaction from a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.3
|
||||
RemoveReaction(reaction *model.Reaction) *model.AppError
|
||||
|
||||
// GetReaction get the reactions of a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.3
|
||||
GetReactions(postId string) ([]*model.Reaction, *model.AppError)
|
||||
|
||||
// SendEphemeralPost creates an ephemeral post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
SendEphemeralPost(userId string, post *model.Post) *model.Post
|
||||
|
||||
// UpdateEphemeralPost updates an ephemeral message previously sent to the user.
|
||||
// EXPERIMENTAL: This API is experimental and can be changed without advance notice.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
UpdateEphemeralPost(userId string, post *model.Post) *model.Post
|
||||
|
||||
// DeleteEphemeralPost deletes an ephemeral message previously sent to the user.
|
||||
// EXPERIMENTAL: This API is experimental and can be changed without advance notice.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
DeleteEphemeralPost(userId, postId string)
|
||||
|
||||
// DeletePost deletes a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
DeletePost(postId string) *model.AppError
|
||||
|
||||
// GetPostThread gets a post with all the other posts in the same thread.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.6
|
||||
GetPostThread(postId string) (*model.PostList, *model.AppError)
|
||||
|
||||
// GetPost gets a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
GetPost(postId string) (*model.Post, *model.AppError)
|
||||
|
||||
// GetPostsSince gets posts created after a specified time as Unix time in milliseconds.
|
||||
//
|
||||
// @tag Post
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetPostsSince(channelId string, time int64) (*model.PostList, *model.AppError)
|
||||
|
||||
// GetPostsAfter gets a page of posts that were posted after the post provided.
|
||||
//
|
||||
// @tag Post
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetPostsAfter(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError)
|
||||
|
||||
// GetPostsBefore gets a page of posts that were posted before the post provided.
|
||||
//
|
||||
// @tag Post
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetPostsBefore(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError)
|
||||
|
||||
// GetPostsForChannel gets a list of posts for a channel.
|
||||
//
|
||||
// @tag Post
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
GetPostsForChannel(channelId string, page, perPage int) (*model.PostList, *model.AppError)
|
||||
|
||||
// GetTeamStats gets a team's statistics
|
||||
//
|
||||
// @tag Team
|
||||
// Minimum server version: 5.8
|
||||
GetTeamStats(teamId string) (*model.TeamStats, *model.AppError)
|
||||
|
||||
// UpdatePost updates a post.
|
||||
//
|
||||
// @tag Post
|
||||
// Minimum server version: 5.2
|
||||
UpdatePost(post *model.Post) (*model.Post, *model.AppError)
|
||||
|
||||
// GetProfileImage gets user's profile image.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
GetProfileImage(userId string) ([]byte, *model.AppError)
|
||||
|
||||
// SetProfileImage sets a user's profile image.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.6
|
||||
SetProfileImage(userId string, data []byte) *model.AppError
|
||||
|
||||
@@ -494,16 +618,19 @@ type API interface {
|
||||
//
|
||||
// The sortBy parameter can be: "name".
|
||||
//
|
||||
// @tag Emoji
|
||||
// Minimum server version: 5.6
|
||||
GetEmojiList(sortBy string, page, perPage int) ([]*model.Emoji, *model.AppError)
|
||||
|
||||
// GetEmojiByName gets an emoji by it's name.
|
||||
//
|
||||
// @tag Emoji
|
||||
// Minimum server version: 5.6
|
||||
GetEmojiByName(name string) (*model.Emoji, *model.AppError)
|
||||
|
||||
// GetEmoji returns a custom emoji based on the emojiId string.
|
||||
//
|
||||
// @tag Emoji
|
||||
// Minimum server version: 5.6
|
||||
GetEmoji(emojiId string) (*model.Emoji, *model.AppError)
|
||||
|
||||
@@ -514,36 +641,45 @@ type API interface {
|
||||
// to CreatePost. Use this API to duplicate a post and its file attachments without
|
||||
// actually duplicating the uploaded files.
|
||||
//
|
||||
// @tag File
|
||||
// @tag User
|
||||
// Minimum server version: 5.2
|
||||
CopyFileInfos(userId string, fileIds []string) ([]string, *model.AppError)
|
||||
|
||||
// GetFileInfo gets a File Info for a specific fileId
|
||||
//
|
||||
// @tag File
|
||||
// Minimum server version: 5.3
|
||||
GetFileInfo(fileId string) (*model.FileInfo, *model.AppError)
|
||||
|
||||
// GetFile gets content of a file by it's ID
|
||||
//
|
||||
// @tag File
|
||||
// Minimum server version: 5.8
|
||||
GetFile(fileId string) ([]byte, *model.AppError)
|
||||
|
||||
// GetFileLink gets the public link to a file by fileId.
|
||||
//
|
||||
// @tag File
|
||||
// Minimum server version: 5.6
|
||||
GetFileLink(fileId string) (string, *model.AppError)
|
||||
|
||||
// ReadFileAtPath reads the file from the backend for a specific path
|
||||
//
|
||||
// @tag File
|
||||
// Minimum server version: 5.3
|
||||
ReadFile(path string) ([]byte, *model.AppError)
|
||||
|
||||
// GetEmojiImage returns the emoji image.
|
||||
//
|
||||
// @tag Emoji
|
||||
// Minimum server version: 5.6
|
||||
GetEmojiImage(emojiId string) ([]byte, string, *model.AppError)
|
||||
|
||||
// UploadFile will upload a file to a channel using a multipart request, to be later attached to a post.
|
||||
//
|
||||
// @tag File
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.6
|
||||
UploadFile(data []byte, channelId string, filename string) (*model.FileInfo, *model.AppError)
|
||||
|
||||
@@ -558,32 +694,38 @@ type API interface {
|
||||
|
||||
// GetPlugins will return a list of plugin manifests for currently active plugins.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
GetPlugins() ([]*model.Manifest, *model.AppError)
|
||||
|
||||
// EnablePlugin will enable an plugin installed.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
EnablePlugin(id string) *model.AppError
|
||||
|
||||
// DisablePlugin will disable an enabled plugin.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
DisablePlugin(id string) *model.AppError
|
||||
|
||||
// RemovePlugin will disable and delete a plugin.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
RemovePlugin(id string) *model.AppError
|
||||
|
||||
// GetPluginStatus will return the status of a plugin.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.6
|
||||
GetPluginStatus(id string) (*model.PluginStatus, *model.AppError)
|
||||
|
||||
// InstallPlugin will upload another plugin with tar.gz file.
|
||||
// Previous version will be replaced on replace true.
|
||||
//
|
||||
// @tag Plugin
|
||||
// Minimum server version: 5.18
|
||||
InstallPlugin(file io.Reader, replace bool) (*model.Manifest, *model.AppError)
|
||||
|
||||
@@ -592,6 +734,7 @@ type API interface {
|
||||
// KVSet stores a key-value pair, unique per plugin.
|
||||
// Provided helper functions and internal plugin code will use the prefix `mmi_` before keys. Do not use this prefix.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.2
|
||||
KVSet(key string, value []byte) *model.AppError
|
||||
|
||||
@@ -601,6 +744,7 @@ type API interface {
|
||||
// Returns (false, nil) if current value != oldValue or key already exists when inserting
|
||||
// Returns (true, nil) if current value == oldValue or new key is inserted
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.12
|
||||
KVCompareAndSet(key string, oldValue, newValue []byte) (bool, *model.AppError)
|
||||
|
||||
@@ -609,6 +753,7 @@ type API interface {
|
||||
// Returns (false, nil) if current value != oldValue or key does not exist when deleting
|
||||
// Returns (true, nil) if current value == oldValue and the key was deleted
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.16
|
||||
KVCompareAndDelete(key string, oldValue []byte) (bool, *model.AppError)
|
||||
|
||||
@@ -623,26 +768,31 @@ type API interface {
|
||||
|
||||
// KVSet stores a key-value pair with an expiry time, unique per plugin.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.6
|
||||
KVSetWithExpiry(key string, value []byte, expireInSeconds int64) *model.AppError
|
||||
|
||||
// KVGet retrieves a value based on the key, unique per plugin. Returns nil for non-existent keys.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.2
|
||||
KVGet(key string) ([]byte, *model.AppError)
|
||||
|
||||
// KVDelete removes a key-value pair, unique per plugin. Returns nil for non-existent keys.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.2
|
||||
KVDelete(key string) *model.AppError
|
||||
|
||||
// KVDeleteAll removes all key-value pairs for a plugin.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.6
|
||||
KVDeleteAll() *model.AppError
|
||||
|
||||
// KVList lists all keys for a plugin.
|
||||
//
|
||||
// @tag KeyValueStore
|
||||
// Minimum server version: 5.6
|
||||
KVList(page, perPage int) ([]string, *model.AppError)
|
||||
|
||||
@@ -656,16 +806,21 @@ type API interface {
|
||||
|
||||
// HasPermissionTo check if the user has the permission at system scope.
|
||||
//
|
||||
// @tag User
|
||||
// Minimum server version: 5.3
|
||||
HasPermissionTo(userId string, permission *model.Permission) bool
|
||||
|
||||
// HasPermissionToTeam check if the user has the permission at team scope.
|
||||
//
|
||||
// @tag User
|
||||
// @tag Team
|
||||
// Minimum server version: 5.3
|
||||
HasPermissionToTeam(userId, teamId string, permission *model.Permission) bool
|
||||
|
||||
// HasPermissionToChannel check if the user has the permission at channel scope.
|
||||
//
|
||||
// @tag User
|
||||
// @tag Channel
|
||||
// Minimum server version: 5.3
|
||||
HasPermissionToChannel(userId, channelId string, permission *model.Permission) bool
|
||||
|
||||
@@ -673,6 +828,7 @@ type API interface {
|
||||
// Appropriate context such as the plugin name will already be added as fields so plugins
|
||||
// do not need to add that info.
|
||||
//
|
||||
// @tag Logging
|
||||
// Minimum server version: 5.2
|
||||
LogDebug(msg string, keyValuePairs ...interface{})
|
||||
|
||||
@@ -680,6 +836,7 @@ type API interface {
|
||||
// Appropriate context such as the plugin name will already be added as fields so plugins
|
||||
// do not need to add that info.
|
||||
//
|
||||
// @tag Logging
|
||||
// Minimum server version: 5.2
|
||||
LogInfo(msg string, keyValuePairs ...interface{})
|
||||
|
||||
@@ -687,6 +844,7 @@ type API interface {
|
||||
// Appropriate context such as the plugin name will already be added as fields so plugins
|
||||
// do not need to add that info.
|
||||
//
|
||||
// @tag Logging
|
||||
// Minimum server version: 5.2
|
||||
LogError(msg string, keyValuePairs ...interface{})
|
||||
|
||||
@@ -694,6 +852,7 @@ type API interface {
|
||||
// Appropriate context such as the plugin name will already be added as fields so plugins
|
||||
// do not need to add that info.
|
||||
//
|
||||
// @tag Logging
|
||||
// Minimum server version: 5.2
|
||||
LogWarn(msg string, keyValuePairs ...interface{})
|
||||
|
||||
@@ -704,49 +863,63 @@ type API interface {
|
||||
|
||||
// CreateBot creates the given bot and corresponding user.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
CreateBot(bot *model.Bot) (*model.Bot, *model.AppError)
|
||||
|
||||
// PatchBot applies the given patch to the bot and corresponding user.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
PatchBot(botUserId string, botPatch *model.BotPatch) (*model.Bot, *model.AppError)
|
||||
|
||||
// GetBot returns the given bot.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
GetBot(botUserId string, includeDeleted bool) (*model.Bot, *model.AppError)
|
||||
|
||||
// GetBots returns the requested page of bots.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
GetBots(options *model.BotGetOptions) ([]*model.Bot, *model.AppError)
|
||||
|
||||
// UpdateBotActive marks a bot as active or inactive, along with its corresponding user.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
UpdateBotActive(botUserId string, active bool) (*model.Bot, *model.AppError)
|
||||
|
||||
// PermanentDeleteBot permanently deletes a bot and its corresponding user.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.10
|
||||
PermanentDeleteBot(botUserId string) *model.AppError
|
||||
|
||||
// GetBotIconImage gets LHS bot icon image.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.14
|
||||
GetBotIconImage(botUserId string) ([]byte, *model.AppError)
|
||||
|
||||
// SetBotIconImage sets LHS bot icon image.
|
||||
// Icon image must be SVG format, all other formats are rejected.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.14
|
||||
SetBotIconImage(botUserId string, data []byte) *model.AppError
|
||||
|
||||
// DeleteBotIconImage deletes LHS bot icon image.
|
||||
//
|
||||
// @tag Bot
|
||||
// Minimum server version: 5.14
|
||||
DeleteBotIconImage(botUserId string) *model.AppError
|
||||
|
||||
// PluginHTTP allows inter-plugin requests to plugin APIs.
|
||||
//
|
||||
// Minimum server version: 5.18
|
||||
PluginHTTP(request *http.Request) *http.Response
|
||||
}
|
||||
|
||||
var handshake = plugin.HandshakeConfig{
|
||||
|
||||
@@ -56,11 +56,13 @@ func (p *hooksPlugin) Client(b *plugin.MuxBroker, client *rpc.Client) (interface
|
||||
}
|
||||
|
||||
type apiRPCClient struct {
|
||||
client *rpc.Client
|
||||
client *rpc.Client
|
||||
muxBroker *plugin.MuxBroker
|
||||
}
|
||||
|
||||
type apiRPCServer struct {
|
||||
impl API
|
||||
impl API
|
||||
muxBroker *plugin.MuxBroker
|
||||
}
|
||||
|
||||
// ErrorString is a fallback for sending unregistered implementations of the error interface across
|
||||
@@ -171,7 +173,8 @@ type Z_OnActivateReturns struct {
|
||||
func (g *hooksRPCClient) OnActivate() error {
|
||||
muxId := g.muxBroker.NextId()
|
||||
go g.muxBroker.AcceptAndServe(muxId, &apiRPCServer{
|
||||
impl: g.apiImpl,
|
||||
impl: g.apiImpl,
|
||||
muxBroker: g.muxBroker,
|
||||
})
|
||||
|
||||
_args := &Z_OnActivateArgs{
|
||||
@@ -192,7 +195,8 @@ func (s *hooksRPCServer) OnActivate(args *Z_OnActivateArgs, returns *Z_OnActivat
|
||||
}
|
||||
|
||||
s.apiRPCClient = &apiRPCClient{
|
||||
client: rpc.NewClient(connection),
|
||||
client: rpc.NewClient(connection),
|
||||
muxBroker: s.muxBroker,
|
||||
}
|
||||
|
||||
if mmplugin, ok := s.impl.(interface {
|
||||
@@ -363,6 +367,76 @@ func (s *hooksRPCServer) ServeHTTP(args *Z_ServeHTTPArgs, returns *struct{}) err
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_PluginHTTPArgs struct {
|
||||
Request *http.Request
|
||||
RequestBody []byte
|
||||
}
|
||||
|
||||
type Z_PluginHTTPReturns struct {
|
||||
Response *http.Response
|
||||
ResponseBody []byte
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) PluginHTTP(request *http.Request) *http.Response {
|
||||
forwardedRequest := &http.Request{
|
||||
Method: request.Method,
|
||||
URL: request.URL,
|
||||
Proto: request.Proto,
|
||||
ProtoMajor: request.ProtoMajor,
|
||||
ProtoMinor: request.ProtoMinor,
|
||||
Header: request.Header,
|
||||
Host: request.Host,
|
||||
RemoteAddr: request.RemoteAddr,
|
||||
RequestURI: request.RequestURI,
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
log.Printf("RPC call to PluginHTTP API failed: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
request.Body.Close()
|
||||
request.Body = nil
|
||||
|
||||
_args := &Z_PluginHTTPArgs{
|
||||
Request: forwardedRequest,
|
||||
RequestBody: requestBody,
|
||||
}
|
||||
|
||||
_returns := &Z_PluginHTTPReturns{}
|
||||
if err := g.client.Call("Plugin.PluginHTTP", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to PluginHTTP API failed: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
_returns.Response.Body = ioutil.NopCloser(bytes.NewBuffer(_returns.ResponseBody))
|
||||
|
||||
return _returns.Response
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) PluginHTTP(args *Z_PluginHTTPArgs, returns *Z_PluginHTTPReturns) error {
|
||||
args.Request.Body = ioutil.NopCloser(bytes.NewBuffer(args.RequestBody))
|
||||
|
||||
if hook, ok := s.impl.(interface {
|
||||
PluginHTTP(request *http.Request) *http.Response
|
||||
}); ok {
|
||||
response := hook.PluginHTTP(args.Request)
|
||||
|
||||
responseBody, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return encodableError(fmt.Errorf("RPC call to PluginHTTP API failed: %s", err.Error()))
|
||||
}
|
||||
response.Body.Close()
|
||||
response.Body = nil
|
||||
|
||||
returns.Response = response
|
||||
returns.ResponseBody = responseBody
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API PluginHTTP called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
hookNameToId["FileWillBeUploaded"] = FileWillBeUploadedId
|
||||
}
|
||||
|
||||
@@ -12,4 +12,5 @@ type Context struct {
|
||||
IpAddress string
|
||||
AcceptLanguage string
|
||||
UserAgent string
|
||||
SourcePluginId string
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
package plugin
|
||||
|
||||
import "github.com/mattermost/mattermost-server/model"
|
||||
import (
|
||||
"github.com/blang/semver"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Helpers interface {
|
||||
// EnsureBot either returns an existing bot user matching the given bot, or creates a bot user from the given bot.
|
||||
@@ -54,3 +58,14 @@ type Helpers interface {
|
||||
type HelpersImpl struct {
|
||||
API API
|
||||
}
|
||||
|
||||
func (p *HelpersImpl) ensureServerVersion(required string) error {
|
||||
serverVersion := p.API.GetServerVersion()
|
||||
currentVersion := semver.MustParse(serverVersion)
|
||||
requiredVersion := semver.MustParse(required)
|
||||
|
||||
if currentVersion.LT(requiredVersion) {
|
||||
return errors.Errorf("incompatible server version for plugin, minimum required version: %s, current version: %s", required, serverVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ import (
|
||||
)
|
||||
|
||||
func (p *HelpersImpl) EnsureBot(bot *model.Bot) (retBotId string, retErr error) {
|
||||
err := p.ensureServerVersion("5.10.0")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to ensure bot")
|
||||
}
|
||||
|
||||
// Must provide a bot with a username
|
||||
if bot == nil || len(bot.Username) < 1 {
|
||||
return "", errors.New("passed a bad bot, nil or no username")
|
||||
|
||||
@@ -24,15 +24,37 @@ func TestEnsureBot(t *testing.T) {
|
||||
Description: "testbotdescription",
|
||||
}
|
||||
|
||||
t.Run("server version incompatible", func(t *testing.T) {
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.9.0")
|
||||
defer api.AssertExpectations(t)
|
||||
|
||||
p := &plugin.HelpersImpl{}
|
||||
p.API = api
|
||||
|
||||
_, retErr := p.EnsureBot(nil)
|
||||
|
||||
assert.NotNil(t, retErr)
|
||||
assert.Equal(t, "failed to ensure bot: incompatible server version for plugin, minimum required version: 5.10.0, current version: 5.9.0", retErr.Error())
|
||||
})
|
||||
|
||||
t.Run("bad parameters", func(t *testing.T) {
|
||||
t.Run("no bot", func(t *testing.T) {
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
|
||||
p := &plugin.HelpersImpl{}
|
||||
p.API = api
|
||||
botId, err := p.EnsureBot(nil)
|
||||
assert.Equal(t, "", botId)
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
t.Run("bad username", func(t *testing.T) {
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
|
||||
p := &plugin.HelpersImpl{}
|
||||
p.API = api
|
||||
botId, err := p.EnsureBot(&model.Bot{
|
||||
Username: "",
|
||||
})
|
||||
@@ -46,6 +68,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
expectedBotId := model.NewId()
|
||||
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return([]byte(expectedBotId), nil)
|
||||
defer api.AssertExpectations(t)
|
||||
|
||||
@@ -60,6 +83,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
|
||||
t.Run("should return an error if unable to get bot", func(t *testing.T) {
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return(nil, &model.AppError{})
|
||||
defer api.AssertExpectations(t)
|
||||
|
||||
@@ -78,6 +102,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
expectedBotId := model.NewId()
|
||||
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return(nil, nil)
|
||||
api.On("GetUserByUsername", testbot.Username).Return(nil, nil)
|
||||
api.On("CreateBot", testbot).Return(&model.Bot{
|
||||
@@ -99,6 +124,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
expectedBotId := model.NewId()
|
||||
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return(nil, nil)
|
||||
api.On("GetUserByUsername", testbot.Username).Return(&model.User{
|
||||
Id: expectedBotId,
|
||||
@@ -119,6 +145,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
t.Run("should return the non-bot account but log a message if user exists with the same name and is not a bot", func(t *testing.T) {
|
||||
expectedBotId := model.NewId()
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return(nil, nil)
|
||||
api.On("GetUserByUsername", testbot.Username).Return(&model.User{
|
||||
Id: expectedBotId,
|
||||
@@ -138,6 +165,7 @@ func TestEnsureBot(t *testing.T) {
|
||||
|
||||
t.Run("should fail if create bot fails", func(t *testing.T) {
|
||||
api := setupAPI()
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
api.On("KVGet", plugin.BOT_USER_KEY).Return(nil, nil)
|
||||
api.On("GetUserByUsername", testbot.Username).Return(nil, nil)
|
||||
api.On("CreateBot", testbot).Return(nil, &model.AppError{})
|
||||
|
||||
@@ -11,6 +11,11 @@ import (
|
||||
|
||||
// KVSetJSON implements Helpers.KVSetJSON.
|
||||
func (p *HelpersImpl) KVSetJSON(key string, value interface{}) error {
|
||||
err := p.ensureServerVersion("5.2.0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -26,9 +31,14 @@ func (p *HelpersImpl) KVSetJSON(key string, value interface{}) error {
|
||||
|
||||
// KVCompareAndSetJSON implements Helpers.KVCompareAndSetJSON.
|
||||
func (p *HelpersImpl) KVCompareAndSetJSON(key string, oldValue interface{}, newValue interface{}) (bool, error) {
|
||||
var oldData, newData []byte
|
||||
var err error
|
||||
|
||||
err = p.ensureServerVersion("5.12.0")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var oldData, newData []byte
|
||||
|
||||
if oldValue != nil {
|
||||
oldData, err = json.Marshal(oldValue)
|
||||
if err != nil {
|
||||
@@ -53,9 +63,15 @@ func (p *HelpersImpl) KVCompareAndSetJSON(key string, oldValue interface{}, newV
|
||||
|
||||
// KVCompareAndDeleteJSON implements Helpers.KVCompareAndDeleteJSON.
|
||||
func (p *HelpersImpl) KVCompareAndDeleteJSON(key string, oldValue interface{}) (bool, error) {
|
||||
var oldData []byte
|
||||
var err error
|
||||
|
||||
err = p.ensureServerVersion("5.16.0")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var oldData []byte
|
||||
|
||||
if oldValue != nil {
|
||||
oldData, err = json.Marshal(oldValue)
|
||||
if err != nil {
|
||||
@@ -73,6 +89,11 @@ func (p *HelpersImpl) KVCompareAndDeleteJSON(key string, oldValue interface{}) (
|
||||
|
||||
// KVGetJSON implements Helpers.KVGetJSON.
|
||||
func (p *HelpersImpl) KVGetJSON(key string, value interface{}) (bool, error) {
|
||||
err := p.ensureServerVersion("5.2.0")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
data, appErr := p.API.KVGet(key)
|
||||
if appErr != nil {
|
||||
return false, appErr
|
||||
@@ -81,7 +102,7 @@ func (p *HelpersImpl) KVGetJSON(key string, value interface{}) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
err := json.Unmarshal(data, value)
|
||||
err = json.Unmarshal(data, value)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -89,8 +110,13 @@ func (p *HelpersImpl) KVGetJSON(key string, value interface{}) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// KVSetWithExpiryJSON implements Helpers.KVSetWithExpiryJSON.
|
||||
// KVSetWithExpiryJSON is a wrapper around KVSetWithExpiry to simplify atomically writing a JSON object with expiry to the key value store.
|
||||
func (p *HelpersImpl) KVSetWithExpiryJSON(key string, value interface{}, expireInSeconds int64) error {
|
||||
err := p.ensureServerVersion("5.6.0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -10,10 +10,26 @@ import (
|
||||
)
|
||||
|
||||
func TestKVGetJSON(t *testing.T) {
|
||||
t.Run("incompatible server version", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.1.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
var dat map[string]interface{}
|
||||
|
||||
ok, err := p.KVGetJSON("test-key", dat)
|
||||
|
||||
api.AssertExpectations(t)
|
||||
assert.False(t, ok)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "incompatible server version for plugin, minimum required version: 5.2.0, current version: 5.1.0", err.Error())
|
||||
})
|
||||
|
||||
t.Run("KVGet error", func(t *testing.T) {
|
||||
p := &plugin.HelpersImpl{}
|
||||
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
api.On("KVGet", "test-key").Return(nil, &model.AppError{})
|
||||
p.API = api
|
||||
|
||||
@@ -30,6 +46,7 @@ func TestKVGetJSON(t *testing.T) {
|
||||
p := &plugin.HelpersImpl{}
|
||||
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
api.On("KVGet", "test-key").Return(nil, nil)
|
||||
p.API = api
|
||||
|
||||
@@ -46,6 +63,7 @@ func TestKVGetJSON(t *testing.T) {
|
||||
p := &plugin.HelpersImpl{}
|
||||
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
api.On("KVGet", "test-key").Return([]byte(`{{:}"val-a": 10}`), nil)
|
||||
p.API = api
|
||||
|
||||
@@ -62,6 +80,7 @@ func TestKVGetJSON(t *testing.T) {
|
||||
p := &plugin.HelpersImpl{}
|
||||
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
api.On("KVGet", "test-key").Return([]byte(`{"val-a": 10}`), nil)
|
||||
p.API = api
|
||||
|
||||
@@ -78,9 +97,25 @@ func TestKVGetJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKVSetJSON(t *testing.T) {
|
||||
t.Run("incompatible server version", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.1.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
err := p.KVSetJSON("test-key", map[string]interface{}{
|
||||
"val-a": float64(10),
|
||||
})
|
||||
|
||||
api.AssertExpectations(t)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "incompatible server version for plugin, minimum required version: 5.2.0, current version: 5.1.0", err.Error())
|
||||
})
|
||||
|
||||
t.Run("JSON marshal error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.AssertNotCalled(t, "KVSet")
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -92,6 +127,7 @@ func TestKVSetJSON(t *testing.T) {
|
||||
t.Run("KVSet error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("KVSet", "test-key", []byte(`{"val-a":10}`)).Return(&model.AppError{})
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -106,6 +142,7 @@ func TestKVSetJSON(t *testing.T) {
|
||||
t.Run("marshallable struct", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("KVSet", "test-key", []byte(`{"val-a":10}`)).Return(nil)
|
||||
api.On("GetServerVersion").Return("5.2.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -119,9 +156,24 @@ func TestKVSetJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
t.Run("incompatible server version", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
ok, err := p.KVCompareAndSetJSON("test-key", nil, map[string]interface{}{
|
||||
"val-b": 20,
|
||||
})
|
||||
|
||||
assert.Equal(t, false, ok)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "incompatible server version for plugin, minimum required version: 5.12.0, current version: 5.10.0", err.Error())
|
||||
})
|
||||
|
||||
t.Run("old value JSON marshal error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.AssertNotCalled(t, "KVCompareAndSet")
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
ok, err := p.KVCompareAndSetJSON("test-key", func() {}, map[string]interface{}{})
|
||||
@@ -133,6 +185,7 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
|
||||
t.Run("new value JSON marshal error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
api.AssertNotCalled(t, "KVCompareAndSet")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
@@ -146,6 +199,7 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
|
||||
t.Run("KVCompareAndSet error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
api.On("KVCompareAndSet", "test-key", []byte(`{"val-a":10}`), []byte(`{"val-b":20}`)).Return(false, &model.AppError{})
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -162,6 +216,7 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
|
||||
t.Run("old value nil", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
api.On("KVCompareAndSet", "test-key", []byte(nil), []byte(`{"val-b":20}`)).Return(true, nil)
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -176,6 +231,7 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
|
||||
t.Run("old value non-nil", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
api.On("KVCompareAndSet", "test-key", []byte(`{"val-a":10}`), []byte(`{"val-b":20}`)).Return(true, nil)
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -192,6 +248,7 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
|
||||
t.Run("new value nil", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.12.0")
|
||||
api.On("KVCompareAndSet", "test-key", []byte(`{"val-a":10}`), []byte(nil)).Return(true, nil)
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -206,8 +263,23 @@ func TestKVCompareAndSetJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKVCompareAndDeleteJSON(t *testing.T) {
|
||||
t.Run("incompatible server version", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.10.0")
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
ok, err := p.KVCompareAndDeleteJSON("test-key", map[string]interface{}{
|
||||
"val-a": 10,
|
||||
})
|
||||
|
||||
assert.Equal(t, false, ok)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "incompatible server version for plugin, minimum required version: 5.16.0, current version: 5.10.0", err.Error())
|
||||
})
|
||||
|
||||
t.Run("old value JSON marshal error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.16.0")
|
||||
api.AssertNotCalled(t, "KVCompareAndDelete")
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -220,6 +292,7 @@ func TestKVCompareAndDeleteJSON(t *testing.T) {
|
||||
|
||||
t.Run("KVCompareAndDelete error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.16.0")
|
||||
api.On("KVCompareAndDelete", "test-key", []byte(`{"val-a":10}`)).Return(false, &model.AppError{})
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -234,6 +307,7 @@ func TestKVCompareAndDeleteJSON(t *testing.T) {
|
||||
|
||||
t.Run("old value nil", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.16.0")
|
||||
api.On("KVCompareAndDelete", "test-key", []byte(nil)).Return(true, nil)
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -246,6 +320,7 @@ func TestKVCompareAndDeleteJSON(t *testing.T) {
|
||||
|
||||
t.Run("old value non-nil", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.16.0")
|
||||
api.On("KVCompareAndDelete", "test-key", []byte(`{"val-a":10}`)).Return(true, nil)
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -260,8 +335,24 @@ func TestKVCompareAndDeleteJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKVSetWithExpiryJSON(t *testing.T) {
|
||||
t.Run("incompatible server version", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.4.0")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
err := p.KVSetWithExpiryJSON("test-key", map[string]interface{}{
|
||||
"val-a": float64(10),
|
||||
}, 100)
|
||||
|
||||
api.AssertExpectations(t)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "incompatible server version for plugin, minimum required version: 5.6.0, current version: 5.4.0", err.Error())
|
||||
})
|
||||
|
||||
t.Run("JSON marshal error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.6.0")
|
||||
api.AssertNotCalled(t, "KVSetWithExpiry")
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
@@ -274,6 +365,7 @@ func TestKVSetWithExpiryJSON(t *testing.T) {
|
||||
|
||||
t.Run("KVSetWithExpiry error", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.6.0")
|
||||
api.On("KVSetWithExpiry", "test-key", []byte(`{"val-a":10}`), int64(100)).Return(&model.AppError{})
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -287,6 +379,7 @@ func TestKVSetWithExpiryJSON(t *testing.T) {
|
||||
|
||||
t.Run("wellformed JSON", func(t *testing.T) {
|
||||
api := &plugintest.API{}
|
||||
api.On("GetServerVersion").Return("5.6.0")
|
||||
api.On("KVSetWithExpiry", "test-key", []byte(`{"val-a":10}`), int64(100)).Return(nil)
|
||||
|
||||
p := &plugin.HelpersImpl{API: api}
|
||||
|
||||
@@ -392,17 +392,18 @@ func getPluginPackageDir() string {
|
||||
func removeExcluded(info *PluginInterfaceInfo) *PluginInterfaceInfo {
|
||||
toBeExcluded := func(item string) bool {
|
||||
excluded := []string{
|
||||
"OnActivate",
|
||||
"FileWillBeUploaded",
|
||||
"Implemented",
|
||||
"LoadPluginConfiguration",
|
||||
"ServeHTTP",
|
||||
"FileWillBeUploaded",
|
||||
"MessageWillBePosted",
|
||||
"MessageWillBeUpdated",
|
||||
"LogDebug",
|
||||
"LogError",
|
||||
"LogInfo",
|
||||
"LogWarn",
|
||||
"LogError",
|
||||
"MessageWillBePosted",
|
||||
"MessageWillBeUpdated",
|
||||
"OnActivate",
|
||||
"PluginHTTP",
|
||||
"ServeHTTP",
|
||||
}
|
||||
for _, exclusion := range excluded {
|
||||
if exclusion == item {
|
||||
|
||||
@@ -6,9 +6,11 @@ package plugintest
|
||||
|
||||
import (
|
||||
io "io"
|
||||
http "net/http"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
model "github.com/mattermost/mattermost-server/model"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// API is an autogenerated mock type for the API type
|
||||
@@ -2334,6 +2336,22 @@ func (_m *API) PermanentDeleteBot(botUserId string) *model.AppError {
|
||||
return r0
|
||||
}
|
||||
|
||||
// PluginHTTP provides a mock function with given fields: request
|
||||
func (_m *API) PluginHTTP(request *http.Request) *http.Response {
|
||||
ret := _m.Called(request)
|
||||
|
||||
var r0 *http.Response
|
||||
if rf, ok := ret.Get(0).(func(*http.Request) *http.Response); ok {
|
||||
r0 = rf(request)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*http.Response)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// PublishWebSocketEvent provides a mock function with given fields: event, payload, broadcast
|
||||
func (_m *API) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *model.WebsocketBroadcast) {
|
||||
_m.Called(event, payload, broadcast)
|
||||
|
||||
@@ -19,7 +19,7 @@ check_prereq()
|
||||
|
||||
if check_version $installed_version $required_version; then
|
||||
echo "$dependency minimum requirement met. Required: $required_version, Found: $installed_version"
|
||||
else
|
||||
else
|
||||
echo "WARNING! Mattermost did not find the minimum supported version of '$dependency' installed. Required: $required_version, Found: $installed_version"
|
||||
echo "We highly recommend stopping installation and updating dependencies before continuing"
|
||||
read -p "Enter Y to continue anyway (not recommended)." -n 1 -r
|
||||
@@ -35,7 +35,7 @@ echo "Checking prerequisites"
|
||||
|
||||
REQUIREDNODEVERSION=8.9.0
|
||||
REQUIREDNPMVERSION=5.6.0
|
||||
REQUIREDGOVERSION=1.12.0
|
||||
REQUIREDGOVERSION=1.13.0
|
||||
REQUIREDDOCKERVERSION=17.0
|
||||
|
||||
NODEVERSION=$(sed 's/v//' <<< $(node -v))
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/mattermost/mattermost-server/einterfaces"
|
||||
)
|
||||
|
||||
type LayeredStoreDatabaseLayer interface {
|
||||
LayeredStoreSupplier
|
||||
Store
|
||||
}
|
||||
|
||||
type LayeredStore struct {
|
||||
TmpContext context.Context
|
||||
DatabaseLayer LayeredStoreDatabaseLayer
|
||||
LocalCacheLayer *LocalCacheSupplier
|
||||
LayerChainHead LayeredStoreSupplier
|
||||
}
|
||||
|
||||
func NewLayeredStore(db LayeredStoreDatabaseLayer, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) Store {
|
||||
store := &LayeredStore{
|
||||
TmpContext: context.TODO(),
|
||||
DatabaseLayer: db,
|
||||
LocalCacheLayer: NewLocalCacheSupplier(metrics, cluster),
|
||||
}
|
||||
|
||||
// Setup the chain
|
||||
store.LocalCacheLayer.SetChainNext(store.DatabaseLayer)
|
||||
store.LayerChainHead = store.LocalCacheLayer
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
type QueryFunction func(LayeredStoreSupplier) *LayeredStoreSupplierResult
|
||||
|
||||
func (s *LayeredStore) GetCurrentSchemaVersion() string {
|
||||
return s.DatabaseLayer.GetCurrentSchemaVersion()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Team() TeamStore {
|
||||
return s.DatabaseLayer.Team()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Channel() ChannelStore {
|
||||
return s.DatabaseLayer.Channel()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Post() PostStore {
|
||||
return s.DatabaseLayer.Post()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) User() UserStore {
|
||||
return s.DatabaseLayer.User()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Bot() BotStore {
|
||||
return s.DatabaseLayer.Bot()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Audit() AuditStore {
|
||||
return s.DatabaseLayer.Audit()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) ClusterDiscovery() ClusterDiscoveryStore {
|
||||
return s.DatabaseLayer.ClusterDiscovery()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Compliance() ComplianceStore {
|
||||
return s.DatabaseLayer.Compliance()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Session() SessionStore {
|
||||
return s.DatabaseLayer.Session()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) OAuth() OAuthStore {
|
||||
return s.DatabaseLayer.OAuth()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) System() SystemStore {
|
||||
return s.DatabaseLayer.System()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Webhook() WebhookStore {
|
||||
return s.DatabaseLayer.Webhook()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Command() CommandStore {
|
||||
return s.DatabaseLayer.Command()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) CommandWebhook() CommandWebhookStore {
|
||||
return s.DatabaseLayer.CommandWebhook()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Preference() PreferenceStore {
|
||||
return s.DatabaseLayer.Preference()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) License() LicenseStore {
|
||||
return s.DatabaseLayer.License()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Token() TokenStore {
|
||||
return s.DatabaseLayer.Token()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Emoji() EmojiStore {
|
||||
return s.DatabaseLayer.Emoji()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Status() StatusStore {
|
||||
return s.DatabaseLayer.Status()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) FileInfo() FileInfoStore {
|
||||
return s.DatabaseLayer.FileInfo()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Reaction() ReactionStore {
|
||||
return s.DatabaseLayer.Reaction()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Job() JobStore {
|
||||
return s.DatabaseLayer.Job()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) UserAccessToken() UserAccessTokenStore {
|
||||
return s.DatabaseLayer.UserAccessToken()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) ChannelMemberHistory() ChannelMemberHistoryStore {
|
||||
return s.DatabaseLayer.ChannelMemberHistory()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Plugin() PluginStore {
|
||||
return s.DatabaseLayer.Plugin()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Role() RoleStore {
|
||||
return s.DatabaseLayer.Role()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) TermsOfService() TermsOfServiceStore {
|
||||
return s.DatabaseLayer.TermsOfService()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) UserTermsOfService() UserTermsOfServiceStore {
|
||||
return s.DatabaseLayer.UserTermsOfService()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Scheme() SchemeStore {
|
||||
return s.DatabaseLayer.Scheme()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Group() GroupStore {
|
||||
return s.DatabaseLayer.Group()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) LinkMetadata() LinkMetadataStore {
|
||||
return s.DatabaseLayer.LinkMetadata()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) MarkSystemRanUnitTests() {
|
||||
s.DatabaseLayer.MarkSystemRanUnitTests()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) Close() {
|
||||
s.DatabaseLayer.Close()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) LockToMaster() {
|
||||
s.DatabaseLayer.LockToMaster()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) UnlockFromMaster() {
|
||||
s.DatabaseLayer.UnlockFromMaster()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) DropAllTables() {
|
||||
defer s.LocalCacheLayer.Invalidate()
|
||||
s.DatabaseLayer.DropAllTables()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) TotalMasterDbConnections() int {
|
||||
return s.DatabaseLayer.TotalMasterDbConnections()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) TotalReadDbConnections() int {
|
||||
return s.DatabaseLayer.TotalReadDbConnections()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) TotalSearchDbConnections() int {
|
||||
return s.DatabaseLayer.TotalSearchDbConnections()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) CheckIntegrity() <-chan IntegrityCheckResult {
|
||||
return s.DatabaseLayer.CheckIntegrity()
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package store
|
||||
|
||||
type LayeredStoreHint int
|
||||
|
||||
const (
|
||||
LSH_NO_CACHE LayeredStoreHint = iota
|
||||
LSH_MASTER_ONLY
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package store
|
||||
|
||||
type LayeredStoreSupplierResult struct {
|
||||
StoreResult
|
||||
}
|
||||
|
||||
func NewSupplierResult() *LayeredStoreSupplierResult {
|
||||
return &LayeredStoreSupplierResult{}
|
||||
}
|
||||
|
||||
type LayeredStoreSupplier interface {
|
||||
//
|
||||
// Control
|
||||
//
|
||||
SetChainNext(LayeredStoreSupplier)
|
||||
Next() LayeredStoreSupplier
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/mattermost/mattermost-server/einterfaces"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
const (
|
||||
CLEAR_CACHE_MESSAGE_DATA = ""
|
||||
)
|
||||
|
||||
type LocalCacheSupplier struct {
|
||||
next LayeredStoreSupplier
|
||||
metrics einterfaces.MetricsInterface
|
||||
cluster einterfaces.ClusterInterface
|
||||
}
|
||||
|
||||
// Caching Interface
|
||||
type ObjectCache interface {
|
||||
AddWithExpiresInSecs(key, value interface{}, expireAtSecs int64)
|
||||
AddWithDefaultExpires(key, value interface{})
|
||||
Purge()
|
||||
Get(key interface{}) (value interface{}, ok bool)
|
||||
Remove(key interface{})
|
||||
Len() int
|
||||
Name() string
|
||||
GetInvalidateClusterEvent() string
|
||||
}
|
||||
|
||||
func NewLocalCacheSupplier(metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) *LocalCacheSupplier {
|
||||
supplier := &LocalCacheSupplier{
|
||||
metrics: metrics,
|
||||
cluster: cluster,
|
||||
}
|
||||
|
||||
return supplier
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) SetChainNext(next LayeredStoreSupplier) {
|
||||
s.next = next
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) Next() LayeredStoreSupplier {
|
||||
return s.next
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) doStandardAddToCache(ctx context.Context, cache ObjectCache, key string, result *LayeredStoreSupplierResult, hints ...LayeredStoreHint) {
|
||||
if result.Err == nil && result.Data != nil {
|
||||
cache.AddWithDefaultExpires(key, result.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) doInvalidateCacheCluster(cache ObjectCache, key string) {
|
||||
cache.Remove(key)
|
||||
if s.cluster != nil {
|
||||
msg := &model.ClusterMessage{
|
||||
Event: cache.GetInvalidateClusterEvent(),
|
||||
SendType: model.CLUSTER_SEND_BEST_EFFORT,
|
||||
Data: key,
|
||||
}
|
||||
s.cluster.SendClusterMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) doClearCacheCluster(cache ObjectCache) {
|
||||
cache.Purge()
|
||||
if s.cluster != nil {
|
||||
msg := &model.ClusterMessage{
|
||||
Event: cache.GetInvalidateClusterEvent(),
|
||||
SendType: model.CLUSTER_SEND_BEST_EFFORT,
|
||||
Data: CLEAR_CACHE_MESSAGE_DATA,
|
||||
}
|
||||
s.cluster.SendClusterMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) Invalidate() {
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func initStores() {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
st.SqlSupplier = sqlstore.NewSqlSupplier(*st.SqlSettings, nil)
|
||||
st.Store = NewLocalCacheLayer(store.NewLayeredStore(st.SqlSupplier, nil, nil), nil, nil)
|
||||
st.Store = NewLocalCacheLayer(st.SqlSupplier, nil, nil)
|
||||
st.Store.DropAllTables()
|
||||
st.Store.MarkSystemRanUnitTests()
|
||||
}()
|
||||
|
||||
@@ -362,7 +362,7 @@ func TestCheckIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckParentChildIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
t.Run("should receive an error", func(t *testing.T) {
|
||||
config := relationalCheckConfig{
|
||||
parentName: "NotValid",
|
||||
@@ -379,7 +379,7 @@ func TestCheckParentChildIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsCommandWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -407,7 +407,7 @@ func TestCheckChannelsCommandWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsChannelMemberHistoryIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -437,7 +437,7 @@ func TestCheckChannelsChannelMemberHistoryIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsChannelMembersIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -465,7 +465,7 @@ func TestCheckChannelsChannelMembersIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsIncomingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -493,7 +493,7 @@ func TestCheckChannelsIncomingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -523,7 +523,7 @@ func TestCheckChannelsOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckChannelsPostsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -550,7 +550,7 @@ func TestCheckChannelsPostsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckCommandsCommandWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -578,7 +578,7 @@ func TestCheckCommandsCommandWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckPostsFileInfoIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -605,7 +605,7 @@ func TestCheckPostsFileInfoIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckPostsPostsParentIdIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -637,7 +637,7 @@ func TestCheckPostsPostsParentIdIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckPostsPostsRootIdIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -667,7 +667,7 @@ func TestCheckPostsPostsRootIdIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckPostsReactionsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -694,7 +694,7 @@ func TestCheckPostsReactionsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckSchemesChannelsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -725,7 +725,7 @@ func TestCheckSchemesChannelsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckSchemesTeamsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -756,7 +756,7 @@ func TestCheckSchemesTeamsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckSessionsAuditsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -787,7 +787,7 @@ func TestCheckSessionsAuditsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckTeamsChannelsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -814,7 +814,7 @@ func TestCheckTeamsChannelsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckTeamsCommandsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -842,7 +842,7 @@ func TestCheckTeamsCommandsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckTeamsIncomingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -870,7 +870,7 @@ func TestCheckTeamsIncomingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckTeamsOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -898,7 +898,7 @@ func TestCheckTeamsOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckTeamsTeamMembersIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -926,7 +926,7 @@ func TestCheckTeamsTeamMembersIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersAuditsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -956,7 +956,7 @@ func TestCheckUsersAuditsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersCommandWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -984,7 +984,7 @@ func TestCheckUsersCommandWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersChannelsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1011,7 +1011,7 @@ func TestCheckUsersChannelsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersChannelMemberHistoryIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1041,7 +1041,7 @@ func TestCheckUsersChannelMemberHistoryIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersChannelMembersIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1071,7 +1071,7 @@ func TestCheckUsersChannelMembersIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersCommandsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1099,7 +1099,7 @@ func TestCheckUsersCommandsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersCompliancesIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1129,7 +1129,7 @@ func TestCheckUsersCompliancesIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersEmojiIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1159,7 +1159,7 @@ func TestCheckUsersEmojiIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersFileInfoIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1188,7 +1188,7 @@ func TestCheckUsersFileInfoIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersIncomingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1216,7 +1216,7 @@ func TestCheckUsersIncomingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersOAuthAccessDataIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1246,7 +1246,7 @@ func TestCheckUsersOAuthAccessDataIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersOAuthAppsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1276,7 +1276,7 @@ func TestCheckUsersOAuthAppsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersOAuthAuthDataIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1306,7 +1306,7 @@ func TestCheckUsersOAuthAuthDataIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1334,7 +1334,7 @@ func TestCheckUsersOutgoingWebhooksIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersPostsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1361,7 +1361,7 @@ func TestCheckUsersPostsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersPreferencesIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1390,7 +1390,7 @@ func TestCheckUsersPreferencesIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersReactionsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1419,7 +1419,7 @@ func TestCheckUsersReactionsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersSessionsIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1447,7 +1447,7 @@ func TestCheckUsersSessionsIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersStatusIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1476,7 +1476,7 @@ func TestCheckUsersStatusIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersTeamMembersIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
@@ -1506,7 +1506,7 @@ func TestCheckUsersTeamMembersIntegrity(t *testing.T) {
|
||||
|
||||
func TestCheckUsersUserAccessTokensIntegrity(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
supplier := ss.(*store.LayeredStore).DatabaseLayer.(*SqlSupplier)
|
||||
supplier := ss.(*SqlSupplier)
|
||||
dbmap := supplier.GetMaster()
|
||||
|
||||
t.Run("should generate a report with no records", func(t *testing.T) {
|
||||
|
||||
@@ -70,7 +70,7 @@ func initStores() {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
st.SqlSupplier = NewSqlSupplier(*st.SqlSettings, nil)
|
||||
st.Store = store.NewLayeredStore(st.SqlSupplier, nil, nil)
|
||||
st.Store = st.SqlSupplier
|
||||
st.Store.DropAllTables()
|
||||
st.Store.MarkSystemRanUnitTests()
|
||||
}()
|
||||
|
||||
@@ -67,7 +67,7 @@ const (
|
||||
EXIT_DOES_COLUMN_EXISTS_SQLITE = 138
|
||||
)
|
||||
|
||||
type SqlSupplierOldStores struct {
|
||||
type SqlSupplierStores struct {
|
||||
team store.TeamStore
|
||||
channel store.ChannelStore
|
||||
post store.PostStore
|
||||
@@ -106,11 +106,10 @@ type SqlSupplier struct {
|
||||
// See https://github.com/mattermost/mattermost-server/pull/7281
|
||||
rrCounter int64
|
||||
srCounter int64
|
||||
next store.LayeredStoreSupplier
|
||||
master *gorp.DbMap
|
||||
replicas []*gorp.DbMap
|
||||
searchReplicas []*gorp.DbMap
|
||||
oldStores SqlSupplierOldStores
|
||||
stores SqlSupplierStores
|
||||
settings *model.SqlSettings
|
||||
lockedToMaster bool
|
||||
}
|
||||
@@ -124,37 +123,37 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
|
||||
|
||||
supplier.initConnection()
|
||||
|
||||
supplier.oldStores.team = NewSqlTeamStore(supplier, metrics)
|
||||
supplier.oldStores.channel = NewSqlChannelStore(supplier, metrics)
|
||||
supplier.oldStores.post = NewSqlPostStore(supplier, metrics)
|
||||
supplier.oldStores.user = NewSqlUserStore(supplier, metrics)
|
||||
supplier.oldStores.bot = NewSqlBotStore(supplier, metrics)
|
||||
supplier.oldStores.audit = NewSqlAuditStore(supplier)
|
||||
supplier.oldStores.cluster = NewSqlClusterDiscoveryStore(supplier)
|
||||
supplier.oldStores.compliance = NewSqlComplianceStore(supplier)
|
||||
supplier.oldStores.session = NewSqlSessionStore(supplier)
|
||||
supplier.oldStores.oauth = NewSqlOAuthStore(supplier)
|
||||
supplier.oldStores.system = NewSqlSystemStore(supplier)
|
||||
supplier.oldStores.webhook = NewSqlWebhookStore(supplier, metrics)
|
||||
supplier.oldStores.command = NewSqlCommandStore(supplier)
|
||||
supplier.oldStores.commandWebhook = NewSqlCommandWebhookStore(supplier)
|
||||
supplier.oldStores.preference = NewSqlPreferenceStore(supplier)
|
||||
supplier.oldStores.license = NewSqlLicenseStore(supplier)
|
||||
supplier.oldStores.token = NewSqlTokenStore(supplier)
|
||||
supplier.oldStores.emoji = NewSqlEmojiStore(supplier, metrics)
|
||||
supplier.oldStores.status = NewSqlStatusStore(supplier)
|
||||
supplier.oldStores.fileInfo = NewSqlFileInfoStore(supplier, metrics)
|
||||
supplier.oldStores.job = NewSqlJobStore(supplier)
|
||||
supplier.oldStores.userAccessToken = NewSqlUserAccessTokenStore(supplier)
|
||||
supplier.oldStores.channelMemberHistory = NewSqlChannelMemberHistoryStore(supplier)
|
||||
supplier.oldStores.plugin = NewSqlPluginStore(supplier)
|
||||
supplier.oldStores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics)
|
||||
supplier.oldStores.UserTermsOfService = NewSqlUserTermsOfServiceStore(supplier)
|
||||
supplier.oldStores.linkMetadata = NewSqlLinkMetadataStore(supplier)
|
||||
supplier.oldStores.reaction = NewSqlReactionStore(supplier)
|
||||
supplier.oldStores.role = NewSqlRoleStore(supplier)
|
||||
supplier.oldStores.scheme = NewSqlSchemeStore(supplier)
|
||||
supplier.oldStores.group = NewSqlGroupStore(supplier)
|
||||
supplier.stores.team = NewSqlTeamStore(supplier, metrics)
|
||||
supplier.stores.channel = NewSqlChannelStore(supplier, metrics)
|
||||
supplier.stores.post = NewSqlPostStore(supplier, metrics)
|
||||
supplier.stores.user = NewSqlUserStore(supplier, metrics)
|
||||
supplier.stores.bot = NewSqlBotStore(supplier, metrics)
|
||||
supplier.stores.audit = NewSqlAuditStore(supplier)
|
||||
supplier.stores.cluster = NewSqlClusterDiscoveryStore(supplier)
|
||||
supplier.stores.compliance = NewSqlComplianceStore(supplier)
|
||||
supplier.stores.session = NewSqlSessionStore(supplier)
|
||||
supplier.stores.oauth = NewSqlOAuthStore(supplier)
|
||||
supplier.stores.system = NewSqlSystemStore(supplier)
|
||||
supplier.stores.webhook = NewSqlWebhookStore(supplier, metrics)
|
||||
supplier.stores.command = NewSqlCommandStore(supplier)
|
||||
supplier.stores.commandWebhook = NewSqlCommandWebhookStore(supplier)
|
||||
supplier.stores.preference = NewSqlPreferenceStore(supplier)
|
||||
supplier.stores.license = NewSqlLicenseStore(supplier)
|
||||
supplier.stores.token = NewSqlTokenStore(supplier)
|
||||
supplier.stores.emoji = NewSqlEmojiStore(supplier, metrics)
|
||||
supplier.stores.status = NewSqlStatusStore(supplier)
|
||||
supplier.stores.fileInfo = NewSqlFileInfoStore(supplier, metrics)
|
||||
supplier.stores.job = NewSqlJobStore(supplier)
|
||||
supplier.stores.userAccessToken = NewSqlUserAccessTokenStore(supplier)
|
||||
supplier.stores.channelMemberHistory = NewSqlChannelMemberHistoryStore(supplier)
|
||||
supplier.stores.plugin = NewSqlPluginStore(supplier)
|
||||
supplier.stores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics)
|
||||
supplier.stores.UserTermsOfService = NewSqlUserTermsOfServiceStore(supplier)
|
||||
supplier.stores.linkMetadata = NewSqlLinkMetadataStore(supplier)
|
||||
supplier.stores.reaction = NewSqlReactionStore(supplier)
|
||||
supplier.stores.role = NewSqlRoleStore(supplier)
|
||||
supplier.stores.scheme = NewSqlSchemeStore(supplier)
|
||||
supplier.stores.group = NewSqlGroupStore(supplier)
|
||||
|
||||
err := supplier.GetMaster().CreateTablesIfNotExists()
|
||||
if err != nil {
|
||||
@@ -170,46 +169,37 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
|
||||
os.Exit(EXIT_GENERIC_FAILURE)
|
||||
}
|
||||
|
||||
supplier.oldStores.team.(*SqlTeamStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.channel.(*SqlChannelStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.post.(*SqlPostStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.user.(*SqlUserStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.bot.(*SqlBotStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.audit.(*SqlAuditStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.compliance.(*SqlComplianceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.session.(*SqlSessionStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.oauth.(*SqlOAuthStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.system.(*SqlSystemStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.command.(*SqlCommandStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.commandWebhook.(*SqlCommandWebhookStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.license.(*SqlLicenseStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.token.(*SqlTokenStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.emoji.(*SqlEmojiStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.status.(*SqlStatusStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.fileInfo.(*SqlFileInfoStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.job.(*SqlJobStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.userAccessToken.(*SqlUserAccessTokenStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.plugin.(*SqlPluginStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.TermsOfService.(SqlTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.UserTermsOfService.(SqlUserTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.linkMetadata.(*SqlLinkMetadataStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.group.(*SqlGroupStore).CreateIndexesIfNotExists()
|
||||
|
||||
supplier.oldStores.preference.(*SqlPreferenceStore).DeleteUnusedFeatures()
|
||||
supplier.stores.team.(*SqlTeamStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.channel.(*SqlChannelStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.post.(*SqlPostStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.user.(*SqlUserStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.bot.(*SqlBotStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.audit.(*SqlAuditStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.compliance.(*SqlComplianceStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.session.(*SqlSessionStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.oauth.(*SqlOAuthStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.system.(*SqlSystemStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.command.(*SqlCommandStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.commandWebhook.(*SqlCommandWebhookStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.license.(*SqlLicenseStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.token.(*SqlTokenStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.emoji.(*SqlEmojiStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.status.(*SqlStatusStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.fileInfo.(*SqlFileInfoStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.job.(*SqlJobStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.userAccessToken.(*SqlUserAccessTokenStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.plugin.(*SqlPluginStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.TermsOfService.(SqlTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.UserTermsOfService.(SqlUserTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.linkMetadata.(*SqlLinkMetadataStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.group.(*SqlGroupStore).CreateIndexesIfNotExists()
|
||||
supplier.stores.preference.(*SqlPreferenceStore).DeleteUnusedFeatures()
|
||||
|
||||
return supplier
|
||||
}
|
||||
|
||||
func (s *SqlSupplier) SetChainNext(next store.LayeredStoreSupplier) {
|
||||
s.next = next
|
||||
}
|
||||
|
||||
func (s *SqlSupplier) Next() store.LayeredStoreSupplier {
|
||||
return s.next
|
||||
}
|
||||
|
||||
func setupConnection(con_type string, dataSource string, settings *model.SqlSettings) *gorp.DbMap {
|
||||
db, err := dbsql.Open(*settings.DriverName, dataSource)
|
||||
if err != nil {
|
||||
@@ -930,127 +920,127 @@ func (ss *SqlSupplier) UnlockFromMaster() {
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Team() store.TeamStore {
|
||||
return ss.oldStores.team
|
||||
return ss.stores.team
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Channel() store.ChannelStore {
|
||||
return ss.oldStores.channel
|
||||
return ss.stores.channel
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Post() store.PostStore {
|
||||
return ss.oldStores.post
|
||||
return ss.stores.post
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) User() store.UserStore {
|
||||
return ss.oldStores.user
|
||||
return ss.stores.user
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Bot() store.BotStore {
|
||||
return ss.oldStores.bot
|
||||
return ss.stores.bot
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Session() store.SessionStore {
|
||||
return ss.oldStores.session
|
||||
return ss.stores.session
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Audit() store.AuditStore {
|
||||
return ss.oldStores.audit
|
||||
return ss.stores.audit
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) ClusterDiscovery() store.ClusterDiscoveryStore {
|
||||
return ss.oldStores.cluster
|
||||
return ss.stores.cluster
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Compliance() store.ComplianceStore {
|
||||
return ss.oldStores.compliance
|
||||
return ss.stores.compliance
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) OAuth() store.OAuthStore {
|
||||
return ss.oldStores.oauth
|
||||
return ss.stores.oauth
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) System() store.SystemStore {
|
||||
return ss.oldStores.system
|
||||
return ss.stores.system
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Webhook() store.WebhookStore {
|
||||
return ss.oldStores.webhook
|
||||
return ss.stores.webhook
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Command() store.CommandStore {
|
||||
return ss.oldStores.command
|
||||
return ss.stores.command
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) CommandWebhook() store.CommandWebhookStore {
|
||||
return ss.oldStores.commandWebhook
|
||||
return ss.stores.commandWebhook
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Preference() store.PreferenceStore {
|
||||
return ss.oldStores.preference
|
||||
return ss.stores.preference
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) License() store.LicenseStore {
|
||||
return ss.oldStores.license
|
||||
return ss.stores.license
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Token() store.TokenStore {
|
||||
return ss.oldStores.token
|
||||
return ss.stores.token
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Emoji() store.EmojiStore {
|
||||
return ss.oldStores.emoji
|
||||
return ss.stores.emoji
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Status() store.StatusStore {
|
||||
return ss.oldStores.status
|
||||
return ss.stores.status
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) FileInfo() store.FileInfoStore {
|
||||
return ss.oldStores.fileInfo
|
||||
return ss.stores.fileInfo
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Reaction() store.ReactionStore {
|
||||
return ss.oldStores.reaction
|
||||
return ss.stores.reaction
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Job() store.JobStore {
|
||||
return ss.oldStores.job
|
||||
return ss.stores.job
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) UserAccessToken() store.UserAccessTokenStore {
|
||||
return ss.oldStores.userAccessToken
|
||||
return ss.stores.userAccessToken
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) ChannelMemberHistory() store.ChannelMemberHistoryStore {
|
||||
return ss.oldStores.channelMemberHistory
|
||||
return ss.stores.channelMemberHistory
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Plugin() store.PluginStore {
|
||||
return ss.oldStores.plugin
|
||||
return ss.stores.plugin
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Role() store.RoleStore {
|
||||
return ss.oldStores.role
|
||||
return ss.stores.role
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) TermsOfService() store.TermsOfServiceStore {
|
||||
return ss.oldStores.TermsOfService
|
||||
return ss.stores.TermsOfService
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) UserTermsOfService() store.UserTermsOfServiceStore {
|
||||
return ss.oldStores.UserTermsOfService
|
||||
return ss.stores.UserTermsOfService
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Scheme() store.SchemeStore {
|
||||
return ss.oldStores.scheme
|
||||
return ss.stores.scheme
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) Group() store.GroupStore {
|
||||
return ss.oldStores.group
|
||||
return ss.stores.group
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) LinkMetadata() store.LinkMetadataStore {
|
||||
return ss.oldStores.linkMetadata
|
||||
return ss.stores.linkMetadata
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) DropAllTables() {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func TestStoreUpgrade(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
sqlStore := ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)
|
||||
sqlStore := ss.(SqlStore)
|
||||
|
||||
t.Run("invalid currentModelVersion", func(t *testing.T) {
|
||||
err := UpgradeDatabase(sqlStore, "notaversion")
|
||||
@@ -81,7 +81,7 @@ func TestStoreUpgrade(t *testing.T) {
|
||||
|
||||
func TestSaveSchemaVersion(t *testing.T) {
|
||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
||||
sqlStore := ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)
|
||||
sqlStore := ss.(SqlStore)
|
||||
|
||||
t.Run("set earliest version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, VERSION_3_0_0)
|
||||
|
||||
@@ -30,33 +30,26 @@ func testEmojiSaveDelete(t *testing.T, ss store.Store) {
|
||||
Name: model.NewId(),
|
||||
}
|
||||
|
||||
if _, err := ss.Emoji().Save(emoji1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err := ss.Emoji().Save(emoji1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if len(emoji1.Id) != 26 {
|
||||
t.Fatal("should've set id for emoji")
|
||||
}
|
||||
assert.Len(t, emoji1.Id, 26, "should've set id for emoji")
|
||||
|
||||
emoji2 := model.Emoji{
|
||||
CreatorId: model.NewId(),
|
||||
Name: emoji1.Name,
|
||||
}
|
||||
if _, err := ss.Emoji().Save(&emoji2); err == nil {
|
||||
t.Fatal("shouldn't be able to save emoji with duplicate name")
|
||||
}
|
||||
_, err = ss.Emoji().Save(&emoji2)
|
||||
require.NotNil(t, err, "shouldn't be able to save emoji with duplicate name")
|
||||
|
||||
if err := ss.Emoji().Delete(emoji1, time.Now().Unix()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Emoji().Delete(emoji1, time.Now().Unix())
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err := ss.Emoji().Save(&emoji2); err != nil {
|
||||
t.Fatal("should be able to save emoji with duplicate name now that original has been deleted", err)
|
||||
}
|
||||
_, err = ss.Emoji().Save(&emoji2)
|
||||
require.Nil(t, err, "should be able to save emoji with duplicate name now that original has been deleted")
|
||||
|
||||
if err := ss.Emoji().Delete(&emoji2, time.Now().Unix()+1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Emoji().Delete(&emoji2, time.Now().Unix()+1)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testEmojiGet(t *testing.T, ss store.Store) {
|
||||
@@ -88,15 +81,13 @@ func testEmojiGet(t *testing.T, ss store.Store) {
|
||||
}()
|
||||
|
||||
for _, emoji := range emojis {
|
||||
if _, err := ss.Emoji().Get(emoji.Id, false); err != nil {
|
||||
t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, err)
|
||||
}
|
||||
_, err := ss.Emoji().Get(emoji.Id, false)
|
||||
require.Nilf(t, err, "failed to get emoji with id %v", emoji.Id)
|
||||
}
|
||||
|
||||
for _, emoji := range emojis {
|
||||
if _, err := ss.Emoji().Get(emoji.Id, true); err != nil {
|
||||
t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, err)
|
||||
}
|
||||
_, err := ss.Emoji().Get(emoji.Id, true)
|
||||
require.Nilf(t, err, "failed to get emoji with id %v", emoji.Id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +175,8 @@ func testEmojiGetByName(t *testing.T, ss store.Store) {
|
||||
}()
|
||||
|
||||
for _, emoji := range emojis {
|
||||
if _, err := ss.Emoji().GetByName(emoji.Name, true); err != nil {
|
||||
t.Fatalf("failed to get emoji with name %v: %v", emoji.Name, err)
|
||||
}
|
||||
_, err := ss.Emoji().GetByName(emoji.Name, true)
|
||||
require.Nilf(t, err, "failed to get emoji with name %v", emoji.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,35 +209,28 @@ func testEmojiGetMultipleByName(t *testing.T, ss store.Store) {
|
||||
}()
|
||||
|
||||
t.Run("one emoji", func(t *testing.T) {
|
||||
if received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name}); err != nil {
|
||||
t.Fatal("could not get emoji", err)
|
||||
} else if len(received) != 1 || *received[0] != emojis[0] {
|
||||
t.Fatal("got incorrect emoji")
|
||||
}
|
||||
received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name})
|
||||
require.Nilf(t, err, "could not get emoji")
|
||||
require.Len(t, received, 1, "got incorrect emoji")
|
||||
require.Equal(t, *received[0], emojis[0], "got incorrect emoji")
|
||||
})
|
||||
|
||||
t.Run("multiple emojis", func(t *testing.T) {
|
||||
if received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name, emojis[1].Name, emojis[2].Name}); err != nil {
|
||||
t.Fatal("could not get emojis", err)
|
||||
} else if len(received) != 3 {
|
||||
t.Fatal("got incorrect emojis")
|
||||
}
|
||||
received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name, emojis[1].Name, emojis[2].Name})
|
||||
require.Nil(t, err, "could not get emojis")
|
||||
require.Len(t, received, 3, "got incorrect emojis")
|
||||
})
|
||||
|
||||
t.Run("one nonexistent emoji", func(t *testing.T) {
|
||||
if received, err := ss.Emoji().GetMultipleByName([]string{"ab"}); err != nil {
|
||||
t.Fatal("could not get emoji", err)
|
||||
} else if len(received) != 0 {
|
||||
t.Fatal("got incorrect emoji")
|
||||
}
|
||||
received, err := ss.Emoji().GetMultipleByName([]string{"ab"})
|
||||
require.Nilf(t, err, "%v, could not get emoji", err)
|
||||
require.Len(t, received, 0, "got incorrect emoji")
|
||||
})
|
||||
|
||||
t.Run("multiple emojis with nonexistent names", func(t *testing.T) {
|
||||
if received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name, emojis[1].Name, emojis[2].Name, "abcd", "1234"}); err != nil {
|
||||
t.Fatal("could not get emojis", err)
|
||||
} else if len(received) != 3 {
|
||||
t.Fatal("got incorrect emojis")
|
||||
}
|
||||
received, err := ss.Emoji().GetMultipleByName([]string{emojis[0].Name, emojis[1].Name, emojis[2].Name, "abcd", "1234"})
|
||||
require.Nil(t, err, "could not get emojis")
|
||||
require.Len(t, received, 3, "got incorrect emojis")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -292,9 +275,7 @@ func testEmojiGetList(t *testing.T, ss store.Store) {
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatalf("failed to get emoji with id %v", emoji.Id)
|
||||
}
|
||||
require.Truef(t, found, "failed to get emoji with id %v", emoji.Id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,38 +328,34 @@ func testEmojiSearch(t *testing.T, ss store.Store) {
|
||||
|
||||
shouldFind := []bool{true, false, false, false}
|
||||
|
||||
if result, err := ss.Emoji().Search("blargh", true, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
for i, emoji := range emojis {
|
||||
found := false
|
||||
result, err := ss.Emoji().Search("blargh", true, 100)
|
||||
require.Nil(t, err)
|
||||
for i, emoji := range emojis {
|
||||
found := false
|
||||
|
||||
for _, savedEmoji := range result {
|
||||
if emoji.Id == savedEmoji.Id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
for _, savedEmoji := range result {
|
||||
if emoji.Id == savedEmoji.Id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||
}
|
||||
|
||||
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||
}
|
||||
|
||||
shouldFind = []bool{true, true, true, false}
|
||||
if result, err := ss.Emoji().Search("blargh", false, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
for i, emoji := range emojis {
|
||||
found := false
|
||||
result, err = ss.Emoji().Search("blargh", false, 100)
|
||||
require.Nil(t, err)
|
||||
for i, emoji := range emojis {
|
||||
found := false
|
||||
|
||||
for _, savedEmoji := range result {
|
||||
if emoji.Id == savedEmoji.Id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
for _, savedEmoji := range result {
|
||||
if emoji.Id == savedEmoji.Id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||
}
|
||||
|
||||
assert.Equal(t, shouldFind[i], found, emoji.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,629 +0,0 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make store-mocks`.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
store "github.com/mattermost/mattermost-server/store"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// LayeredStoreDatabaseLayer is an autogenerated mock type for the LayeredStoreDatabaseLayer type
|
||||
type LayeredStoreDatabaseLayer struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Audit provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Audit() store.AuditStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.AuditStore
|
||||
if rf, ok := ret.Get(0).(func() store.AuditStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.AuditStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Bot provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Bot() store.BotStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.BotStore
|
||||
if rf, ok := ret.Get(0).(func() store.BotStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.BotStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Channel provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Channel() store.ChannelStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.ChannelStore
|
||||
if rf, ok := ret.Get(0).(func() store.ChannelStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.ChannelStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ChannelMemberHistory provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) ChannelMemberHistory() store.ChannelMemberHistoryStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.ChannelMemberHistoryStore
|
||||
if rf, ok := ret.Get(0).(func() store.ChannelMemberHistoryStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.ChannelMemberHistoryStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// CheckIntegrity provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) CheckIntegrity() <-chan store.IntegrityCheckResult {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 <-chan store.IntegrityCheckResult
|
||||
if rf, ok := ret.Get(0).(func() <-chan store.IntegrityCheckResult); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(<-chan store.IntegrityCheckResult)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Close() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// ClusterDiscovery provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) ClusterDiscovery() store.ClusterDiscoveryStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.ClusterDiscoveryStore
|
||||
if rf, ok := ret.Get(0).(func() store.ClusterDiscoveryStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.ClusterDiscoveryStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Command provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Command() store.CommandStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.CommandStore
|
||||
if rf, ok := ret.Get(0).(func() store.CommandStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.CommandStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// CommandWebhook provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) CommandWebhook() store.CommandWebhookStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.CommandWebhookStore
|
||||
if rf, ok := ret.Get(0).(func() store.CommandWebhookStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.CommandWebhookStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Compliance provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Compliance() store.ComplianceStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.ComplianceStore
|
||||
if rf, ok := ret.Get(0).(func() store.ComplianceStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.ComplianceStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// DropAllTables provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) DropAllTables() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// Emoji provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Emoji() store.EmojiStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.EmojiStore
|
||||
if rf, ok := ret.Get(0).(func() store.EmojiStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.EmojiStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// FileInfo provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) FileInfo() store.FileInfoStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.FileInfoStore
|
||||
if rf, ok := ret.Get(0).(func() store.FileInfoStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.FileInfoStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetCurrentSchemaVersion provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) GetCurrentSchemaVersion() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Group provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Group() store.GroupStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.GroupStore
|
||||
if rf, ok := ret.Get(0).(func() store.GroupStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.GroupStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Job provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Job() store.JobStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.JobStore
|
||||
if rf, ok := ret.Get(0).(func() store.JobStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.JobStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// License provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) License() store.LicenseStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LicenseStore
|
||||
if rf, ok := ret.Get(0).(func() store.LicenseStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LicenseStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LinkMetadata provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) LinkMetadata() store.LinkMetadataStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LinkMetadataStore
|
||||
if rf, ok := ret.Get(0).(func() store.LinkMetadataStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LinkMetadataStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LockToMaster provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) LockToMaster() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// MarkSystemRanUnitTests provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) MarkSystemRanUnitTests() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// Next provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Next() store.LayeredStoreSupplier {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LayeredStoreSupplier
|
||||
if rf, ok := ret.Get(0).(func() store.LayeredStoreSupplier); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LayeredStoreSupplier)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// OAuth provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) OAuth() store.OAuthStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.OAuthStore
|
||||
if rf, ok := ret.Get(0).(func() store.OAuthStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.OAuthStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Plugin provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Plugin() store.PluginStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.PluginStore
|
||||
if rf, ok := ret.Get(0).(func() store.PluginStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.PluginStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Post provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Post() store.PostStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.PostStore
|
||||
if rf, ok := ret.Get(0).(func() store.PostStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.PostStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Preference provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Preference() store.PreferenceStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.PreferenceStore
|
||||
if rf, ok := ret.Get(0).(func() store.PreferenceStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.PreferenceStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Reaction provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Reaction() store.ReactionStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.ReactionStore
|
||||
if rf, ok := ret.Get(0).(func() store.ReactionStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.ReactionStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Role provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Role() store.RoleStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.RoleStore
|
||||
if rf, ok := ret.Get(0).(func() store.RoleStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.RoleStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Scheme provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Scheme() store.SchemeStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.SchemeStore
|
||||
if rf, ok := ret.Get(0).(func() store.SchemeStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.SchemeStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Session provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Session() store.SessionStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.SessionStore
|
||||
if rf, ok := ret.Get(0).(func() store.SessionStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.SessionStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetChainNext provides a mock function with given fields: _a0
|
||||
func (_m *LayeredStoreDatabaseLayer) SetChainNext(_a0 store.LayeredStoreSupplier) {
|
||||
_m.Called(_a0)
|
||||
}
|
||||
|
||||
// Status provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Status() store.StatusStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.StatusStore
|
||||
if rf, ok := ret.Get(0).(func() store.StatusStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StatusStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// System provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) System() store.SystemStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.SystemStore
|
||||
if rf, ok := ret.Get(0).(func() store.SystemStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.SystemStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Team provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Team() store.TeamStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.TeamStore
|
||||
if rf, ok := ret.Get(0).(func() store.TeamStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.TeamStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TermsOfService provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) TermsOfService() store.TermsOfServiceStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.TermsOfServiceStore
|
||||
if rf, ok := ret.Get(0).(func() store.TermsOfServiceStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.TermsOfServiceStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Token provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Token() store.TokenStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.TokenStore
|
||||
if rf, ok := ret.Get(0).(func() store.TokenStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.TokenStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TotalMasterDbConnections provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) TotalMasterDbConnections() int {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int
|
||||
if rf, ok := ret.Get(0).(func() int); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TotalReadDbConnections provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) TotalReadDbConnections() int {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int
|
||||
if rf, ok := ret.Get(0).(func() int); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TotalSearchDbConnections provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) TotalSearchDbConnections() int {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int
|
||||
if rf, ok := ret.Get(0).(func() int); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UnlockFromMaster provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) UnlockFromMaster() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// User provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) User() store.UserStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.UserStore
|
||||
if rf, ok := ret.Get(0).(func() store.UserStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.UserStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UserAccessToken provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) UserAccessToken() store.UserAccessTokenStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.UserAccessTokenStore
|
||||
if rf, ok := ret.Get(0).(func() store.UserAccessTokenStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.UserAccessTokenStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UserTermsOfService provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) UserTermsOfService() store.UserTermsOfServiceStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.UserTermsOfServiceStore
|
||||
if rf, ok := ret.Get(0).(func() store.UserTermsOfServiceStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.UserTermsOfServiceStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Webhook provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) Webhook() store.WebhookStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.WebhookStore
|
||||
if rf, ok := ret.Get(0).(func() store.WebhookStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.WebhookStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make store-mocks`.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
store "github.com/mattermost/mattermost-server/store"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// LayeredStoreSupplier is an autogenerated mock type for the LayeredStoreSupplier type
|
||||
type LayeredStoreSupplier struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Next provides a mock function with given fields:
|
||||
func (_m *LayeredStoreSupplier) Next() store.LayeredStoreSupplier {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LayeredStoreSupplier
|
||||
if rf, ok := ret.Get(0).(func() store.LayeredStoreSupplier); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LayeredStoreSupplier)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetChainNext provides a mock function with given fields: _a0
|
||||
func (_m *LayeredStoreSupplier) SetChainNext(_a0 store.LayeredStoreSupplier) {
|
||||
_m.Called(_a0)
|
||||
}
|
||||
@@ -69,18 +69,15 @@ func testTeamStoreSave(t *testing.T, ss store.Store) {
|
||||
o1.Email = MakeEmail()
|
||||
o1.Type = model.TEAM_OPEN
|
||||
|
||||
if _, err := ss.Team().Save(&o1); err != nil {
|
||||
t.Fatal("couldn't save item", err)
|
||||
}
|
||||
_, err := ss.Team().Save(&o1)
|
||||
require.Nil(t, err, "couldn't save item")
|
||||
|
||||
if _, err := ss.Team().Save(&o1); err == nil {
|
||||
t.Fatal("shouldn't be able to update from save")
|
||||
}
|
||||
_, err = ss.Team().Save(&o1)
|
||||
require.NotNil(t, err, "shouldn't be able to update from save")
|
||||
|
||||
o1.Id = ""
|
||||
if _, err := ss.Team().Save(&o1); err == nil {
|
||||
t.Fatal("should be unique domain")
|
||||
}
|
||||
_, err = ss.Team().Save(&o1)
|
||||
require.NotNil(t, err, "should be unique domain")
|
||||
}
|
||||
|
||||
func testTeamStoreUpdate(t *testing.T, ss store.Store) {
|
||||
@@ -89,25 +86,21 @@ func testTeamStoreUpdate(t *testing.T, ss store.Store) {
|
||||
o1.Name = "z-z-z" + model.NewId() + "b"
|
||||
o1.Email = MakeEmail()
|
||||
o1.Type = model.TEAM_OPEN
|
||||
if _, err := ss.Team().Save(&o1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err := ss.Team().Save(&o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
if _, err := ss.Team().Update(&o1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = ss.Team().Update(&o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
o1.Id = "missing"
|
||||
if _, err := ss.Team().Update(&o1); err == nil {
|
||||
t.Fatal("Update should have failed because of missing key")
|
||||
}
|
||||
_, err = ss.Team().Update(&o1)
|
||||
require.NotNil(t, err, "Update should have failed because of missing key")
|
||||
|
||||
o1.Id = model.NewId()
|
||||
if _, err := ss.Team().Update(&o1); err == nil {
|
||||
t.Fatal("Update should have faile because id change")
|
||||
}
|
||||
_, err = ss.Team().Update(&o1)
|
||||
require.NotNil(t, err, "Update should have faile because id change")
|
||||
}
|
||||
|
||||
func testTeamStoreGet(t *testing.T, ss store.Store) {
|
||||
@@ -134,21 +127,15 @@ func testTeamStoreGetByName(t *testing.T, ss store.Store) {
|
||||
o1.Email = MakeEmail()
|
||||
o1.Type = model.TEAM_OPEN
|
||||
|
||||
if _, err := ss.Team().Save(&o1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err := ss.Team().Save(&o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if team, err := ss.Team().GetByName(o1.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if team.ToJson() != o1.ToJson() {
|
||||
t.Fatal("invalid returned team")
|
||||
}
|
||||
}
|
||||
team, err := ss.Team().GetByName(o1.Name)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, *team, o1, "invalid returned team")
|
||||
|
||||
if _, err := ss.Team().GetByName(""); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Team().GetByName("")
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testTeamStoreSearchAll(t *testing.T, ss store.Store) {
|
||||
@@ -363,9 +350,7 @@ func testTeamStoreGetByInviteId(t *testing.T, ss store.Store) {
|
||||
o1.InviteId = model.NewId()
|
||||
|
||||
save1, err := ss.Team().Save(&o1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Nil(t, err)
|
||||
|
||||
o2 := model.Team{}
|
||||
o2.DisplayName = "DisplayName"
|
||||
@@ -373,17 +358,12 @@ func testTeamStoreGetByInviteId(t *testing.T, ss store.Store) {
|
||||
o2.Email = MakeEmail()
|
||||
o2.Type = model.TEAM_OPEN
|
||||
|
||||
if r1, err := ss.Team().GetByInviteId(save1.InviteId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if r1.ToJson() != o1.ToJson() {
|
||||
t.Fatal("invalid returned team")
|
||||
}
|
||||
}
|
||||
r1, err := ss.Team().GetByInviteId(save1.InviteId)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, *r1, o1, "invalid returned team")
|
||||
|
||||
if _, err := ss.Team().GetByInviteId(""); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Team().GetByInviteId("")
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testTeamStoreByUserId(t *testing.T, ss store.Store) {
|
||||
@@ -400,18 +380,10 @@ func testTeamStoreByUserId(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().SaveMember(m1, -1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teams, err := ss.Team().GetTeamsByUserId(m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(teams) == 0 {
|
||||
t.Fatal("Should return a team")
|
||||
}
|
||||
|
||||
if teams[0].Id != o1.Id {
|
||||
t.Fatal("should be a member")
|
||||
}
|
||||
|
||||
}
|
||||
teams, err := ss.Team().GetTeamsByUserId(m1.UserId)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teams, 1, "Should return a team")
|
||||
require.Equal(t, teams[0].Id, o1.Id, "should be a member")
|
||||
}
|
||||
|
||||
func testGetAllTeamListing(t *testing.T, ss store.Store) {
|
||||
@@ -449,19 +421,13 @@ func testGetAllTeamListing(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().Save(&o4)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teams, err := ss.Team().GetAllTeamListing(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
for _, team := range teams {
|
||||
if !team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
}
|
||||
|
||||
if len(teams) == 0 {
|
||||
t.Fatal("failed team listing")
|
||||
}
|
||||
teams, err := ss.Team().GetAllTeamListing()
|
||||
require.Nil(t, err)
|
||||
for _, team := range teams {
|
||||
require.True(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
|
||||
require.NotEmpty(t, teams, "failed team listing")
|
||||
}
|
||||
|
||||
func testGetAllTeamPageListing(t *testing.T, ss store.Store) {
|
||||
@@ -505,14 +471,10 @@ func testGetAllTeamPageListing(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, team := range teams {
|
||||
if !team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
require.True(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
|
||||
if len(teams) > 10 {
|
||||
t.Fatal("should have returned max of 10 teams")
|
||||
}
|
||||
require.LessOrEqual(t, len(teams), 10, "should have returned max of 10 teams")
|
||||
|
||||
o5 := model.Team{}
|
||||
o5.DisplayName = "DisplayName"
|
||||
@@ -527,27 +489,19 @@ func testGetAllTeamPageListing(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, team := range teams {
|
||||
if !team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
require.True(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
|
||||
if len(teams) > 4 {
|
||||
t.Fatal("should have returned max of 4 teams")
|
||||
}
|
||||
require.LessOrEqual(t, len(teams), 4, "should have returned max of 4 teams")
|
||||
|
||||
teams, err = ss.Team().GetAllTeamPageListing(1, 1)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, team := range teams {
|
||||
if !team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
require.True(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as true")
|
||||
}
|
||||
|
||||
if len(teams) > 1 {
|
||||
t.Fatal("should have returned max of 1 team")
|
||||
}
|
||||
require.LessOrEqual(t, len(teams), 1, "should have returned max of 1 team")
|
||||
}
|
||||
|
||||
func testGetAllPrivateTeamListing(t *testing.T, ss store.Store) {
|
||||
@@ -585,18 +539,12 @@ func testGetAllPrivateTeamListing(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().Save(&o4)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teams, err := ss.Team().GetAllPrivateTeamListing(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
for _, team := range teams {
|
||||
if team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
}
|
||||
teams, err := ss.Team().GetAllPrivateTeamListing()
|
||||
require.Nil(t, err)
|
||||
require.NotEmpty(t, teams, "failed team listing")
|
||||
|
||||
if len(teams) == 0 {
|
||||
t.Fatal("failed team listing")
|
||||
}
|
||||
for _, team := range teams {
|
||||
require.False(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,20 +585,14 @@ func testGetAllPrivateTeamPageListing(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().Save(&o4)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teams, listErr := ss.Team().GetAllPrivateTeamPageListing(0, 10); listErr != nil {
|
||||
t.Fatal(listErr)
|
||||
} else {
|
||||
for _, team := range teams {
|
||||
if team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
}
|
||||
|
||||
if len(teams) > 10 {
|
||||
t.Fatal("should have returned max of 10 teams")
|
||||
}
|
||||
teams, listErr := ss.Team().GetAllPrivateTeamPageListing(0, 10)
|
||||
require.Nil(t, listErr)
|
||||
for _, team := range teams {
|
||||
require.False(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
|
||||
require.LessOrEqual(t, len(teams), 10, "should have returned max of 10 teams")
|
||||
|
||||
o5 := model.Team{}
|
||||
o5.DisplayName = "DisplayName"
|
||||
o5.Name = "z-z-z" + model.NewId() + "b"
|
||||
@@ -660,33 +602,21 @@ func testGetAllPrivateTeamPageListing(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().Save(&o5)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teams, listErr := ss.Team().GetAllPrivateTeamPageListing(0, 4); listErr != nil {
|
||||
t.Fatal(listErr)
|
||||
} else {
|
||||
for _, team := range teams {
|
||||
if team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
}
|
||||
|
||||
if len(teams) > 4 {
|
||||
t.Fatal("should have returned max of 4 teams")
|
||||
}
|
||||
teams, listErr = ss.Team().GetAllPrivateTeamPageListing(0, 4)
|
||||
require.Nil(t, listErr)
|
||||
for _, team := range teams {
|
||||
require.False(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
|
||||
if teams, listErr := ss.Team().GetAllPrivateTeamPageListing(1, 1); listErr != nil {
|
||||
t.Fatal(listErr)
|
||||
} else {
|
||||
for _, team := range teams {
|
||||
if team.AllowOpenInvite {
|
||||
t.Fatal("should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
}
|
||||
require.LessOrEqual(t, len(teams), 4, "should have returned max of 4 teams")
|
||||
|
||||
if len(teams) > 1 {
|
||||
t.Fatal("should have returned max of 1 team")
|
||||
}
|
||||
teams, listErr = ss.Team().GetAllPrivateTeamPageListing(1, 1)
|
||||
require.Nil(t, listErr)
|
||||
for _, team := range teams {
|
||||
require.False(t, team.AllowOpenInvite, "should have returned team with AllowOpenInvite as false")
|
||||
}
|
||||
|
||||
require.LessOrEqual(t, len(teams), 1, "should have returned max of 1 team")
|
||||
}
|
||||
|
||||
func testGetAllPublicTeamPageListing(t *testing.T, ss store.Store) {
|
||||
@@ -767,9 +697,8 @@ func testDelete(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().Save(&o2)
|
||||
require.Nil(t, err)
|
||||
|
||||
if r1 := ss.Team().PermanentDelete(o1.Id); r1 != nil {
|
||||
t.Fatal(r1)
|
||||
}
|
||||
r1 := ss.Team().PermanentDelete(o1.Id)
|
||||
require.Nil(t, r1)
|
||||
}
|
||||
|
||||
func testPublicTeamCount(t *testing.T, ss store.Store) {
|
||||
@@ -852,13 +781,9 @@ func testTeamCount(t *testing.T, ss store.Store) {
|
||||
_, err := ss.Team().Save(&o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if teamCount, err := ss.Team().AnalyticsTeamCount(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if teamCount == 0 {
|
||||
t.Fatal("should be at least 1 team")
|
||||
}
|
||||
}
|
||||
teamCount, err := ss.Team().AnalyticsTeamCount()
|
||||
require.Nil(t, err)
|
||||
require.NotEqual(t, 0, int(teamCount), "should be at least 1 team")
|
||||
}
|
||||
|
||||
func testTeamMembers(t *testing.T, ss store.Store) {
|
||||
@@ -880,47 +805,33 @@ func testTeamMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
assert.Len(t, ms, 2)
|
||||
|
||||
if ms, err = ss.Team().GetMembers(teamId2, 0, 100, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
ms, err = ss.Team().GetMembers(teamId2, 0, 100, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m3.UserId, ms[0].UserId)
|
||||
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m3.UserId, ms[0].UserId)
|
||||
}
|
||||
ms, err = ss.Team().GetTeamsForUser(m1.UserId)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m1.TeamId, ms[0].TeamId)
|
||||
|
||||
if ms, err = ss.Team().GetTeamsForUser(m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
err = ss.Team().RemoveMember(teamId1, m1.UserId)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m1.TeamId, ms[0].TeamId)
|
||||
}
|
||||
|
||||
if err = ss.Team().RemoveMember(teamId1, m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ms, err = ss.Team().GetMembers(teamId1, 0, 100, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m2.UserId, ms[0].UserId)
|
||||
}
|
||||
ms, err = ss.Team().GetMembers(teamId1, 0, 100, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 1)
|
||||
require.Equal(t, m2.UserId, ms[0].UserId)
|
||||
|
||||
_, err = ss.Team().SaveMember(m1, -1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if err = ss.Team().RemoveAllMembersByTeam(teamId1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Team().RemoveAllMembersByTeam(teamId1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if ms, err = ss.Team().GetMembers(teamId1, 0, 100, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
|
||||
require.Len(t, ms, 0)
|
||||
}
|
||||
ms, err = ss.Team().GetMembers(teamId1, 0, 100, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 0)
|
||||
|
||||
uid := model.NewId()
|
||||
m4 := &model.TeamMember{TeamId: teamId1, UserId: uid}
|
||||
@@ -930,23 +841,16 @@ func testTeamMembers(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Team().SaveMember(m5, -1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if ms, err = ss.Team().GetTeamsForUser(uid); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
ms, err = ss.Team().GetTeamsForUser(uid)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 2)
|
||||
|
||||
require.Len(t, ms, 2)
|
||||
}
|
||||
err = ss.Team().RemoveAllMembersByUser(uid)
|
||||
require.Nil(t, err)
|
||||
|
||||
if err = ss.Team().RemoveAllMembersByUser(uid); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ms, err = ss.Team().GetTeamsForUser(m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
|
||||
require.Len(t, ms, 0)
|
||||
}
|
||||
ms, err = ss.Team().GetTeamsForUser(m1.UserId)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 0)
|
||||
}
|
||||
|
||||
func testTeamMembersWithPagination(t *testing.T, ss store.Store) {
|
||||
@@ -1044,11 +948,9 @@ func testSaveTeamMemberMaxMembers(t *testing.T, ss store.Store) {
|
||||
}(userIds[i])
|
||||
}
|
||||
|
||||
if totalMemberCount, err := ss.Team().GetTotalMemberCount(team.Id, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if int(totalMemberCount) != maxUsersPerTeam {
|
||||
t.Fatalf("should start with 5 team members, had %v instead", totalMemberCount)
|
||||
}
|
||||
totalMemberCount, err := ss.Team().GetTotalMemberCount(team.Id, nil)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int(totalMemberCount), maxUsersPerTeam, "should start with 5 team members, had %v instead", totalMemberCount)
|
||||
|
||||
user, err := ss.User().Save(&model.User{
|
||||
Username: model.NewId(),
|
||||
@@ -1060,47 +962,36 @@ func testSaveTeamMemberMaxMembers(t *testing.T, ss store.Store) {
|
||||
ss.User().PermanentDelete(newUserId)
|
||||
}()
|
||||
|
||||
if _, err = ss.Team().SaveMember(&model.TeamMember{
|
||||
_, err = ss.Team().SaveMember(&model.TeamMember{
|
||||
TeamId: team.Id,
|
||||
UserId: newUserId,
|
||||
}, maxUsersPerTeam); err == nil {
|
||||
t.Fatal("shouldn't be able to save member when at maximum members per team")
|
||||
}
|
||||
}, maxUsersPerTeam)
|
||||
require.NotNil(t, err, "shouldn't be able to save member when at maximum members per team")
|
||||
|
||||
if totalMemberCount, teamErr := ss.Team().GetTotalMemberCount(team.Id, nil); teamErr != nil {
|
||||
t.Fatal(teamErr)
|
||||
} else if int(totalMemberCount) != maxUsersPerTeam {
|
||||
t.Fatalf("should still have 5 team members, had %v instead", totalMemberCount)
|
||||
}
|
||||
totalMemberCount, teamErr := ss.Team().GetTotalMemberCount(team.Id, nil)
|
||||
require.Nil(t, teamErr)
|
||||
require.Equal(t, maxUsersPerTeam, int(totalMemberCount), "should still have 5 team members, had %v instead", totalMemberCount)
|
||||
|
||||
// Leaving the team from the UI sets DeleteAt instead of using TeamStore.RemoveMember
|
||||
if _, teamErr := ss.Team().UpdateMember(&model.TeamMember{
|
||||
_, teamErr = ss.Team().UpdateMember(&model.TeamMember{
|
||||
TeamId: team.Id,
|
||||
UserId: userIds[0],
|
||||
DeleteAt: 1234,
|
||||
}); teamErr != nil {
|
||||
panic(teamErr)
|
||||
}
|
||||
})
|
||||
require.Nil(t, teamErr)
|
||||
|
||||
if totalMemberCount, teamErr := ss.Team().GetTotalMemberCount(team.Id, nil); teamErr != nil {
|
||||
t.Fatal(teamErr)
|
||||
} else if int(totalMemberCount) != maxUsersPerTeam-1 {
|
||||
t.Fatalf("should now only have 4 team members, had %v instead", totalMemberCount)
|
||||
}
|
||||
totalMemberCount, teamErr = ss.Team().GetTotalMemberCount(team.Id, nil)
|
||||
require.Nil(t, teamErr)
|
||||
require.Equal(t, maxUsersPerTeam-1, int(totalMemberCount), "should now only have 4 team members, had %v instead", totalMemberCount)
|
||||
|
||||
if _, err = ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId}, maxUsersPerTeam); err != nil {
|
||||
t.Fatal("should've been able to save new member after deleting one", err)
|
||||
} else {
|
||||
defer func(userId string) {
|
||||
ss.Team().RemoveMember(team.Id, userId)
|
||||
}(newUserId)
|
||||
}
|
||||
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId}, maxUsersPerTeam)
|
||||
require.Nil(t, err, "should've been able to save new member after deleting one")
|
||||
|
||||
if totalMemberCount, teamErr := ss.Team().GetTotalMemberCount(team.Id, nil); teamErr != nil {
|
||||
t.Fatal(teamErr)
|
||||
} else if int(totalMemberCount) != maxUsersPerTeam {
|
||||
t.Fatalf("should have 5 team members again, had %v instead", totalMemberCount)
|
||||
}
|
||||
defer ss.Team().RemoveMember(team.Id, newUserId)
|
||||
|
||||
totalMemberCount, teamErr = ss.Team().GetTotalMemberCount(team.Id, nil)
|
||||
require.Nil(t, teamErr)
|
||||
require.Equal(t, maxUsersPerTeam, int(totalMemberCount), "should have 5 team members again, had %v instead", totalMemberCount)
|
||||
|
||||
// Deactivating a user should make them stop counting against max members
|
||||
user2, err := ss.User().Get(userIds[1])
|
||||
@@ -1115,13 +1006,10 @@ func testSaveTeamMemberMaxMembers(t *testing.T, ss store.Store) {
|
||||
})
|
||||
require.Nil(t, err)
|
||||
newUserId2 := user.Id
|
||||
if _, err := ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId2}, maxUsersPerTeam); err != nil {
|
||||
t.Fatal("should've been able to save new member after deleting one", err)
|
||||
} else {
|
||||
defer func(userId string) {
|
||||
ss.Team().RemoveMember(team.Id, userId)
|
||||
}(newUserId2)
|
||||
}
|
||||
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId2}, maxUsersPerTeam)
|
||||
require.Nil(t, err, "should've been able to save new member after deleting one")
|
||||
|
||||
defer ss.Team().RemoveMember(team.Id, newUserId2)
|
||||
}
|
||||
|
||||
func testGetTeamMember(t *testing.T, ss store.Store) {
|
||||
@@ -1132,26 +1020,18 @@ func testGetTeamMember(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
var rm1 *model.TeamMember
|
||||
if rm1, err = ss.Team().GetMember(m1.TeamId, m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
rm1, err = ss.Team().GetMember(m1.TeamId, m1.UserId)
|
||||
require.Nil(t, err)
|
||||
|
||||
if rm1.TeamId != m1.TeamId {
|
||||
t.Fatal("bad team id")
|
||||
}
|
||||
require.Equal(t, rm1.TeamId, m1.TeamId, "bad team id")
|
||||
|
||||
if rm1.UserId != m1.UserId {
|
||||
t.Fatal("bad user id")
|
||||
}
|
||||
}
|
||||
require.Equal(t, rm1.UserId, m1.UserId, "bad user id")
|
||||
|
||||
if _, err = ss.Team().GetMember(m1.TeamId, ""); err == nil {
|
||||
t.Fatal("empty user id - should have failed")
|
||||
}
|
||||
_, err = ss.Team().GetMember(m1.TeamId, "")
|
||||
require.NotNil(t, err, "empty user id - should have failed")
|
||||
|
||||
if _, err = ss.Team().GetMember("", m1.UserId); err == nil {
|
||||
t.Fatal("empty team id - should have failed")
|
||||
}
|
||||
_, err = ss.Team().GetMember("", m1.UserId)
|
||||
require.NotNil(t, err, "empty team id - should have failed")
|
||||
|
||||
// Test with a custom team scheme.
|
||||
s2 := &model.Scheme{
|
||||
@@ -1204,36 +1084,24 @@ func testGetTeamMembersByIds(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
var r []*model.TeamMember
|
||||
if r, err = ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
rm1 := r[0]
|
||||
r, err = ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}, nil)
|
||||
require.Nil(t, err)
|
||||
rm1 := r[0]
|
||||
|
||||
if rm1.TeamId != m1.TeamId {
|
||||
t.Fatal("bad team id")
|
||||
}
|
||||
|
||||
if rm1.UserId != m1.UserId {
|
||||
t.Fatal("bad user id")
|
||||
}
|
||||
}
|
||||
require.Equal(t, rm1.TeamId, m1.TeamId, "bad team id")
|
||||
require.Equal(t, rm1.UserId, m1.UserId, "bad user id")
|
||||
|
||||
m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()}
|
||||
_, err = ss.Team().SaveMember(m2, -1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if rm, err := ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
rm, err := ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
if len(rm) != 2 {
|
||||
t.Fatal("return wrong number of results")
|
||||
}
|
||||
}
|
||||
require.Len(t, rm, 2, "return wrong number of results")
|
||||
|
||||
if _, err := ss.Team().GetMembersByIds(m1.TeamId, []string{}, nil); err == nil {
|
||||
t.Fatal("empty user ids - should have failed")
|
||||
}
|
||||
_, err = ss.Team().GetMembersByIds(m1.TeamId, []string{}, nil)
|
||||
require.NotNil(t, err, "empty user ids - should have failed")
|
||||
}
|
||||
|
||||
func testTeamStoreMemberCount(t *testing.T, ss store.Store) {
|
||||
@@ -1258,42 +1126,26 @@ func testTeamStoreMemberCount(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
var totalMemberCount int64
|
||||
if totalMemberCount, err = ss.Team().GetTotalMemberCount(teamId1, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if totalMemberCount != 2 {
|
||||
t.Fatal("wrong count")
|
||||
}
|
||||
}
|
||||
totalMemberCount, err = ss.Team().GetTotalMemberCount(teamId1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int(totalMemberCount), 2, "wrong count")
|
||||
|
||||
var result int64
|
||||
if result, err = ss.Team().GetActiveMemberCount(teamId1, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if result != 1 {
|
||||
t.Fatal("wrong count")
|
||||
}
|
||||
}
|
||||
result, err = ss.Team().GetActiveMemberCount(teamId1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, int(result), "wrong count")
|
||||
|
||||
m3 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()}
|
||||
_, err = ss.Team().SaveMember(m3, -1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if totalMemberCount, err := ss.Team().GetTotalMemberCount(teamId1, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if totalMemberCount != 2 {
|
||||
t.Fatal("wrong count")
|
||||
}
|
||||
}
|
||||
totalMemberCount, err = ss.Team().GetTotalMemberCount(teamId1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 2, int(totalMemberCount), "wrong count")
|
||||
|
||||
if result, err := ss.Team().GetActiveMemberCount(teamId1, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if result != 1 {
|
||||
t.Fatal("wrong count")
|
||||
}
|
||||
}
|
||||
result, err = ss.Team().GetActiveMemberCount(teamId1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, int(result), "wrong count")
|
||||
}
|
||||
|
||||
func testGetChannelUnreadsForAllTeams(t *testing.T, ss store.Store) {
|
||||
@@ -1323,48 +1175,35 @@ func testGetChannelUnreadsForAllTeams(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Channel().SaveMember(cm2)
|
||||
require.Nil(t, err)
|
||||
|
||||
if ms1, err := ss.Team().GetChannelUnreadsForAllTeams("", uid); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
membersMap := make(map[string]bool)
|
||||
for i := range ms1 {
|
||||
id := ms1[i].TeamId
|
||||
if _, ok := membersMap[id]; !ok {
|
||||
membersMap[id] = true
|
||||
}
|
||||
}
|
||||
if len(membersMap) != 2 {
|
||||
t.Fatal("Should be the unreads for all the teams")
|
||||
ms1, err := ss.Team().GetChannelUnreadsForAllTeams("", uid)
|
||||
require.Nil(t, err)
|
||||
membersMap := make(map[string]bool)
|
||||
for i := range ms1 {
|
||||
id := ms1[i].TeamId
|
||||
if _, ok := membersMap[id]; !ok {
|
||||
membersMap[id] = true
|
||||
}
|
||||
}
|
||||
require.Len(t, membersMap, 2, "Should be the unreads for all the teams")
|
||||
|
||||
if ms1[0].MsgCount != 10 {
|
||||
t.Fatal("subtraction failed")
|
||||
require.Equal(t, 10, int(ms1[0].MsgCount), "subtraction failed")
|
||||
|
||||
ms2, err := ss.Team().GetChannelUnreadsForAllTeams(teamId1, uid)
|
||||
require.Nil(t, err)
|
||||
membersMap = make(map[string]bool)
|
||||
for i := range ms2 {
|
||||
id := ms2[i].TeamId
|
||||
if _, ok := membersMap[id]; !ok {
|
||||
membersMap[id] = true
|
||||
}
|
||||
}
|
||||
|
||||
if ms2, err := ss.Team().GetChannelUnreadsForAllTeams(teamId1, uid); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
membersMap := make(map[string]bool)
|
||||
for i := range ms2 {
|
||||
id := ms2[i].TeamId
|
||||
if _, ok := membersMap[id]; !ok {
|
||||
membersMap[id] = true
|
||||
}
|
||||
}
|
||||
require.Len(t, membersMap, 1, "Should be the unreads for just one team")
|
||||
|
||||
if len(membersMap) != 1 {
|
||||
t.Fatal("Should be the unreads for just one team")
|
||||
}
|
||||
require.Equal(t, 10, int(ms2[0].MsgCount), "subtraction failed")
|
||||
|
||||
if ms2[0].MsgCount != 10 {
|
||||
t.Fatal("subtraction failed")
|
||||
}
|
||||
}
|
||||
|
||||
if err := ss.Team().RemoveAllMembersByUser(uid); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Team().RemoveAllMembersByUser(uid)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testGetChannelUnreadsForTeam(t *testing.T, ss store.Store) {
|
||||
@@ -1390,17 +1229,11 @@ func testGetChannelUnreadsForTeam(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Channel().SaveMember(cm2)
|
||||
require.Nil(t, err)
|
||||
|
||||
if ms, err := ss.Team().GetChannelUnreadsForTeam(m1.TeamId, m1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(ms) != 2 {
|
||||
t.Fatal("wrong length")
|
||||
}
|
||||
ms, err := ss.Team().GetChannelUnreadsForTeam(m1.TeamId, m1.UserId)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, ms, 2, "wrong length")
|
||||
|
||||
if ms[0].MsgCount != 10 {
|
||||
t.Fatal("subtraction failed")
|
||||
}
|
||||
}
|
||||
require.Equal(t, 10, int(ms[0].MsgCount), "subtraction failed")
|
||||
}
|
||||
|
||||
func testUpdateLastTeamIconUpdate(t *testing.T, ss store.Store) {
|
||||
@@ -1419,16 +1252,13 @@ func testUpdateLastTeamIconUpdate(t *testing.T, ss store.Store) {
|
||||
|
||||
curTime := model.GetMillis()
|
||||
|
||||
if err = ss.Team().UpdateLastTeamIconUpdate(o1.Id, curTime); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Team().UpdateLastTeamIconUpdate(o1.Id, curTime)
|
||||
require.Nil(t, err)
|
||||
|
||||
ro1, err := ss.Team().Get(o1.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
if ro1.LastTeamIconUpdate <= lastTeamIconUpdateInitial {
|
||||
t.Fatal("LastTeamIconUpdate not updated")
|
||||
}
|
||||
require.Greater(t, ro1.LastTeamIconUpdate, lastTeamIconUpdateInitial, "LastTeamIconUpdate not updated")
|
||||
}
|
||||
|
||||
func testGetTeamsByScheme(t *testing.T, ss store.Store) {
|
||||
|
||||
@@ -43,13 +43,11 @@ func TestWebhookStore(t *testing.T, ss store.Store) {
|
||||
func testWebhookStoreSaveIncoming(t *testing.T, ss store.Store) {
|
||||
o1 := buildIncomingWebhook()
|
||||
|
||||
if _, err := ss.Webhook().SaveIncoming(o1); err != nil {
|
||||
t.Fatal("couldn't save item", err)
|
||||
}
|
||||
_, err := ss.Webhook().SaveIncoming(o1)
|
||||
require.Nil(t, err, "couldn't save item")
|
||||
|
||||
if _, err := ss.Webhook().SaveIncoming(o1); err == nil {
|
||||
t.Fatal("shouldn't be able to update from save")
|
||||
}
|
||||
_, err = ss.Webhook().SaveIncoming(o1)
|
||||
require.NotNil(t, err, "shouldn't be able to update from save")
|
||||
}
|
||||
|
||||
func testWebhookStoreUpdateIncoming(t *testing.T, ss store.Store) {
|
||||
@@ -58,9 +56,7 @@ func testWebhookStoreUpdateIncoming(t *testing.T, ss store.Store) {
|
||||
|
||||
o1 := buildIncomingWebhook()
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
previousUpdatedAt := o1.UpdateAt
|
||||
|
||||
@@ -70,14 +66,9 @@ func testWebhookStoreUpdateIncoming(t *testing.T, ss store.Store) {
|
||||
webhook, err := ss.Webhook().UpdateIncoming(o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if webhook.UpdateAt == previousUpdatedAt {
|
||||
t.Fatal("should have updated the UpdatedAt of the hook")
|
||||
}
|
||||
|
||||
if webhook.DisplayName != "TestHook" {
|
||||
t.Fatal("display name is not updated")
|
||||
}
|
||||
require.NotEqual(t, webhook.UpdateAt, previousUpdatedAt, "should have updated the UpdatedAt of the hook")
|
||||
|
||||
require.Equal(t, "TestHook", webhook.DisplayName, "display name is not updated")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetIncoming(t *testing.T, ss store.Store) {
|
||||
@@ -85,33 +76,25 @@ func testWebhookStoreGetIncoming(t *testing.T, ss store.Store) {
|
||||
|
||||
o1 := buildIncomingWebhook()
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
webhook, err := ss.Webhook().GetIncoming(o1.Id, false)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
webhook, err = ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if _, err = ss.Webhook().GetIncoming("123", false); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetIncoming("123", false)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
|
||||
if _, err = ss.Webhook().GetIncoming("123", true); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetIncoming("123", true)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
|
||||
if _, err = ss.Webhook().GetIncoming("123", true); err.StatusCode != http.StatusNotFound {
|
||||
t.Fatal("Should have set the status as not found for missing id")
|
||||
}
|
||||
_, err = ss.Webhook().GetIncoming("123", true)
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, err.StatusCode, http.StatusNotFound, "Should have set the status as not found for missing id")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetIncomingList(t *testing.T, ss store.Store) {
|
||||
@@ -122,31 +105,22 @@ func testWebhookStoreGetIncomingList(t *testing.T, ss store.Store) {
|
||||
|
||||
var err *model.AppError
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
if hooks, err := ss.Webhook().GetIncomingList(0, 1000); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
found := false
|
||||
for _, hook := range hooks {
|
||||
if hook.Id == o1.Id {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("missing webhook")
|
||||
}
|
||||
}
|
||||
hooks, err := ss.Webhook().GetIncomingList(0, 1000)
|
||||
require.Nil(t, err)
|
||||
|
||||
if hooks, err := ss.Webhook().GetIncomingList(0, 1); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(hooks) != 1 {
|
||||
t.Fatal("only 1 should be returned")
|
||||
found := false
|
||||
for _, hook := range hooks {
|
||||
if hook.Id == o1.Id {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
require.True(t, found, "missing webhook")
|
||||
|
||||
hooks, err = ss.Webhook().GetIncomingList(0, 1)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, hooks, 1, "only 1 should be returned")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetIncomingListByUser(t *testing.T, ss store.Store) {
|
||||
@@ -179,21 +153,13 @@ func testWebhookStoreGetIncomingByTeam(t *testing.T, ss store.Store) {
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
require.Nil(t, err)
|
||||
|
||||
if hooks, err := ss.Webhook().GetIncomingByTeam(o1.TeamId, 0, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if hooks[0].CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
}
|
||||
hooks, err := ss.Webhook().GetIncomingByTeam(o1.TeamId, 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, hooks[0].CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if hooks, err := ss.Webhook().GetIncomingByTeam("123", 0, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(hooks) != 0 {
|
||||
t.Fatal("no webhooks should have returned")
|
||||
}
|
||||
}
|
||||
hooks, err = ss.Webhook().GetIncomingByTeam("123", 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, hooks, 0, "no webhooks should have returned")
|
||||
}
|
||||
|
||||
func TestWebhookStoreGetIncomingByTeamByUser(t *testing.T, ss store.Store) {
|
||||
@@ -232,23 +198,15 @@ func TestWebhookStoreGetIncomingByChannel(t *testing.T, ss store.Store) {
|
||||
o1 := buildIncomingWebhook()
|
||||
|
||||
o1, err := ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook")
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
webhooks, err := ss.Webhook().GetIncomingByChannel(o1.ChannelId)
|
||||
require.Nil(t, err)
|
||||
if webhooks[0].CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhooks[0].CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if webhooks, err = ss.Webhook().GetIncomingByChannel("123"); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(webhooks) != 0 {
|
||||
t.Fatal("no webhooks should have returned")
|
||||
}
|
||||
}
|
||||
webhooks, err = ss.Webhook().GetIncomingByChannel("123")
|
||||
require.Nil(t, err)
|
||||
require.Len(t, webhooks, 0, "no webhooks should have returned")
|
||||
}
|
||||
|
||||
func testWebhookStoreDeleteIncoming(t *testing.T, ss store.Store) {
|
||||
@@ -256,19 +214,14 @@ func testWebhookStoreDeleteIncoming(t *testing.T, ss store.Store) {
|
||||
|
||||
o1 := buildIncomingWebhook()
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
webhook, err := ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err = ss.Webhook().DeleteIncoming(o1.Id, model.GetMillis()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().DeleteIncoming(o1.Id, model.GetMillis())
|
||||
require.Nil(t, err)
|
||||
|
||||
webhook, err = ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.NotNil(t, err)
|
||||
@@ -279,23 +232,17 @@ func testWebhookStoreDeleteIncomingByChannel(t *testing.T, ss store.Store) {
|
||||
|
||||
o1 := buildIncomingWebhook()
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
webhook, err := ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err = ss.Webhook().PermanentDeleteIncomingByChannel(o1.ChannelId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().PermanentDeleteIncomingByChannel(o1.ChannelId)
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err = ss.Webhook().GetIncoming(o1.Id, true); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testWebhookStoreDeleteIncomingByUser(t *testing.T, ss store.Store) {
|
||||
@@ -303,23 +250,17 @@ func testWebhookStoreDeleteIncomingByUser(t *testing.T, ss store.Store) {
|
||||
|
||||
o1 := buildIncomingWebhook()
|
||||
o1, err = ss.Webhook().SaveIncoming(o1)
|
||||
if err != nil {
|
||||
t.Fatal("unable to save webhook", err)
|
||||
}
|
||||
require.Nil(t, err, "unable to save webhook")
|
||||
|
||||
webhook, err := ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err = ss.Webhook().PermanentDeleteIncomingByUser(o1.UserId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().PermanentDeleteIncomingByUser(o1.UserId)
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err = ss.Webhook().GetIncoming(o1.Id, true); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetIncoming(o1.Id, true)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func buildIncomingWebhook() *model.IncomingWebhook {
|
||||
@@ -340,13 +281,11 @@ func testWebhookStoreSaveOutgoing(t *testing.T, ss store.Store) {
|
||||
o1.Username = "test-user-name"
|
||||
o1.IconURL = "http://nowhere.com/icon"
|
||||
|
||||
if _, err := ss.Webhook().SaveOutgoing(&o1); err != nil {
|
||||
t.Fatal("couldn't save item", err)
|
||||
}
|
||||
_, err := ss.Webhook().SaveOutgoing(&o1)
|
||||
require.Nil(t, err, "couldn't save item")
|
||||
|
||||
if _, err := ss.Webhook().SaveOutgoing(&o1); err == nil {
|
||||
t.Fatal("shouldn't be able to update from save")
|
||||
}
|
||||
_, err = ss.Webhook().SaveOutgoing(&o1)
|
||||
require.NotNil(t, err, "shouldn't be able to update from save")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetOutgoing(t *testing.T, ss store.Store) {
|
||||
@@ -362,13 +301,10 @@ func testWebhookStoreGetOutgoing(t *testing.T, ss store.Store) {
|
||||
|
||||
webhook, err := ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if _, err := ss.Webhook().GetOutgoing("123"); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetOutgoing("123")
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetOutgoingListByUser(t *testing.T, ss store.Store) {
|
||||
@@ -412,38 +348,28 @@ func testWebhookStoreGetOutgoingList(t *testing.T, ss store.Store) {
|
||||
|
||||
o2, _ = ss.Webhook().SaveOutgoing(o2)
|
||||
|
||||
if r1, err := ss.Webhook().GetOutgoingList(0, 1000); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
hooks := r1
|
||||
found1 := false
|
||||
found2 := false
|
||||
r1, err := ss.Webhook().GetOutgoingList(0, 1000)
|
||||
require.Nil(t, err)
|
||||
hooks := r1
|
||||
found1 := false
|
||||
found2 := false
|
||||
|
||||
for _, hook := range hooks {
|
||||
if hook.CreateAt != o1.CreateAt {
|
||||
found1 = true
|
||||
}
|
||||
|
||||
if hook.CreateAt != o2.CreateAt {
|
||||
found2 = true
|
||||
}
|
||||
for _, hook := range hooks {
|
||||
if hook.CreateAt != o1.CreateAt {
|
||||
found1 = true
|
||||
}
|
||||
|
||||
if !found1 {
|
||||
t.Fatal("missing hook1")
|
||||
}
|
||||
if !found2 {
|
||||
t.Fatal("missing hook2")
|
||||
if hook.CreateAt != o2.CreateAt {
|
||||
found2 = true
|
||||
}
|
||||
}
|
||||
|
||||
if result, err := ss.Webhook().GetOutgoingList(0, 2); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(result) != 2 {
|
||||
t.Fatal("wrong number of hooks returned")
|
||||
}
|
||||
}
|
||||
require.True(t, found1, "missing hook1")
|
||||
require.True(t, found2, "missing hook2")
|
||||
|
||||
result, err := ss.Webhook().GetOutgoingList(0, 2)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, result, 2, "wrong number of hooks returned")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetOutgoingByChannel(t *testing.T, ss store.Store) {
|
||||
@@ -455,21 +381,13 @@ func testWebhookStoreGetOutgoingByChannel(t *testing.T, ss store.Store) {
|
||||
|
||||
o1, _ = ss.Webhook().SaveOutgoing(o1)
|
||||
|
||||
if r1, err := ss.Webhook().GetOutgoingByChannel(o1.ChannelId, 0, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if r1[0].CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
}
|
||||
r1, err := ss.Webhook().GetOutgoingByChannel(o1.ChannelId, 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, r1[0].CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if result, err := ss.Webhook().GetOutgoingByChannel("123", -1, -1); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(result) != 0 {
|
||||
t.Fatal("no webhooks should have returned")
|
||||
}
|
||||
}
|
||||
result, err := ss.Webhook().GetOutgoingByChannel("123", -1, -1)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, result, 0, "no webhooks should have returned")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetOutgoingByChannelByUser(t *testing.T, ss store.Store) {
|
||||
@@ -520,21 +438,13 @@ func testWebhookStoreGetOutgoingByTeam(t *testing.T, ss store.Store) {
|
||||
|
||||
o1, _ = ss.Webhook().SaveOutgoing(o1)
|
||||
|
||||
if r1, err := ss.Webhook().GetOutgoingByTeam(o1.TeamId, 0, 100); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if r1[0].CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
}
|
||||
r1, err := ss.Webhook().GetOutgoingByTeam(o1.TeamId, 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, r1[0].CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if result, err := ss.Webhook().GetOutgoingByTeam("123", -1, -1); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if len(result) != 0 {
|
||||
t.Fatal("no webhooks should have returned")
|
||||
}
|
||||
}
|
||||
result, err := ss.Webhook().GetOutgoingByTeam("123", -1, -1)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, result, 0, "no webhooks should have returned")
|
||||
}
|
||||
|
||||
func testWebhookStoreGetOutgoingByTeamByUser(t *testing.T, ss store.Store) {
|
||||
@@ -589,17 +499,13 @@ func testWebhookStoreDeleteOutgoing(t *testing.T, ss store.Store) {
|
||||
|
||||
webhook, err := ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err := ss.Webhook().DeleteOutgoing(o1.Id, model.GetMillis()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().DeleteOutgoing(o1.Id, model.GetMillis())
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err := ss.Webhook().GetOutgoing(o1.Id); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testWebhookStoreDeleteOutgoingByChannel(t *testing.T, ss store.Store) {
|
||||
@@ -613,17 +519,13 @@ func testWebhookStoreDeleteOutgoingByChannel(t *testing.T, ss store.Store) {
|
||||
|
||||
webhook, err := ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err := ss.Webhook().PermanentDeleteOutgoingByChannel(o1.ChannelId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().PermanentDeleteOutgoingByChannel(o1.ChannelId)
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err := ss.Webhook().GetOutgoing(o1.Id); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testWebhookStoreDeleteOutgoingByUser(t *testing.T, ss store.Store) {
|
||||
@@ -637,17 +539,13 @@ func testWebhookStoreDeleteOutgoingByUser(t *testing.T, ss store.Store) {
|
||||
|
||||
webhook, err := ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.Nil(t, err)
|
||||
if webhook.CreateAt != o1.CreateAt {
|
||||
t.Fatal("invalid returned webhook")
|
||||
}
|
||||
require.Equal(t, webhook.CreateAt, o1.CreateAt, "invalid returned webhook")
|
||||
|
||||
if err := ss.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ss.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId)
|
||||
require.Nil(t, err)
|
||||
|
||||
if _, err := ss.Webhook().GetOutgoing(o1.Id); err == nil {
|
||||
t.Fatal("Missing id should have failed")
|
||||
}
|
||||
_, err = ss.Webhook().GetOutgoing(o1.Id)
|
||||
require.NotNil(t, err, "Missing id should have failed")
|
||||
}
|
||||
|
||||
func testWebhookStoreUpdateOutgoing(t *testing.T, ss store.Store) {
|
||||
@@ -664,9 +562,8 @@ func testWebhookStoreUpdateOutgoing(t *testing.T, ss store.Store) {
|
||||
o1.Token = model.NewId()
|
||||
o1.Username = "another-test-user-name"
|
||||
|
||||
if _, err := ss.Webhook().UpdateOutgoing(o1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err := ss.Webhook().UpdateOutgoing(o1)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testWebhookStoreCountIncoming(t *testing.T, ss store.Store) {
|
||||
@@ -678,13 +575,9 @@ func testWebhookStoreCountIncoming(t *testing.T, ss store.Store) {
|
||||
_, _ = ss.Webhook().SaveIncoming(o1)
|
||||
|
||||
c, err := ss.Webhook().AnalyticsIncomingCount("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.Nil(t, err)
|
||||
|
||||
if c == 0 {
|
||||
t.Fatal("should have at least 1 incoming hook")
|
||||
}
|
||||
require.NotEqual(t, 0, c, "should have at least 1 incoming hook")
|
||||
}
|
||||
|
||||
func testWebhookStoreCountOutgoing(t *testing.T, ss store.Store) {
|
||||
@@ -696,11 +589,7 @@ func testWebhookStoreCountOutgoing(t *testing.T, ss store.Store) {
|
||||
|
||||
ss.Webhook().SaveOutgoing(o1)
|
||||
|
||||
if r, err := ss.Webhook().AnalyticsOutgoingCount(""); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if r == 0 {
|
||||
t.Fatal("should have at least 1 outgoing hook")
|
||||
}
|
||||
}
|
||||
r, err := ss.Webhook().AnalyticsOutgoingCount("")
|
||||
require.Nil(t, err)
|
||||
require.NotEqual(t, 0, r, "should have at least 1 outgoing hook")
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func (h *MainHelper) setupStore() {
|
||||
h.ClusterInterface = &FakeClusterInterface{}
|
||||
h.SqlSupplier = sqlstore.NewSqlSupplier(*h.Settings, nil)
|
||||
h.Store = &TestStore{
|
||||
store.NewLayeredStore(h.SqlSupplier, nil, h.ClusterInterface),
|
||||
h.SqlSupplier,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const (
|
||||
actionSymlink
|
||||
)
|
||||
|
||||
const root = "___mattermost-server"
|
||||
|
||||
type testResourceDetails struct {
|
||||
src string
|
||||
dest string
|
||||
@@ -50,6 +52,15 @@ func findFile(path string) string {
|
||||
}
|
||||
|
||||
func findDir(dir string) (string, bool) {
|
||||
if dir == root {
|
||||
srcPath := findFile("go.mod")
|
||||
if srcPath == "" {
|
||||
return "./", false
|
||||
}
|
||||
|
||||
return path.Dir(srcPath), true
|
||||
}
|
||||
|
||||
found := fileutils.FindPath(dir, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
|
||||
return fileInfo.IsDir()
|
||||
})
|
||||
@@ -65,7 +76,7 @@ func getTestResourcesToSetup() []testResourceDetails {
|
||||
var found bool
|
||||
|
||||
var testResourcesToSetup = []testResourceDetails{
|
||||
{"mattermost-server", "mattermost-server", resourceTypeFolder, actionSymlink},
|
||||
{root, "mattermost-server", resourceTypeFolder, actionSymlink},
|
||||
{"i18n", "i18n", resourceTypeFolder, actionSymlink},
|
||||
{"templates", "templates", resourceTypeFolder, actionSymlink},
|
||||
{"tests", "tests", resourceTypeFolder, actionSymlink},
|
||||
|
||||
15
testlib/resources_test.go
Обычный файл
15
testlib/resources_test.go
Обычный файл
@@ -0,0 +1,15 @@
|
||||
package testlib
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFindDir(t *testing.T) {
|
||||
t.Run("find root", func(t *testing.T) {
|
||||
path, found := findDir(root)
|
||||
assert.True(t, found, "failed to find root")
|
||||
assert.NotEmpty(t, path)
|
||||
})
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLRU(t *testing.T) {
|
||||
@@ -20,50 +21,39 @@ func TestLRU(t *testing.T) {
|
||||
for i := 0; i < 256; i++ {
|
||||
l.Add(i, i)
|
||||
}
|
||||
if l.Len() != 128 {
|
||||
t.Fatalf("bad len: %v", l.Len())
|
||||
}
|
||||
require.Equalf(t, l.Len(), 128, "bad len: %v", l.Len())
|
||||
|
||||
for i, k := range l.Keys() {
|
||||
if v, ok := l.Get(k); !ok || v != k || v != i+128 {
|
||||
t.Fatalf("bad key: %v", k)
|
||||
}
|
||||
v, ok := l.Get(k)
|
||||
require.True(t, ok, "bad key: %v", k)
|
||||
require.Equalf(t, v, k, "bad key: %v", k)
|
||||
require.Equalf(t, i+128, v, "bad key: %v", k)
|
||||
}
|
||||
for i := 0; i < 128; i++ {
|
||||
_, ok := l.Get(i)
|
||||
if ok {
|
||||
t.Fatalf("should be evicted")
|
||||
}
|
||||
require.False(t, ok, "should be evicted")
|
||||
}
|
||||
for i := 128; i < 256; i++ {
|
||||
_, ok := l.Get(i)
|
||||
if !ok {
|
||||
t.Fatalf("should not be evicted")
|
||||
}
|
||||
require.True(t, ok, "should not be evicted")
|
||||
}
|
||||
for i := 128; i < 192; i++ {
|
||||
l.Remove(i)
|
||||
_, ok := l.Get(i)
|
||||
if ok {
|
||||
t.Fatalf("should be deleted")
|
||||
}
|
||||
require.False(t, ok, "should be deleted")
|
||||
}
|
||||
|
||||
l.Get(192) // expect 192 to be last key in l.Keys()
|
||||
|
||||
for i, k := range l.Keys() {
|
||||
if (i < 63 && k != i+193) || (i == 63 && k != 192) {
|
||||
t.Fatalf("out of order key: %v", k)
|
||||
}
|
||||
require.Falsef(t, (i < 63 && k != i+193), "out of order key: %v", k)
|
||||
require.Falsef(t, (i == 63 && k != 192), "out of order key: %v", k)
|
||||
}
|
||||
|
||||
l.Purge()
|
||||
if l.Len() != 0 {
|
||||
t.Fatalf("bad len: %v", l.Len())
|
||||
}
|
||||
if _, ok := l.Get(200); ok {
|
||||
t.Fatalf("should contain nothing")
|
||||
}
|
||||
require.Equalf(t, l.Len(), 0, "bad len: %v", l.Len())
|
||||
_, ok := l.Get(200)
|
||||
require.False(t, ok, "should contain nothing")
|
||||
}
|
||||
|
||||
func TestLRUExpire(t *testing.T) {
|
||||
@@ -75,13 +65,11 @@ func TestLRUExpire(t *testing.T) {
|
||||
|
||||
time.Sleep(time.Millisecond * 2100)
|
||||
|
||||
if r1, ok := l.Get(1); ok {
|
||||
t.Fatal(r1)
|
||||
}
|
||||
r1, ok := l.Get(1)
|
||||
require.False(t, ok, r1)
|
||||
|
||||
if _, ok2 := l.Get(3); !ok2 {
|
||||
t.Fatal("should exist")
|
||||
}
|
||||
_, ok2 := l.Get(3)
|
||||
require.True(t, ok2, "should exist")
|
||||
}
|
||||
|
||||
func TestLRUGetOrAdd(t *testing.T) {
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/testlib"
|
||||
|
||||
"github.com/mattermost/mattermost-server/app"
|
||||
"github.com/mattermost/mattermost-server/config"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
@@ -97,11 +95,6 @@ func Setup() *TestHelper {
|
||||
}
|
||||
|
||||
func (th *TestHelper) InitPlugins() *TestHelper {
|
||||
|
||||
if th.tempWorkspace == "" {
|
||||
th.tempWorkspace, _ = testlib.SetupTestResources()
|
||||
}
|
||||
|
||||
pluginDir := filepath.Join(th.tempWorkspace, "plugins")
|
||||
webappDir := filepath.Join(th.tempWorkspace, "webapp")
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user