[MM-11861] Design & implement a better way for plugins to update their own configuration (#9712)
* [MM-11861] Design & implement a better way for plugins to update their own configuration Added GetPluginConfig and SavePluginConfig plugin APIs. Added test cases for testing new APIs. * Fixed gofmt error * Minor changes requested in PR
Этот коммит содержится в:
коммит произвёл
Jesse Hallam
родитель
a50e8ac5b9
Коммит
7a6f957638
@@ -84,6 +84,20 @@ func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError {
|
|||||||
return api.app.SaveConfig(config, true)
|
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 {
|
func (api *PluginAPI) GetServerVersion() string {
|
||||||
return model.CurrentVersion
|
return model.CurrentVersion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,84 @@ func TestPluginAPIUpdateUserStatus(t *testing.T) {
|
|||||||
assert.Nil(t, status)
|
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) {
|
func TestPluginAPILoadPluginConfiguration(t *testing.T) {
|
||||||
th := Setup().InitBasic()
|
th := Setup().InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ type API interface {
|
|||||||
// SaveConfig sets the given config and persists the changes
|
// SaveConfig sets the given config and persists the changes
|
||||||
SaveConfig(config *model.Config) *model.AppError
|
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
|
// GetServerVersion return the current Mattermost server version
|
||||||
//
|
//
|
||||||
// Minimum server version: 5.4
|
// Minimum server version: 5.4
|
||||||
|
|||||||
@@ -656,6 +656,61 @@ func (s *apiRPCServer) SaveConfig(args *Z_SaveConfigArgs, returns *Z_SaveConfigR
|
|||||||
return nil
|
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 {
|
type Z_GetServerVersionArgs struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -581,6 +581,20 @@ func (_m *API) GetConfig() *model.Config {
|
|||||||
return r0
|
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
|
// GetDirectChannel provides a mock function with given fields: userId1, userId2
|
||||||
func (_m *API) GetDirectChannel(userId1 string, userId2 string) (*model.Channel, *model.AppError) {
|
func (_m *API) GetDirectChannel(userId1 string, userId2 string) (*model.Channel, *model.AppError) {
|
||||||
ret := _m.Called(userId1, userId2)
|
ret := _m.Called(userId1, userId2)
|
||||||
@@ -1819,6 +1833,22 @@ func (_m *API) SaveConfig(config *model.Config) *model.AppError {
|
|||||||
return r0
|
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
|
// SearchChannels provides a mock function with given fields: teamId, term
|
||||||
func (_m *API) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
|
func (_m *API) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
|
||||||
ret := _m.Called(teamId, term)
|
ret := _m.Called(teamId, term)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user