diff --git a/app/plugin_api.go b/app/plugin_api.go index 157c9a519b..bcd9f887b1 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "net/http" + "path/filepath" "strings" "github.com/mattermost/mattermost-server/mlog" @@ -98,6 +99,15 @@ func (api *PluginAPI) SavePluginConfig(pluginConfig map[string]interface{}) *mod return api.app.SaveConfig(cfg, true) } +func (api *PluginAPI) GetBundlePath() (string, error) { + bundlePath, err := filepath.Abs(filepath.Join(*api.GetConfig().PluginSettings.Directory, api.manifest.Id)) + if err != nil { + return "", err + } + + return bundlePath, err +} + func (api *PluginAPI) GetLicense() *model.License { return api.app.License() } diff --git a/app/plugin_api_test.go b/app/plugin_api_test.go index 55dc1b660f..f13d6d41bf 100644 --- a/app/plugin_api_test.go +++ b/app/plugin_api_test.go @@ -510,6 +510,47 @@ func TestPluginAPILoadPluginConfigurationDefaults(t *testing.T) { assert.Equal(t, "override35true", ret) } +func TestPluginAPIGetBundlePath(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + setupPluginApiTest(t, + ` + package main + + import ( + "github.com/mattermost/mattermost-server/plugin" + "github.com/mattermost/mattermost-server/model" + ) + + type MyPlugin struct { + plugin.MattermostPlugin + } + + func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { + bundlePath, err := p.API.GetBundlePath() + if err != nil { + return nil, err.Error() + "failed get bundle path" + } + + return nil, bundlePath + } + + func main() { + plugin.ClientMain(&MyPlugin{}) + } + `, `{"id": "testplugin", "backend": {"executable": "backend.exe"}}`, "testplugin", th.App) + + hooks, err := th.App.GetPluginsEnvironment().HooksForPlugin("testplugin") + require.Nil(t, err) + require.NotNil(t, hooks) + bundlePath, err := filepath.Abs(filepath.Join(*th.App.Config().PluginSettings.Directory, "testplugin")) + require.Nil(t, err) + + _, errString := hooks.MessageWillBePosted(nil, nil) + assert.Equal(t, bundlePath, errString) +} + func TestPluginAPIGetProfileImage(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() diff --git a/plugin/api.go b/plugin/api.go index d5d6b4fa97..d43162525a 100644 --- a/plugin/api.go +++ b/plugin/api.go @@ -44,7 +44,12 @@ type API interface { // Minimum server version: 5.6 SavePluginConfig(config map[string]interface{}) *model.AppError - // GetLicense returns the current license used by the Mattermoset server. Returns nil if the + // GetBundlePath returns the absolute path where the plugin's bundle was unpacked. + // + // 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. // // Minimum server version: 5.10 diff --git a/plugin/client_rpc_generated.go b/plugin/client_rpc_generated.go index bf9b49b369..4c69375317 100644 --- a/plugin/client_rpc_generated.go +++ b/plugin/client_rpc_generated.go @@ -671,6 +671,34 @@ func (s *apiRPCServer) SavePluginConfig(args *Z_SavePluginConfigArgs, returns *Z return nil } +type Z_GetBundlePathArgs struct { +} + +type Z_GetBundlePathReturns struct { + A string + B error +} + +func (g *apiRPCClient) GetBundlePath() (string, error) { + _args := &Z_GetBundlePathArgs{} + _returns := &Z_GetBundlePathReturns{} + if err := g.client.Call("Plugin.GetBundlePath", _args, _returns); err != nil { + log.Printf("RPC call to GetBundlePath API failed: %s", err.Error()) + } + return _returns.A, _returns.B +} + +func (s *apiRPCServer) GetBundlePath(args *Z_GetBundlePathArgs, returns *Z_GetBundlePathReturns) error { + if hook, ok := s.impl.(interface { + GetBundlePath() (string, error) + }); ok { + returns.A, returns.B = hook.GetBundlePath() + } else { + return encodableError(fmt.Errorf("API GetBundlePath called but not implemented.")) + } + return nil +} + type Z_GetLicenseArgs struct { } diff --git a/plugin/plugintest/api.go b/plugin/plugintest/api.go index 509a5198c3..83006bd16f 100644 --- a/plugin/plugintest/api.go +++ b/plugin/plugintest/api.go @@ -445,6 +445,27 @@ func (_m *API) GetBots(options *model.BotGetOptions) ([]*model.Bot, *model.AppEr return r0, r1 } +// GetBundlePath provides a mock function with given fields: +func (_m *API) GetBundlePath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetChannel provides a mock function with given fields: channelId func (_m *API) GetChannel(channelId string) (*model.Channel, *model.AppError) { ret := _m.Called(channelId) @@ -1699,13 +1720,13 @@ func (_m *API) GetUserStatusesByIds(userIds []string) ([]*model.Status, *model.A return r0, r1 } -// GetUsers provides a mock function with given fields: _a0 -func (_m *API) GetUsers(_a0 *model.UserGetOptions) ([]*model.User, *model.AppError) { - ret := _m.Called(_a0) +// GetUsers provides a mock function with given fields: options +func (_m *API) GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError) { + ret := _m.Called(options) var r0 []*model.User if rf, ok := ret.Get(0).(func(*model.UserGetOptions) []*model.User); ok { - r0 = rf(_a0) + r0 = rf(options) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.User) @@ -1714,7 +1735,7 @@ func (_m *API) GetUsers(_a0 *model.UserGetOptions) ([]*model.User, *model.AppErr var r1 *model.AppError if rf, ok := ret.Get(1).(func(*model.UserGetOptions) *model.AppError); ok { - r1 = rf(_a0) + r1 = rf(options) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(*model.AppError)