diff --git a/app/plugin_api.go b/app/plugin_api.go index 477ab8ca5d..63d3b21211 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -84,6 +84,20 @@ func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError { return api.app.SaveConfig(config, true) } +func (api *PluginAPI) GetPluginConfig() map[string]interface{} { + cfg := api.app.GetConfig() + if pluginConfig, isOk := cfg.PluginSettings.Plugins[api.manifest.Id]; isOk { + return pluginConfig + } + return map[string]interface{}{} +} + +func (api *PluginAPI) SavePluginConfig(pluginConfig map[string]interface{}) *model.AppError { + cfg := api.app.GetConfig() + cfg.PluginSettings.Plugins[api.manifest.Id] = pluginConfig + return api.app.SaveConfig(cfg, true) +} + func (api *PluginAPI) GetServerVersion() string { return model.CurrentVersion } diff --git a/app/plugin_api_test.go b/app/plugin_api_test.go index b239cb07a2..347fd6c327 100644 --- a/app/plugin_api_test.go +++ b/app/plugin_api_test.go @@ -63,6 +63,84 @@ func TestPluginAPIUpdateUserStatus(t *testing.T) { assert.Nil(t, status) } +func TestPluginAPISavePluginConfig(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + manifest := &model.Manifest{ + Id: "pluginid", + SettingsSchema: &model.PluginSettingsSchema{ + Settings: []*model.PluginSetting{ + {Key: "MyStringSetting", Type: "text"}, + {Key: "MyIntSetting", Type: "text"}, + {Key: "MyBoolSetting", Type: "bool"}, + }, + }, + } + + api := NewPluginAPI(th.App, manifest) + + pluginConfigJsonString := `{"mystringsetting": "str", "MyIntSetting": 32, "myboolsetting": true}` + + var pluginConfig map[string]interface{} + if err := json.Unmarshal([]byte(pluginConfigJsonString), &pluginConfig); err != nil { + t.Fatal(err) + } + + if err := api.SavePluginConfig(pluginConfig); err != nil{ + t.Fatal(err) + } + + type Configuration struct { + MyStringSetting string + MyIntSetting int + MyBoolSetting bool + } + + savedConfiguration := new(Configuration) + if err := api.LoadPluginConfiguration(savedConfiguration); err != nil{ + t.Fatal(err) + } + + expectedConfiguration := new(Configuration) + if err := json.Unmarshal([]byte(pluginConfigJsonString), &expectedConfiguration); err != nil { + t.Fatal(err) + } + + assert.Equal(t, expectedConfiguration, savedConfiguration) +} + +func TestPluginAPIGetPluginConfig(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + manifest := &model.Manifest{ + Id: "pluginid", + SettingsSchema: &model.PluginSettingsSchema{ + Settings: []*model.PluginSetting{ + {Key: "MyStringSetting", Type: "text"}, + {Key: "MyIntSetting", Type: "text"}, + {Key: "MyBoolSetting", Type: "bool"}, + }, + }, + } + + api := NewPluginAPI(th.App, manifest) + + pluginConfigJsonString := `{"mystringsetting": "str", "MyIntSetting": 32, "myboolsetting": true}` + var pluginConfig map[string]interface{} + + if err := json.Unmarshal([]byte(pluginConfigJsonString), &pluginConfig); err != nil { + t.Fatal(err) + } + th.App.UpdateConfig(func(cfg *model.Config) { + cfg.PluginSettings.Plugins["pluginid"] = pluginConfig + }) + + savedPluginConfig := api.GetPluginConfig() + assert.Equal(t, pluginConfig, savedPluginConfig) +} + func TestPluginAPILoadPluginConfiguration(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() diff --git a/plugin/api.go b/plugin/api.go index 58a8812769..53cfea1031 100644 --- a/plugin/api.go +++ b/plugin/api.go @@ -34,6 +34,16 @@ type API interface { // SaveConfig sets the given config and persists the changes SaveConfig(config *model.Config) *model.AppError + // GetPluginConfig fetches the currently persisted config of plugin + // + // Minimum server version: 5.6 + GetPluginConfig() map[string]interface{} + + // SavePluginConfig sets the given config for plugin and persists the changes + // + // Minimum server version: 5.6 + SavePluginConfig(config map[string]interface{}) *model.AppError + // GetServerVersion return the current Mattermost server version // // Minimum server version: 5.4 diff --git a/plugin/client_rpc_generated.go b/plugin/client_rpc_generated.go index 3c1599fc7c..6b928c9019 100644 --- a/plugin/client_rpc_generated.go +++ b/plugin/client_rpc_generated.go @@ -656,6 +656,61 @@ func (s *apiRPCServer) SaveConfig(args *Z_SaveConfigArgs, returns *Z_SaveConfigR return nil } +type Z_GetPluginConfigArgs struct { +} + +type Z_GetPluginConfigReturns struct { + A map[string]interface{} +} + +func (g *apiRPCClient) GetPluginConfig() map[string]interface{} { + _args := &Z_GetPluginConfigArgs{} + _returns := &Z_GetPluginConfigReturns{} + if err := g.client.Call("Plugin.GetPluginConfig", _args, _returns); err != nil { + log.Printf("RPC call to GetPluginConfig API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) GetPluginConfig(args *Z_GetPluginConfigArgs, returns *Z_GetPluginConfigReturns) error { + if hook, ok := s.impl.(interface { + GetPluginConfig() map[string]interface{} + }); ok { + returns.A = hook.GetPluginConfig() + } else { + return encodableError(fmt.Errorf("API GetPluginConfig called but not implemented.")) + } + return nil +} + +type Z_SavePluginConfigArgs struct { + A map[string]interface{} +} + +type Z_SavePluginConfigReturns struct { + A *model.AppError +} + +func (g *apiRPCClient) SavePluginConfig(config map[string]interface{}) *model.AppError { + _args := &Z_SavePluginConfigArgs{config} + _returns := &Z_SavePluginConfigReturns{} + if err := g.client.Call("Plugin.SavePluginConfig", _args, _returns); err != nil { + log.Printf("RPC call to SavePluginConfig API failed: %s", err.Error()) + } + return _returns.A +} + +func (s *apiRPCServer) SavePluginConfig(args *Z_SavePluginConfigArgs, returns *Z_SavePluginConfigReturns) error { + if hook, ok := s.impl.(interface { + SavePluginConfig(config map[string]interface{}) *model.AppError + }); ok { + returns.A = hook.SavePluginConfig(args.A) + } else { + return encodableError(fmt.Errorf("API SavePluginConfig called but not implemented.")) + } + return nil +} + type Z_GetServerVersionArgs struct { } diff --git a/plugin/plugintest/api.go b/plugin/plugintest/api.go index 201aa4a11d..6788adf9b6 100644 --- a/plugin/plugintest/api.go +++ b/plugin/plugintest/api.go @@ -581,6 +581,20 @@ func (_m *API) GetConfig() *model.Config { return r0 } +// GetPluginConfig provides a mock function with given fields: +func (_m *API) GetPluginConfig() map[string]interface{} { + ret := _m.Called() + + var r0 map[string]interface{} + if rf, ok := ret.Get(0).(func() map[string]interface{}); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(map[string]interface{}) + } + + return r0 +} + // GetDirectChannel provides a mock function with given fields: userId1, userId2 func (_m *API) GetDirectChannel(userId1 string, userId2 string) (*model.Channel, *model.AppError) { ret := _m.Called(userId1, userId2) @@ -1819,6 +1833,22 @@ func (_m *API) SaveConfig(config *model.Config) *model.AppError { return r0 } +// SavePluginConfig provides a mock function with given fields: pluginConfig +func (_m *API) SavePluginConfig(pluginConfig map[string]interface{}) *model.AppError { + ret := _m.Called(pluginConfig) + + var r0 *model.AppError + if rf, ok := ret.Get(0).(func(map[string]interface{}) *model.AppError); ok { + r0 = rf(pluginConfig) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.AppError) + } + } + + return r0 +} + // SearchChannels provides a mock function with given fields: teamId, term func (_m *API) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) { ret := _m.Called(teamId, term)