github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/plugin_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "encoding/base64" 9 "encoding/json" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "net/http/httptest" 14 "os" 15 "path/filepath" 16 "sort" 17 "strings" 18 "testing" 19 "time" 20 21 svg "github.com/h2non/go-is-svg" 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 25 "github.com/masterhung0112/hk_server/v5/model" 26 "github.com/masterhung0112/hk_server/v5/plugin" 27 "github.com/masterhung0112/hk_server/v5/testlib" 28 "github.com/masterhung0112/hk_server/v5/utils/fileutils" 29 ) 30 31 func TestPlugin(t *testing.T) { 32 th := Setup(t) 33 defer th.TearDown() 34 35 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 36 statesJson, err := json.Marshal(th.App.Config().PluginSettings.PluginStates) 37 require.NoError(t, err) 38 states := map[string]*model.PluginState{} 39 json.Unmarshal(statesJson, &states) 40 th.App.UpdateConfig(func(cfg *model.Config) { 41 *cfg.PluginSettings.Enable = true 42 *cfg.PluginSettings.EnableUploads = true 43 *cfg.PluginSettings.AllowInsecureDownloadUrl = true 44 }) 45 46 path, _ := fileutils.FindDir("tests") 47 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 48 require.NoError(t, err) 49 50 // Install from URL 51 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 52 res.WriteHeader(http.StatusOK) 53 res.Write(tarData) 54 })) 55 defer func() { testServer.Close() }() 56 57 url := testServer.URL 58 59 manifest, resp := client.InstallPluginFromUrl(url, false) 60 CheckNoError(t, resp) 61 assert.Equal(t, "testplugin", manifest.Id) 62 63 _, resp = client.InstallPluginFromUrl(url, false) 64 CheckBadRequestStatus(t, resp) 65 66 manifest, resp = client.InstallPluginFromUrl(url, true) 67 CheckNoError(t, resp) 68 assert.Equal(t, "testplugin", manifest.Id) 69 70 // Stored in File Store: Install Plugin from URL case 71 pluginStored, appErr := th.App.FileExists("./plugins/" + manifest.Id + ".tar.gz") 72 assert.Nil(t, appErr) 73 assert.True(t, pluginStored) 74 75 ok, resp := client.RemovePlugin(manifest.Id) 76 CheckNoError(t, resp) 77 require.True(t, ok) 78 79 t.Run("install plugin from URL with slow response time", func(t *testing.T) { 80 if testing.Short() { 81 t.Skip("skipping test to install plugin from a slow response server") 82 } 83 84 // Install from URL - slow server to simulate longer bundle download times 85 slowTestServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 86 time.Sleep(60 * time.Second) // Wait longer than the previous default 30 seconds timeout 87 res.WriteHeader(http.StatusOK) 88 res.Write(tarData) 89 })) 90 defer func() { slowTestServer.Close() }() 91 92 manifest, resp = client.InstallPluginFromUrl(slowTestServer.URL, true) 93 CheckNoError(t, resp) 94 assert.Equal(t, "testplugin", manifest.Id) 95 }) 96 97 th.App.RemovePlugin(manifest.Id) 98 99 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) 100 101 _, resp = client.InstallPluginFromUrl(url, false) 102 CheckNotImplementedStatus(t, resp) 103 104 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) 105 106 _, resp = th.Client.InstallPluginFromUrl(url, false) 107 CheckForbiddenStatus(t, resp) 108 109 _, resp = client.InstallPluginFromUrl("http://nodata", false) 110 CheckBadRequestStatus(t, resp) 111 112 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.AllowInsecureDownloadUrl = false }) 113 114 _, resp = client.InstallPluginFromUrl(url, false) 115 CheckBadRequestStatus(t, resp) 116 117 // Successful upload 118 manifest, resp = client.UploadPlugin(bytes.NewReader(tarData)) 119 CheckNoError(t, resp) 120 121 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.EnableUploads = true }) 122 123 manifest, resp = client.UploadPluginForced(bytes.NewReader(tarData)) 124 defer os.RemoveAll("plugins/testplugin") 125 CheckNoError(t, resp) 126 127 assert.Equal(t, "testplugin", manifest.Id) 128 129 // Stored in File Store: Upload Plugin case 130 pluginStored, appErr = th.App.FileExists("./plugins/" + manifest.Id + ".tar.gz") 131 assert.Nil(t, appErr) 132 assert.True(t, pluginStored) 133 134 // Upload error cases 135 _, resp = client.UploadPlugin(bytes.NewReader([]byte("badfile"))) 136 CheckBadRequestStatus(t, resp) 137 138 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) 139 _, resp = client.UploadPlugin(bytes.NewReader(tarData)) 140 CheckNotImplementedStatus(t, resp) 141 142 th.App.UpdateConfig(func(cfg *model.Config) { 143 *cfg.PluginSettings.Enable = true 144 *cfg.PluginSettings.EnableUploads = false 145 }) 146 _, resp = client.UploadPlugin(bytes.NewReader(tarData)) 147 CheckNotImplementedStatus(t, resp) 148 149 _, resp = client.InstallPluginFromUrl(url, false) 150 CheckNotImplementedStatus(t, resp) 151 152 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.EnableUploads = true }) 153 _, resp = th.Client.UploadPlugin(bytes.NewReader(tarData)) 154 CheckForbiddenStatus(t, resp) 155 156 // Successful gets 157 pluginsResp, resp := client.GetPlugins() 158 CheckNoError(t, resp) 159 160 found := false 161 for _, m := range pluginsResp.Inactive { 162 if m.Id == manifest.Id { 163 found = true 164 } 165 } 166 167 assert.True(t, found) 168 169 found = false 170 for _, m := range pluginsResp.Active { 171 if m.Id == manifest.Id { 172 found = true 173 } 174 } 175 176 assert.False(t, found) 177 178 // Successful activate 179 ok, resp = client.EnablePlugin(manifest.Id) 180 CheckNoError(t, resp) 181 assert.True(t, ok) 182 183 pluginsResp, resp = client.GetPlugins() 184 CheckNoError(t, resp) 185 186 found = false 187 for _, m := range pluginsResp.Active { 188 if m.Id == manifest.Id { 189 found = true 190 } 191 } 192 193 assert.True(t, found) 194 195 // Activate error case 196 ok, resp = client.EnablePlugin("junk") 197 CheckNotFoundStatus(t, resp) 198 assert.False(t, ok) 199 200 ok, resp = client.EnablePlugin("JUNK") 201 CheckNotFoundStatus(t, resp) 202 assert.False(t, ok) 203 204 // Successful deactivate 205 ok, resp = client.DisablePlugin(manifest.Id) 206 CheckNoError(t, resp) 207 assert.True(t, ok) 208 209 pluginsResp, resp = client.GetPlugins() 210 CheckNoError(t, resp) 211 212 found = false 213 for _, m := range pluginsResp.Inactive { 214 if m.Id == manifest.Id { 215 found = true 216 } 217 } 218 219 assert.True(t, found) 220 221 // Deactivate error case 222 ok, resp = client.DisablePlugin("junk") 223 CheckNotFoundStatus(t, resp) 224 assert.False(t, ok) 225 226 // Get error cases 227 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) 228 _, resp = client.GetPlugins() 229 CheckNotImplementedStatus(t, resp) 230 231 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) 232 _, resp = th.Client.GetPlugins() 233 CheckForbiddenStatus(t, resp) 234 235 // Successful webapp get 236 _, resp = client.EnablePlugin(manifest.Id) 237 CheckNoError(t, resp) 238 239 manifests, resp := th.Client.GetWebappPlugins() 240 CheckNoError(t, resp) 241 242 found = false 243 for _, m := range manifests { 244 if m.Id == manifest.Id { 245 found = true 246 } 247 } 248 249 assert.True(t, found) 250 251 // Successful remove 252 ok, resp = client.RemovePlugin(manifest.Id) 253 CheckNoError(t, resp) 254 assert.True(t, ok) 255 256 // Remove error cases 257 ok, resp = client.RemovePlugin(manifest.Id) 258 CheckNotFoundStatus(t, resp) 259 assert.False(t, ok) 260 261 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = false }) 262 _, resp = client.RemovePlugin(manifest.Id) 263 CheckNotImplementedStatus(t, resp) 264 265 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) 266 _, resp = th.Client.RemovePlugin(manifest.Id) 267 CheckForbiddenStatus(t, resp) 268 269 _, resp = client.RemovePlugin("bad.id") 270 CheckNotFoundStatus(t, resp) 271 }) 272 } 273 274 func TestNotifyClusterPluginEvent(t *testing.T) { 275 th := Setup(t) 276 defer th.TearDown() 277 278 testCluster := &testlib.FakeClusterInterface{} 279 th.Server.Cluster = testCluster 280 281 th.App.UpdateConfig(func(cfg *model.Config) { 282 *cfg.PluginSettings.Enable = true 283 *cfg.PluginSettings.EnableUploads = true 284 }) 285 286 path, _ := fileutils.FindDir("tests") 287 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 288 require.NoError(t, err) 289 290 testCluster.ClearMessages() 291 292 // Successful upload 293 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 294 CheckNoError(t, resp) 295 require.Equal(t, "testplugin", manifest.Id) 296 297 // Stored in File Store: Upload Plugin case 298 expectedPath := filepath.Join("./plugins", manifest.Id) + ".tar.gz" 299 pluginStored, appErr := th.App.FileExists(expectedPath) 300 require.Nil(t, appErr) 301 require.True(t, pluginStored) 302 303 messages := testCluster.GetMessages() 304 expectedPluginData := model.PluginEventData{ 305 Id: manifest.Id, 306 } 307 expectedInstallMessage := &model.ClusterMessage{ 308 Event: model.CLUSTER_EVENT_INSTALL_PLUGIN, 309 SendType: model.CLUSTER_SEND_RELIABLE, 310 WaitForAllToSend: true, 311 Data: expectedPluginData.ToJson(), 312 } 313 actualMessages := findClusterMessages(model.CLUSTER_EVENT_INSTALL_PLUGIN, messages) 314 require.Equal(t, []*model.ClusterMessage{expectedInstallMessage}, actualMessages) 315 316 // Upgrade 317 testCluster.ClearMessages() 318 manifest, resp = th.SystemAdminClient.UploadPluginForced(bytes.NewReader(tarData)) 319 CheckNoError(t, resp) 320 require.Equal(t, "testplugin", manifest.Id) 321 322 // Successful remove 323 webSocketClient, appErr := th.CreateWebSocketSystemAdminClient() 324 require.Nil(t, appErr) 325 webSocketClient.Listen() 326 defer webSocketClient.Close() 327 done := make(chan bool) 328 go func() { 329 for { 330 select { 331 case resp := <-webSocketClient.EventChannel: 332 if resp.EventType() == model.WEBSOCKET_EVENT_PLUGIN_STATUSES_CHANGED && len(resp.GetData()["plugin_statuses"].([]interface{})) == 0 { 333 done <- true 334 return 335 } 336 case <-time.After(5 * time.Second): 337 done <- false 338 return 339 } 340 } 341 }() 342 343 testCluster.ClearMessages() 344 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 345 CheckNoError(t, resp) 346 require.True(t, ok) 347 348 result := <-done 349 require.True(t, result, "plugin_statuses_changed websocket event was not received") 350 351 messages = testCluster.GetMessages() 352 353 expectedRemoveMessage := &model.ClusterMessage{ 354 Event: model.CLUSTER_EVENT_REMOVE_PLUGIN, 355 SendType: model.CLUSTER_SEND_RELIABLE, 356 WaitForAllToSend: true, 357 Data: expectedPluginData.ToJson(), 358 } 359 actualMessages = findClusterMessages(model.CLUSTER_EVENT_REMOVE_PLUGIN, messages) 360 require.Equal(t, []*model.ClusterMessage{expectedRemoveMessage}, actualMessages) 361 362 pluginStored, appErr = th.App.FileExists(expectedPath) 363 require.Nil(t, appErr) 364 require.False(t, pluginStored) 365 } 366 367 func TestDisableOnRemove(t *testing.T) { 368 path, _ := fileutils.FindDir("tests") 369 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 370 require.NoError(t, err) 371 372 testCases := []struct { 373 Description string 374 Upgrade bool 375 }{ 376 { 377 "Remove without upgrading", 378 false, 379 }, 380 { 381 "Remove after upgrading", 382 true, 383 }, 384 } 385 386 th := Setup(t).InitBasic() 387 defer th.TearDown() 388 389 for _, tc := range testCases { 390 t.Run(tc.Description, func(t *testing.T) { 391 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 392 th.App.UpdateConfig(func(cfg *model.Config) { 393 *cfg.PluginSettings.Enable = true 394 *cfg.PluginSettings.EnableUploads = true 395 }) 396 397 // Upload 398 manifest, resp := client.UploadPlugin(bytes.NewReader(tarData)) 399 CheckNoError(t, resp) 400 require.Equal(t, "testplugin", manifest.Id) 401 402 // Check initial status 403 pluginsResp, resp := client.GetPlugins() 404 CheckNoError(t, resp) 405 require.Empty(t, pluginsResp.Active) 406 require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ 407 Manifest: *manifest, 408 }}) 409 410 // Enable plugin 411 ok, resp := client.EnablePlugin(manifest.Id) 412 CheckNoError(t, resp) 413 require.True(t, ok) 414 415 // Confirm enabled status 416 pluginsResp, resp = client.GetPlugins() 417 CheckNoError(t, resp) 418 require.Empty(t, pluginsResp.Inactive) 419 require.Equal(t, pluginsResp.Active, []*model.PluginInfo{{ 420 Manifest: *manifest, 421 }}) 422 423 if tc.Upgrade { 424 // Upgrade 425 manifest, resp = client.UploadPluginForced(bytes.NewReader(tarData)) 426 CheckNoError(t, resp) 427 require.Equal(t, "testplugin", manifest.Id) 428 429 // Plugin should remain active 430 pluginsResp, resp = client.GetPlugins() 431 CheckNoError(t, resp) 432 require.Empty(t, pluginsResp.Inactive) 433 require.Equal(t, pluginsResp.Active, []*model.PluginInfo{{ 434 Manifest: *manifest, 435 }}) 436 } 437 438 // Remove plugin 439 ok, resp = client.RemovePlugin(manifest.Id) 440 CheckNoError(t, resp) 441 require.True(t, ok) 442 443 // Plugin should have no status 444 pluginsResp, resp = client.GetPlugins() 445 CheckNoError(t, resp) 446 require.Empty(t, pluginsResp.Inactive) 447 require.Empty(t, pluginsResp.Active) 448 449 // Upload same plugin 450 manifest, resp = client.UploadPlugin(bytes.NewReader(tarData)) 451 CheckNoError(t, resp) 452 require.Equal(t, "testplugin", manifest.Id) 453 454 // Plugin should be inactive 455 pluginsResp, resp = client.GetPlugins() 456 CheckNoError(t, resp) 457 require.Empty(t, pluginsResp.Active) 458 require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ 459 Manifest: *manifest, 460 }}) 461 462 // Clean up 463 ok, resp = client.RemovePlugin(manifest.Id) 464 CheckNoError(t, resp) 465 require.True(t, ok) 466 }) 467 }) 468 } 469 } 470 471 func TestGetMarketplacePlugins(t *testing.T) { 472 th := Setup(t) 473 defer th.TearDown() 474 475 th.App.UpdateConfig(func(cfg *model.Config) { 476 *cfg.PluginSettings.Enable = true 477 *cfg.PluginSettings.EnableUploads = true 478 *cfg.PluginSettings.EnableMarketplace = false 479 }) 480 481 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 482 th.App.UpdateConfig(func(cfg *model.Config) { 483 *cfg.PluginSettings.EnableMarketplace = false 484 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 485 }) 486 487 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 488 CheckNotImplementedStatus(t, resp) 489 require.Nil(t, plugins) 490 }, "marketplace disabled") 491 492 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 493 th.App.UpdateConfig(func(cfg *model.Config) { 494 *cfg.PluginSettings.EnableMarketplace = true 495 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 496 }) 497 498 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 499 CheckInternalErrorStatus(t, resp) 500 require.Nil(t, plugins) 501 }, "no server") 502 503 t.Run("no permission", func(t *testing.T) { 504 th.App.UpdateConfig(func(cfg *model.Config) { 505 *cfg.PluginSettings.EnableMarketplace = true 506 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 507 }) 508 509 plugins, resp := th.Client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 510 CheckForbiddenStatus(t, resp) 511 require.Nil(t, plugins) 512 }) 513 514 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 515 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 516 res.WriteHeader(http.StatusOK) 517 json, err := json.Marshal([]*model.MarketplacePlugin{}) 518 require.NoError(t, err) 519 res.Write(json) 520 })) 521 defer func() { testServer.Close() }() 522 523 th.App.UpdateConfig(func(cfg *model.Config) { 524 *cfg.PluginSettings.EnableMarketplace = true 525 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 526 }) 527 528 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 529 CheckNoError(t, resp) 530 require.Empty(t, plugins) 531 }, "empty response from server") 532 533 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 534 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 535 serverVersion, ok := req.URL.Query()["server_version"] 536 require.True(t, ok) 537 require.Len(t, serverVersion, 1) 538 require.Equal(t, model.CurrentVersion, serverVersion[0]) 539 require.NotEqual(t, 0, len(serverVersion[0])) 540 541 res.WriteHeader(http.StatusOK) 542 json, err := json.Marshal([]*model.MarketplacePlugin{}) 543 require.NoError(t, err) 544 res.Write(json) 545 })) 546 defer func() { testServer.Close() }() 547 548 th.App.UpdateConfig(func(cfg *model.Config) { 549 *cfg.PluginSettings.EnableMarketplace = true 550 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 551 }) 552 553 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 554 CheckNoError(t, resp) 555 require.Empty(t, plugins) 556 }, "verify server version is passed through") 557 558 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 559 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 560 licenseType, ok := req.URL.Query()["enterprise_plugins"] 561 require.True(t, ok) 562 require.Len(t, licenseType, 1) 563 require.Equal(t, "false", licenseType[0]) 564 565 res.WriteHeader(http.StatusOK) 566 json, err := json.Marshal([]*model.MarketplacePlugin{}) 567 require.NoError(t, err) 568 res.Write(json) 569 })) 570 defer func() { testServer.Close() }() 571 572 th.App.UpdateConfig(func(cfg *model.Config) { 573 *cfg.PluginSettings.EnableMarketplace = true 574 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 575 }) 576 577 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 578 CheckNoError(t, resp) 579 require.Empty(t, plugins) 580 }, "verify EnterprisePlugins is false for TE") 581 582 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 583 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 584 licenseType, ok := req.URL.Query()["enterprise_plugins"] 585 require.True(t, ok) 586 require.Len(t, licenseType, 1) 587 require.Equal(t, "false", licenseType[0]) 588 589 res.WriteHeader(http.StatusOK) 590 json, err := json.Marshal([]*model.MarketplacePlugin{}) 591 require.NoError(t, err) 592 res.Write(json) 593 })) 594 defer func() { testServer.Close() }() 595 596 th.App.UpdateConfig(func(cfg *model.Config) { 597 *cfg.PluginSettings.EnableMarketplace = true 598 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 599 }) 600 601 l := model.NewTestLicense() 602 // model.NewTestLicense generates a E20 license 603 *l.Features.EnterprisePlugins = false 604 th.App.Srv().SetLicense(l) 605 606 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 607 CheckNoError(t, resp) 608 require.Empty(t, plugins) 609 }, "verify EnterprisePlugins is false for E10") 610 611 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 612 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 613 licenseType, ok := req.URL.Query()["enterprise_plugins"] 614 require.True(t, ok) 615 require.Len(t, licenseType, 1) 616 require.Equal(t, "true", licenseType[0]) 617 618 res.WriteHeader(http.StatusOK) 619 json, err := json.Marshal([]*model.MarketplacePlugin{}) 620 require.NoError(t, err) 621 res.Write(json) 622 })) 623 defer func() { testServer.Close() }() 624 625 th.App.UpdateConfig(func(cfg *model.Config) { 626 *cfg.PluginSettings.EnableMarketplace = true 627 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 628 }) 629 630 th.App.Srv().SetLicense(model.NewTestLicense("enterprise_plugins")) 631 632 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 633 CheckNoError(t, resp) 634 require.Empty(t, plugins) 635 }, "verify EnterprisePlugins is true for E20") 636 637 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 638 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 639 cloud, ok := req.URL.Query()["cloud"] 640 require.True(t, ok) 641 require.Len(t, cloud, 1) 642 require.Equal(t, "false", cloud[0]) 643 644 res.WriteHeader(http.StatusOK) 645 json, err := json.Marshal([]*model.MarketplacePlugin{}) 646 require.NoError(t, err) 647 res.Write(json) 648 })) 649 defer func() { testServer.Close() }() 650 651 th.App.UpdateConfig(func(cfg *model.Config) { 652 *cfg.PluginSettings.EnableMarketplace = true 653 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 654 }) 655 656 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 657 CheckNoError(t, resp) 658 require.Empty(t, plugins) 659 }, "verify EnterprisePlugins is false if there is no license") 660 661 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 662 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 663 cloud, ok := req.URL.Query()["cloud"] 664 require.True(t, ok) 665 require.Len(t, cloud, 1) 666 require.Equal(t, "true", cloud[0]) 667 668 res.WriteHeader(http.StatusOK) 669 json, err := json.Marshal([]*model.MarketplacePlugin{}) 670 require.NoError(t, err) 671 res.Write(json) 672 })) 673 defer func() { testServer.Close() }() 674 675 th.App.UpdateConfig(func(cfg *model.Config) { 676 *cfg.PluginSettings.EnableMarketplace = true 677 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 678 }) 679 680 th.App.Srv().SetLicense(model.NewTestLicense("cloud")) 681 682 plugins, resp := client.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 683 CheckNoError(t, resp) 684 require.Empty(t, plugins) 685 }, "verify Cloud is true for cloud license") 686 } 687 688 func TestGetInstalledMarketplacePlugins(t *testing.T) { 689 samplePlugins := []*model.MarketplacePlugin{ 690 { 691 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 692 HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps", 693 IconData: "https://example.com/icon.svg", 694 DownloadURL: "https://example.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.4/com.mattermost.nps-1.0.4.tar.gz", 695 Labels: []model.MarketplaceLabel{ 696 { 697 Name: "someName", 698 Description: "some Description", 699 }, 700 }, 701 Manifest: &model.Manifest{ 702 Id: "com.mattermost.nps", 703 Name: "User Satisfaction Surveys", 704 Description: "This plugin sends quarterly user satisfaction surveys to gather feedback and help improve Mattermost.", 705 Version: "1.0.4", 706 MinServerVersion: "5.14.0", 707 }, 708 }, 709 InstalledVersion: "", 710 }, 711 } 712 713 path, _ := fileutils.FindDir("tests") 714 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 715 require.NoError(t, err) 716 717 t.Run("marketplace client returns not-installed plugin", func(t *testing.T) { 718 th := Setup(t) 719 defer th.TearDown() 720 721 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 722 res.WriteHeader(http.StatusOK) 723 json, err := json.Marshal(samplePlugins) 724 require.NoError(t, err) 725 res.Write(json) 726 })) 727 defer func() { testServer.Close() }() 728 729 th.App.UpdateConfig(func(cfg *model.Config) { 730 *cfg.PluginSettings.Enable = true 731 *cfg.PluginSettings.EnableUploads = true 732 *cfg.PluginSettings.EnableMarketplace = true 733 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 734 }) 735 736 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 737 CheckNoError(t, resp) 738 require.Equal(t, samplePlugins, plugins) 739 740 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 741 CheckNoError(t, resp) 742 743 testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) 744 require.NoError(t, err) 745 require.True(t, svg.Is(testIcon)) 746 testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) 747 748 expectedPlugins := append(samplePlugins, &model.MarketplacePlugin{ 749 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 750 HomepageURL: "https://example.com/homepage", 751 IconData: testIconData, 752 DownloadURL: "", 753 ReleaseNotesURL: "https://example.com/releases/v0.0.1", 754 Labels: []model.MarketplaceLabel{{ 755 Name: "Local", 756 Description: "This plugin is not listed in the marketplace", 757 }}, 758 Manifest: manifest, 759 }, 760 InstalledVersion: manifest.Version, 761 }) 762 sort.SliceStable(expectedPlugins, func(i, j int) bool { 763 return strings.ToLower(expectedPlugins[i].Manifest.Name) < strings.ToLower(expectedPlugins[j].Manifest.Name) 764 }) 765 766 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 767 CheckNoError(t, resp) 768 require.Equal(t, expectedPlugins, plugins) 769 770 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 771 CheckNoError(t, resp) 772 assert.True(t, ok) 773 774 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 775 CheckNoError(t, resp) 776 require.Equal(t, samplePlugins, plugins) 777 }) 778 779 t.Run("marketplace client returns installed plugin", func(t *testing.T) { 780 th := Setup(t) 781 defer th.TearDown() 782 783 th.App.UpdateConfig(func(cfg *model.Config) { 784 *cfg.PluginSettings.Enable = true 785 *cfg.PluginSettings.EnableUploads = true 786 *cfg.PluginSettings.EnableMarketplace = true 787 }) 788 789 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 790 CheckNoError(t, resp) 791 792 newPlugin := &model.MarketplacePlugin{ 793 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 794 HomepageURL: "HomepageURL", 795 IconData: "IconData", 796 DownloadURL: "DownloadURL", 797 Manifest: manifest, 798 }, 799 InstalledVersion: manifest.Version, 800 } 801 expectedPlugins := append(samplePlugins, newPlugin) 802 sort.SliceStable(expectedPlugins, func(i, j int) bool { 803 return strings.ToLower(expectedPlugins[i].Manifest.Name) < strings.ToLower(expectedPlugins[j].Manifest.Name) 804 }) 805 806 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 807 res.WriteHeader(http.StatusOK) 808 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[0], newPlugin}) 809 require.NoError(t, err) 810 res.Write(json) 811 })) 812 defer func() { testServer.Close() }() 813 th.App.UpdateConfig(func(cfg *model.Config) { 814 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 815 }) 816 817 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 818 CheckNoError(t, resp) 819 require.Equal(t, expectedPlugins, plugins) 820 821 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 822 CheckNoError(t, resp) 823 assert.True(t, ok) 824 825 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 826 CheckNoError(t, resp) 827 newPlugin.InstalledVersion = "" 828 require.Equal(t, expectedPlugins, plugins) 829 }) 830 } 831 832 func TestSearchGetMarketplacePlugins(t *testing.T) { 833 samplePlugins := []*model.MarketplacePlugin{ 834 { 835 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 836 HomepageURL: "example.com/mattermost/mattermost-plugin-nps", 837 IconData: "Cjxzdmcgdmlld0JveD0nMCAwIDEwNSA5MycgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz4KPHBhdGggZD0nTTY2LDBoMzl2OTN6TTM4LDBoLTM4djkzek01MiwzNWwyNSw1OGgtMTZsLTgtMThoLTE4eicgZmlsbD0nI0VEMUMyNCcvPgo8L3N2Zz4K", 838 DownloadURL: "example.com/mattermost/mattermost-plugin-nps/releases/download/v1.0.4/com.mattermost.nps-1.0.4.tar.gz", 839 Manifest: &model.Manifest{ 840 Id: "com.mattermost.nps", 841 Name: "User Satisfaction Surveys", 842 Description: "This plugin sends quarterly user satisfaction surveys to gather feedback and help improve Mattermost.", 843 Version: "1.0.4", 844 MinServerVersion: "5.14.0", 845 }, 846 }, 847 InstalledVersion: "", 848 }, 849 } 850 851 path, _ := fileutils.FindDir("tests") 852 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 853 require.NoError(t, err) 854 855 tarDataV2, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) 856 require.NoError(t, err) 857 858 testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) 859 require.NoError(t, err) 860 require.True(t, svg.Is(testIcon)) 861 testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) 862 863 t.Run("search installed plugin", func(t *testing.T) { 864 th := Setup(t).InitBasic() 865 defer th.TearDown() 866 867 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 868 res.WriteHeader(http.StatusOK) 869 json, err := json.Marshal(samplePlugins) 870 require.NoError(t, err) 871 res.Write(json) 872 })) 873 defer func() { testServer.Close() }() 874 875 th.App.UpdateConfig(func(cfg *model.Config) { 876 *cfg.PluginSettings.Enable = true 877 *cfg.PluginSettings.EnableUploads = true 878 *cfg.PluginSettings.EnableMarketplace = true 879 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 880 }) 881 882 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 883 CheckNoError(t, resp) 884 require.Equal(t, samplePlugins, plugins) 885 886 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 887 CheckNoError(t, resp) 888 889 plugin1 := &model.MarketplacePlugin{ 890 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 891 HomepageURL: "https://example.com/homepage", 892 IconData: testIconData, 893 DownloadURL: "", 894 ReleaseNotesURL: "https://example.com/releases/v0.0.1", 895 Labels: []model.MarketplaceLabel{{ 896 Name: "Local", 897 Description: "This plugin is not listed in the marketplace", 898 }}, 899 Manifest: manifest, 900 }, 901 InstalledVersion: manifest.Version, 902 } 903 expectedPlugins := append(samplePlugins, plugin1) 904 905 manifest, resp = th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarDataV2)) 906 CheckNoError(t, resp) 907 908 plugin2 := &model.MarketplacePlugin{ 909 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 910 IconData: testIconData, 911 HomepageURL: "https://example.com/homepage", 912 DownloadURL: "", 913 ReleaseNotesURL: "https://example.com/releases/v1.2.3", 914 Labels: []model.MarketplaceLabel{{ 915 Name: "Local", 916 Description: "This plugin is not listed in the marketplace", 917 }}, 918 Manifest: manifest, 919 }, 920 InstalledVersion: manifest.Version, 921 } 922 expectedPlugins = append(expectedPlugins, plugin2) 923 sort.SliceStable(expectedPlugins, func(i, j int) bool { 924 return strings.ToLower(expectedPlugins[i].Manifest.Name) < strings.ToLower(expectedPlugins[j].Manifest.Name) 925 }) 926 927 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 928 CheckNoError(t, resp) 929 require.Equal(t, expectedPlugins, plugins) 930 931 // Search for plugins from the server 932 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{Filter: "testplugin2"}) 933 CheckNoError(t, resp) 934 require.Equal(t, []*model.MarketplacePlugin{plugin2}, plugins) 935 936 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{Filter: "a second plugin"}) 937 CheckNoError(t, resp) 938 require.Equal(t, []*model.MarketplacePlugin{plugin2}, plugins) 939 940 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{Filter: "User Satisfaction Surveys"}) 941 CheckNoError(t, resp) 942 require.Equal(t, samplePlugins, plugins) 943 944 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{Filter: "NOFILTER"}) 945 CheckNoError(t, resp) 946 require.Nil(t, plugins) 947 948 // cleanup 949 ok, resp := th.SystemAdminClient.RemovePlugin(plugin1.Manifest.Id) 950 CheckNoError(t, resp) 951 assert.True(t, ok) 952 953 ok, resp = th.SystemAdminClient.RemovePlugin(plugin2.Manifest.Id) 954 CheckNoError(t, resp) 955 assert.True(t, ok) 956 }) 957 } 958 959 func TestGetLocalPluginInMarketplace(t *testing.T) { 960 th := Setup(t) 961 defer th.TearDown() 962 963 samplePlugins := []*model.MarketplacePlugin{ 964 { 965 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 966 HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps", 967 IconData: "https://example.com/icon.svg", 968 DownloadURL: "www.github.com/example", 969 Manifest: &model.Manifest{ 970 Id: "testplugin2", 971 Name: "testplugin2", 972 Description: "a second plugin", 973 Version: "1.2.2", 974 MinServerVersion: "", 975 }, 976 }, 977 InstalledVersion: "", 978 }, 979 } 980 981 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 982 res.WriteHeader(http.StatusOK) 983 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[0]}) 984 require.NoError(t, err) 985 res.Write(json) 986 })) 987 defer testServer.Close() 988 989 th.App.UpdateConfig(func(cfg *model.Config) { 990 *cfg.PluginSettings.Enable = true 991 *cfg.PluginSettings.EnableMarketplace = true 992 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 993 }) 994 995 t.Run("Get plugins with EnableRemoteMarketplace enabled", func(t *testing.T) { 996 th.App.UpdateConfig(func(cfg *model.Config) { 997 *cfg.PluginSettings.EnableRemoteMarketplace = true 998 }) 999 1000 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1001 CheckNoError(t, resp) 1002 1003 require.Len(t, plugins, len(samplePlugins)) 1004 require.Equal(t, samplePlugins, plugins) 1005 }) 1006 1007 t.Run("get remote and local plugins", func(t *testing.T) { 1008 th.App.UpdateConfig(func(cfg *model.Config) { 1009 *cfg.PluginSettings.EnableRemoteMarketplace = true 1010 *cfg.PluginSettings.EnableUploads = true 1011 }) 1012 1013 // Upload one local plugin 1014 path, _ := fileutils.FindDir("tests") 1015 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 1016 require.NoError(t, err) 1017 1018 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 1019 CheckNoError(t, resp) 1020 1021 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1022 CheckNoError(t, resp) 1023 1024 require.Len(t, plugins, 2) 1025 1026 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 1027 CheckNoError(t, resp) 1028 assert.True(t, ok) 1029 }) 1030 1031 t.Run("EnableRemoteMarketplace disabled", func(t *testing.T) { 1032 th.App.UpdateConfig(func(cfg *model.Config) { 1033 *cfg.PluginSettings.EnableRemoteMarketplace = false 1034 *cfg.PluginSettings.EnableUploads = true 1035 }) 1036 1037 // No marketplace plugins returned 1038 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1039 CheckNoError(t, resp) 1040 1041 require.Len(t, plugins, 0) 1042 1043 // Upload one local plugin 1044 path, _ := fileutils.FindDir("tests") 1045 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 1046 require.NoError(t, err) 1047 1048 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 1049 CheckNoError(t, resp) 1050 1051 testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) 1052 require.NoError(t, err) 1053 require.True(t, svg.Is(testIcon)) 1054 testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) 1055 1056 newPlugin := &model.MarketplacePlugin{ 1057 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1058 IconData: testIconData, 1059 HomepageURL: "https://example.com/homepage", 1060 ReleaseNotesURL: "https://example.com/releases/v0.0.1", 1061 Manifest: manifest, 1062 }, 1063 InstalledVersion: manifest.Version, 1064 } 1065 1066 plugins, resp = th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1067 CheckNoError(t, resp) 1068 1069 // Only get the local plugins 1070 require.Len(t, plugins, 1) 1071 require.Equal(t, newPlugin, plugins[0]) 1072 1073 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 1074 CheckNoError(t, resp) 1075 assert.True(t, ok) 1076 }) 1077 1078 t.Run("local_only true", func(t *testing.T) { 1079 th.App.UpdateConfig(func(cfg *model.Config) { 1080 *cfg.PluginSettings.EnableRemoteMarketplace = true 1081 *cfg.PluginSettings.EnableUploads = true 1082 }) 1083 1084 // Upload one local plugin 1085 path, _ := fileutils.FindDir("tests") 1086 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin.tar.gz")) 1087 require.NoError(t, err) 1088 1089 manifest, resp := th.SystemAdminClient.UploadPlugin(bytes.NewReader(tarData)) 1090 CheckNoError(t, resp) 1091 1092 testIcon, err := ioutil.ReadFile(filepath.Join(path, "test.svg")) 1093 require.NoError(t, err) 1094 require.True(t, svg.Is(testIcon)) 1095 testIconData := fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(testIcon)) 1096 1097 newPlugin := &model.MarketplacePlugin{ 1098 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1099 Manifest: manifest, 1100 IconData: testIconData, 1101 HomepageURL: "https://example.com/homepage", 1102 ReleaseNotesURL: "https://example.com/releases/v0.0.1", 1103 Labels: []model.MarketplaceLabel{{ 1104 Name: "Local", 1105 Description: "This plugin is not listed in the marketplace", 1106 }}, 1107 }, 1108 InstalledVersion: manifest.Version, 1109 } 1110 1111 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{LocalOnly: true}) 1112 CheckNoError(t, resp) 1113 1114 require.Len(t, plugins, 1) 1115 require.Equal(t, newPlugin, plugins[0]) 1116 1117 ok, resp := th.SystemAdminClient.RemovePlugin(manifest.Id) 1118 CheckNoError(t, resp) 1119 assert.True(t, ok) 1120 }) 1121 } 1122 1123 func TestGetPrepackagedPluginInMarketplace(t *testing.T) { 1124 th := Setup(t) 1125 defer th.TearDown() 1126 1127 marketplacePlugins := []*model.MarketplacePlugin{ 1128 { 1129 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1130 HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps", 1131 IconData: "https://example.com/icon.svg", 1132 DownloadURL: "www.github.com/example", 1133 Manifest: &model.Manifest{ 1134 Id: "marketplace.test", 1135 Name: "marketplacetest", 1136 Description: "a marketplace plugin", 1137 Version: "0.1.2", 1138 MinServerVersion: "", 1139 }, 1140 }, 1141 InstalledVersion: "", 1142 }, 1143 } 1144 1145 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1146 res.WriteHeader(http.StatusOK) 1147 json, err := json.Marshal([]*model.MarketplacePlugin{marketplacePlugins[0]}) 1148 require.NoError(t, err) 1149 res.Write(json) 1150 })) 1151 defer testServer.Close() 1152 1153 th.App.UpdateConfig(func(cfg *model.Config) { 1154 *cfg.PluginSettings.Enable = true 1155 *cfg.PluginSettings.EnableMarketplace = true 1156 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1157 }) 1158 1159 prepackagePlugin := &plugin.PrepackagedPlugin{ 1160 Manifest: &model.Manifest{ 1161 Version: "0.0.1", 1162 Id: "prepackaged.test", 1163 }, 1164 } 1165 1166 env := th.App.GetPluginsEnvironment() 1167 env.SetPrepackagedPlugins([]*plugin.PrepackagedPlugin{prepackagePlugin}) 1168 1169 t.Run("get remote and prepackaged plugins", func(t *testing.T) { 1170 th.App.UpdateConfig(func(cfg *model.Config) { 1171 *cfg.PluginSettings.EnableRemoteMarketplace = true 1172 *cfg.PluginSettings.EnableUploads = true 1173 }) 1174 1175 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1176 CheckNoError(t, resp) 1177 1178 expectedPlugins := marketplacePlugins 1179 expectedPlugins = append(expectedPlugins, &model.MarketplacePlugin{ 1180 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1181 Manifest: prepackagePlugin.Manifest, 1182 }, 1183 }) 1184 1185 require.ElementsMatch(t, expectedPlugins, plugins) 1186 require.Len(t, plugins, 2) 1187 }) 1188 1189 t.Run("EnableRemoteMarketplace disabled", func(t *testing.T) { 1190 th.App.UpdateConfig(func(cfg *model.Config) { 1191 *cfg.PluginSettings.EnableRemoteMarketplace = false 1192 *cfg.PluginSettings.EnableUploads = true 1193 }) 1194 1195 // No marketplace plugins returned 1196 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1197 CheckNoError(t, resp) 1198 1199 // Only returns the prepackaged plugins 1200 require.Len(t, plugins, 1) 1201 require.Equal(t, prepackagePlugin.Manifest, plugins[0].Manifest) 1202 }) 1203 1204 t.Run("get prepackaged plugin if newer", func(t *testing.T) { 1205 th.App.UpdateConfig(func(cfg *model.Config) { 1206 *cfg.PluginSettings.EnableRemoteMarketplace = true 1207 *cfg.PluginSettings.EnableUploads = true 1208 }) 1209 1210 manifest := &model.Manifest{ 1211 Version: "1.2.3", 1212 Id: "marketplace.test", 1213 } 1214 1215 newerPrepackagePlugin := &plugin.PrepackagedPlugin{ 1216 Manifest: manifest, 1217 } 1218 1219 env := th.App.GetPluginsEnvironment() 1220 env.SetPrepackagedPlugins([]*plugin.PrepackagedPlugin{newerPrepackagePlugin}) 1221 1222 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1223 CheckNoError(t, resp) 1224 1225 require.Len(t, plugins, 1) 1226 require.Equal(t, newerPrepackagePlugin.Manifest, plugins[0].Manifest) 1227 }) 1228 1229 t.Run("prepackaged plugins are not shown in Cloud", func(t *testing.T) { 1230 th.App.UpdateConfig(func(cfg *model.Config) { 1231 *cfg.PluginSettings.EnableRemoteMarketplace = true 1232 *cfg.PluginSettings.EnableUploads = true 1233 }) 1234 1235 th.App.Srv().SetLicense(model.NewTestLicense("cloud")) 1236 1237 plugins, resp := th.SystemAdminClient.GetMarketplacePlugins(&model.MarketplacePluginFilter{}) 1238 CheckNoError(t, resp) 1239 1240 require.ElementsMatch(t, marketplacePlugins, plugins) 1241 require.Len(t, plugins, 1) 1242 }) 1243 } 1244 1245 func TestInstallMarketplacePlugin(t *testing.T) { 1246 th := Setup(t).InitBasic() 1247 defer th.TearDown() 1248 1249 th.App.UpdateConfig(func(cfg *model.Config) { 1250 *cfg.PluginSettings.Enable = true 1251 *cfg.PluginSettings.EnableUploads = true 1252 *cfg.PluginSettings.EnableMarketplace = false 1253 }) 1254 1255 path, _ := fileutils.FindDir("tests") 1256 signatureFilename := "testplugin2.tar.gz.sig" 1257 signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename)) 1258 require.NoError(t, err) 1259 sigFile, err := ioutil.ReadAll(signatureFileReader) 1260 require.NoError(t, err) 1261 pluginSignature := base64.StdEncoding.EncodeToString(sigFile) 1262 1263 tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz")) 1264 require.NoError(t, err) 1265 pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1266 res.WriteHeader(http.StatusOK) 1267 res.Write(tarData) 1268 })) 1269 defer pluginServer.Close() 1270 1271 samplePlugins := []*model.MarketplacePlugin{ 1272 { 1273 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1274 HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps", 1275 IconData: "https://example.com/icon.svg", 1276 DownloadURL: pluginServer.URL, 1277 Manifest: &model.Manifest{ 1278 Id: "testplugin2", 1279 Name: "testplugin2", 1280 Description: "a second plugin", 1281 Version: "1.2.2", 1282 MinServerVersion: "", 1283 }, 1284 }, 1285 InstalledVersion: "", 1286 }, 1287 { 1288 BaseMarketplacePlugin: &model.BaseMarketplacePlugin{ 1289 HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps", 1290 IconData: "https://example.com/icon.svg", 1291 DownloadURL: pluginServer.URL, 1292 Manifest: &model.Manifest{ 1293 Id: "testplugin2", 1294 Name: "testplugin2", 1295 Description: "a second plugin", 1296 Version: "1.2.3", 1297 MinServerVersion: "", 1298 }, 1299 Signature: pluginSignature, 1300 }, 1301 InstalledVersion: "", 1302 }, 1303 } 1304 1305 request := &model.InstallMarketplacePluginRequest{Id: "", Version: ""} 1306 1307 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1308 th.App.UpdateConfig(func(cfg *model.Config) { 1309 *cfg.PluginSettings.EnableMarketplace = false 1310 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 1311 }) 1312 plugin, resp := client.InstallMarketplacePlugin(request) 1313 CheckNotImplementedStatus(t, resp) 1314 require.Nil(t, plugin) 1315 }, "marketplace disabled") 1316 1317 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1318 th.App.UpdateConfig(func(cfg *model.Config) { 1319 *cfg.PluginSettings.Enable = true 1320 *cfg.PluginSettings.RequirePluginSignature = true 1321 }) 1322 manifest, resp := client.UploadPlugin(bytes.NewReader(tarData)) 1323 CheckNotImplementedStatus(t, resp) 1324 require.Nil(t, manifest) 1325 1326 manifest, resp = client.InstallPluginFromUrl("some_url", true) 1327 CheckNotImplementedStatus(t, resp) 1328 require.Nil(t, manifest) 1329 }, "RequirePluginSignature enabled") 1330 1331 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1332 th.App.UpdateConfig(func(cfg *model.Config) { 1333 *cfg.PluginSettings.EnableMarketplace = true 1334 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 1335 }) 1336 1337 plugin, resp := client.InstallMarketplacePlugin(request) 1338 CheckInternalErrorStatus(t, resp) 1339 require.Nil(t, plugin) 1340 }, "no server") 1341 1342 t.Run("no permission", func(t *testing.T) { 1343 th.App.UpdateConfig(func(cfg *model.Config) { 1344 *cfg.PluginSettings.EnableMarketplace = true 1345 *cfg.PluginSettings.MarketplaceUrl = "invalid.com" 1346 }) 1347 1348 plugin, resp := th.Client.InstallMarketplacePlugin(request) 1349 CheckForbiddenStatus(t, resp) 1350 require.Nil(t, plugin) 1351 }) 1352 1353 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1354 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1355 res.WriteHeader(http.StatusOK) 1356 json, err := json.Marshal([]*model.MarketplacePlugin{}) 1357 require.NoError(t, err) 1358 res.Write(json) 1359 })) 1360 defer testServer.Close() 1361 1362 th.App.UpdateConfig(func(cfg *model.Config) { 1363 *cfg.PluginSettings.EnableMarketplace = true 1364 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1365 }) 1366 pRequest := &model.InstallMarketplacePluginRequest{Id: "some_plugin_id", Version: "0.0.1"} 1367 plugin, resp := client.InstallMarketplacePlugin(pRequest) 1368 CheckInternalErrorStatus(t, resp) 1369 require.Nil(t, plugin) 1370 }, "plugin not found on the server") 1371 1372 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1373 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1374 res.WriteHeader(http.StatusOK) 1375 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[0]}) 1376 require.NoError(t, err) 1377 res.Write(json) 1378 })) 1379 defer testServer.Close() 1380 1381 th.App.UpdateConfig(func(cfg *model.Config) { 1382 *cfg.PluginSettings.EnableMarketplace = true 1383 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1384 *cfg.PluginSettings.AllowInsecureDownloadUrl = true 1385 }) 1386 pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin2", Version: "1.2.2"} 1387 plugin, resp := client.InstallMarketplacePlugin(pRequest) 1388 CheckInternalErrorStatus(t, resp) 1389 require.Nil(t, plugin) 1390 }, "plugin not verified") 1391 1392 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1393 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1394 serverVersion := req.URL.Query().Get("server_version") 1395 require.NotEmpty(t, serverVersion) 1396 require.Equal(t, model.CurrentVersion, serverVersion) 1397 res.WriteHeader(http.StatusOK) 1398 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[1]}) 1399 require.NoError(t, err) 1400 res.Write(json) 1401 })) 1402 defer testServer.Close() 1403 1404 th.App.UpdateConfig(func(cfg *model.Config) { 1405 *cfg.PluginSettings.EnableMarketplace = true 1406 *cfg.PluginSettings.EnableRemoteMarketplace = true 1407 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1408 }) 1409 1410 key, err := os.Open(filepath.Join(path, "development-private-key.asc")) 1411 require.NoError(t, err) 1412 appErr := th.App.AddPublicKey("pub_key", key) 1413 require.Nil(t, appErr) 1414 1415 pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin2", Version: "1.2.3"} 1416 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1417 CheckNoError(t, resp) 1418 require.NotNil(t, manifest) 1419 require.Equal(t, "testplugin2", manifest.Id) 1420 require.Equal(t, "1.2.3", manifest.Version) 1421 1422 filePath := filepath.Join("plugins", "testplugin2.tar.gz.sig") 1423 savedSigFile, appErr := th.App.ReadFile(filePath) 1424 require.Nil(t, appErr) 1425 require.EqualValues(t, sigFile, savedSigFile) 1426 1427 ok, resp := client.RemovePlugin(manifest.Id) 1428 CheckNoError(t, resp) 1429 assert.True(t, ok) 1430 exists, appErr := th.App.FileExists(filePath) 1431 require.Nil(t, appErr) 1432 require.False(t, exists) 1433 1434 appErr = th.App.DeletePublicKey("pub_key") 1435 require.Nil(t, appErr) 1436 }, "verify, install and remove plugin") 1437 1438 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1439 requestHandled := false 1440 1441 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1442 licenseType, ok := req.URL.Query()["enterprise_plugins"] 1443 require.True(t, ok) 1444 require.Len(t, licenseType, 1) 1445 require.Equal(t, "false", licenseType[0]) 1446 1447 res.WriteHeader(http.StatusOK) 1448 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[0]}) 1449 require.NoError(t, err) 1450 _, err = res.Write(json) 1451 require.NoError(t, err) 1452 1453 requestHandled = true 1454 })) 1455 defer func() { testServer.Close() }() 1456 1457 th.App.UpdateConfig(func(cfg *model.Config) { 1458 *cfg.PluginSettings.EnableMarketplace = true 1459 *cfg.PluginSettings.EnableRemoteMarketplace = true 1460 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1461 }) 1462 1463 // The content of the request is irrelevant. This test only cares about enterprise_plugins. 1464 pRequest := &model.InstallMarketplacePluginRequest{} 1465 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1466 CheckInternalErrorStatus(t, resp) 1467 require.Nil(t, manifest) 1468 assert.True(t, requestHandled) 1469 }, "verify EnterprisePlugins is false for TE") 1470 1471 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1472 requestHandled := false 1473 1474 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1475 licenseType, ok := req.URL.Query()["enterprise_plugins"] 1476 require.True(t, ok) 1477 require.Len(t, licenseType, 1) 1478 require.Equal(t, "false", licenseType[0]) 1479 1480 res.WriteHeader(http.StatusOK) 1481 json, err := json.Marshal([]*model.MarketplacePlugin{}) 1482 require.NoError(t, err) 1483 _, err = res.Write(json) 1484 require.NoError(t, err) 1485 1486 requestHandled = true 1487 })) 1488 defer func() { testServer.Close() }() 1489 1490 th.App.UpdateConfig(func(cfg *model.Config) { 1491 *cfg.PluginSettings.EnableMarketplace = true 1492 *cfg.PluginSettings.EnableRemoteMarketplace = true 1493 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1494 }) 1495 1496 l := model.NewTestLicense() 1497 // model.NewTestLicense generates a E20 license 1498 *l.Features.EnterprisePlugins = false 1499 th.App.Srv().SetLicense(l) 1500 1501 // The content of the request is irrelevant. This test only cares about enterprise_plugins. 1502 pRequest := &model.InstallMarketplacePluginRequest{} 1503 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1504 CheckInternalErrorStatus(t, resp) 1505 require.Nil(t, manifest) 1506 assert.True(t, requestHandled) 1507 }, "verify EnterprisePlugins is false for E10") 1508 1509 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1510 requestHandled := false 1511 1512 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1513 licenseType, ok := req.URL.Query()["enterprise_plugins"] 1514 require.True(t, ok) 1515 require.Len(t, licenseType, 1) 1516 require.Equal(t, "true", licenseType[0]) 1517 1518 res.WriteHeader(http.StatusOK) 1519 json, err := json.Marshal([]*model.MarketplacePlugin{}) 1520 require.NoError(t, err) 1521 _, err = res.Write(json) 1522 require.NoError(t, err) 1523 1524 requestHandled = true 1525 })) 1526 defer func() { testServer.Close() }() 1527 1528 th.App.UpdateConfig(func(cfg *model.Config) { 1529 *cfg.PluginSettings.EnableMarketplace = true 1530 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1531 }) 1532 1533 th.App.Srv().SetLicense(model.NewTestLicense("enterprise_plugins")) 1534 1535 // The content of the request is irrelevant. This test only cares about enterprise_plugins. 1536 pRequest := &model.InstallMarketplacePluginRequest{} 1537 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1538 CheckInternalErrorStatus(t, resp) 1539 require.Nil(t, manifest) 1540 assert.True(t, requestHandled) 1541 }, "verify EnterprisePlugins is true for E20") 1542 1543 t.Run("install prepackaged and remote plugins through marketplace", func(t *testing.T) { 1544 prepackagedPluginsDir := "prepackaged_plugins" 1545 1546 os.RemoveAll(prepackagedPluginsDir) 1547 err := os.Mkdir(prepackagedPluginsDir, os.ModePerm) 1548 require.NoError(t, err) 1549 defer os.RemoveAll(prepackagedPluginsDir) 1550 1551 prepackagedPluginsDir, found := fileutils.FindDir(prepackagedPluginsDir) 1552 require.True(t, found, "failed to find prepackaged plugins directory") 1553 1554 err = testlib.CopyFile(filepath.Join(path, "testplugin.tar.gz"), filepath.Join(prepackagedPluginsDir, "testplugin.tar.gz")) 1555 require.NoError(t, err) 1556 err = testlib.CopyFile(filepath.Join(path, "testplugin.tar.gz.asc"), filepath.Join(prepackagedPluginsDir, "testplugin.tar.gz.sig")) 1557 require.NoError(t, err) 1558 1559 th2 := SetupConfig(t, func(cfg *model.Config) { 1560 // Disable auto-installing prepackaged plugins 1561 *cfg.PluginSettings.AutomaticPrepackagedPlugins = false 1562 }).InitBasic() 1563 defer th2.TearDown() 1564 1565 th2.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1566 pluginSignatureFile, err := os.Open(filepath.Join(path, "testplugin.tar.gz.asc")) 1567 require.NoError(t, err) 1568 pluginSignatureData, err := ioutil.ReadAll(pluginSignatureFile) 1569 require.NoError(t, err) 1570 1571 key, err := os.Open(filepath.Join(path, "development-private-key.asc")) 1572 require.NoError(t, err) 1573 appErr := th2.App.AddPublicKey("pub_key", key) 1574 require.Nil(t, appErr) 1575 1576 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1577 serverVersion := req.URL.Query().Get("server_version") 1578 require.NotEmpty(t, serverVersion) 1579 require.Equal(t, model.CurrentVersion, serverVersion) 1580 res.WriteHeader(http.StatusOK) 1581 json, err := json.Marshal([]*model.MarketplacePlugin{samplePlugins[1]}) 1582 require.NoError(t, err) 1583 res.Write(json) 1584 })) 1585 defer testServer.Close() 1586 1587 th2.App.UpdateConfig(func(cfg *model.Config) { 1588 *cfg.PluginSettings.EnableMarketplace = true 1589 *cfg.PluginSettings.EnableRemoteMarketplace = false 1590 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1591 *cfg.PluginSettings.AllowInsecureDownloadUrl = false 1592 }) 1593 1594 env := th2.App.GetPluginsEnvironment() 1595 1596 pluginsResp, resp := client.GetPlugins() 1597 CheckNoError(t, resp) 1598 require.Len(t, pluginsResp.Active, 0) 1599 require.Len(t, pluginsResp.Inactive, 0) 1600 1601 // Should fail to install unknown prepackaged plugin 1602 pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin", Version: "0.0.2"} 1603 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1604 CheckInternalErrorStatus(t, resp) 1605 require.Nil(t, manifest) 1606 1607 plugins := env.PrepackagedPlugins() 1608 require.Len(t, plugins, 1) 1609 require.Equal(t, "testplugin", plugins[0].Manifest.Id) 1610 require.Equal(t, pluginSignatureData, plugins[0].Signature) 1611 1612 pluginsResp, resp = client.GetPlugins() 1613 CheckNoError(t, resp) 1614 require.Len(t, pluginsResp.Active, 0) 1615 require.Len(t, pluginsResp.Inactive, 0) 1616 1617 pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin", Version: "0.0.1"} 1618 manifest1, resp := client.InstallMarketplacePlugin(pRequest) 1619 CheckNoError(t, resp) 1620 require.NotNil(t, manifest1) 1621 require.Equal(t, "testplugin", manifest1.Id) 1622 require.Equal(t, "0.0.1", manifest1.Version) 1623 1624 pluginsResp, resp = client.GetPlugins() 1625 CheckNoError(t, resp) 1626 require.Len(t, pluginsResp.Active, 0) 1627 require.Equal(t, pluginsResp.Inactive, []*model.PluginInfo{{ 1628 Manifest: *manifest1, 1629 }}) 1630 1631 // Try to install remote marketplace plugin 1632 pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2", Version: "1.2.3"} 1633 manifest, resp = client.InstallMarketplacePlugin(pRequest) 1634 CheckInternalErrorStatus(t, resp) 1635 require.Nil(t, manifest) 1636 1637 // Enable remote marketplace 1638 th2.App.UpdateConfig(func(cfg *model.Config) { 1639 *cfg.PluginSettings.EnableMarketplace = true 1640 *cfg.PluginSettings.EnableRemoteMarketplace = true 1641 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1642 *cfg.PluginSettings.AllowInsecureDownloadUrl = true 1643 }) 1644 1645 pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2", Version: "1.2.3"} 1646 manifest2, resp := client.InstallMarketplacePlugin(pRequest) 1647 CheckNoError(t, resp) 1648 require.NotNil(t, manifest2) 1649 require.Equal(t, "testplugin2", manifest2.Id) 1650 require.Equal(t, "1.2.3", manifest2.Version) 1651 1652 pluginsResp, resp = client.GetPlugins() 1653 CheckNoError(t, resp) 1654 require.Len(t, pluginsResp.Active, 0) 1655 require.ElementsMatch(t, pluginsResp.Inactive, []*model.PluginInfo{ 1656 { 1657 Manifest: *manifest1, 1658 }, 1659 { 1660 Manifest: *manifest2, 1661 }, 1662 }) 1663 1664 // Clean up 1665 ok, resp := client.RemovePlugin(manifest1.Id) 1666 CheckNoError(t, resp) 1667 assert.True(t, ok) 1668 1669 ok, resp = client.RemovePlugin(manifest2.Id) 1670 CheckNoError(t, resp) 1671 assert.True(t, ok) 1672 1673 appErr = th2.App.DeletePublicKey("pub_key") 1674 require.Nil(t, appErr) 1675 }) 1676 }) 1677 1678 th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { 1679 prepackagedPluginsDir := "prepackaged_plugins" 1680 1681 os.RemoveAll(prepackagedPluginsDir) 1682 err := os.Mkdir(prepackagedPluginsDir, os.ModePerm) 1683 require.NoError(t, err) 1684 defer os.RemoveAll(prepackagedPluginsDir) 1685 1686 prepackagedPluginsDir, found := fileutils.FindDir(prepackagedPluginsDir) 1687 require.True(t, found, "failed to find prepackaged plugins directory") 1688 1689 err = testlib.CopyFile(filepath.Join(path, "testplugin.tar.gz"), filepath.Join(prepackagedPluginsDir, "testplugin.tar.gz")) 1690 require.NoError(t, err) 1691 1692 th := SetupConfig(t, func(cfg *model.Config) { 1693 // Disable auto-installing prepackged plugins 1694 *cfg.PluginSettings.AutomaticPrepackagedPlugins = false 1695 }).InitBasic() 1696 defer th.TearDown() 1697 1698 key, err := os.Open(filepath.Join(path, "development-private-key.asc")) 1699 require.NoError(t, err) 1700 appErr := th.App.AddPublicKey("pub_key", key) 1701 require.Nil(t, appErr) 1702 1703 testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { 1704 serverVersion := req.URL.Query().Get("server_version") 1705 require.NotEmpty(t, serverVersion) 1706 require.Equal(t, model.CurrentVersion, serverVersion) 1707 1708 mPlugins := []*model.MarketplacePlugin{samplePlugins[0]} 1709 require.Empty(t, mPlugins[0].Signature) 1710 res.WriteHeader(http.StatusOK) 1711 json, err := json.Marshal(mPlugins) 1712 require.NoError(t, err) 1713 res.Write(json) 1714 })) 1715 defer testServer.Close() 1716 1717 th.App.UpdateConfig(func(cfg *model.Config) { 1718 *cfg.PluginSettings.EnableMarketplace = true 1719 *cfg.PluginSettings.EnableRemoteMarketplace = true 1720 *cfg.PluginSettings.MarketplaceUrl = testServer.URL 1721 *cfg.PluginSettings.AllowInsecureDownloadUrl = true 1722 }) 1723 1724 env := th.App.GetPluginsEnvironment() 1725 plugins := env.PrepackagedPlugins() 1726 require.Len(t, plugins, 1) 1727 require.Equal(t, "testplugin", plugins[0].Manifest.Id) 1728 require.Empty(t, plugins[0].Signature) 1729 1730 pluginsResp, resp := client.GetPlugins() 1731 CheckNoError(t, resp) 1732 require.Len(t, pluginsResp.Active, 0) 1733 require.Len(t, pluginsResp.Inactive, 0) 1734 1735 pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin", Version: "0.0.1"} 1736 manifest, resp := client.InstallMarketplacePlugin(pRequest) 1737 CheckInternalErrorStatus(t, resp) 1738 require.Nil(t, manifest) 1739 1740 pluginsResp, resp = client.GetPlugins() 1741 CheckNoError(t, resp) 1742 require.Len(t, pluginsResp.Active, 0) 1743 require.Len(t, pluginsResp.Inactive, 0) 1744 1745 pRequest = &model.InstallMarketplacePluginRequest{Id: "testplugin2", Version: "1.2.3"} 1746 manifest, resp = client.InstallMarketplacePlugin(pRequest) 1747 CheckInternalErrorStatus(t, resp) 1748 require.Nil(t, manifest) 1749 1750 pluginsResp, resp = client.GetPlugins() 1751 CheckNoError(t, resp) 1752 require.Len(t, pluginsResp.Active, 0) 1753 require.Len(t, pluginsResp.Inactive, 0) 1754 1755 // Clean up 1756 appErr = th.App.DeletePublicKey("pub_key") 1757 require.Nil(t, appErr) 1758 }, "missing prepackaged and remote plugin signatures") 1759 } 1760 1761 func findClusterMessages(event string, msgs []*model.ClusterMessage) []*model.ClusterMessage { 1762 var result []*model.ClusterMessage 1763 for _, msg := range msgs { 1764 if msg.Event == event { 1765 result = append(result, msg) 1766 } 1767 } 1768 return result 1769 }