github.com/adacta-ru/mattermost-server@v5.11.1+incompatible/app/post_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 "fmt" 8 "net/http" 9 "sync" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 "github.com/mattermost/mattermost-server/model" 17 "github.com/mattermost/mattermost-server/store" 18 "github.com/mattermost/mattermost-server/store/storetest" 19 ) 20 21 func TestCreatePostDeduplicate(t *testing.T) { 22 th := Setup(t).InitBasic() 23 defer th.TearDown() 24 25 t.Run("duplicate create post is idempotent", func(t *testing.T) { 26 pendingPostId := model.NewId() 27 post, err := th.App.CreatePostAsUser(&model.Post{ 28 UserId: th.BasicUser.Id, 29 ChannelId: th.BasicChannel.Id, 30 Message: "message", 31 PendingPostId: pendingPostId, 32 }, "") 33 require.Nil(t, err) 34 require.Equal(t, "message", post.Message) 35 36 duplicatePost, err := th.App.CreatePostAsUser(&model.Post{ 37 UserId: th.BasicUser.Id, 38 ChannelId: th.BasicChannel.Id, 39 Message: "message", 40 PendingPostId: pendingPostId, 41 }, "") 42 require.Nil(t, err) 43 require.Equal(t, post.Id, duplicatePost.Id, "should have returned previously created post id") 44 require.Equal(t, "message", duplicatePost.Message) 45 }) 46 47 t.Run("post rejected by plugin leaves cache ready for non-deduplicated try", func(t *testing.T) { 48 setupPluginApiTest(t, ` 49 package main 50 51 import ( 52 "github.com/mattermost/mattermost-server/plugin" 53 "github.com/mattermost/mattermost-server/model" 54 ) 55 56 type MyPlugin struct { 57 plugin.MattermostPlugin 58 allow bool 59 } 60 61 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 62 if !p.allow { 63 p.allow = true 64 return nil, "rejected" 65 } 66 67 return nil, "" 68 } 69 70 func main() { 71 plugin.ClientMain(&MyPlugin{}) 72 } 73 `, `{"id": "testrejectfirstpost", "backend": {"executable": "backend.exe"}}`, "testrejectfirstpost", th.App) 74 75 pendingPostId := model.NewId() 76 post, err := th.App.CreatePostAsUser(&model.Post{ 77 UserId: th.BasicUser.Id, 78 ChannelId: th.BasicChannel.Id, 79 Message: "message", 80 PendingPostId: pendingPostId, 81 }, "") 82 require.NotNil(t, err) 83 require.Equal(t, "Post rejected by plugin. rejected", err.Id) 84 require.Nil(t, post) 85 86 duplicatePost, err := th.App.CreatePostAsUser(&model.Post{ 87 UserId: th.BasicUser.Id, 88 ChannelId: th.BasicChannel.Id, 89 Message: "message", 90 PendingPostId: pendingPostId, 91 }, "") 92 require.Nil(t, err) 93 require.Equal(t, "message", duplicatePost.Message) 94 }) 95 96 t.Run("slow posting after cache entry blocks duplicate request", func(t *testing.T) { 97 setupPluginApiTest(t, ` 98 package main 99 100 import ( 101 "github.com/mattermost/mattermost-server/plugin" 102 "github.com/mattermost/mattermost-server/model" 103 "time" 104 ) 105 106 type MyPlugin struct { 107 plugin.MattermostPlugin 108 instant bool 109 } 110 111 func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) { 112 if !p.instant { 113 p.instant = true 114 time.Sleep(3 * time.Second) 115 } 116 117 return nil, "" 118 } 119 120 func main() { 121 plugin.ClientMain(&MyPlugin{}) 122 } 123 `, `{"id": "testdelayfirstpost", "backend": {"executable": "backend.exe"}}`, "testdelayfirstpost", th.App) 124 125 var post *model.Post 126 pendingPostId := model.NewId() 127 128 wg := sync.WaitGroup{} 129 130 // Launch a goroutine to make the first CreatePost call that will get delayed 131 // by the plugin above. 132 wg.Add(1) 133 go func() { 134 defer wg.Done() 135 var err error 136 post, err = th.App.CreatePostAsUser(&model.Post{ 137 UserId: th.BasicUser.Id, 138 ChannelId: th.BasicChannel.Id, 139 Message: "plugin delayed", 140 PendingPostId: pendingPostId, 141 }, "") 142 require.Nil(t, err) 143 require.Equal(t, post.Message, "plugin delayed") 144 }() 145 146 // Give the goroutine above a chance to start and get delayed by the plugin. 147 time.Sleep(2 * time.Second) 148 149 // Try creating a duplicate post 150 duplicatePost, err := th.App.CreatePostAsUser(&model.Post{ 151 UserId: th.BasicUser.Id, 152 ChannelId: th.BasicChannel.Id, 153 Message: "plugin delayed", 154 PendingPostId: pendingPostId, 155 }, "") 156 require.NotNil(t, err) 157 require.Equal(t, "api.post.deduplicate_create_post.pending", err.Id) 158 require.Nil(t, duplicatePost) 159 160 // Wait for the first CreatePost to finish to ensure assertions are made. 161 wg.Wait() 162 }) 163 164 t.Run("duplicate create post after cache expires is not idempotent", func(t *testing.T) { 165 pendingPostId := model.NewId() 166 post, err := th.App.CreatePostAsUser(&model.Post{ 167 UserId: th.BasicUser.Id, 168 ChannelId: th.BasicChannel.Id, 169 Message: "message", 170 PendingPostId: pendingPostId, 171 }, "") 172 require.Nil(t, err) 173 require.Equal(t, "message", post.Message) 174 175 time.Sleep(PENDING_POST_IDS_CACHE_TTL) 176 177 duplicatePost, err := th.App.CreatePostAsUser(&model.Post{ 178 UserId: th.BasicUser.Id, 179 ChannelId: th.BasicChannel.Id, 180 Message: "message", 181 PendingPostId: pendingPostId, 182 }, "") 183 require.Nil(t, err) 184 require.NotEqual(t, post.Id, duplicatePost.Id, "should have created new post id") 185 require.Equal(t, "message", duplicatePost.Message) 186 }) 187 } 188 189 func TestAttachFilesToPost(t *testing.T) { 190 t.Run("should attach files", func(t *testing.T) { 191 th := Setup(t).InitBasic() 192 defer th.TearDown() 193 194 info1 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 195 CreatorId: th.BasicUser.Id, 196 Path: "path.txt", 197 })).(*model.FileInfo) 198 info2 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 199 CreatorId: th.BasicUser.Id, 200 Path: "path.txt", 201 })).(*model.FileInfo) 202 203 post := th.BasicPost 204 post.FileIds = []string{info1.Id, info2.Id} 205 206 err := th.App.attachFilesToPost(post) 207 assert.Nil(t, err) 208 209 infos, err := th.App.GetFileInfosForPost(post.Id) 210 assert.Nil(t, err) 211 assert.Len(t, infos, 2) 212 }) 213 214 t.Run("should update File.PostIds after failing to add files", func(t *testing.T) { 215 th := Setup(t).InitBasic() 216 defer th.TearDown() 217 218 info1 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 219 CreatorId: th.BasicUser.Id, 220 Path: "path.txt", 221 PostId: model.NewId(), 222 })).(*model.FileInfo) 223 info2 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 224 CreatorId: th.BasicUser.Id, 225 Path: "path.txt", 226 })).(*model.FileInfo) 227 228 post := th.BasicPost 229 post.FileIds = []string{info1.Id, info2.Id} 230 231 err := th.App.attachFilesToPost(post) 232 assert.Nil(t, err) 233 234 infos, err := th.App.GetFileInfosForPost(post.Id) 235 assert.Nil(t, err) 236 assert.Len(t, infos, 1) 237 assert.Equal(t, info2.Id, infos[0].Id) 238 239 updated, err := th.App.GetSinglePost(post.Id) 240 require.Nil(t, err) 241 assert.Len(t, updated.FileIds, 1) 242 assert.Contains(t, updated.FileIds, info2.Id) 243 }) 244 } 245 246 func TestUpdatePostEditAt(t *testing.T) { 247 th := Setup(t).InitBasic() 248 defer th.TearDown() 249 250 post := &model.Post{} 251 *post = *th.BasicPost 252 253 post.IsPinned = true 254 if saved, err := th.App.UpdatePost(post, true); err != nil { 255 t.Fatal(err) 256 } else if saved.EditAt != post.EditAt { 257 t.Fatal("shouldn't have updated post.EditAt when pinning post") 258 259 *post = *saved 260 } 261 262 time.Sleep(time.Millisecond * 100) 263 264 post.Message = model.NewId() 265 if saved, err := th.App.UpdatePost(post, true); err != nil { 266 t.Fatal(err) 267 } else if saved.EditAt == post.EditAt { 268 t.Fatal("should have updated post.EditAt when updating post message") 269 } 270 271 time.Sleep(time.Millisecond * 200) 272 } 273 274 func TestUpdatePostTimeLimit(t *testing.T) { 275 th := Setup(t).InitBasic() 276 defer th.TearDown() 277 278 post := &model.Post{} 279 *post = *th.BasicPost 280 281 th.App.SetLicense(model.NewTestLicense()) 282 283 th.App.UpdateConfig(func(cfg *model.Config) { 284 *cfg.ServiceSettings.PostEditTimeLimit = -1 285 }) 286 if _, err := th.App.UpdatePost(post, true); err != nil { 287 t.Fatal(err) 288 } 289 290 th.App.UpdateConfig(func(cfg *model.Config) { 291 *cfg.ServiceSettings.PostEditTimeLimit = 1000000000 292 }) 293 post.Message = model.NewId() 294 if _, err := th.App.UpdatePost(post, true); err != nil { 295 t.Fatal("should allow you to edit the post") 296 } 297 298 th.App.UpdateConfig(func(cfg *model.Config) { 299 *cfg.ServiceSettings.PostEditTimeLimit = 1 300 }) 301 post.Message = model.NewId() 302 if _, err := th.App.UpdatePost(post, true); err == nil { 303 t.Fatal("should fail on update old post") 304 } 305 306 th.App.UpdateConfig(func(cfg *model.Config) { 307 *cfg.ServiceSettings.PostEditTimeLimit = -1 308 }) 309 } 310 311 func TestUpdatePostInArchivedChannel(t *testing.T) { 312 th := Setup(t).InitBasic() 313 defer th.TearDown() 314 315 archivedChannel := th.CreateChannel(th.BasicTeam) 316 post := th.CreatePost(archivedChannel) 317 th.App.DeleteChannel(archivedChannel, "") 318 319 _, err := th.App.UpdatePost(post, true) 320 require.NotNil(t, err) 321 require.Equal(t, "api.post.update_post.can_not_update_post_in_deleted.error", err.Id) 322 } 323 324 func TestPostReplyToPostWhereRootPosterLeftChannel(t *testing.T) { 325 // This test ensures that when replying to a root post made by a user who has since left the channel, the reply 326 // post completes successfully. This is a regression test for PLT-6523. 327 th := Setup(t).InitBasic() 328 defer th.TearDown() 329 330 channel := th.BasicChannel 331 userInChannel := th.BasicUser2 332 userNotInChannel := th.BasicUser 333 rootPost := th.BasicPost 334 335 if _, err := th.App.AddUserToChannel(userInChannel, channel); err != nil { 336 t.Fatal(err) 337 } 338 339 if err := th.App.RemoveUserFromChannel(userNotInChannel.Id, "", channel); err != nil { 340 t.Fatal(err) 341 } 342 343 replyPost := model.Post{ 344 Message: "asd", 345 ChannelId: channel.Id, 346 RootId: rootPost.Id, 347 ParentId: rootPost.Id, 348 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 349 UserId: userInChannel.Id, 350 CreateAt: 0, 351 } 352 353 if _, err := th.App.CreatePostAsUser(&replyPost, ""); err != nil { 354 t.Fatal(err) 355 } 356 } 357 358 func TestPostAttachPostToChildPost(t *testing.T) { 359 th := Setup(t).InitBasic() 360 defer th.TearDown() 361 362 channel := th.BasicChannel 363 user := th.BasicUser 364 rootPost := th.BasicPost 365 366 replyPost1 := model.Post{ 367 Message: "reply one", 368 ChannelId: channel.Id, 369 RootId: rootPost.Id, 370 ParentId: rootPost.Id, 371 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 372 UserId: user.Id, 373 CreateAt: 0, 374 } 375 376 res1, err := th.App.CreatePostAsUser(&replyPost1, "") 377 if err != nil { 378 t.Fatal(err) 379 } 380 381 replyPost2 := model.Post{ 382 Message: "reply two", 383 ChannelId: channel.Id, 384 RootId: res1.Id, 385 ParentId: res1.Id, 386 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 387 UserId: user.Id, 388 CreateAt: 0, 389 } 390 391 _, err = th.App.CreatePostAsUser(&replyPost2, "") 392 if err.StatusCode != http.StatusBadRequest { 393 t.Fatal(fmt.Sprintf("Expected BadRequest error, got %v", err)) 394 } 395 396 replyPost3 := model.Post{ 397 Message: "reply three", 398 ChannelId: channel.Id, 399 RootId: rootPost.Id, 400 ParentId: rootPost.Id, 401 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 402 UserId: user.Id, 403 CreateAt: 0, 404 } 405 406 if _, err := th.App.CreatePostAsUser(&replyPost3, ""); err != nil { 407 t.Fatal(err) 408 } 409 } 410 411 func TestPostChannelMentions(t *testing.T) { 412 th := Setup(t).InitBasic() 413 defer th.TearDown() 414 415 channel := th.BasicChannel 416 user := th.BasicUser 417 418 channelToMention, err := th.App.CreateChannel(&model.Channel{ 419 DisplayName: "Mention Test", 420 Name: "mention-test", 421 Type: model.CHANNEL_OPEN, 422 TeamId: th.BasicTeam.Id, 423 }, false) 424 if err != nil { 425 t.Fatal(err.Error()) 426 } 427 defer th.App.PermanentDeleteChannel(channelToMention) 428 429 _, err = th.App.AddUserToChannel(user, channel) 430 require.Nil(t, err) 431 432 post := &model.Post{ 433 Message: fmt.Sprintf("hello, ~%v!", channelToMention.Name), 434 ChannelId: channel.Id, 435 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 436 UserId: user.Id, 437 CreateAt: 0, 438 } 439 440 result, err := th.App.CreatePostAsUser(post, "") 441 require.Nil(t, err) 442 assert.Equal(t, map[string]interface{}{ 443 "mention-test": map[string]interface{}{ 444 "display_name": "Mention Test", 445 }, 446 }, result.Props["channel_mentions"]) 447 448 post.Message = fmt.Sprintf("goodbye, ~%v!", channelToMention.Name) 449 result, err = th.App.UpdatePost(post, false) 450 require.Nil(t, err) 451 assert.Equal(t, map[string]interface{}{ 452 "mention-test": map[string]interface{}{ 453 "display_name": "Mention Test", 454 }, 455 }, result.Props["channel_mentions"]) 456 } 457 458 func TestImageProxy(t *testing.T) { 459 th := Setup(t).InitBasic() 460 defer th.TearDown() 461 462 th.App.UpdateConfig(func(cfg *model.Config) { 463 *cfg.ServiceSettings.SiteURL = "http://mymattermost.com" 464 }) 465 466 for name, tc := range map[string]struct { 467 ProxyType string 468 ProxyURL string 469 ProxyOptions string 470 ImageURL string 471 ProxiedImageURL string 472 }{ 473 "atmos/camo": { 474 ProxyType: model.IMAGE_PROXY_TYPE_ATMOS_CAMO, 475 ProxyURL: "https://127.0.0.1", 476 ProxyOptions: "foo", 477 ImageURL: "http://mydomain.com/myimage", 478 ProxiedImageURL: "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765", 479 }, 480 "atmos/camo_SameSite": { 481 ProxyType: model.IMAGE_PROXY_TYPE_ATMOS_CAMO, 482 ProxyURL: "https://127.0.0.1", 483 ProxyOptions: "foo", 484 ImageURL: "http://mymattermost.com/myimage", 485 ProxiedImageURL: "http://mymattermost.com/myimage", 486 }, 487 "atmos/camo_PathOnly": { 488 ProxyType: model.IMAGE_PROXY_TYPE_ATMOS_CAMO, 489 ProxyURL: "https://127.0.0.1", 490 ProxyOptions: "foo", 491 ImageURL: "/myimage", 492 ProxiedImageURL: "/myimage", 493 }, 494 "atmos/camo_EmptyImageURL": { 495 ProxyType: model.IMAGE_PROXY_TYPE_ATMOS_CAMO, 496 ProxyURL: "https://127.0.0.1", 497 ProxyOptions: "foo", 498 ImageURL: "", 499 ProxiedImageURL: "", 500 }, 501 "local": { 502 ProxyType: model.IMAGE_PROXY_TYPE_LOCAL, 503 ImageURL: "http://mydomain.com/myimage", 504 ProxiedImageURL: "http://mymattermost.com/api/v4/image?url=http%3A%2F%2Fmydomain.com%2Fmyimage", 505 }, 506 "local_SameSite": { 507 ProxyType: model.IMAGE_PROXY_TYPE_LOCAL, 508 ImageURL: "http://mymattermost.com/myimage", 509 ProxiedImageURL: "http://mymattermost.com/myimage", 510 }, 511 "local_PathOnly": { 512 ProxyType: model.IMAGE_PROXY_TYPE_LOCAL, 513 ImageURL: "/myimage", 514 ProxiedImageURL: "/myimage", 515 }, 516 "local_EmptyImageURL": { 517 ProxyType: model.IMAGE_PROXY_TYPE_LOCAL, 518 ImageURL: "", 519 ProxiedImageURL: "", 520 }, 521 } { 522 t.Run(name, func(t *testing.T) { 523 th.App.UpdateConfig(func(cfg *model.Config) { 524 cfg.ImageProxySettings.Enable = model.NewBool(true) 525 cfg.ImageProxySettings.ImageProxyType = model.NewString(tc.ProxyType) 526 cfg.ImageProxySettings.RemoteImageProxyOptions = model.NewString(tc.ProxyOptions) 527 cfg.ImageProxySettings.RemoteImageProxyURL = model.NewString(tc.ProxyURL) 528 }) 529 530 post := &model.Post{ 531 Id: model.NewId(), 532 Message: "![foo](" + tc.ImageURL + ")", 533 } 534 535 list := model.NewPostList() 536 list.Posts[post.Id] = post 537 538 assert.Equal(t, "![foo]("+tc.ProxiedImageURL+")", th.App.PostWithProxyAddedToImageURLs(post).Message) 539 540 assert.Equal(t, "![foo]("+tc.ImageURL+")", th.App.PostWithProxyRemovedFromImageURLs(post).Message) 541 post.Message = "![foo](" + tc.ProxiedImageURL + ")" 542 assert.Equal(t, "![foo]("+tc.ImageURL+")", th.App.PostWithProxyRemovedFromImageURLs(post).Message) 543 544 if tc.ImageURL != "" { 545 post.Message = "![foo](" + tc.ImageURL + " =500x200)" 546 assert.Equal(t, "![foo]("+tc.ProxiedImageURL+" =500x200)", th.App.PostWithProxyAddedToImageURLs(post).Message) 547 assert.Equal(t, "![foo]("+tc.ImageURL+" =500x200)", th.App.PostWithProxyRemovedFromImageURLs(post).Message) 548 post.Message = "![foo](" + tc.ProxiedImageURL + " =500x200)" 549 assert.Equal(t, "![foo]("+tc.ImageURL+" =500x200)", th.App.PostWithProxyRemovedFromImageURLs(post).Message) 550 } 551 }) 552 } 553 } 554 555 func TestMaxPostSize(t *testing.T) { 556 t.Parallel() 557 558 testCases := []struct { 559 Description string 560 StoreMaxPostSize int 561 ExpectedMaxPostSize int 562 ExpectedError *model.AppError 563 }{ 564 { 565 "error fetching max post size", 566 0, 567 model.POST_MESSAGE_MAX_RUNES_V1, 568 model.NewAppError("TestMaxPostSize", "this is an error", nil, "", http.StatusBadRequest), 569 }, 570 { 571 "4000 rune limit", 572 4000, 573 4000, 574 nil, 575 }, 576 { 577 "16383 rune limit", 578 16383, 579 16383, 580 nil, 581 }, 582 } 583 584 for _, testCase := range testCases { 585 testCase := testCase 586 t.Run(testCase.Description, func(t *testing.T) { 587 t.Parallel() 588 589 mockStore := &storetest.Store{} 590 defer mockStore.AssertExpectations(t) 591 592 mockStore.PostStore.On("GetMaxPostSize").Return( 593 storetest.NewStoreChannel(store.StoreResult{ 594 Data: testCase.StoreMaxPostSize, 595 Err: testCase.ExpectedError, 596 }), 597 ) 598 599 app := App{ 600 Srv: &Server{ 601 Store: mockStore, 602 }, 603 } 604 605 assert.Equal(t, testCase.ExpectedMaxPostSize, app.MaxPostSize()) 606 }) 607 } 608 } 609 610 func TestDeletePostWithFileAttachments(t *testing.T) { 611 th := Setup(t).InitBasic() 612 defer th.TearDown() 613 614 // Create a post with a file attachment. 615 teamId := th.BasicTeam.Id 616 channelId := th.BasicChannel.Id 617 userId := th.BasicUser.Id 618 filename := "test" 619 data := []byte("abcd") 620 621 info1, err := th.App.DoUploadFile(time.Date(2007, 2, 4, 1, 2, 3, 4, time.Local), teamId, channelId, userId, filename, data) 622 if err != nil { 623 t.Fatal(err) 624 } else { 625 defer func() { 626 <-th.App.Srv.Store.FileInfo().PermanentDelete(info1.Id) 627 th.App.RemoveFile(info1.Path) 628 }() 629 } 630 631 post := &model.Post{ 632 Message: "asd", 633 ChannelId: channelId, 634 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 635 UserId: userId, 636 CreateAt: 0, 637 FileIds: []string{info1.Id}, 638 } 639 640 post, err = th.App.CreatePost(post, th.BasicChannel, false) 641 assert.Nil(t, err) 642 643 // Delete the post. 644 post, err = th.App.DeletePost(post.Id, userId) 645 assert.Nil(t, err) 646 647 // Wait for the cleanup routine to finish. 648 time.Sleep(time.Millisecond * 100) 649 650 // Check that the file can no longer be reached. 651 _, err = th.App.GetFileInfo(info1.Id) 652 assert.NotNil(t, err) 653 } 654 655 func TestDeletePostInArchivedChannel(t *testing.T) { 656 th := Setup(t).InitBasic() 657 defer th.TearDown() 658 659 archivedChannel := th.CreateChannel(th.BasicTeam) 660 post := th.CreatePost(archivedChannel) 661 th.App.DeleteChannel(archivedChannel, "") 662 663 _, err := th.App.DeletePost(post.Id, "") 664 require.NotNil(t, err) 665 require.Equal(t, "api.post.delete_post.can_not_delete_post_in_deleted.error", err.Id) 666 } 667 668 func TestCreatePost(t *testing.T) { 669 t.Run("call PreparePostForClient before returning", func(t *testing.T) { 670 th := Setup(t).InitBasic() 671 defer th.TearDown() 672 673 th.App.UpdateConfig(func(cfg *model.Config) { 674 *cfg.ExperimentalSettings.DisablePostMetadata = true 675 *cfg.ImageProxySettings.Enable = true 676 *cfg.ImageProxySettings.ImageProxyType = "atmos/camo" 677 *cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1" 678 *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" 679 }) 680 681 imageURL := "http://mydomain.com/myimage" 682 proxiedImageURL := "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765" 683 684 post := &model.Post{ 685 ChannelId: th.BasicChannel.Id, 686 Message: "![image](" + imageURL + ")", 687 UserId: th.BasicUser.Id, 688 } 689 690 rpost, err := th.App.CreatePost(post, th.BasicChannel, false) 691 require.Nil(t, err) 692 assert.Equal(t, "![image]("+proxiedImageURL+")", rpost.Message) 693 }) 694 } 695 696 func TestPatchPost(t *testing.T) { 697 t.Run("call PreparePostForClient before returning", func(t *testing.T) { 698 th := Setup(t).InitBasic() 699 defer th.TearDown() 700 701 th.App.UpdateConfig(func(cfg *model.Config) { 702 *cfg.ExperimentalSettings.DisablePostMetadata = true 703 *cfg.ImageProxySettings.Enable = true 704 *cfg.ImageProxySettings.ImageProxyType = "atmos/camo" 705 *cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1" 706 *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" 707 }) 708 709 imageURL := "http://mydomain.com/myimage" 710 proxiedImageURL := "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765" 711 712 post := &model.Post{ 713 ChannelId: th.BasicChannel.Id, 714 Message: "![image](http://mydomain/anotherimage)", 715 UserId: th.BasicUser.Id, 716 } 717 718 rpost, err := th.App.CreatePost(post, th.BasicChannel, false) 719 require.Nil(t, err) 720 assert.NotEqual(t, "![image]("+proxiedImageURL+")", rpost.Message) 721 722 patch := &model.PostPatch{ 723 Message: model.NewString("![image](" + imageURL + ")"), 724 } 725 726 rpost, err = th.App.PatchPost(rpost.Id, patch) 727 require.Nil(t, err) 728 assert.Equal(t, "![image]("+proxiedImageURL+")", rpost.Message) 729 }) 730 } 731 732 func TestPatchPostInArchivedChannel(t *testing.T) { 733 th := Setup(t).InitBasic() 734 defer th.TearDown() 735 736 archivedChannel := th.CreateChannel(th.BasicTeam) 737 post := th.CreatePost(archivedChannel) 738 th.App.DeleteChannel(archivedChannel, "") 739 740 _, err := th.App.PatchPost(post.Id, &model.PostPatch{IsPinned: model.NewBool(true)}) 741 require.NotNil(t, err) 742 require.Equal(t, "api.post.patch_post.can_not_update_post_in_deleted.error", err.Id) 743 } 744 745 func TestUpdatePost(t *testing.T) { 746 t.Run("call PreparePostForClient before returning", func(t *testing.T) { 747 th := Setup(t).InitBasic() 748 defer th.TearDown() 749 750 th.App.UpdateConfig(func(cfg *model.Config) { 751 *cfg.ExperimentalSettings.DisablePostMetadata = true 752 *cfg.ImageProxySettings.Enable = true 753 *cfg.ImageProxySettings.ImageProxyType = "atmos/camo" 754 *cfg.ImageProxySettings.RemoteImageProxyURL = "https://127.0.0.1" 755 *cfg.ImageProxySettings.RemoteImageProxyOptions = "foo" 756 }) 757 758 imageURL := "http://mydomain.com/myimage" 759 proxiedImageURL := "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765" 760 761 post := &model.Post{ 762 ChannelId: th.BasicChannel.Id, 763 Message: "![image](http://mydomain/anotherimage)", 764 UserId: th.BasicUser.Id, 765 } 766 767 rpost, err := th.App.CreatePost(post, th.BasicChannel, false) 768 require.Nil(t, err) 769 assert.NotEqual(t, "![image]("+proxiedImageURL+")", rpost.Message) 770 771 post.Id = rpost.Id 772 post.Message = "![image](" + imageURL + ")" 773 774 rpost, err = th.App.UpdatePost(post, false) 775 require.Nil(t, err) 776 assert.Equal(t, "![image]("+proxiedImageURL+")", rpost.Message) 777 }) 778 }