diff --git a/api4/plugin.go b/api4/plugin.go index 45a00b2a7d..c37683fb41 100644 --- a/api4/plugin.go +++ b/api4/plugin.go @@ -66,7 +66,11 @@ func uploadPlugin(c *Context, w http.ResponseWriter, r *http.Request) { } defer file.Close() - manifest, unpackErr := c.App.InstallPlugin(file, false) + force := false + if len(m.Value["force"]) > 0 && m.Value["force"][0] == "true" { + force = true + } + manifest, unpackErr := c.App.InstallPlugin(file, force) if unpackErr != nil { c.Err = unpackErr diff --git a/api4/plugin_test.go b/api4/plugin_test.go index 1a1bccfdf0..ed32a32a1f 100644 --- a/api4/plugin_test.go +++ b/api4/plugin_test.go @@ -6,6 +6,7 @@ package api4 import ( "bytes" "encoding/json" + "io/ioutil" "os" "path/filepath" "testing" @@ -38,14 +39,15 @@ func TestPlugin(t *testing.T) { }) path, _ := utils.FindDir("tests") - file, err := os.Open(filepath.Join(path, "testplugin.tar.gz")) + tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) if err != nil { t.Fatal(err) } - defer file.Close() // Successful upload - manifest, resp := th.SystemAdminClient.UploadPlugin(file) + manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) + CheckNoError(t, resp) + manifest, resp = th.SystemAdminClient.UploadPluginForced(bytes.NewReader(tarData)) defer os.RemoveAll("plugins/testplugin") CheckNoError(t, resp) @@ -56,18 +58,18 @@ func TestPlugin(t *testing.T) { CheckBadRequestStatus(t, resp) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) - _, resp = th.SystemAdminClient.UploadPlugin(file) + _, resp = th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) CheckNotImplementedStatus(t, resp) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true *cfg.PluginSettings.EnableUploads = false }) - _, resp = th.SystemAdminClient.UploadPlugin(file) + _, resp = th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) CheckNotImplementedStatus(t, resp) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.EnableUploads = true }) - _, resp = th.Client.UploadPlugin(file) + _, resp = th.Client.UploadPlugin(bytes.NewReader(tarData)) CheckForbiddenStatus(t, resp) // Successful gets diff --git a/model/client4.go b/model/client4.go index d064794dba..40a2ccd8be 100644 --- a/model/client4.go +++ b/model/client4.go @@ -3783,9 +3783,24 @@ func (c *Client4) GetChannelsForScheme(schemeId string, page int, perPage int) ( // UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin. // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) { + return c.uploadPlugin(file, false) +} + +func (c *Client4) UploadPluginForced(file io.Reader) (*Manifest, *Response) { + return c.uploadPlugin(file, true) +} + +func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response) { body := new(bytes.Buffer) writer := multipart.NewWriter(body) + if force { + err := writer.WriteField("force", "true") + if err != nil { + return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} + } + } + part, err := writer.CreateFormFile("plugin", "plugin.tar.gz") if err != nil { return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}