From 4c1ddcff10b359baf5728b334acb60cc3e1b1123 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 6 Jul 2018 06:07:09 -0700 Subject: MM-10703 Adding blank request context to plugin hooks for future use. (#9043) * Adding blank request context to plugin hooks for future use. * Rename RequestContext to Context * Adding context to ServeHTTP and ExecuteCommand * Fixing import cycle in test. --- Makefile | 1 + app/plugin_commands.go | 3 +- app/plugin_requests.go | 5 +- app/plugin_test.go | 3 +- app/post.go | 12 +- plugin/client_rpc.go | 10 +- plugin/client_rpc_generated.go | 55 +-- plugin/hooks.go | 12 +- plugin/mock_api_test.go | 779 +++++++++++++++++++++++++++++++++++++++++ plugin/plugintest/hooks.go | 61 ++-- plugin/request_context.go | 11 + plugin/supervisor_test.go | 3 +- web/context.go | 9 + 13 files changed, 890 insertions(+), 74 deletions(-) create mode 100644 plugin/mock_api_test.go create mode 100644 plugin/request_context.go diff --git a/Makefile b/Makefile index 1cb8deff8..9a7d457e7 100644 --- a/Makefile +++ b/Makefile @@ -282,6 +282,7 @@ ldap-mocks: ## Creates mock files for ldap. plugin-mocks: ## Creates mock files for plugins. go get github.com/vektra/mockery/... $(GOPATH)/bin/mockery -dir plugin -name API -output plugin/plugintest -outpkg plugintest -case underscore -note 'Regenerate this file using `make plugin-mocks`.' + $(GOPATH)/bin/mockery -dir plugin -name API -inpkg -output plugin -testonly -outpkg plugin -case underscore -note 'Regenerate this file using `make plugin-mocks`.' $(GOPATH)/bin/mockery -dir plugin -name Hooks -output plugin/plugintest -outpkg plugintest -case underscore -note 'Regenerate this file using `make plugin-mocks`.' pluginapi: ## Generates api and hooks glue code for plugins diff --git a/app/plugin_commands.go b/app/plugin_commands.go index 0f361f410..060defc86 100644 --- a/app/plugin_commands.go +++ b/app/plugin_commands.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/plugin" ) type PluginCommand struct { @@ -104,7 +105,7 @@ func (a *App) ExecutePluginCommand(args *model.CommandArgs) (*model.Command, *mo if err != nil { return pc.Command, nil, model.NewAppError("ExecutePluginCommand", "model.plugin_command.error.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) } - response, appErr := pluginHooks.ExecuteCommand(args) + response, appErr := pluginHooks.ExecuteCommand(plugin.NewBlankContext(), args) return pc.Command, response, appErr } } diff --git a/app/plugin_requests.go b/app/plugin_requests.go index b7515d950..10ef758b4 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -10,6 +10,7 @@ import ( "github.com/gorilla/mux" "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/plugin" ) func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { @@ -33,7 +34,7 @@ func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { a.servePluginRequest(w, r, hooks.ServeHTTP) } -func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler http.HandlerFunc) { +func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) { token := "" authHeader := r.Header.Get(model.HEADER_AUTH) @@ -71,5 +72,5 @@ func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler r.URL.RawQuery = newQuery.Encode() r.URL.Path = strings.TrimPrefix(r.URL.Path, "/plugins/"+params["plugin_id"]) - handler(w, r) + handler(plugin.NewBlankContext(), w, r) } diff --git a/app/plugin_test.go b/app/plugin_test.go index b0b6e9c1b..02b492d28 100644 --- a/app/plugin_test.go +++ b/app/plugin_test.go @@ -10,6 +10,7 @@ import ( "github.com/gorilla/mux" "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/plugin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -68,7 +69,7 @@ func TestHandlePluginRequest(t *testing.T) { var assertions func(*http.Request) router := mux.NewRouter() router.HandleFunc("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}/{anything:.*}", func(_ http.ResponseWriter, r *http.Request) { - th.App.servePluginRequest(nil, r, func(_ http.ResponseWriter, r *http.Request) { + th.App.servePluginRequest(nil, r, func(_ *plugin.Context, _ http.ResponseWriter, r *http.Request) { assertions(r) }) }) diff --git a/app/post.go b/app/post.go index 7e53de2f9..8d94aba2e 100644 --- a/app/post.go +++ b/app/post.go @@ -163,8 +163,9 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo if a.PluginsReady() { var rejectionReason string + pluginContext := &plugin.Context{} a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { - post, rejectionReason = hooks.MessageWillBePosted(post) + post, rejectionReason = hooks.MessageWillBePosted(pluginContext, post) return post != nil }, plugin.MessageWillBePostedId) if post == nil { @@ -181,8 +182,9 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo if a.PluginsReady() { a.Go(func() { + pluginContext := &plugin.Context{} a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { - hooks.MessageHasBeenPosted(rpost) + hooks.MessageHasBeenPosted(pluginContext, rpost) return true }, plugin.MessageHasBeenPostedId) }) @@ -394,8 +396,9 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model if a.PluginsReady() { var rejectionReason string + pluginContext := &plugin.Context{} a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { - newPost, rejectionReason = hooks.MessageWillBeUpdated(newPost, oldPost) + newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost, oldPost) return post != nil }, plugin.MessageWillBeUpdatedId) if newPost == nil { @@ -410,8 +413,9 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model if a.PluginsReady() { a.Go(func() { + pluginContext := &plugin.Context{} a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { - hooks.MessageHasBeenUpdated(newPost, oldPost) + hooks.MessageHasBeenUpdated(pluginContext, newPost, oldPost) return true }, plugin.MessageHasBeenUpdatedId) }) diff --git a/plugin/client_rpc.go b/plugin/client_rpc.go index f58bbd22b..39d91a3e7 100644 --- a/plugin/client_rpc.go +++ b/plugin/client_rpc.go @@ -226,10 +226,11 @@ func init() { type ServeHTTPArgs struct { ResponseWriterStream uint32 Request *http.Request + Context *Context RequestBodyStream uint32 } -func (g *HooksRPCClient) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (g *HooksRPCClient) ServeHTTP(c *Context, w http.ResponseWriter, r *http.Request) { if !g.implemented[ServeHTTPId] { http.NotFound(w, r) return @@ -282,6 +283,7 @@ func (g *HooksRPCClient) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if err := g.client.Call("Plugin.ServeHTTP", ServeHTTPArgs{ + Context: c, ResponseWriterStream: serveHTTPStreamId, Request: forwardedRequest, RequestBodyStream: requestBodyStreamId, @@ -314,8 +316,10 @@ func (s *HooksRPCServer) ServeHTTP(args *ServeHTTPArgs, returns *struct{}) error } defer r.Body.Close() - if hook, ok := s.impl.(http.Handler); ok { - hook.ServeHTTP(w, r) + if hook, ok := s.impl.(interface { + ServeHTTP(c *Context, w http.ResponseWriter, r *http.Request) + }); ok { + hook.ServeHTTP(args.Context, w, r) } else { http.NotFound(w, r) } diff --git a/plugin/client_rpc_generated.go b/plugin/client_rpc_generated.go index 897d6be04..3abc799af 100644 --- a/plugin/client_rpc_generated.go +++ b/plugin/client_rpc_generated.go @@ -84,7 +84,8 @@ func init() { } type ExecuteCommandArgs struct { - A *model.CommandArgs + A *Context + B *model.CommandArgs } type ExecuteCommandReturns struct { @@ -92,8 +93,8 @@ type ExecuteCommandReturns struct { B *model.AppError } -func (g *HooksRPCClient) ExecuteCommand(args *model.CommandArgs) (*model.CommandResponse, *model.AppError) { - _args := &ExecuteCommandArgs{args} +func (g *HooksRPCClient) ExecuteCommand(c *Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) { + _args := &ExecuteCommandArgs{c, args} _returns := &ExecuteCommandReturns{} if g.implemented[ExecuteCommandId] { if err := g.client.Call("Plugin.ExecuteCommand", _args, _returns); err != nil { @@ -105,9 +106,9 @@ func (g *HooksRPCClient) ExecuteCommand(args *model.CommandArgs) (*model.Command func (s *HooksRPCServer) ExecuteCommand(args *ExecuteCommandArgs, returns *ExecuteCommandReturns) error { if hook, ok := s.impl.(interface { - ExecuteCommand(args *model.CommandArgs) (*model.CommandResponse, *model.AppError) + ExecuteCommand(c *Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) }); ok { - returns.A, returns.B = hook.ExecuteCommand(args.A) + returns.A, returns.B = hook.ExecuteCommand(args.A, args.B) } else { return fmt.Errorf("Hook ExecuteCommand called but not implemented.") } @@ -119,7 +120,8 @@ func init() { } type MessageWillBePostedArgs struct { - A *model.Post + A *Context + B *model.Post } type MessageWillBePostedReturns struct { @@ -127,8 +129,8 @@ type MessageWillBePostedReturns struct { B string } -func (g *HooksRPCClient) MessageWillBePosted(post *model.Post) (*model.Post, string) { - _args := &MessageWillBePostedArgs{post} +func (g *HooksRPCClient) MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) { + _args := &MessageWillBePostedArgs{c, post} _returns := &MessageWillBePostedReturns{} if g.implemented[MessageWillBePostedId] { if err := g.client.Call("Plugin.MessageWillBePosted", _args, _returns); err != nil { @@ -140,9 +142,9 @@ func (g *HooksRPCClient) MessageWillBePosted(post *model.Post) (*model.Post, str func (s *HooksRPCServer) MessageWillBePosted(args *MessageWillBePostedArgs, returns *MessageWillBePostedReturns) error { if hook, ok := s.impl.(interface { - MessageWillBePosted(post *model.Post) (*model.Post, string) + MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) }); ok { - returns.A, returns.B = hook.MessageWillBePosted(args.A) + returns.A, returns.B = hook.MessageWillBePosted(args.A, args.B) } else { return fmt.Errorf("Hook MessageWillBePosted called but not implemented.") } @@ -154,8 +156,9 @@ func init() { } type MessageWillBeUpdatedArgs struct { - A *model.Post + A *Context B *model.Post + C *model.Post } type MessageWillBeUpdatedReturns struct { @@ -163,8 +166,8 @@ type MessageWillBeUpdatedReturns struct { B string } -func (g *HooksRPCClient) MessageWillBeUpdated(newPost, oldPost *model.Post) (*model.Post, string) { - _args := &MessageWillBeUpdatedArgs{newPost, oldPost} +func (g *HooksRPCClient) MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) { + _args := &MessageWillBeUpdatedArgs{c, newPost, oldPost} _returns := &MessageWillBeUpdatedReturns{} if g.implemented[MessageWillBeUpdatedId] { if err := g.client.Call("Plugin.MessageWillBeUpdated", _args, _returns); err != nil { @@ -176,9 +179,9 @@ func (g *HooksRPCClient) MessageWillBeUpdated(newPost, oldPost *model.Post) (*mo func (s *HooksRPCServer) MessageWillBeUpdated(args *MessageWillBeUpdatedArgs, returns *MessageWillBeUpdatedReturns) error { if hook, ok := s.impl.(interface { - MessageWillBeUpdated(newPost, oldPost *model.Post) (*model.Post, string) + MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) }); ok { - returns.A, returns.B = hook.MessageWillBeUpdated(args.A, args.B) + returns.A, returns.B = hook.MessageWillBeUpdated(args.A, args.B, args.C) } else { return fmt.Errorf("Hook MessageWillBeUpdated called but not implemented.") } @@ -190,14 +193,15 @@ func init() { } type MessageHasBeenPostedArgs struct { - A *model.Post + A *Context + B *model.Post } type MessageHasBeenPostedReturns struct { } -func (g *HooksRPCClient) MessageHasBeenPosted(post *model.Post) { - _args := &MessageHasBeenPostedArgs{post} +func (g *HooksRPCClient) MessageHasBeenPosted(c *Context, post *model.Post) { + _args := &MessageHasBeenPostedArgs{c, post} _returns := &MessageHasBeenPostedReturns{} if g.implemented[MessageHasBeenPostedId] { if err := g.client.Call("Plugin.MessageHasBeenPosted", _args, _returns); err != nil { @@ -209,9 +213,9 @@ func (g *HooksRPCClient) MessageHasBeenPosted(post *model.Post) { func (s *HooksRPCServer) MessageHasBeenPosted(args *MessageHasBeenPostedArgs, returns *MessageHasBeenPostedReturns) error { if hook, ok := s.impl.(interface { - MessageHasBeenPosted(post *model.Post) + MessageHasBeenPosted(c *Context, post *model.Post) }); ok { - hook.MessageHasBeenPosted(args.A) + hook.MessageHasBeenPosted(args.A, args.B) } else { return fmt.Errorf("Hook MessageHasBeenPosted called but not implemented.") } @@ -223,15 +227,16 @@ func init() { } type MessageHasBeenUpdatedArgs struct { - A *model.Post + A *Context B *model.Post + C *model.Post } type MessageHasBeenUpdatedReturns struct { } -func (g *HooksRPCClient) MessageHasBeenUpdated(newPost, oldPost *model.Post) { - _args := &MessageHasBeenUpdatedArgs{newPost, oldPost} +func (g *HooksRPCClient) MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post) { + _args := &MessageHasBeenUpdatedArgs{c, newPost, oldPost} _returns := &MessageHasBeenUpdatedReturns{} if g.implemented[MessageHasBeenUpdatedId] { if err := g.client.Call("Plugin.MessageHasBeenUpdated", _args, _returns); err != nil { @@ -243,9 +248,9 @@ func (g *HooksRPCClient) MessageHasBeenUpdated(newPost, oldPost *model.Post) { func (s *HooksRPCServer) MessageHasBeenUpdated(args *MessageHasBeenUpdatedArgs, returns *MessageHasBeenUpdatedReturns) error { if hook, ok := s.impl.(interface { - MessageHasBeenUpdated(newPost, oldPost *model.Post) + MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post) }); ok { - hook.MessageHasBeenUpdated(args.A, args.B) + hook.MessageHasBeenUpdated(args.A, args.B, args.C) } else { return fmt.Errorf("Hook MessageHasBeenUpdated called but not implemented.") } diff --git a/plugin/hooks.go b/plugin/hooks.go index 68eca8ede..852f4684c 100644 --- a/plugin/hooks.go +++ b/plugin/hooks.go @@ -48,11 +48,11 @@ type Hooks interface { // // The Mattermost-User-Id header will be present if (and only if) the request is by an // authenticated user. - ServeHTTP(w http.ResponseWriter, r *http.Request) + ServeHTTP(c *Context, w http.ResponseWriter, r *http.Request) // ExecuteCommand executes a command that has been previously registered via the RegisterCommand // API. - ExecuteCommand(args *model.CommandArgs) (*model.CommandResponse, *model.AppError) + ExecuteCommand(c *Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) // MessageWillBePosted is invoked when a message is posted by a user before it is commited // to the database. If you also want to act on edited posts, see MessageWillBeUpdated. @@ -62,7 +62,7 @@ type Hooks interface { // // Note that this method will be called for posts created by plugins, including the plugin that // created the post. - MessageWillBePosted(post *model.Post) (*model.Post, string) + MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) // MessageWillBeUpdated is invoked when a message is updated by a user before it is commited // to the database. If you also want to act on new posts, see MessageWillBePosted. @@ -73,17 +73,17 @@ type Hooks interface { // // Note that this method will be called for posts updated by plugins, including the plugin that // updated the post. - MessageWillBeUpdated(newPost, oldPost *model.Post) (*model.Post, string) + MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) // MessageHasBeenPosted is invoked after the message has been commited to the databse. // If you need to modify or reject the post, see MessageWillBePosted // Note that this method will be called for posts created by plugins, including the plugin that // created the post. - MessageHasBeenPosted(post *model.Post) + MessageHasBeenPosted(c *Context, post *model.Post) // MessageHasBeenUpdated is invoked after a message is updated and has been updated in the databse. // If you need to modify or reject the post, see MessageWillBeUpdated // Note that this method will be called for posts created by plugins, including the plugin that // created the post. - MessageHasBeenUpdated(newPost, oldPost *model.Post) + MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post) } diff --git a/plugin/mock_api_test.go b/plugin/mock_api_test.go new file mode 100644 index 000000000..5e86ad65b --- /dev/null +++ b/plugin/mock_api_test.go @@ -0,0 +1,779 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +// Regenerate this file using `make plugin-mocks`. + +package plugin + +import mock "github.com/stretchr/testify/mock" +import model "github.com/mattermost/mattermost-server/model" + +// MockAPI is an autogenerated mock type for the API type +type MockAPI struct { + mock.Mock +} + +// AddChannelMember provides a mock function with given fields: channelId, userId +func (_m *MockAPI) AddChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError) { + ret := _m.Called(channelId, userId) + + var r0 *model.ChannelMember + if rf, ok := ret.Get(0).(func(string, string) *model.ChannelMember); ok { + r0 = rf(channelId, userId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.ChannelMember) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string) *model.AppError); ok { + r1 = rf(channelId, userId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// CreateChannel provides a mock function with given fields: channel +func (_m *MockAPI) CreateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { + ret := _m.Called(channel) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func(*model.Channel) *model.Channel); ok { + r0 = rf(channel) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Channel) *model.AppError); ok { + r1 = rf(channel) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// CreatePost provides a mock function with given fields: post +func (_m *MockAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) { + ret := _m.Called(post) + + var r0 *model.Post + if rf, ok := ret.Get(0).(func(*model.Post) *model.Post); ok { + r0 = rf(post) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Post) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Post) *model.AppError); ok { + r1 = rf(post) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// CreateTeam provides a mock function with given fields: team +func (_m *MockAPI) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { + ret := _m.Called(team) + + var r0 *model.Team + if rf, ok := ret.Get(0).(func(*model.Team) *model.Team); ok { + r0 = rf(team) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Team) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Team) *model.AppError); ok { + r1 = rf(team) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// CreateUser provides a mock function with given fields: user +func (_m *MockAPI) CreateUser(user *model.User) (*model.User, *model.AppError) { + ret := _m.Called(user) + + var r0 *model.User + if rf, ok := ret.Get(0).(func(*model.User) *model.User); ok { + r0 = rf(user) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.User) *model.AppError); ok { + r1 = rf(user) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// DeleteChannel provides a mock function with given fields: channelId +func (_m *MockAPI) DeleteChannel(channelId string) *model.AppError { + ret := _m.Called(channelId) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(channelId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// DeleteChannelMember provides a mock function with given fields: channelId, userId +func (_m *MockAPI) DeleteChannelMember(channelId string, userId string) *model.AppError { + ret := _m.Called(channelId, userId) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, string) *model.AppError); ok { + r0 = rf(channelId, userId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// DeletePost provides a mock function with given fields: postId +func (_m *MockAPI) DeletePost(postId string) *model.AppError { + ret := _m.Called(postId) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(postId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// DeleteTeam provides a mock function with given fields: teamId +func (_m *MockAPI) DeleteTeam(teamId string) *model.AppError { + ret := _m.Called(teamId) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(teamId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// DeleteUser provides a mock function with given fields: userId +func (_m *MockAPI) DeleteUser(userId string) *model.AppError { + ret := _m.Called(userId) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(userId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// GetChannel provides a mock function with given fields: channelId +func (_m *MockAPI) GetChannel(channelId string) (*model.Channel, *model.AppError) { + ret := _m.Called(channelId) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func(string) *model.Channel); ok { + r0 = rf(channelId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(channelId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetChannelByName provides a mock function with given fields: name, teamId +func (_m *MockAPI) GetChannelByName(name string, teamId string) (*model.Channel, *model.AppError) { + ret := _m.Called(name, teamId) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func(string, string) *model.Channel); ok { + r0 = rf(name, teamId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string) *model.AppError); ok { + r1 = rf(name, teamId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetChannelMember provides a mock function with given fields: channelId, userId +func (_m *MockAPI) GetChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError) { + ret := _m.Called(channelId, userId) + + var r0 *model.ChannelMember + if rf, ok := ret.Get(0).(func(string, string) *model.ChannelMember); ok { + r0 = rf(channelId, userId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.ChannelMember) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string) *model.AppError); ok { + r1 = rf(channelId, userId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetDirectChannel provides a mock function with given fields: userId1, userId2 +func (_m *MockAPI) GetDirectChannel(userId1 string, userId2 string) (*model.Channel, *model.AppError) { + ret := _m.Called(userId1, userId2) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func(string, string) *model.Channel); ok { + r0 = rf(userId1, userId2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string) *model.AppError); ok { + r1 = rf(userId1, userId2) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetGroupChannel provides a mock function with given fields: userIds +func (_m *MockAPI) GetGroupChannel(userIds []string) (*model.Channel, *model.AppError) { + ret := _m.Called(userIds) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func([]string) *model.Channel); ok { + r0 = rf(userIds) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func([]string) *model.AppError); ok { + r1 = rf(userIds) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetPost provides a mock function with given fields: postId +func (_m *MockAPI) GetPost(postId string) (*model.Post, *model.AppError) { + ret := _m.Called(postId) + + var r0 *model.Post + if rf, ok := ret.Get(0).(func(string) *model.Post); ok { + r0 = rf(postId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Post) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(postId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetTeam provides a mock function with given fields: teamId +func (_m *MockAPI) GetTeam(teamId string) (*model.Team, *model.AppError) { + ret := _m.Called(teamId) + + var r0 *model.Team + if rf, ok := ret.Get(0).(func(string) *model.Team); ok { + r0 = rf(teamId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Team) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(teamId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetTeamByName provides a mock function with given fields: name +func (_m *MockAPI) GetTeamByName(name string) (*model.Team, *model.AppError) { + ret := _m.Called(name) + + var r0 *model.Team + if rf, ok := ret.Get(0).(func(string) *model.Team); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Team) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(name) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetUser provides a mock function with given fields: userId +func (_m *MockAPI) GetUser(userId string) (*model.User, *model.AppError) { + ret := _m.Called(userId) + + var r0 *model.User + if rf, ok := ret.Get(0).(func(string) *model.User); ok { + r0 = rf(userId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(userId) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetUserByEmail provides a mock function with given fields: email +func (_m *MockAPI) GetUserByEmail(email string) (*model.User, *model.AppError) { + ret := _m.Called(email) + + var r0 *model.User + if rf, ok := ret.Get(0).(func(string) *model.User); ok { + r0 = rf(email) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(email) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// GetUserByUsername provides a mock function with given fields: name +func (_m *MockAPI) GetUserByUsername(name string) (*model.User, *model.AppError) { + ret := _m.Called(name) + + var r0 *model.User + if rf, ok := ret.Get(0).(func(string) *model.User); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(name) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// KVDelete provides a mock function with given fields: key +func (_m *MockAPI) KVDelete(key string) *model.AppError { + ret := _m.Called(key) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string) *model.AppError); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// KVGet provides a mock function with given fields: key +func (_m *MockAPI) KVGet(key string) ([]byte, *model.AppError) { + ret := _m.Called(key) + + var r0 []byte + if rf, ok := ret.Get(0).(func(string) []byte); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string) *model.AppError); ok { + r1 = rf(key) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// KVSet provides a mock function with given fields: key, value +func (_m *MockAPI) KVSet(key string, value []byte) *model.AppError { + ret := _m.Called(key, value) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(string, []byte) *model.AppError); ok { + r0 = rf(key, value) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + +// LoadPluginConfiguration provides a mock function with given fields: dest +func (_m *MockAPI) LoadPluginConfiguration(dest interface{}) error { + ret := _m.Called(dest) + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(dest) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogDebug provides a mock function with given fields: msg, keyValuePairs +func (_m *MockAPI) LogDebug(msg string, keyValuePairs ...interface{}) { + var _ca []interface{} + _ca = append(_ca, msg) + _ca = append(_ca, keyValuePairs...) + _m.Called(_ca...) +} + +// LogError provides a mock function with given fields: msg, keyValuePairs +func (_m *MockAPI) LogError(msg string, keyValuePairs ...interface{}) { + var _ca []interface{} + _ca = append(_ca, msg) + _ca = append(_ca, keyValuePairs...) + _m.Called(_ca...) +} + +// LogInfo provides a mock function with given fields: msg, keyValuePairs +func (_m *MockAPI) LogInfo(msg string, keyValuePairs ...interface{}) { + var _ca []interface{} + _ca = append(_ca, msg) + _ca = append(_ca, keyValuePairs...) + _m.Called(_ca...) +} + +// LogWarn provides a mock function with given fields: msg, keyValuePairs +func (_m *MockAPI) LogWarn(msg string, keyValuePairs ...interface{}) { + var _ca []interface{} + _ca = append(_ca, msg) + _ca = append(_ca, keyValuePairs...) + _m.Called(_ca...) +} + +// PublishWebSocketEvent provides a mock function with given fields: event, payload, broadcast +func (_m *MockAPI) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *model.WebsocketBroadcast) { + _m.Called(event, payload, broadcast) +} + +// RegisterCommand provides a mock function with given fields: command +func (_m *MockAPI) RegisterCommand(command *model.Command) error { + ret := _m.Called(command) + + var r0 error + if rf, ok := ret.Get(0).(func(*model.Command) error); ok { + r0 = rf(command) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnregisterCommand provides a mock function with given fields: teamId, trigger +func (_m *MockAPI) UnregisterCommand(teamId string, trigger string) error { + ret := _m.Called(teamId, trigger) + + var r0 error + if rf, ok := ret.Get(0).(func(string, string) error); ok { + r0 = rf(teamId, trigger) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateChannel provides a mock function with given fields: channel +func (_m *MockAPI) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { + ret := _m.Called(channel) + + var r0 *model.Channel + if rf, ok := ret.Get(0).(func(*model.Channel) *model.Channel); ok { + r0 = rf(channel) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Channel) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Channel) *model.AppError); ok { + r1 = rf(channel) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// UpdateChannelMemberNotifications provides a mock function with given fields: channelId, userId, notifications +func (_m *MockAPI) UpdateChannelMemberNotifications(channelId string, userId string, notifications map[string]string) (*model.ChannelMember, *model.AppError) { + ret := _m.Called(channelId, userId, notifications) + + var r0 *model.ChannelMember + if rf, ok := ret.Get(0).(func(string, string, map[string]string) *model.ChannelMember); ok { + r0 = rf(channelId, userId, notifications) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.ChannelMember) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string, map[string]string) *model.AppError); ok { + r1 = rf(channelId, userId, notifications) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// UpdateChannelMemberRoles provides a mock function with given fields: channelId, userId, newRoles +func (_m *MockAPI) UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError) { + ret := _m.Called(channelId, userId, newRoles) + + var r0 *model.ChannelMember + if rf, ok := ret.Get(0).(func(string, string, string) *model.ChannelMember); ok { + r0 = rf(channelId, userId, newRoles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.ChannelMember) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(string, string, string) *model.AppError); ok { + r1 = rf(channelId, userId, newRoles) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// UpdatePost provides a mock function with given fields: post +func (_m *MockAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) { + ret := _m.Called(post) + + var r0 *model.Post + if rf, ok := ret.Get(0).(func(*model.Post) *model.Post); ok { + r0 = rf(post) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Post) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Post) *model.AppError); ok { + r1 = rf(post) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// UpdateTeam provides a mock function with given fields: team +func (_m *MockAPI) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) { + ret := _m.Called(team) + + var r0 *model.Team + if rf, ok := ret.Get(0).(func(*model.Team) *model.Team); ok { + r0 = rf(team) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Team) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.Team) *model.AppError); ok { + r1 = rf(team) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} + +// UpdateUser provides a mock function with given fields: user +func (_m *MockAPI) UpdateUser(user *model.User) (*model.User, *model.AppError) { + ret := _m.Called(user) + + var r0 *model.User + if rf, ok := ret.Get(0).(func(*model.User) *model.User); ok { + r0 = rf(user) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.User) + } + } + + var r1 *model.AppError + if rf, ok := ret.Get(1).(func(*model.User) *model.AppError); ok { + r1 = rf(user) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*model.AppError) + } + } + + return r0, r1 +} diff --git a/plugin/plugintest/hooks.go b/plugin/plugintest/hooks.go index 790a5a993..94a675cd7 100644 --- a/plugin/plugintest/hooks.go +++ b/plugin/plugintest/hooks.go @@ -7,19 +7,20 @@ package plugintest import http "net/http" import mock "github.com/stretchr/testify/mock" import model "github.com/mattermost/mattermost-server/model" +import plugin "github.com/mattermost/mattermost-server/plugin" // Hooks is an autogenerated mock type for the Hooks type type Hooks struct { mock.Mock } -// ExecuteCommand provides a mock function with given fields: args -func (_m *Hooks) ExecuteCommand(args *model.CommandArgs) (*model.CommandResponse, *model.AppError) { - ret := _m.Called(args) +// ExecuteCommand provides a mock function with given fields: c, args +func (_m *Hooks) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) { + ret := _m.Called(c, args) var r0 *model.CommandResponse - if rf, ok := ret.Get(0).(func(*model.CommandArgs) *model.CommandResponse); ok { - r0 = rf(args) + if rf, ok := ret.Get(0).(func(*plugin.Context, *model.CommandArgs) *model.CommandResponse); ok { + r0 = rf(c, args) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.CommandResponse) @@ -27,8 +28,8 @@ func (_m *Hooks) ExecuteCommand(args *model.CommandArgs) (*model.CommandResponse } var r1 *model.AppError - if rf, ok := ret.Get(1).(func(*model.CommandArgs) *model.AppError); ok { - r1 = rf(args) + if rf, ok := ret.Get(1).(func(*plugin.Context, *model.CommandArgs) *model.AppError); ok { + r1 = rf(c, args) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(*model.AppError) @@ -61,23 +62,23 @@ func (_m *Hooks) Implemented() ([]string, error) { return r0, r1 } -// MessageHasBeenPosted provides a mock function with given fields: post -func (_m *Hooks) MessageHasBeenPosted(post *model.Post) { - _m.Called(post) +// MessageHasBeenPosted provides a mock function with given fields: c, post +func (_m *Hooks) MessageHasBeenPosted(c *plugin.Context, post *model.Post) { + _m.Called(c, post) } -// MessageHasBeenUpdated provides a mock function with given fields: newPost, oldPost -func (_m *Hooks) MessageHasBeenUpdated(newPost *model.Post, oldPost *model.Post) { - _m.Called(newPost, oldPost) +// MessageHasBeenUpdated provides a mock function with given fields: c, newPost, oldPost +func (_m *Hooks) MessageHasBeenUpdated(c *plugin.Context, newPost *model.Post, oldPost *model.Post) { + _m.Called(c, newPost, oldPost) } -// MessageWillBePosted provides a mock function with given fields: post -func (_m *Hooks) MessageWillBePosted(post *model.Post) (*model.Post, string) { - ret := _m.Called(post) +// MessageWillBePosted provides a mock function with given fields: c, post +func (_m *Hooks) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { + ret := _m.Called(c, post) var r0 *model.Post - if rf, ok := ret.Get(0).(func(*model.Post) *model.Post); ok { - r0 = rf(post) + if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post) *model.Post); ok { + r0 = rf(c, post) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.Post) @@ -85,8 +86,8 @@ func (_m *Hooks) MessageWillBePosted(post *model.Post) (*model.Post, string) { } var r1 string - if rf, ok := ret.Get(1).(func(*model.Post) string); ok { - r1 = rf(post) + if rf, ok := ret.Get(1).(func(*plugin.Context, *model.Post) string); ok { + r1 = rf(c, post) } else { r1 = ret.Get(1).(string) } @@ -94,13 +95,13 @@ func (_m *Hooks) MessageWillBePosted(post *model.Post) (*model.Post, string) { return r0, r1 } -// MessageWillBeUpdated provides a mock function with given fields: newPost, oldPost -func (_m *Hooks) MessageWillBeUpdated(newPost *model.Post, oldPost *model.Post) (*model.Post, string) { - ret := _m.Called(newPost, oldPost) +// MessageWillBeUpdated provides a mock function with given fields: c, newPost, oldPost +func (_m *Hooks) MessageWillBeUpdated(c *plugin.Context, newPost *model.Post, oldPost *model.Post) (*model.Post, string) { + ret := _m.Called(c, newPost, oldPost) var r0 *model.Post - if rf, ok := ret.Get(0).(func(*model.Post, *model.Post) *model.Post); ok { - r0 = rf(newPost, oldPost) + if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post, *model.Post) *model.Post); ok { + r0 = rf(c, newPost, oldPost) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.Post) @@ -108,8 +109,8 @@ func (_m *Hooks) MessageWillBeUpdated(newPost *model.Post, oldPost *model.Post) } var r1 string - if rf, ok := ret.Get(1).(func(*model.Post, *model.Post) string); ok { - r1 = rf(newPost, oldPost) + if rf, ok := ret.Get(1).(func(*plugin.Context, *model.Post, *model.Post) string); ok { + r1 = rf(c, newPost, oldPost) } else { r1 = ret.Get(1).(string) } @@ -159,7 +160,7 @@ func (_m *Hooks) OnDeactivate() error { return r0 } -// ServeHTTP provides a mock function with given fields: w, r -func (_m *Hooks) ServeHTTP(w http.ResponseWriter, r *http.Request) { - _m.Called(w, r) +// ServeHTTP provides a mock function with given fields: c, w, r +func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { + _m.Called(c, w, r) } diff --git a/plugin/request_context.go b/plugin/request_context.go new file mode 100644 index 000000000..a7a3d89fd --- /dev/null +++ b/plugin/request_context.go @@ -0,0 +1,11 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package plugin + +type Context struct { +} + +func NewBlankContext() *Context { + return &Context{} +} diff --git a/plugin/supervisor_test.go b/plugin/supervisor_test.go index 605835f68..ddd04696f 100644 --- a/plugin/supervisor_test.go +++ b/plugin/supervisor_test.go @@ -12,7 +12,6 @@ import ( "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/plugin/plugintest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -66,7 +65,7 @@ func testSupervisor(t *testing.T) { ioutil.WriteFile(filepath.Join(dir, "plugin.json"), []byte(`{"id": "foo", "backend": {"executable": "backend.exe"}}`), 0600) bundle := model.BundleInfoForPath(dir) - var api plugintest.API + var api MockAPI api.On("LoadPluginConfiguration", mock.Anything).Return(nil) log := mlog.NewLogger(&mlog.LoggerConfiguration{ EnableConsole: true, diff --git a/web/context.go b/web/context.go index 5eb8c94d5..3b2ffa17c 100644 --- a/web/context.go +++ b/web/context.go @@ -14,6 +14,7 @@ import ( "github.com/mattermost/mattermost-server/app" "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/plugin" "github.com/mattermost/mattermost-server/utils" ) @@ -526,3 +527,11 @@ func (c *Context) RequireRoleName() *Context { return c } + +func (c *Context) ToPluginContext() *plugin.Context { + return &plugin.Context{ + //sessionId: c.Session.Id, + //requestId: c.RequestId, + //userIp: c.IpAddress, + } +} -- cgit v1.2.3-1-g7c22