diff options
author | Christopher Speller <crspeller@gmail.com> | 2018-05-15 13:33:47 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-15 13:33:47 -0700 |
commit | df6a7f8b19e2381ee57f946d5b184185653b2ee1 (patch) | |
tree | 622ff6b13b23bf4506ea41eb010141930e143815 /plugin/rpcplugin | |
parent | fbbe1f7cefd52a27fd52893509b5365d275f9bee (diff) | |
download | chat-df6a7f8b19e2381ee57f946d5b184185653b2ee1.tar.gz chat-df6a7f8b19e2381ee57f946d5b184185653b2ee1.tar.bz2 chat-df6a7f8b19e2381ee57f946d5b184185653b2ee1.zip |
MM-10249 Adding plugin ability to intercept posts before they reach the DB. (#8791)
* Adding plugin ability to intercept posts before they reach the DB.
* s/envoked/invoked/
Diffstat (limited to 'plugin/rpcplugin')
-rw-r--r-- | plugin/rpcplugin/api_test.go | 60 | ||||
-rw-r--r-- | plugin/rpcplugin/hooks.go | 106 | ||||
-rw-r--r-- | plugin/rpcplugin/hooks_test.go | 24 |
3 files changed, 160 insertions, 30 deletions
diff --git a/plugin/rpcplugin/api_test.go b/plugin/rpcplugin/api_test.go index d7b3733ea..04d8e5d86 100644 --- a/plugin/rpcplugin/api_test.go +++ b/plugin/rpcplugin/api_test.go @@ -90,10 +90,10 @@ func TestAPI(t *testing.T) { api.On("UnregisterCommand", "team", "trigger").Return(nil).Once() assert.NoError(t, remote.UnregisterCommand("team", "trigger")) - api.On("CreateChannel", mock.AnythingOfType("*model.Channel")).Return(func(c *model.Channel) (*model.Channel, *model.AppError) { + api.On("CreateChannel", mock.AnythingOfType("*model.Channel")).Return(func(c *model.Channel) *model.Channel { c.Id = "thechannelid" - return c, nil - }).Once() + return c + }, nil).Once() channel, err := remote.CreateChannel(testChannel) assert.Equal(t, "thechannelid", channel.Id) assert.Nil(t, err) @@ -121,9 +121,9 @@ func TestAPI(t *testing.T) { assert.Equal(t, testChannel, channel) assert.Nil(t, err) - api.On("UpdateChannel", mock.AnythingOfType("*model.Channel")).Return(func(c *model.Channel) (*model.Channel, *model.AppError) { - return c, nil - }).Once() + api.On("UpdateChannel", mock.AnythingOfType("*model.Channel")).Return(func(c *model.Channel) *model.Channel { + return c + }, nil).Once() channel, err = remote.UpdateChannel(testChannel) assert.Equal(t, testChannel, channel) assert.Nil(t, err) @@ -154,10 +154,10 @@ func TestAPI(t *testing.T) { err = remote.DeleteChannelMember("thechannelid", "theuserid") assert.Nil(t, err) - api.On("CreateUser", mock.AnythingOfType("*model.User")).Return(func(u *model.User) (*model.User, *model.AppError) { + api.On("CreateUser", mock.AnythingOfType("*model.User")).Return(func(u *model.User) *model.User { u.Id = "theuserid" - return u, nil - }).Once() + return u + }, nil).Once() user, err := remote.CreateUser(testUser) assert.Equal(t, "theuserid", user.Id) assert.Nil(t, err) @@ -180,17 +180,17 @@ func TestAPI(t *testing.T) { assert.Equal(t, testUser, user) assert.Nil(t, err) - api.On("UpdateUser", mock.AnythingOfType("*model.User")).Return(func(u *model.User) (*model.User, *model.AppError) { - return u, nil - }).Once() + api.On("UpdateUser", mock.AnythingOfType("*model.User")).Return(func(u *model.User) *model.User { + return u + }, nil).Once() user, err = remote.UpdateUser(testUser) assert.Equal(t, testUser, user) assert.Nil(t, err) - api.On("CreateTeam", mock.AnythingOfType("*model.Team")).Return(func(t *model.Team) (*model.Team, *model.AppError) { + api.On("CreateTeam", mock.AnythingOfType("*model.Team")).Return(func(t *model.Team) *model.Team { t.Id = "theteamid" - return t, nil - }).Once() + return t + }, nil).Once() team, err := remote.CreateTeam(testTeam) assert.Equal(t, "theteamid", team.Id) assert.Nil(t, err) @@ -213,17 +213,17 @@ func TestAPI(t *testing.T) { assert.Nil(t, team) assert.Equal(t, teamNotFoundError, err) - api.On("UpdateTeam", mock.AnythingOfType("*model.Team")).Return(func(t *model.Team) (*model.Team, *model.AppError) { - return t, nil - }).Once() + api.On("UpdateTeam", mock.AnythingOfType("*model.Team")).Return(func(t *model.Team) *model.Team { + return t + }, nil).Once() team, err = remote.UpdateTeam(testTeam) assert.Equal(t, testTeam, team) assert.Nil(t, err) - api.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) (*model.Post, *model.AppError) { + api.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) *model.Post { p.Id = "thepostid" - return p, nil - }).Once() + return p + }, nil).Once() post, err := remote.CreatePost(testPost) require.Nil(t, err) assert.NotEmpty(t, post.Id) @@ -237,9 +237,9 @@ func TestAPI(t *testing.T) { assert.Equal(t, testPost, post) assert.Nil(t, err) - api.On("UpdatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) (*model.Post, *model.AppError) { - return p, nil - }).Once() + api.On("UpdatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) *model.Post { + return p + }, nil).Once() post, err = remote.UpdatePost(testPost) assert.Equal(t, testPost, post) assert.Nil(t, err) @@ -248,9 +248,9 @@ func TestAPI(t *testing.T) { err = remote.KeyValueStore().Set("thekey", []byte("thevalue")) assert.Nil(t, err) - api.KeyValueStore().(*plugintest.KeyValueStore).On("Get", "thekey").Return(func(key string) ([]byte, *model.AppError) { - return []byte("thevalue"), nil - }).Once() + api.KeyValueStore().(*plugintest.KeyValueStore).On("Get", "thekey").Return(func(key string) []byte { + return []byte("thevalue") + }, nil).Once() ret, err := remote.KeyValueStore().Get("thekey") assert.Nil(t, err) assert.Equal(t, []byte("thevalue"), ret) @@ -267,10 +267,10 @@ func TestAPI_GobRegistration(t *testing.T) { defer api.AssertExpectations(t) testAPIRPC(&api, func(remote plugin.API) { - api.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) (*model.Post, *model.AppError) { + api.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(func(p *model.Post) *model.Post { p.Id = "thepostid" - return p, nil - }).Once() + return p + }, nil).Once() _, err := remote.CreatePost(&model.Post{ Message: "hello", Props: map[string]interface{}{ diff --git a/plugin/rpcplugin/hooks.go b/plugin/rpcplugin/hooks.go index 90734fd1c..6af98873a 100644 --- a/plugin/rpcplugin/hooks.go +++ b/plugin/rpcplugin/hooks.go @@ -141,6 +141,52 @@ func (h *LocalHooks) ExecuteCommand(args *model.CommandArgs, reply *HooksExecute return nil } +type MessageWillBeReply struct { + Post *model.Post + RejectionReason string +} + +type MessageUpdatedArgs struct { + NewPost *model.Post + OldPost *model.Post +} + +func (h *LocalHooks) MessageWillBePosted(args *model.Post, reply *MessageWillBeReply) error { + if hook, ok := h.hooks.(interface { + MessageWillBePosted(*model.Post) (*model.Post, string) + }); ok { + reply.Post, reply.RejectionReason = hook.MessageWillBePosted(args) + } + return nil +} + +func (h *LocalHooks) MessageWillBeUpdated(args *MessageUpdatedArgs, reply *MessageWillBeReply) error { + if hook, ok := h.hooks.(interface { + MessageWillBeUpdated(*model.Post, *model.Post) (*model.Post, string) + }); ok { + reply.Post, reply.RejectionReason = hook.MessageWillBeUpdated(args.NewPost, args.OldPost) + } + return nil +} + +func (h *LocalHooks) MessageHasBeenPosted(args *model.Post, reply *struct{}) error { + if hook, ok := h.hooks.(interface { + MessageHasBeenPosted(*model.Post) + }); ok { + hook.MessageHasBeenPosted(args) + } + return nil +} + +func (h *LocalHooks) MessageHasBeenUpdated(args *MessageUpdatedArgs, reply *struct{}) error { + if hook, ok := h.hooks.(interface { + MessageHasBeenUpdated(*model.Post, *model.Post) + }); ok { + hook.MessageHasBeenUpdated(args.NewPost, args.OldPost) + } + return nil +} + func ServeHooks(hooks interface{}, conn io.ReadWriteCloser, muxer *Muxer) { server := rpc.NewServer() server.Register(&LocalHooks{ @@ -158,6 +204,10 @@ const ( remoteServeHTTP = 2 remoteOnConfigurationChange = 3 remoteExecuteCommand = 4 + remoteMessageWillBePosted = 5 + remoteMessageWillBeUpdated = 6 + remoteMessageHasBeenPosted = 7 + remoteMessageHasBeenUpdated = 8 maxRemoteHookCount = iota ) @@ -255,6 +305,54 @@ func (h *RemoteHooks) ExecuteCommand(args *model.CommandArgs) (*model.CommandRes return reply.Response, reply.Error } +func (h *RemoteHooks) MessageWillBePosted(args *model.Post) (*model.Post, string) { + if !h.implemented[remoteMessageWillBePosted] { + return args, "" + } + var reply MessageWillBeReply + if err := h.client.Call("LocalHooks.MessageWillBePosted", args, &reply); err != nil { + return nil, "" + } + return reply.Post, reply.RejectionReason +} + +func (h *RemoteHooks) MessageWillBeUpdated(newPost, oldPost *model.Post) (*model.Post, string) { + if !h.implemented[remoteMessageWillBeUpdated] { + return newPost, "" + } + var reply MessageWillBeReply + args := &MessageUpdatedArgs{ + NewPost: newPost, + OldPost: oldPost, + } + if err := h.client.Call("LocalHooks.MessageWillBeUpdated", args, &reply); err != nil { + return nil, "" + } + return reply.Post, reply.RejectionReason +} + +func (h *RemoteHooks) MessageHasBeenPosted(args *model.Post) { + if !h.implemented[remoteMessageHasBeenPosted] { + return + } + if err := h.client.Call("LocalHooks.MessageHasBeenPosted", args, nil); err != nil { + return + } +} + +func (h *RemoteHooks) MessageHasBeenUpdated(newPost, oldPost *model.Post) { + if !h.implemented[remoteMessageHasBeenUpdated] { + return + } + args := &MessageUpdatedArgs{ + NewPost: newPost, + OldPost: oldPost, + } + if err := h.client.Call("LocalHooks.MessageHasBeenUpdated", args, nil); err != nil { + return + } +} + func (h *RemoteHooks) Close() error { if h.apiCloser != nil { h.apiCloser.Close() @@ -286,6 +384,14 @@ func ConnectHooks(conn io.ReadWriteCloser, muxer *Muxer, pluginId string) (*Remo remote.implemented[remoteServeHTTP] = true case "ExecuteCommand": remote.implemented[remoteExecuteCommand] = true + case "MessageWillBePosted": + remote.implemented[remoteMessageWillBePosted] = true + case "MessageWillBeUpdated": + remote.implemented[remoteMessageWillBeUpdated] = true + case "MessageHasBeenPosted": + remote.implemented[remoteMessageHasBeenPosted] = true + case "MessageHasBeenUpdated": + remote.implemented[remoteMessageHasBeenUpdated] = true } } return remote, nil diff --git a/plugin/rpcplugin/hooks_test.go b/plugin/rpcplugin/hooks_test.go index c404442b7..a7bac982e 100644 --- a/plugin/rpcplugin/hooks_test.go +++ b/plugin/rpcplugin/hooks_test.go @@ -91,6 +91,30 @@ func TestHooks(t *testing.T) { }) assert.Equal(t, "bar", commandResponse.Text) assert.Nil(t, appErr) + + hooks.On("MessageWillBePosted", mock.AnythingOfType("*model.Post")).Return(func(post *model.Post) *model.Post { + post.Message += "_testing" + return post + }, "changemessage") + post, changemessage := remote.MessageWillBePosted(&model.Post{Id: "1", Message: "base"}) + assert.Equal(t, "changemessage", changemessage) + assert.Equal(t, "base_testing", post.Message) + assert.Equal(t, "1", post.Id) + + hooks.On("MessageWillBeUpdated", mock.AnythingOfType("*model.Post"), mock.AnythingOfType("*model.Post")).Return(func(newPost, oldPost *model.Post) *model.Post { + newPost.Message += "_testing" + return newPost + }, "changemessage2") + post2, changemessage2 := remote.MessageWillBeUpdated(&model.Post{Id: "2", Message: "base2"}, &model.Post{Id: "OLD", Message: "OLDMESSAGE"}) + assert.Equal(t, "changemessage2", changemessage2) + assert.Equal(t, "base2_testing", post2.Message) + assert.Equal(t, "2", post2.Id) + + hooks.On("MessageHasBeenPosted", mock.AnythingOfType("*model.Post")).Return(nil) + remote.MessageHasBeenPosted(&model.Post{}) + + hooks.On("MessageHasBeenUpdated", mock.AnythingOfType("*model.Post"), mock.AnythingOfType("*model.Post")).Return(nil) + remote.MessageHasBeenUpdated(&model.Post{}, &model.Post{}) })) } |