From c208de7c4476735ef3af0c7c7ad05a68f59b091a Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 14 Jan 2019 09:03:16 -0800 Subject: [PATCH] MM-13312 Prevent clobbering of new fields by old plugins. (#10087) * Prevent clobbering of new fields by old plugins. * Apply suggestions from code review Spelling and copy paste error. Co-Authored-By: crspeller --- plugin/client_rpc.go | 83 +++++++++++++++++++++++++++++- plugin/client_rpc_generated.go | 75 --------------------------- plugin/interface_generator/main.go | 2 + 3 files changed, 84 insertions(+), 76 deletions(-) diff --git a/plugin/client_rpc.go b/plugin/client_rpc.go index ad69b958a7..51735fc018 100644 --- a/plugin/client_rpc.go +++ b/plugin/client_rpc.go @@ -407,7 +407,7 @@ func (g *hooksRPCClient) FileWillBeUploaded(c *Context, info *model.FileInfo, fi }() _args := &Z_FileWillBeUploadedArgs{c, info, uploadedFileStreamId, replacementFileStreamId} - _returns := &Z_FileWillBeUploadedReturns{} + _returns := &Z_FileWillBeUploadedReturns{A: _args.B} if g.implemented[FileWillBeUploadedId] { if err := g.client.Call("Plugin.FileWillBeUploaded", _args, _returns); err != nil { g.log.Error("RPC call FileWillBeUploaded to plugin failed.", mlog.Err(err)) @@ -443,3 +443,84 @@ func (s *hooksRPCServer) FileWillBeUploaded(args *Z_FileWillBeUploadedArgs, retu } return nil } + +// MessageWillBePosted is in this file because of the difficulty of identifiying which fields need special behaviour. +// The special behaviour needed is decoding the returned post into the original one to avoid the unintentional removal +// of fields by older plugins. +func init() { + hookNameToId["MessageWillBePosted"] = MessageWillBePostedId +} + +type Z_MessageWillBePostedArgs struct { + A *Context + B *model.Post +} + +type Z_MessageWillBePostedReturns struct { + A *model.Post + B string +} + +func (g *hooksRPCClient) MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) { + _args := &Z_MessageWillBePostedArgs{c, post} + _returns := &Z_MessageWillBePostedReturns{A: _args.B} + if g.implemented[MessageWillBePostedId] { + if err := g.client.Call("Plugin.MessageWillBePosted", _args, _returns); err != nil { + g.log.Error("RPC call MessageWillBePosted to plugin failed.", mlog.Err(err)) + } + } + return _returns.A, _returns.B +} + +func (s *hooksRPCServer) MessageWillBePosted(args *Z_MessageWillBePostedArgs, returns *Z_MessageWillBePostedReturns) error { + if hook, ok := s.impl.(interface { + MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) + }); ok { + returns.A, returns.B = hook.MessageWillBePosted(args.A, args.B) + + } else { + return encodableError(fmt.Errorf("Hook MessageWillBePosted called but not implemented.")) + } + return nil +} + +// MessageWillBeUpdated is in this file because of the difficulty of identifiying which fields need special behaviour. +// The special behavour needed is decoding the returned post into the original one to avoid the unintentional removal +// of fields by older plugins. +func init() { + hookNameToId["MessageWillBeUpdated"] = MessageWillBeUpdatedId +} + +type Z_MessageWillBeUpdatedArgs struct { + A *Context + B *model.Post + C *model.Post +} + +type Z_MessageWillBeUpdatedReturns struct { + A *model.Post + B string +} + +func (g *hooksRPCClient) MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) { + _args := &Z_MessageWillBeUpdatedArgs{c, newPost, oldPost} + _returns := &Z_MessageWillBeUpdatedReturns{A: _args.B} + if g.implemented[MessageWillBeUpdatedId] { + if err := g.client.Call("Plugin.MessageWillBeUpdated", _args, _returns); err != nil { + g.log.Error("RPC call MessageWillBeUpdated to plugin failed.", mlog.Err(err)) + } + } + return _returns.A, _returns.B +} + +func (s *hooksRPCServer) MessageWillBeUpdated(args *Z_MessageWillBeUpdatedArgs, returns *Z_MessageWillBeUpdatedReturns) error { + if hook, ok := s.impl.(interface { + MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) + }); ok { + returns.A, returns.B = hook.MessageWillBeUpdated(args.A, args.B, args.C) + + } else { + return encodableError(fmt.Errorf("Hook MessageWillBeUpdated called but not implemented.")) + } + return nil +} diff --git a/plugin/client_rpc_generated.go b/plugin/client_rpc_generated.go index c248b94daf..6d60cd3458 100644 --- a/plugin/client_rpc_generated.go +++ b/plugin/client_rpc_generated.go @@ -119,81 +119,6 @@ func (s *hooksRPCServer) ExecuteCommand(args *Z_ExecuteCommandArgs, returns *Z_E return nil } -func init() { - hookNameToId["MessageWillBePosted"] = MessageWillBePostedId -} - -type Z_MessageWillBePostedArgs struct { - A *Context - B *model.Post -} - -type Z_MessageWillBePostedReturns struct { - A *model.Post - B string -} - -func (g *hooksRPCClient) MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) { - _args := &Z_MessageWillBePostedArgs{c, post} - _returns := &Z_MessageWillBePostedReturns{} - if g.implemented[MessageWillBePostedId] { - if err := g.client.Call("Plugin.MessageWillBePosted", _args, _returns); err != nil { - g.log.Error("RPC call MessageWillBePosted to plugin failed.", mlog.Err(err)) - } - } - return _returns.A, _returns.B -} - -func (s *hooksRPCServer) MessageWillBePosted(args *Z_MessageWillBePostedArgs, returns *Z_MessageWillBePostedReturns) error { - if hook, ok := s.impl.(interface { - MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) - }); ok { - returns.A, returns.B = hook.MessageWillBePosted(args.A, args.B) - - } else { - return encodableError(fmt.Errorf("Hook MessageWillBePosted called but not implemented.")) - } - return nil -} - -func init() { - hookNameToId["MessageWillBeUpdated"] = MessageWillBeUpdatedId -} - -type Z_MessageWillBeUpdatedArgs struct { - A *Context - B *model.Post - C *model.Post -} - -type Z_MessageWillBeUpdatedReturns struct { - A *model.Post - B string -} - -func (g *hooksRPCClient) MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) { - _args := &Z_MessageWillBeUpdatedArgs{c, newPost, oldPost} - _returns := &Z_MessageWillBeUpdatedReturns{} - if g.implemented[MessageWillBeUpdatedId] { - if err := g.client.Call("Plugin.MessageWillBeUpdated", _args, _returns); err != nil { - g.log.Error("RPC call MessageWillBeUpdated to plugin failed.", mlog.Err(err)) - } - } - return _returns.A, _returns.B -} - -func (s *hooksRPCServer) MessageWillBeUpdated(args *Z_MessageWillBeUpdatedArgs, returns *Z_MessageWillBeUpdatedReturns) error { - if hook, ok := s.impl.(interface { - MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) - }); ok { - returns.A, returns.B = hook.MessageWillBeUpdated(args.A, args.B, args.C) - - } else { - return encodableError(fmt.Errorf("Hook MessageWillBeUpdated called but not implemented.")) - } - return nil -} - func init() { hookNameToId["MessageHasBeenPosted"] = MessageHasBeenPostedId } diff --git a/plugin/interface_generator/main.go b/plugin/interface_generator/main.go index 95977713ec..4afb254436 100644 --- a/plugin/interface_generator/main.go +++ b/plugin/interface_generator/main.go @@ -397,6 +397,8 @@ func removeExcluded(info *PluginInterfaceInfo) *PluginInterfaceInfo { "LoadPluginConfiguration", "ServeHTTP", "FileWillBeUploaded", + "MessageWillBePosted", + "MessageWillBeUpdated", } for _, exclusion := range excluded { if exclusion == item {