diff --git a/server/channels/api4/plugin_test.go b/server/channels/api4/plugin_test.go index 98ff5ac3f1..8a923d1d0c 100644 --- a/server/channels/api4/plugin_test.go +++ b/server/channels/api4/plugin_test.go @@ -1722,14 +1722,26 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) { appErr := th.App.AddPublicKey("pub_key", key) require.Nil(t, appErr) + t.Cleanup(func() { + appErr = th.App.DeletePublicKey("pub_key") + require.Nil(t, appErr) + }) + testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { serverVersion := req.URL.Query().Get("server_version") require.NotEmpty(t, serverVersion) require.Equal(t, model.CurrentVersion, serverVersion) res.WriteHeader(http.StatusOK) + var out []byte - out, err = json.Marshal([]*model.MarketplacePlugin{samplePlugins[1]}) - require.NoError(t, err) + + // Return something if testplugin2 or no specific plugin is requested + pluginID := req.URL.Query().Get("plugin_id") + if pluginID == "" || pluginID == samplePlugins[1].Manifest.Id { + out, err = json.Marshal([]*model.MarketplacePlugin{samplePlugins[1]}) + require.NoError(t, err) + } + res.Write(out) })) defer testServer.Close() @@ -1748,43 +1760,52 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) { require.Len(t, pluginsResp.Active, 0) require.Len(t, pluginsResp.Inactive, 0) - // Should fail to install unknown prepackaged plugin - pRequest := &model.InstallMarketplacePluginRequest{Id: "testpluginXX"} - manifest, resp, err := client.InstallMarketplacePlugin(pRequest) - require.Error(t, err) - CheckInternalErrorStatus(t, resp) - require.Nil(t, manifest) + t.Run("Should fail to install unknown prepackaged plugin", func(t *testing.T) { + pRequest := &model.InstallMarketplacePluginRequest{Id: "testpluginXX"} + manifest, resp, err := client.InstallMarketplacePlugin(pRequest) + require.Error(t, err) + CheckInternalErrorStatus(t, resp) + require.Nil(t, manifest) - plugins := env.PrepackagedPlugins() - require.Len(t, plugins, 1) - require.Equal(t, "testplugin", plugins[0].Manifest.Id) - require.Equal(t, pluginSignatureData, plugins[0].Signature) + plugins := env.PrepackagedPlugins() + require.Len(t, plugins, 1) + require.Equal(t, "testplugin", plugins[0].Manifest.Id) + require.Equal(t, pluginSignatureData, plugins[0].Signature) - pluginsResp, _, err = client.GetPlugins() - require.NoError(t, err) - require.Len(t, pluginsResp.Active, 0) - require.Len(t, pluginsResp.Inactive, 0) + pluginsResp, _, err = client.GetPlugins() + require.NoError(t, err) + require.Len(t, pluginsResp.Active, 0) + require.Len(t, pluginsResp.Inactive, 0) + }) - pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin"} - manifest1, _, err := client.InstallMarketplacePlugin(pRequest) - require.NoError(t, err) - require.NotNil(t, manifest1) - require.Equal(t, "testplugin", manifest1.Id) - require.Equal(t, "0.0.1", manifest1.Version) + t.Run("Install prepackaged plugin with Marketplace disabled", func(t *testing.T) { + pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"} + manifest, _, err := client.InstallMarketplacePlugin(pRequest) + require.NoError(t, err) + require.NotNil(t, manifest) + require.Equal(t, "testplugin", manifest.Id) + require.Equal(t, "0.0.1", manifest.Version) - pluginsResp, _, err = client.GetPlugins() - require.NoError(t, err) - require.Len(t, pluginsResp.Active, 0) - require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ - Manifest: *manifest1, - }}) + t.Cleanup(func() { + _, err = client.RemovePlugin(manifest.Id) + require.NoError(t, err) + }) - // Try to install remote marketplace plugin - pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2"} - manifest, resp, err = client.InstallMarketplacePlugin(pRequest) - require.Error(t, err) - CheckInternalErrorStatus(t, resp) - require.Nil(t, manifest) + pluginsResp, _, err = client.GetPlugins() + require.NoError(t, err) + require.Len(t, pluginsResp.Active, 0) + require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ + Manifest: *manifest, + }}) + }) + + t.Run("Try to install remote marketplace plugin while Marketplace is disabled", func(t *testing.T) { + pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin2"} + manifest, resp, err := client.InstallMarketplacePlugin(pRequest) + require.Error(t, err) + CheckInternalErrorStatus(t, resp) + require.Nil(t, manifest) + }) // Enable remote marketplace th.App.UpdateConfig(func(cfg *model.Config) { @@ -1794,31 +1815,58 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) { *cfg.PluginSettings.AllowInsecureDownloadURL = true }) - pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2"} - manifest2, _, err := client.InstallMarketplacePlugin(pRequest) - require.NoError(t, err) - require.NotNil(t, manifest2) - require.Equal(t, "testplugin2", manifest2.Id) - require.Equal(t, "1.2.3", manifest2.Version) + t.Run("Install prepackaged, not listed plugin with Marketplace enabled", func(t *testing.T) { + pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"} + manifest, _, err := client.InstallMarketplacePlugin(pRequest) + require.NoError(t, err) - pluginsResp, _, err = client.GetPlugins() - require.NoError(t, err) - require.Len(t, pluginsResp.Active, 0) - require.ElementsMatch(t, pluginsResp.Inactive, []*model.PluginInfo{ - { - Manifest: *manifest1, - }, - { - Manifest: *manifest2, - }, + t.Cleanup(func() { + _, err = client.RemovePlugin(manifest.Id) + require.NoError(t, err) + }) + + require.NotNil(t, manifest) + assert.Equal(t, "testplugin", manifest.Id) + assert.Equal(t, "0.0.1", manifest.Version) }) - // Clean up - _, err = client.RemovePlugin(manifest1.Id) - require.NoError(t, err) + t.Run("Install both a prepacked and a Marketplace plugin", func(t *testing.T) { + pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"} + manifest1, _, err := client.InstallMarketplacePlugin(pRequest) + require.NoError(t, err) + require.NotNil(t, manifest1) + assert.Equal(t, "testplugin", manifest1.Id) + assert.Equal(t, "0.0.1", manifest1.Version) - _, err = client.RemovePlugin(manifest2.Id) - require.NoError(t, err) + t.Cleanup(func() { + _, err = client.RemovePlugin(manifest1.Id) + require.NoError(t, err) + }) + + pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2"} + manifest2, _, err := client.InstallMarketplacePlugin(pRequest) + require.NoError(t, err) + require.NotNil(t, manifest2) + require.Equal(t, "testplugin2", manifest2.Id) + require.Equal(t, "1.2.3", manifest2.Version) + + t.Cleanup(func() { + _, err = client.RemovePlugin(manifest2.Id) + require.NoError(t, err) + }) + + pluginsResp, _, err = client.GetPlugins() + require.NoError(t, err) + require.Len(t, pluginsResp.Active, 0) + require.ElementsMatch(t, pluginsResp.Inactive, []*model.PluginInfo{ + { + Manifest: *manifest1, + }, + { + Manifest: *manifest2, + }, + }) + }) appErr = th.App.DeletePublicKey("pub_key") require.Nil(t, appErr) diff --git a/server/channels/app/plugin_install.go b/server/channels/app/plugin_install.go index de40c6838a..59ae9be613 100644 --- a/server/channels/app/plugin_install.go +++ b/server/channels/app/plugin_install.go @@ -203,35 +203,38 @@ func (ch *Channels) InstallMarketplacePlugin(request *model.InstallMarketplacePl if *ch.cfgSvc.Config().PluginSettings.EnableRemoteMarketplace { var plugin *model.BaseMarketplacePlugin plugin, appErr = ch.getRemoteMarketplacePlugin(request.Id, request.Version) - if appErr != nil { - return nil, appErr + // The plugin might only be prepackaged and not on the Marketplace. + if appErr != nil && appErr.Id != "app.plugin.marketplace_plugins.not_found.app_error" { + mlog.Warn("Failed to reach Marketplace to install plugin", mlog.String("plugin_id", request.Id), mlog.Err(appErr)) } - var prepackagedVersion semver.Version - if prepackagedPlugin != nil { - var err error - prepackagedVersion, err = semver.Parse(prepackagedPlugin.Manifest.Version) - if err != nil { - return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) + if plugin != nil { + var prepackagedVersion semver.Version + if prepackagedPlugin != nil { + var err error + prepackagedVersion, err = semver.Parse(prepackagedPlugin.Manifest.Version) + if err != nil { + return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) + } } - } - marketplaceVersion, err := semver.Parse(plugin.Manifest.Version) - if err != nil { - return nil, model.NewAppError("InstallMarketplacePlugin", "app.prepackged-plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) - } + marketplaceVersion, err := semver.Parse(plugin.Manifest.Version) + if err != nil { + return nil, model.NewAppError("InstallMarketplacePlugin", "app.prepackged-plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) + } - if prepackagedVersion.LT(marketplaceVersion) { // Always true if no prepackaged plugin was found - downloadedPluginBytes, err := ch.srv.downloadFromURL(plugin.DownloadURL) - if err != nil { - return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.install_marketplace_plugin.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + if prepackagedVersion.LT(marketplaceVersion) { // Always true if no prepackaged plugin was found + downloadedPluginBytes, err := ch.srv.downloadFromURL(plugin.DownloadURL) + if err != nil { + return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.install_marketplace_plugin.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + signature, err := plugin.DecodeSignature() + if err != nil { + return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.signature_decode.app_error", nil, "", http.StatusNotImplemented).Wrap(err) + } + pluginFile = bytes.NewReader(downloadedPluginBytes) + signatureFile = signature } - signature, err := plugin.DecodeSignature() - if err != nil { - return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.signature_decode.app_error", nil, "", http.StatusNotImplemented).Wrap(err) - } - pluginFile = bytes.NewReader(downloadedPluginBytes) - signatureFile = signature } }