mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-27 05:37:15 -05:00
Add plugin methods to plugin API (#9744)
This commit is contained in:
committed by
Christopher Speller
parent
93e581d642
commit
e67d89b9a8
@@ -438,6 +438,41 @@ func (api *PluginAPI) GetEmojiImage(emojiId string) ([]byte, string, *model.AppE
|
||||
return api.app.GetEmojiImage(emojiId)
|
||||
}
|
||||
|
||||
// Plugin Section
|
||||
|
||||
func (api *PluginAPI) GetPlugins() ([]*model.Manifest, *model.AppError) {
|
||||
plugins, err := api.app.GetPlugins()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var manifests []*model.Manifest
|
||||
for _, manifest := range plugins.Active {
|
||||
manifests = append(manifests, &manifest.Manifest)
|
||||
}
|
||||
for _, manifest := range plugins.Inactive {
|
||||
manifests = append(manifests, &manifest.Manifest)
|
||||
}
|
||||
return manifests, nil
|
||||
}
|
||||
|
||||
func (api *PluginAPI) EnablePlugin(id string) *model.AppError {
|
||||
return api.app.EnablePlugin(id)
|
||||
}
|
||||
|
||||
func (api *PluginAPI) DisablePlugin(id string) *model.AppError {
|
||||
return api.app.DisablePlugin(id)
|
||||
}
|
||||
|
||||
func (api *PluginAPI) RemovePlugin(id string) *model.AppError {
|
||||
return api.app.RemovePlugin(id)
|
||||
}
|
||||
|
||||
func (api *PluginAPI) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {
|
||||
return api.app.GetPluginStatus(id)
|
||||
}
|
||||
|
||||
// KV Store Section
|
||||
|
||||
func (api *PluginAPI) KVSet(key string, value []byte) *model.AppError {
|
||||
return api.app.SetPluginKey(api.id, key, value)
|
||||
}
|
||||
|
||||
+63
-1
@@ -5,6 +5,7 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -31,7 +32,10 @@ func setupPluginApiTest(t *testing.T, pluginCode string, pluginManifest string,
|
||||
compileGo(t, pluginCode, backend)
|
||||
|
||||
ioutil.WriteFile(filepath.Join(pluginDir, pluginId, "plugin.json"), []byte(pluginManifest), 0600)
|
||||
env.Activate(pluginId)
|
||||
manifest, activated, reterr := env.Activate(pluginId)
|
||||
require.Nil(t, reterr)
|
||||
require.NotNil(t, manifest)
|
||||
require.True(t, activated)
|
||||
|
||||
app.Srv.Plugins = env
|
||||
}
|
||||
@@ -215,3 +219,61 @@ func TestPluginAPIGetProfileImage(t *testing.T) {
|
||||
require.NotNil(t, err)
|
||||
require.Nil(t, data)
|
||||
}
|
||||
|
||||
func TestPluginAPIGetPlugins(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
api := th.SetupPluginAPI()
|
||||
|
||||
pluginCode := `
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/plugin"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func main() {
|
||||
plugin.ClientMain(&MyPlugin{})
|
||||
}
|
||||
`
|
||||
|
||||
pluginDir, err := ioutil.TempDir("", "")
|
||||
require.NoError(t, err)
|
||||
webappPluginDir, err := ioutil.TempDir("", "")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(pluginDir)
|
||||
defer os.RemoveAll(webappPluginDir)
|
||||
|
||||
env, err := plugin.NewEnvironment(th.App.NewPluginAPI, pluginDir, webappPluginDir, th.App.Log)
|
||||
require.NoError(t, err)
|
||||
|
||||
pluginIDs := []string{"pluginid1", "pluginid2", "pluginid3"}
|
||||
var pluginManifests []*model.Manifest
|
||||
for _, pluginID := range pluginIDs {
|
||||
backend := filepath.Join(pluginDir, pluginID, "backend.exe")
|
||||
compileGo(t, pluginCode, backend)
|
||||
|
||||
ioutil.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(fmt.Sprintf(`{"id": "%s", "server": {"executable": "backend.exe"}}`, pluginID)), 0600)
|
||||
manifest, activated, reterr := env.Activate(pluginID)
|
||||
|
||||
require.Nil(t, reterr)
|
||||
require.NotNil(t, manifest)
|
||||
require.True(t, activated)
|
||||
pluginManifests = append(pluginManifests, manifest)
|
||||
}
|
||||
th.App.Srv.Plugins = env
|
||||
|
||||
// Decative the last one for testing
|
||||
sucess := env.Deactivate(pluginIDs[len(pluginIDs)-1])
|
||||
require.True(t, sucess)
|
||||
|
||||
// check existing user first
|
||||
plugins, err := api.GetPlugins()
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, plugins)
|
||||
assert.Equal(t, pluginManifests, plugins)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,27 @@ import (
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
// GetPluginStatus returns the status for a plugin installed on this server.
|
||||
func (a *App) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {
|
||||
if a.Srv.Plugins == nil || !*a.Config().PluginSettings.Enable {
|
||||
return nil, model.NewAppError("GetPluginStatus", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
pluginStatuses, err := a.Srv.Plugins.Statuses()
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("GetPluginStatus", "app.plugin.get_statuses.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Add our cluster ID
|
||||
for _, status := range pluginStatuses {
|
||||
if status.PluginId == id {
|
||||
status.ClusterId = a.GetClusterId()
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
return nil, model.NewAppError("GetPluginStatus", "app.plugin.not_installed.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// GetPluginStatuses returns the status for plugins installed on this server.
|
||||
func (a *App) GetPluginStatuses() (model.PluginStatuses, *model.AppError) {
|
||||
if a.Srv.Plugins == nil || !*a.Config().PluginSettings.Enable {
|
||||
|
||||
+3
-3
@@ -3771,7 +3771,7 @@ func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response) {
|
||||
}
|
||||
}
|
||||
|
||||
// RemovePlugin will deactivate and delete a plugin.
|
||||
// RemovePlugin will disable and delete a plugin.
|
||||
// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
|
||||
func (c *Client4) RemovePlugin(id string) (bool, *Response) {
|
||||
if r, err := c.DoApiDelete(c.GetPluginRoute(id)); err != nil {
|
||||
@@ -3793,7 +3793,7 @@ func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) {
|
||||
}
|
||||
}
|
||||
|
||||
// ActivatePlugin will activate an plugin installed.
|
||||
// EnablePlugin will enable an plugin installed.
|
||||
// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
|
||||
func (c *Client4) EnablePlugin(id string) (bool, *Response) {
|
||||
if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/enable", ""); err != nil {
|
||||
@@ -3804,7 +3804,7 @@ func (c *Client4) EnablePlugin(id string) (bool, *Response) {
|
||||
}
|
||||
}
|
||||
|
||||
// DeactivatePlugin will deactivate an active plugin.
|
||||
// DisablePlugin will disable an enabled plugin.
|
||||
// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
|
||||
func (c *Client4) DisablePlugin(id string) (bool, *Response) {
|
||||
if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/disable", ""); err != nil {
|
||||
|
||||
@@ -314,6 +314,35 @@ type API interface {
|
||||
// Minimum server version: 5.6
|
||||
UploadFile(data []byte, channelId string, filename string) (*model.FileInfo, *model.AppError)
|
||||
|
||||
// Plugin Section
|
||||
|
||||
// GetPlugins will return a list of plugin manifests for currently active plugins.
|
||||
//
|
||||
// Minimum server version: 5.6
|
||||
GetPlugins() ([]*model.Manifest, *model.AppError)
|
||||
|
||||
// EnablePlugin will enable an plugin installed.
|
||||
//
|
||||
// Minimum server version: 5.6
|
||||
EnablePlugin(id string) *model.AppError
|
||||
|
||||
// DisablePlugin will disable an enabled plugin.
|
||||
//
|
||||
// Minimum server version: 5.6
|
||||
DisablePlugin(id string) *model.AppError
|
||||
|
||||
// RemovePlugin will disable and delete a plugin.
|
||||
//
|
||||
// Minimum server version: 5.6
|
||||
RemovePlugin(id string) *model.AppError
|
||||
|
||||
// GetPluginStatus will return the status of a plugin.
|
||||
//
|
||||
// Minimum server version: 5.6
|
||||
GetPluginStatus(id string) (*model.PluginStatus, *model.AppError)
|
||||
|
||||
// KV Store Section
|
||||
|
||||
// KVSet will store a key-value pair, unique per plugin.
|
||||
KVSet(key string, value []byte) *model.AppError
|
||||
|
||||
|
||||
@@ -2728,6 +2728,147 @@ func (s *apiRPCServer) UploadFile(args *Z_UploadFileArgs, returns *Z_UploadFileR
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_GetPluginsArgs struct {
|
||||
}
|
||||
|
||||
type Z_GetPluginsReturns struct {
|
||||
A []*model.Manifest
|
||||
B *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) GetPlugins() ([]*model.Manifest, *model.AppError) {
|
||||
_args := &Z_GetPluginsArgs{}
|
||||
_returns := &Z_GetPluginsReturns{}
|
||||
if err := g.client.Call("Plugin.GetPlugins", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to GetPlugins API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A, _returns.B
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) GetPlugins(args *Z_GetPluginsArgs, returns *Z_GetPluginsReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
GetPlugins() ([]*model.Manifest, *model.AppError)
|
||||
}); ok {
|
||||
returns.A, returns.B = hook.GetPlugins()
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API GetPlugins called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_GetPluginStatusArgs struct {
|
||||
A string
|
||||
}
|
||||
|
||||
type Z_GetPluginStatusReturns struct {
|
||||
A *model.PluginStatus
|
||||
B *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {
|
||||
_args := &Z_GetPluginStatusArgs{id}
|
||||
_returns := &Z_GetPluginStatusReturns{}
|
||||
if err := g.client.Call("Plugin.GetPluginStatus", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to GetPluginStatus API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A, _returns.B
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) GetPluginStatus(args *Z_GetPluginStatusArgs, returns *Z_GetPluginStatusReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
GetPluginStatus(id string) (*model.PluginStatus, *model.AppError)
|
||||
}); ok {
|
||||
returns.A, returns.B = hook.GetPluginStatus(args.A)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API GetPluginStatus called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_EnablePluginArgs struct {
|
||||
A string
|
||||
}
|
||||
|
||||
type Z_EnablePluginReturns struct {
|
||||
A *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) EnablePlugin(id string) *model.AppError {
|
||||
_args := &Z_EnablePluginArgs{id}
|
||||
_returns := &Z_EnablePluginReturns{}
|
||||
if err := g.client.Call("Plugin.EnablePlugin", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to EnablePlugin API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) EnablePlugin(args *Z_EnablePluginArgs, returns *Z_EnablePluginReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
EnablePlugin(id string) *model.AppError
|
||||
}); ok {
|
||||
returns.A = hook.EnablePlugin(args.A)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API EnablePlugin called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_DisablePluginArgs struct {
|
||||
A string
|
||||
}
|
||||
|
||||
type Z_DisablePluginReturns struct {
|
||||
A *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) DisablePlugin(id string) *model.AppError {
|
||||
_args := &Z_DisablePluginArgs{id}
|
||||
_returns := &Z_DisablePluginReturns{}
|
||||
if err := g.client.Call("Plugin.DisablePlugin", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to DisablePlugin API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) DisablePlugin(args *Z_DisablePluginArgs, returns *Z_DisablePluginReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
DisablePlugin(id string) *model.AppError
|
||||
}); ok {
|
||||
returns.A = hook.DisablePlugin(args.A)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API DisablePlugin called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_RemovePluginArgs struct {
|
||||
A string
|
||||
}
|
||||
|
||||
type Z_RemovePluginReturns struct {
|
||||
A *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) RemovePlugin(id string) *model.AppError {
|
||||
_args := &Z_RemovePluginArgs{id}
|
||||
_returns := &Z_RemovePluginReturns{}
|
||||
if err := g.client.Call("Plugin.RemovePlugin", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to RemovePlugin API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) RemovePlugin(args *Z_RemovePluginArgs, returns *Z_RemovePluginReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
RemovePlugin(id string) *model.AppError
|
||||
}); ok {
|
||||
returns.A = hook.RemovePlugin(args.A)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API RemovePlugin called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_KVSetArgs struct {
|
||||
A string
|
||||
B []byte
|
||||
|
||||
@@ -333,6 +333,38 @@ func (_m *API) DeleteUser(userId string) *model.AppError {
|
||||
return r0
|
||||
}
|
||||
|
||||
// DisablePlugin provides a mock function with given fields: id
|
||||
func (_m *API) DisablePlugin(id string) *model.AppError {
|
||||
ret := _m.Called(id)
|
||||
|
||||
var r0 *model.AppError
|
||||
if rf, ok := ret.Get(0).(func(string) *model.AppError); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// EnablePlugin provides a mock function with given fields: id
|
||||
func (_m *API) EnablePlugin(id string) *model.AppError {
|
||||
ret := _m.Called(id)
|
||||
|
||||
var r0 *model.AppError
|
||||
if rf, ok := ret.Get(0).(func(string) *model.AppError); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetChannel provides a mock function with given fields: channelId
|
||||
func (_m *API) GetChannel(channelId string) (*model.Channel, *model.AppError) {
|
||||
ret := _m.Called(channelId)
|
||||
@@ -779,6 +811,56 @@ func (_m *API) GetLDAPUserAttributes(userId string, attributes []string) (map[st
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPluginStatus provides a mock function with given fields: id
|
||||
func (_m *API) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {
|
||||
ret := _m.Called(id)
|
||||
|
||||
var r0 *model.PluginStatus
|
||||
if rf, ok := ret.Get(0).(func(string) *model.PluginStatus); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.PluginStatus)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
|
||||
r1 = rf(id)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPlugins provides a mock function with given fields:
|
||||
func (_m *API) GetPlugins() ([]*model.Manifest, *model.AppError) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []*model.Manifest
|
||||
if rf, ok := ret.Get(0).(func() []*model.Manifest); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Manifest)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPost provides a mock function with given fields: postId
|
||||
func (_m *API) GetPost(postId string) (*model.Post, *model.AppError) {
|
||||
ret := _m.Called(postId)
|
||||
@@ -1664,6 +1746,22 @@ func (_m *API) RegisterCommand(command *model.Command) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemovePlugin provides a mock function with given fields: id
|
||||
func (_m *API) RemovePlugin(id string) *model.AppError {
|
||||
ret := _m.Called(id)
|
||||
|
||||
var r0 *model.AppError
|
||||
if rf, ok := ret.Get(0).(func(string) *model.AppError); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveReaction provides a mock function with given fields: reaction
|
||||
func (_m *API) RemoveReaction(reaction *model.Reaction) *model.AppError {
|
||||
ret := _m.Called(reaction)
|
||||
|
||||
Reference in New Issue
Block a user