[MM-45296] Fix installation of pre-packaged plugins that are not in the Marketplace (#21895)

Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
This commit is contained in:
Ben Schumacher 2023-04-25 00:02:51 +02:00 committed by GitHub
parent a52a6d9abd
commit e8915b3182
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 78 deletions

View File

@ -1722,14 +1722,26 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) {
appErr := th.App.AddPublicKey("pub_key", key) appErr := th.App.AddPublicKey("pub_key", key)
require.Nil(t, appErr) 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) { testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
serverVersion := req.URL.Query().Get("server_version") serverVersion := req.URL.Query().Get("server_version")
require.NotEmpty(t, serverVersion) require.NotEmpty(t, serverVersion)
require.Equal(t, model.CurrentVersion, serverVersion) require.Equal(t, model.CurrentVersion, serverVersion)
res.WriteHeader(http.StatusOK) res.WriteHeader(http.StatusOK)
var out []byte 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) res.Write(out)
})) }))
defer testServer.Close() defer testServer.Close()
@ -1748,43 +1760,52 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) {
require.Len(t, pluginsResp.Active, 0) require.Len(t, pluginsResp.Active, 0)
require.Len(t, pluginsResp.Inactive, 0) require.Len(t, pluginsResp.Inactive, 0)
// Should fail to install unknown prepackaged plugin t.Run("Should fail to install unknown prepackaged plugin", func(t *testing.T) {
pRequest := &model.InstallMarketplacePluginRequest{Id: "testpluginXX"} pRequest := &model.InstallMarketplacePluginRequest{Id: "testpluginXX"}
manifest, resp, err := client.InstallMarketplacePlugin(pRequest) manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
require.Error(t, err) require.Error(t, err)
CheckInternalErrorStatus(t, resp) CheckInternalErrorStatus(t, resp)
require.Nil(t, manifest) require.Nil(t, manifest)
plugins := env.PrepackagedPlugins() plugins := env.PrepackagedPlugins()
require.Len(t, plugins, 1) require.Len(t, plugins, 1)
require.Equal(t, "testplugin", plugins[0].Manifest.Id) require.Equal(t, "testplugin", plugins[0].Manifest.Id)
require.Equal(t, pluginSignatureData, plugins[0].Signature) require.Equal(t, pluginSignatureData, plugins[0].Signature)
pluginsResp, _, err = client.GetPlugins() pluginsResp, _, err = client.GetPlugins()
require.NoError(t, err) require.NoError(t, err)
require.Len(t, pluginsResp.Active, 0) require.Len(t, pluginsResp.Active, 0)
require.Len(t, pluginsResp.Inactive, 0) require.Len(t, pluginsResp.Inactive, 0)
})
pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin"} t.Run("Install prepackaged plugin with Marketplace disabled", func(t *testing.T) {
manifest1, _, err := client.InstallMarketplacePlugin(pRequest) pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
require.NoError(t, err) manifest, _, err := client.InstallMarketplacePlugin(pRequest)
require.NotNil(t, manifest1) require.NoError(t, err)
require.Equal(t, "testplugin", manifest1.Id) require.NotNil(t, manifest)
require.Equal(t, "0.0.1", manifest1.Version) require.Equal(t, "testplugin", manifest.Id)
require.Equal(t, "0.0.1", manifest.Version)
pluginsResp, _, err = client.GetPlugins() t.Cleanup(func() {
require.NoError(t, err) _, err = client.RemovePlugin(manifest.Id)
require.Len(t, pluginsResp.Active, 0) require.NoError(t, err)
require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ })
Manifest: *manifest1,
}})
// Try to install remote marketplace plugin pluginsResp, _, err = client.GetPlugins()
pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2"} require.NoError(t, err)
manifest, resp, err = client.InstallMarketplacePlugin(pRequest) require.Len(t, pluginsResp.Active, 0)
require.Error(t, err) require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{
CheckInternalErrorStatus(t, resp) Manifest: *manifest,
require.Nil(t, 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 // Enable remote marketplace
th.App.UpdateConfig(func(cfg *model.Config) { th.App.UpdateConfig(func(cfg *model.Config) {
@ -1794,31 +1815,58 @@ func TestInstallMarketplacePluginPrepackagedDisabled(t *testing.T) {
*cfg.PluginSettings.AllowInsecureDownloadURL = true *cfg.PluginSettings.AllowInsecureDownloadURL = true
}) })
pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2"} t.Run("Install prepackaged, not listed plugin with Marketplace enabled", func(t *testing.T) {
manifest2, _, err := client.InstallMarketplacePlugin(pRequest) pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
require.NoError(t, err) manifest, _, err := client.InstallMarketplacePlugin(pRequest)
require.NotNil(t, manifest2) require.NoError(t, err)
require.Equal(t, "testplugin2", manifest2.Id)
require.Equal(t, "1.2.3", manifest2.Version)
pluginsResp, _, err = client.GetPlugins() t.Cleanup(func() {
require.NoError(t, err) _, err = client.RemovePlugin(manifest.Id)
require.Len(t, pluginsResp.Active, 0) require.NoError(t, err)
require.ElementsMatch(t, pluginsResp.Inactive, []*model.PluginInfo{ })
{
Manifest: *manifest1, require.NotNil(t, manifest)
}, assert.Equal(t, "testplugin", manifest.Id)
{ assert.Equal(t, "0.0.1", manifest.Version)
Manifest: *manifest2,
},
}) })
// Clean up t.Run("Install both a prepacked and a Marketplace plugin", func(t *testing.T) {
_, err = client.RemovePlugin(manifest1.Id) pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
require.NoError(t, err) 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) t.Cleanup(func() {
require.NoError(t, err) _, 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") appErr = th.App.DeletePublicKey("pub_key")
require.Nil(t, appErr) require.Nil(t, appErr)

View File

@ -203,35 +203,38 @@ func (ch *Channels) InstallMarketplacePlugin(request *model.InstallMarketplacePl
if *ch.cfgSvc.Config().PluginSettings.EnableRemoteMarketplace { if *ch.cfgSvc.Config().PluginSettings.EnableRemoteMarketplace {
var plugin *model.BaseMarketplacePlugin var plugin *model.BaseMarketplacePlugin
plugin, appErr = ch.getRemoteMarketplacePlugin(request.Id, request.Version) plugin, appErr = ch.getRemoteMarketplacePlugin(request.Id, request.Version)
if appErr != nil { // The plugin might only be prepackaged and not on the Marketplace.
return nil, appErr 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 plugin != nil {
if prepackagedPlugin != nil { var prepackagedVersion semver.Version
var err error if prepackagedPlugin != nil {
prepackagedVersion, err = semver.Parse(prepackagedPlugin.Manifest.Version) var err error
if err != nil { prepackagedVersion, err = semver.Parse(prepackagedPlugin.Manifest.Version)
return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) 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) marketplaceVersion, err := semver.Parse(plugin.Manifest.Version)
if err != nil { if err != nil {
return nil, model.NewAppError("InstallMarketplacePlugin", "app.prepackged-plugin.invalid_version.app_error", nil, "", http.StatusBadRequest).Wrap(err) 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 if prepackagedVersion.LT(marketplaceVersion) { // Always true if no prepackaged plugin was found
downloadedPluginBytes, err := ch.srv.downloadFromURL(plugin.DownloadURL) downloadedPluginBytes, err := ch.srv.downloadFromURL(plugin.DownloadURL)
if err != nil { if err != nil {
return nil, model.NewAppError("InstallMarketplacePlugin", "app.plugin.install_marketplace_plugin.app_error", nil, "", http.StatusInternalServerError).Wrap(err) 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
} }
} }