github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+incompatible/app/plugin_hooks_test.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "bytes" 8 "io" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "testing" 14 "time" 15 16 "github.com/pkg/errors" 17 18 "github.com/mattermost/mattermost-server/model" 19 "github.com/mattermost/mattermost-server/plugin" 20 "github.com/mattermost/mattermost-server/plugin/plugintest" 21 "github.com/mattermost/mattermost-server/plugin/plugintest/mock" 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func compileGo(t *testing.T, sourceCode, outputPath string) { 27 dir, err := ioutil.TempDir(".", "") 28 require.NoError(t, err) 29 defer os.RemoveAll(dir) 30 require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte(sourceCode), 0600)) 31 cmd := exec.Command("go", "build", "-o", outputPath, "main.go") 32 cmd.Dir = dir 33 cmd.Stdout = os.Stdout 34 cmd.Stderr = os.Stderr 35 require.NoError(t, cmd.Run()) 36 } 37 38 func SetAppEnvironmentWithPlugins(t *testing.T, pluginCode []string, app *App, apiFunc func(*model.Manifest) plugin.API) []error { 39 pluginDir, err := ioutil.TempDir("", "") 40 require.NoError(t, err) 41 webappPluginDir, err := ioutil.TempDir("", "") 42 require.NoError(t, err) 43 defer os.RemoveAll(pluginDir) 44 defer os.RemoveAll(webappPluginDir) 45 46 env, err := plugin.NewEnvironment(apiFunc, pluginDir, webappPluginDir, app.Log) 47 require.NoError(t, err) 48 49 app.Plugins = env 50 activationErrors := []error{} 51 for _, code := range pluginCode { 52 pluginId := model.NewId() 53 backend := filepath.Join(pluginDir, pluginId, "backend.exe") 54 compileGo(t, code, backend) 55 56 ioutil.WriteFile(filepath.Join(pluginDir, pluginId, "plugin.json"), []byte(`{"id": "`+pluginId+`", "backend": {"executable": "backend.exe"}}`), 0600) 57 _, _, activationErr := env.Activate(pluginId) 58 activationErrors = append(activationErrors, activationErr) 59 } 60 61 return activationErrors 62 } 63 64 func TestHookMessageWillBePosted(t *testing.T) { 65 t.Run("rejected", func(t *testing.T) { 66 th := Setup().InitBasic() 67 defer th.TearDown() 68 69 SetAppEnvironmentWithPlugins(t, []string{ 70 ` 71 package main 72 73 import ( 74 "github.com/mattermost/mattermost-server/plugin" 75 "github.com/mattermost/mattermost-server/model" 76 ) 77 78 type MyPlugin struct { 79 plugin.MattermostPlugin 80 } 81 82 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 83 return nil, "rejected" 84 } 85 86 func main() { 87 plugin.ClientMain(&MyPlugin{}) 88 } 89 `, 90 }, th.App, th.App.NewPluginAPI) 91 92 post := &model.Post{ 93 UserId: th.BasicUser.Id, 94 ChannelId: th.BasicChannel.Id, 95 Message: "message_", 96 CreateAt: model.GetMillis() - 10000, 97 } 98 _, err := th.App.CreatePost(post, th.BasicChannel, false) 99 if assert.NotNil(t, err) { 100 assert.Equal(t, "Post rejected by plugin. rejected", err.Message) 101 } 102 }) 103 104 t.Run("rejected, returned post ignored", func(t *testing.T) { 105 th := Setup().InitBasic() 106 defer th.TearDown() 107 108 SetAppEnvironmentWithPlugins(t, []string{ 109 ` 110 package main 111 112 import ( 113 "github.com/mattermost/mattermost-server/plugin" 114 "github.com/mattermost/mattermost-server/model" 115 ) 116 117 type MyPlugin struct { 118 plugin.MattermostPlugin 119 } 120 121 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 122 post.Message = "ignored" 123 return post, "rejected" 124 } 125 126 func main() { 127 plugin.ClientMain(&MyPlugin{}) 128 } 129 `, 130 }, th.App, th.App.NewPluginAPI) 131 132 post := &model.Post{ 133 UserId: th.BasicUser.Id, 134 ChannelId: th.BasicChannel.Id, 135 Message: "message_", 136 CreateAt: model.GetMillis() - 10000, 137 } 138 _, err := th.App.CreatePost(post, th.BasicChannel, false) 139 if assert.NotNil(t, err) { 140 assert.Equal(t, "Post rejected by plugin. rejected", err.Message) 141 } 142 }) 143 144 t.Run("allowed", func(t *testing.T) { 145 th := Setup().InitBasic() 146 defer th.TearDown() 147 148 SetAppEnvironmentWithPlugins(t, []string{ 149 ` 150 package main 151 152 import ( 153 "github.com/mattermost/mattermost-server/plugin" 154 "github.com/mattermost/mattermost-server/model" 155 ) 156 157 type MyPlugin struct { 158 plugin.MattermostPlugin 159 } 160 161 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 162 return nil, "" 163 } 164 165 func main() { 166 plugin.ClientMain(&MyPlugin{}) 167 } 168 `, 169 }, th.App, th.App.NewPluginAPI) 170 171 post := &model.Post{ 172 UserId: th.BasicUser.Id, 173 ChannelId: th.BasicChannel.Id, 174 Message: "message", 175 CreateAt: model.GetMillis() - 10000, 176 } 177 post, err := th.App.CreatePost(post, th.BasicChannel, false) 178 if err != nil { 179 t.Fatal(err) 180 } 181 assert.Equal(t, "message", post.Message) 182 if result := <-th.App.Srv.Store.Post().GetSingle(post.Id); result.Err != nil { 183 t.Fatal(err) 184 } else { 185 assert.Equal(t, "message", result.Data.(*model.Post).Message) 186 } 187 }) 188 189 t.Run("updated", func(t *testing.T) { 190 th := Setup().InitBasic() 191 defer th.TearDown() 192 193 SetAppEnvironmentWithPlugins(t, []string{ 194 ` 195 package main 196 197 import ( 198 "github.com/mattermost/mattermost-server/plugin" 199 "github.com/mattermost/mattermost-server/model" 200 ) 201 202 type MyPlugin struct { 203 plugin.MattermostPlugin 204 } 205 206 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 207 post.Message = post.Message + "_fromplugin" 208 return post, "" 209 } 210 211 func main() { 212 plugin.ClientMain(&MyPlugin{}) 213 } 214 `, 215 }, th.App, th.App.NewPluginAPI) 216 217 post := &model.Post{ 218 UserId: th.BasicUser.Id, 219 ChannelId: th.BasicChannel.Id, 220 Message: "message", 221 CreateAt: model.GetMillis() - 10000, 222 } 223 post, err := th.App.CreatePost(post, th.BasicChannel, false) 224 if err != nil { 225 t.Fatal(err) 226 } 227 assert.Equal(t, "message_fromplugin", post.Message) 228 if result := <-th.App.Srv.Store.Post().GetSingle(post.Id); result.Err != nil { 229 t.Fatal(err) 230 } else { 231 assert.Equal(t, "message_fromplugin", result.Data.(*model.Post).Message) 232 } 233 }) 234 235 t.Run("multiple updated", func(t *testing.T) { 236 th := Setup().InitBasic() 237 defer th.TearDown() 238 239 SetAppEnvironmentWithPlugins(t, []string{ 240 ` 241 package main 242 243 import ( 244 "github.com/mattermost/mattermost-server/plugin" 245 "github.com/mattermost/mattermost-server/model" 246 ) 247 248 type MyPlugin struct { 249 plugin.MattermostPlugin 250 } 251 252 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 253 254 post.Message = "prefix_" + post.Message 255 return post, "" 256 } 257 258 func main() { 259 plugin.ClientMain(&MyPlugin{}) 260 } 261 `, 262 ` 263 package main 264 265 import ( 266 "github.com/mattermost/mattermost-server/plugin" 267 "github.com/mattermost/mattermost-server/model" 268 ) 269 270 type MyPlugin struct { 271 plugin.MattermostPlugin 272 } 273 274 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 275 post.Message = post.Message + "_suffix" 276 return post, "" 277 } 278 279 func main() { 280 plugin.ClientMain(&MyPlugin{}) 281 } 282 `, 283 }, th.App, th.App.NewPluginAPI) 284 285 post := &model.Post{ 286 UserId: th.BasicUser.Id, 287 ChannelId: th.BasicChannel.Id, 288 Message: "message", 289 CreateAt: model.GetMillis() - 10000, 290 } 291 post, err := th.App.CreatePost(post, th.BasicChannel, false) 292 if err != nil { 293 t.Fatal(err) 294 } 295 assert.Equal(t, "prefix_message_suffix", post.Message) 296 }) 297 } 298 299 func TestHookMessageHasBeenPosted(t *testing.T) { 300 th := Setup().InitBasic() 301 defer th.TearDown() 302 303 var mockAPI plugintest.API 304 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 305 mockAPI.On("LogDebug", "message").Return(nil) 306 307 SetAppEnvironmentWithPlugins(t, 308 []string{ 309 ` 310 package main 311 312 import ( 313 "github.com/mattermost/mattermost-server/plugin" 314 "github.com/mattermost/mattermost-server/model" 315 ) 316 317 type MyPlugin struct { 318 plugin.MattermostPlugin 319 } 320 321 func (p *MyPlugin) MessageHasBeenPosted(c *plugin.Context, post *model.Post) { 322 p.API.LogDebug(post.Message) 323 } 324 325 func main() { 326 plugin.ClientMain(&MyPlugin{}) 327 } 328 `}, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 329 330 post := &model.Post{ 331 UserId: th.BasicUser.Id, 332 ChannelId: th.BasicChannel.Id, 333 Message: "message", 334 CreateAt: model.GetMillis() - 10000, 335 } 336 _, err := th.App.CreatePost(post, th.BasicChannel, false) 337 if err != nil { 338 t.Fatal(err) 339 } 340 } 341 342 func TestHookMessageWillBeUpdated(t *testing.T) { 343 th := Setup().InitBasic() 344 defer th.TearDown() 345 346 SetAppEnvironmentWithPlugins(t, 347 []string{ 348 ` 349 package main 350 351 import ( 352 "github.com/mattermost/mattermost-server/plugin" 353 "github.com/mattermost/mattermost-server/model" 354 ) 355 356 type MyPlugin struct { 357 plugin.MattermostPlugin 358 } 359 360 func (p *MyPlugin) MessageWillBeUpdated(c *plugin.Context, newPost, oldPost *model.Post) (*model.Post, string) { 361 newPost.Message = newPost.Message + "fromplugin" 362 return newPost, "" 363 } 364 365 func main() { 366 plugin.ClientMain(&MyPlugin{}) 367 } 368 `}, th.App, th.App.NewPluginAPI) 369 370 post := &model.Post{ 371 UserId: th.BasicUser.Id, 372 ChannelId: th.BasicChannel.Id, 373 Message: "message_", 374 CreateAt: model.GetMillis() - 10000, 375 } 376 post, err := th.App.CreatePost(post, th.BasicChannel, false) 377 if err != nil { 378 t.Fatal(err) 379 } 380 assert.Equal(t, "message_", post.Message) 381 post.Message = post.Message + "edited_" 382 post, err = th.App.UpdatePost(post, true) 383 if err != nil { 384 t.Fatal(err) 385 } 386 assert.Equal(t, "message_edited_fromplugin", post.Message) 387 } 388 389 func TestHookMessageHasBeenUpdated(t *testing.T) { 390 th := Setup().InitBasic() 391 defer th.TearDown() 392 393 var mockAPI plugintest.API 394 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 395 mockAPI.On("LogDebug", "message_edited").Return(nil) 396 mockAPI.On("LogDebug", "message_").Return(nil) 397 SetAppEnvironmentWithPlugins(t, 398 []string{ 399 ` 400 package main 401 402 import ( 403 "github.com/mattermost/mattermost-server/plugin" 404 "github.com/mattermost/mattermost-server/model" 405 ) 406 407 type MyPlugin struct { 408 plugin.MattermostPlugin 409 } 410 411 func (p *MyPlugin) MessageHasBeenUpdated(c *plugin.Context, newPost, oldPost *model.Post) { 412 p.API.LogDebug(newPost.Message) 413 p.API.LogDebug(oldPost.Message) 414 } 415 416 func main() { 417 plugin.ClientMain(&MyPlugin{}) 418 } 419 `}, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 420 421 post := &model.Post{ 422 UserId: th.BasicUser.Id, 423 ChannelId: th.BasicChannel.Id, 424 Message: "message_", 425 CreateAt: model.GetMillis() - 10000, 426 } 427 post, err := th.App.CreatePost(post, th.BasicChannel, false) 428 if err != nil { 429 t.Fatal(err) 430 } 431 assert.Equal(t, "message_", post.Message) 432 post.Message = post.Message + "edited" 433 _, err = th.App.UpdatePost(post, true) 434 if err != nil { 435 t.Fatal(err) 436 } 437 } 438 439 func TestHookFileWillBeUploaded(t *testing.T) { 440 t.Run("rejected", func(t *testing.T) { 441 th := Setup().InitBasic() 442 defer th.TearDown() 443 444 var mockAPI plugintest.API 445 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 446 mockAPI.On("LogDebug", "testhook.txt").Return(nil) 447 mockAPI.On("LogDebug", "inputfile").Return(nil) 448 SetAppEnvironmentWithPlugins(t, []string{ 449 ` 450 package main 451 452 import ( 453 "io" 454 "github.com/mattermost/mattermost-server/plugin" 455 "github.com/mattermost/mattermost-server/model" 456 ) 457 458 type MyPlugin struct { 459 plugin.MattermostPlugin 460 } 461 462 func (p *MyPlugin) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) { 463 return nil, "rejected" 464 } 465 466 func main() { 467 plugin.ClientMain(&MyPlugin{}) 468 } 469 `, 470 }, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 471 472 _, err := th.App.UploadFiles( 473 "noteam", 474 th.BasicChannel.Id, 475 th.BasicUser.Id, 476 []io.ReadCloser{ioutil.NopCloser(bytes.NewBufferString("inputfile"))}, 477 []string{"testhook.txt"}, 478 []string{}, 479 time.Now(), 480 ) 481 if assert.NotNil(t, err) { 482 assert.Equal(t, "File rejected by plugin. rejected", err.Message) 483 } 484 }) 485 486 t.Run("rejected, returned file ignored", func(t *testing.T) { 487 th := Setup().InitBasic() 488 defer th.TearDown() 489 490 var mockAPI plugintest.API 491 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 492 mockAPI.On("LogDebug", "testhook.txt").Return(nil) 493 mockAPI.On("LogDebug", "inputfile").Return(nil) 494 SetAppEnvironmentWithPlugins(t, []string{ 495 ` 496 package main 497 498 import ( 499 "io" 500 "github.com/mattermost/mattermost-server/plugin" 501 "github.com/mattermost/mattermost-server/model" 502 ) 503 504 type MyPlugin struct { 505 plugin.MattermostPlugin 506 } 507 508 func (p *MyPlugin) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) { 509 output.Write([]byte("ignored")) 510 info.Name = "ignored" 511 return info, "rejected" 512 } 513 514 func main() { 515 plugin.ClientMain(&MyPlugin{}) 516 } 517 `, 518 }, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 519 520 _, err := th.App.UploadFiles( 521 "noteam", 522 th.BasicChannel.Id, 523 th.BasicUser.Id, 524 []io.ReadCloser{ioutil.NopCloser(bytes.NewBufferString("inputfile"))}, 525 []string{"testhook.txt"}, 526 []string{}, 527 time.Now(), 528 ) 529 if assert.NotNil(t, err) { 530 assert.Equal(t, "File rejected by plugin. rejected", err.Message) 531 } 532 }) 533 534 t.Run("allowed", func(t *testing.T) { 535 th := Setup().InitBasic() 536 defer th.TearDown() 537 538 var mockAPI plugintest.API 539 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 540 mockAPI.On("LogDebug", "testhook.txt").Return(nil) 541 mockAPI.On("LogDebug", "inputfile").Return(nil) 542 SetAppEnvironmentWithPlugins(t, []string{ 543 ` 544 package main 545 546 import ( 547 "io" 548 "github.com/mattermost/mattermost-server/plugin" 549 "github.com/mattermost/mattermost-server/model" 550 ) 551 552 type MyPlugin struct { 553 plugin.MattermostPlugin 554 } 555 556 func (p *MyPlugin) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) { 557 return nil, "" 558 } 559 560 func main() { 561 plugin.ClientMain(&MyPlugin{}) 562 } 563 `, 564 }, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 565 566 response, err := th.App.UploadFiles( 567 "noteam", 568 th.BasicChannel.Id, 569 th.BasicUser.Id, 570 []io.ReadCloser{ioutil.NopCloser(bytes.NewBufferString("inputfile"))}, 571 []string{"testhook.txt"}, 572 []string{}, 573 time.Now(), 574 ) 575 assert.Nil(t, err) 576 assert.NotNil(t, response) 577 assert.Equal(t, 1, len(response.FileInfos)) 578 fileId := response.FileInfos[0].Id 579 580 fileInfo, err := th.App.GetFileInfo(fileId) 581 assert.Nil(t, err) 582 assert.NotNil(t, fileInfo) 583 assert.Equal(t, "testhook.txt", fileInfo.Name) 584 585 fileReader, err := th.App.FileReader(fileInfo.Path) 586 assert.Nil(t, err) 587 var resultBuf bytes.Buffer 588 io.Copy(&resultBuf, fileReader) 589 assert.Equal(t, "inputfile", resultBuf.String()) 590 }) 591 592 t.Run("updated", func(t *testing.T) { 593 th := Setup().InitBasic() 594 defer th.TearDown() 595 596 var mockAPI plugintest.API 597 mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil) 598 mockAPI.On("LogDebug", "testhook.txt").Return(nil) 599 mockAPI.On("LogDebug", "inputfile").Return(nil) 600 SetAppEnvironmentWithPlugins(t, []string{ 601 ` 602 package main 603 604 import ( 605 "io" 606 "bytes" 607 "github.com/mattermost/mattermost-server/plugin" 608 "github.com/mattermost/mattermost-server/model" 609 ) 610 611 type MyPlugin struct { 612 plugin.MattermostPlugin 613 } 614 615 func (p *MyPlugin) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) { 616 p.API.LogDebug(info.Name) 617 var buf bytes.Buffer 618 buf.ReadFrom(file) 619 p.API.LogDebug(buf.String()) 620 621 outbuf := bytes.NewBufferString("changedtext") 622 io.Copy(output, outbuf) 623 info.Name = "modifiedinfo" 624 return info, "" 625 } 626 627 func main() { 628 plugin.ClientMain(&MyPlugin{}) 629 } 630 `, 631 }, th.App, func(*model.Manifest) plugin.API { return &mockAPI }) 632 633 response, err := th.App.UploadFiles( 634 "noteam", 635 th.BasicChannel.Id, 636 th.BasicUser.Id, 637 []io.ReadCloser{ioutil.NopCloser(bytes.NewBufferString("inputfile"))}, 638 []string{"testhook.txt"}, 639 []string{}, 640 time.Now(), 641 ) 642 assert.Nil(t, err) 643 assert.NotNil(t, response) 644 assert.Equal(t, 1, len(response.FileInfos)) 645 fileId := response.FileInfos[0].Id 646 647 fileInfo, err := th.App.GetFileInfo(fileId) 648 assert.Nil(t, err) 649 assert.NotNil(t, fileInfo) 650 assert.Equal(t, "modifiedinfo", fileInfo.Name) 651 652 fileReader, err := th.App.FileReader(fileInfo.Path) 653 assert.Nil(t, err) 654 var resultBuf bytes.Buffer 655 io.Copy(&resultBuf, fileReader) 656 assert.Equal(t, "changedtext", resultBuf.String()) 657 }) 658 } 659 660 func TestUserWillLogIn_Blocked(t *testing.T) { 661 th := Setup().InitBasic() 662 defer th.TearDown() 663 664 err := th.App.UpdatePassword(th.BasicUser, "hunter2") 665 666 if err != nil { 667 t.Errorf("Error updating user password: %s", err) 668 } 669 670 SetAppEnvironmentWithPlugins(t, 671 []string{ 672 ` 673 package main 674 675 import ( 676 "github.com/mattermost/mattermost-server/plugin" 677 "github.com/mattermost/mattermost-server/model" 678 ) 679 680 type MyPlugin struct { 681 plugin.MattermostPlugin 682 } 683 684 func (p *MyPlugin) UserWillLogIn(c *plugin.Context, user *model.User) string { 685 return "Blocked By Plugin" 686 } 687 688 func main() { 689 plugin.ClientMain(&MyPlugin{}) 690 } 691 `}, th.App, th.App.NewPluginAPI) 692 693 user, err := th.App.AuthenticateUserForLogin("", th.BasicUser.Email, "hunter2", "", false) 694 695 if user != nil { 696 t.Errorf("Expected nil, got %+v", user) 697 } 698 699 if err == nil { 700 t.Errorf("Expected err, got nil") 701 } 702 } 703 704 func TestUserWillLogInIn_Passed(t *testing.T) { 705 th := Setup().InitBasic() 706 defer th.TearDown() 707 708 err := th.App.UpdatePassword(th.BasicUser, "hunter2") 709 710 if err != nil { 711 t.Errorf("Error updating user password: %s", err) 712 } 713 714 SetAppEnvironmentWithPlugins(t, 715 []string{ 716 ` 717 package main 718 719 import ( 720 "github.com/mattermost/mattermost-server/plugin" 721 "github.com/mattermost/mattermost-server/model" 722 ) 723 724 type MyPlugin struct { 725 plugin.MattermostPlugin 726 } 727 728 func (p *MyPlugin) UserWillLogIn(c *plugin.Context, user *model.User) string { 729 return "" 730 } 731 732 func main() { 733 plugin.ClientMain(&MyPlugin{}) 734 } 735 `}, th.App, th.App.NewPluginAPI) 736 737 user, err := th.App.AuthenticateUserForLogin("", th.BasicUser.Email, "hunter2", "", false) 738 739 if user == nil { 740 t.Errorf("Expected user object, got nil") 741 } 742 743 if err != nil { 744 t.Errorf("Expected nil, got %s", err) 745 } 746 } 747 748 func TestUserHasLoggedIn(t *testing.T) { 749 th := Setup().InitBasic() 750 defer th.TearDown() 751 752 err := th.App.UpdatePassword(th.BasicUser, "hunter2") 753 754 if err != nil { 755 t.Errorf("Error updating user password: %s", err) 756 } 757 758 SetAppEnvironmentWithPlugins(t, 759 []string{ 760 ` 761 package main 762 763 import ( 764 "github.com/mattermost/mattermost-server/plugin" 765 "github.com/mattermost/mattermost-server/model" 766 ) 767 768 type MyPlugin struct { 769 plugin.MattermostPlugin 770 } 771 772 func (p *MyPlugin) UserHasLoggedIn(c *plugin.Context, user *model.User) { 773 user.FirstName = "plugin-callback-success" 774 p.API.UpdateUser(user) 775 } 776 777 func main() { 778 plugin.ClientMain(&MyPlugin{}) 779 } 780 `}, th.App, th.App.NewPluginAPI) 781 782 user, err := th.App.AuthenticateUserForLogin("", th.BasicUser.Email, "hunter2", "", false) 783 784 if user == nil { 785 t.Errorf("Expected user object, got nil") 786 } 787 788 if err != nil { 789 t.Errorf("Expected nil, got %s", err) 790 } 791 792 time.Sleep(2 * time.Second) 793 794 user, _ = th.App.GetUser(th.BasicUser.Id) 795 796 if user.FirstName != "plugin-callback-success" { 797 t.Errorf("Expected firstname overwrite, got default") 798 } 799 } 800 801 func TestErrorString(t *testing.T) { 802 th := Setup().InitBasic() 803 defer th.TearDown() 804 805 t.Run("errors.New", func(t *testing.T) { 806 activationErrors := SetAppEnvironmentWithPlugins(t, 807 []string{ 808 ` 809 package main 810 811 import ( 812 "github.com/pkg/errors" 813 814 "github.com/mattermost/mattermost-server/plugin" 815 ) 816 817 type MyPlugin struct { 818 plugin.MattermostPlugin 819 } 820 821 func (p *MyPlugin) OnActivate() error { 822 return errors.New("simulate failure") 823 } 824 825 func main() { 826 plugin.ClientMain(&MyPlugin{}) 827 } 828 `}, th.App, th.App.NewPluginAPI) 829 830 require.Len(t, activationErrors, 1) 831 require.NotNil(t, activationErrors[0]) 832 require.Contains(t, activationErrors[0].Error(), "simulate failure") 833 }) 834 835 t.Run("AppError", func(t *testing.T) { 836 activationErrors := SetAppEnvironmentWithPlugins(t, 837 []string{ 838 ` 839 package main 840 841 import ( 842 "github.com/mattermost/mattermost-server/plugin" 843 "github.com/mattermost/mattermost-server/model" 844 ) 845 846 type MyPlugin struct { 847 plugin.MattermostPlugin 848 } 849 850 func (p *MyPlugin) OnActivate() error { 851 return model.NewAppError("where", "id", map[string]interface{}{"param": 1}, "details", 42) 852 } 853 854 func main() { 855 plugin.ClientMain(&MyPlugin{}) 856 } 857 `}, th.App, th.App.NewPluginAPI) 858 859 require.Len(t, activationErrors, 1) 860 require.NotNil(t, activationErrors[0]) 861 862 cause := errors.Cause(activationErrors[0]) 863 require.IsType(t, &model.AppError{}, cause) 864 865 // params not expected, since not exported 866 expectedErr := model.NewAppError("where", "id", nil, "details", 42) 867 require.Equal(t, expectedErr, cause) 868 }) 869 }