github.com/vnforks/kid@v5.11.1+incompatible/api4/post_test.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package api4 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "net/http/httptest" 11 "net/url" 12 "reflect" 13 "strconv" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/stretchr/testify/assert" 19 20 "github.com/mattermost/mattermost-server/app" 21 "github.com/mattermost/mattermost-server/model" 22 "github.com/mattermost/mattermost-server/utils" 23 "github.com/mattermost/mattermost-server/utils/testutils" 24 ) 25 26 func TestCreatePost(t *testing.T) { 27 th := Setup().InitBasic() 28 defer th.TearDown() 29 Client := th.Client 30 31 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a", Props: model.StringInterface{model.PROPS_ADD_CHANNEL_MEMBER: "no good"}} 32 rpost, resp := Client.CreatePost(post) 33 CheckNoError(t, resp) 34 CheckCreatedStatus(t, resp) 35 36 if rpost.Message != post.Message { 37 t.Fatal("message didn't match") 38 } 39 40 if rpost.Hashtags != "#hashtag" { 41 t.Fatal("hashtag didn't match") 42 } 43 44 if len(rpost.FileIds) != 0 { 45 t.Fatal("shouldn't have files") 46 } 47 48 if rpost.EditAt != 0 { 49 t.Fatal("newly created post shouldn't have EditAt set") 50 } 51 52 if rpost.Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 53 t.Fatal("newly created post shouldn't have Props['add_channel_member'] set") 54 } 55 56 post.RootId = rpost.Id 57 post.ParentId = rpost.Id 58 _, resp = Client.CreatePost(post) 59 CheckNoError(t, resp) 60 61 post.RootId = "junk" 62 _, resp = Client.CreatePost(post) 63 CheckBadRequestStatus(t, resp) 64 65 post.RootId = rpost.Id 66 post.ParentId = "junk" 67 _, resp = Client.CreatePost(post) 68 CheckBadRequestStatus(t, resp) 69 70 post2 := &model.Post{ChannelId: th.BasicChannel2.Id, Message: "zz" + model.NewId() + "a", CreateAt: 123} 71 rpost2, _ := Client.CreatePost(post2) 72 73 if rpost2.CreateAt == post2.CreateAt { 74 t.Fatal("create at should not match") 75 } 76 77 post.RootId = "" 78 post.ParentId = "" 79 post.Type = model.POST_SYSTEM_GENERIC 80 _, resp = Client.CreatePost(post) 81 CheckBadRequestStatus(t, resp) 82 83 post.Type = "" 84 post.RootId = rpost2.Id 85 post.ParentId = rpost2.Id 86 _, resp = Client.CreatePost(post) 87 CheckBadRequestStatus(t, resp) 88 89 post.RootId = "" 90 post.ParentId = "" 91 post.ChannelId = "junk" 92 _, resp = Client.CreatePost(post) 93 CheckForbiddenStatus(t, resp) 94 95 post.ChannelId = model.NewId() 96 _, resp = Client.CreatePost(post) 97 CheckForbiddenStatus(t, resp) 98 99 if r, err := Client.DoApiPost("/posts", "garbage"); err == nil { 100 t.Fatal("should have errored") 101 } else { 102 if r.StatusCode != http.StatusBadRequest { 103 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 104 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 105 t.Fatal("wrong status code") 106 } 107 } 108 109 Client.Logout() 110 _, resp = Client.CreatePost(post) 111 CheckUnauthorizedStatus(t, resp) 112 113 post.ChannelId = th.BasicChannel.Id 114 post.CreateAt = 123 115 rpost, resp = th.SystemAdminClient.CreatePost(post) 116 CheckNoError(t, resp) 117 118 if rpost.CreateAt != post.CreateAt { 119 t.Fatal("create at should match") 120 } 121 } 122 123 func TestCreatePostEphemeral(t *testing.T) { 124 th := Setup().InitBasic() 125 defer th.TearDown() 126 Client := th.SystemAdminClient 127 128 ephemeralPost := &model.PostEphemeral{ 129 UserID: th.BasicUser2.Id, 130 Post: &model.Post{ChannelId: th.BasicChannel.Id, Message: "a" + model.NewId() + "a", Props: model.StringInterface{model.PROPS_ADD_CHANNEL_MEMBER: "no good"}}, 131 } 132 133 rpost, resp := Client.CreatePostEphemeral(ephemeralPost) 134 CheckNoError(t, resp) 135 CheckCreatedStatus(t, resp) 136 137 if rpost.Message != ephemeralPost.Post.Message { 138 t.Fatal("message didn't match") 139 } 140 141 if rpost.EditAt != 0 { 142 t.Fatal("newly created ephemeral post shouldn't have EditAt set") 143 } 144 145 if r, err := Client.DoApiPost("/posts/ephemeral", "garbage"); err == nil { 146 t.Fatal("should have errored") 147 } else { 148 if r.StatusCode != http.StatusBadRequest { 149 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 150 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 151 t.Fatal("wrong status code") 152 } 153 } 154 155 Client.Logout() 156 _, resp = Client.CreatePostEphemeral(ephemeralPost) 157 CheckUnauthorizedStatus(t, resp) 158 159 Client = th.Client 160 _, resp = Client.CreatePostEphemeral(ephemeralPost) 161 CheckForbiddenStatus(t, resp) 162 } 163 164 func testCreatePostWithOutgoingHook( 165 t *testing.T, 166 hookContentType, expectedContentType, message, triggerWord string, 167 fileIds []string, 168 triggerWhen int, 169 commentPostType bool, 170 ) { 171 th := Setup().InitBasic() 172 defer th.TearDown() 173 user := th.SystemAdminUser 174 team := th.BasicTeam 175 channel := th.BasicChannel 176 177 enableOutgoingWebhooks := *th.App.Config().ServiceSettings.EnableOutgoingWebhooks 178 allowedUntrustedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections 179 defer func() { 180 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOutgoingWebhooks = enableOutgoingWebhooks }) 181 th.App.UpdateConfig(func(cfg *model.Config) { 182 *cfg.ServiceSettings.AllowedUntrustedInternalConnections = allowedUntrustedInternalConnections 183 }) 184 }() 185 186 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOutgoingWebhooks = true }) 187 th.App.UpdateConfig(func(cfg *model.Config) { 188 *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1" 189 }) 190 191 var hook *model.OutgoingWebhook 192 var post *model.Post 193 194 // Create a test server that is the target of the outgoing webhook. It will 195 // validate the webhook body fields and write to the success channel on 196 // success/failure. 197 success := make(chan bool) 198 wait := make(chan bool, 1) 199 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 200 <-wait 201 202 requestContentType := r.Header.Get("Content-Type") 203 if requestContentType != expectedContentType { 204 t.Logf("Content-Type is %s, should be %s", requestContentType, expectedContentType) 205 success <- false 206 return 207 } 208 209 expectedPayload := &model.OutgoingWebhookPayload{ 210 Token: hook.Token, 211 TeamId: hook.TeamId, 212 TeamDomain: team.Name, 213 ChannelId: post.ChannelId, 214 ChannelName: channel.Name, 215 Timestamp: post.CreateAt, 216 UserId: post.UserId, 217 UserName: user.Username, 218 PostId: post.Id, 219 Text: post.Message, 220 TriggerWord: triggerWord, 221 FileIds: strings.Join(post.FileIds, ","), 222 } 223 224 // depending on the Content-Type, we expect to find a JSON or form encoded payload 225 if requestContentType == "application/json" { 226 decoder := json.NewDecoder(r.Body) 227 o := &model.OutgoingWebhookPayload{} 228 decoder.Decode(&o) 229 230 if !reflect.DeepEqual(expectedPayload, o) { 231 t.Logf("JSON payload is %+v, should be %+v", o, expectedPayload) 232 success <- false 233 return 234 } 235 } else { 236 err := r.ParseForm() 237 if err != nil { 238 t.Logf("Error parsing form: %q", err) 239 success <- false 240 return 241 } 242 243 expectedFormValues, _ := url.ParseQuery(expectedPayload.ToFormValues()) 244 245 if !reflect.DeepEqual(expectedFormValues, r.Form) { 246 t.Logf("Form values are: %q\n, should be: %q\n", r.Form, expectedFormValues) 247 success <- false 248 return 249 } 250 } 251 252 respPostType := "" //if is empty or post will do a normal post. 253 if commentPostType { 254 respPostType = model.OUTGOING_HOOK_RESPONSE_TYPE_COMMENT 255 } 256 257 outGoingHookResponse := &model.OutgoingWebhookResponse{ 258 Text: model.NewString("some test text"), 259 Username: "TestCommandServer", 260 IconURL: "https://www.mattermost.org/wp-content/uploads/2016/04/icon.png", 261 Type: "custom_as", 262 ResponseType: respPostType, 263 } 264 265 fmt.Fprintf(w, outGoingHookResponse.ToJson()) 266 success <- true 267 })) 268 defer ts.Close() 269 270 // create an outgoing webhook, passing it the test server URL 271 var triggerWords []string 272 if triggerWord != "" { 273 triggerWords = []string{triggerWord} 274 } 275 276 hook = &model.OutgoingWebhook{ 277 ChannelId: channel.Id, 278 TeamId: team.Id, 279 ContentType: hookContentType, 280 TriggerWords: triggerWords, 281 TriggerWhen: triggerWhen, 282 CallbackURLs: []string{ts.URL}, 283 } 284 285 hook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook) 286 CheckNoError(t, resp) 287 288 // create a post to trigger the webhook 289 post = &model.Post{ 290 ChannelId: channel.Id, 291 Message: message, 292 FileIds: fileIds, 293 } 294 295 post, resp = th.SystemAdminClient.CreatePost(post) 296 CheckNoError(t, resp) 297 298 wait <- true 299 300 // We wait for the test server to write to the success channel and we make 301 // the test fail if that doesn't happen before the timeout. 302 select { 303 case ok := <-success: 304 if !ok { 305 t.Fatal("Test server did send an invalid webhook.") 306 } 307 case <-time.After(time.Second): 308 t.Fatal("Timeout, test server did not send the webhook.") 309 } 310 311 if commentPostType { 312 time.Sleep(time.Millisecond * 100) 313 postList, resp := th.SystemAdminClient.GetPostThread(post.Id, "") 314 CheckNoError(t, resp) 315 if postList.Order[0] != post.Id { 316 t.Fatal("wrong order") 317 } 318 319 if _, ok := postList.Posts[post.Id]; !ok { 320 t.Fatal("should have had post") 321 } 322 323 if len(postList.Posts) != 2 { 324 t.Fatal("should have 2 posts") 325 } 326 327 } 328 } 329 330 func TestCreatePostWithOutgoingHook_form_urlencoded(t *testing.T) { 331 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 332 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 333 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 334 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 335 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, true) 336 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, true) 337 } 338 339 func TestCreatePostWithOutgoingHook_json(t *testing.T) { 340 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, false) 341 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH, false) 342 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 343 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 344 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, true) 345 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, true) 346 } 347 348 // hooks created before we added the ContentType field should be considered as 349 // application/x-www-form-urlencoded 350 func TestCreatePostWithOutgoingHook_no_content_type(t *testing.T) { 351 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 352 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 353 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, false) 354 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH, false) 355 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, true) 356 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, true) 357 } 358 359 func TestCreatePostPublic(t *testing.T) { 360 th := Setup().InitBasic() 361 defer th.TearDown() 362 Client := th.Client 363 364 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a"} 365 366 user := model.User{Email: th.GenerateTestEmail(), Nickname: "Joram Wilander", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID} 367 368 ruser, resp := Client.CreateUser(&user) 369 CheckNoError(t, resp) 370 371 Client.Login(user.Email, user.Password) 372 373 _, resp = Client.CreatePost(post) 374 CheckForbiddenStatus(t, resp) 375 376 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_POST_ALL_PUBLIC_ROLE_ID, false) 377 th.App.InvalidateAllCaches() 378 379 Client.Login(user.Email, user.Password) 380 381 _, resp = Client.CreatePost(post) 382 CheckNoError(t, resp) 383 384 post.ChannelId = th.BasicPrivateChannel.Id 385 _, resp = Client.CreatePost(post) 386 CheckForbiddenStatus(t, resp) 387 388 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID, false) 389 th.App.JoinUserToTeam(th.BasicTeam, ruser, "") 390 th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, model.TEAM_USER_ROLE_ID+" "+model.TEAM_POST_ALL_PUBLIC_ROLE_ID) 391 th.App.InvalidateAllCaches() 392 393 Client.Login(user.Email, user.Password) 394 395 post.ChannelId = th.BasicPrivateChannel.Id 396 _, resp = Client.CreatePost(post) 397 CheckForbiddenStatus(t, resp) 398 399 post.ChannelId = th.BasicChannel.Id 400 _, resp = Client.CreatePost(post) 401 CheckNoError(t, resp) 402 } 403 404 func TestCreatePostAll(t *testing.T) { 405 th := Setup().InitBasic() 406 defer th.TearDown() 407 Client := th.Client 408 409 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a"} 410 411 user := model.User{Email: th.GenerateTestEmail(), Nickname: "Joram Wilander", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID} 412 413 directChannel, _ := th.App.GetOrCreateDirectChannel(th.BasicUser.Id, th.BasicUser2.Id) 414 415 ruser, resp := Client.CreateUser(&user) 416 CheckNoError(t, resp) 417 418 Client.Login(user.Email, user.Password) 419 420 _, resp = Client.CreatePost(post) 421 CheckForbiddenStatus(t, resp) 422 423 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_POST_ALL_ROLE_ID, false) 424 th.App.InvalidateAllCaches() 425 426 Client.Login(user.Email, user.Password) 427 428 _, resp = Client.CreatePost(post) 429 CheckNoError(t, resp) 430 431 post.ChannelId = th.BasicPrivateChannel.Id 432 _, resp = Client.CreatePost(post) 433 CheckNoError(t, resp) 434 435 post.ChannelId = directChannel.Id 436 _, resp = Client.CreatePost(post) 437 CheckNoError(t, resp) 438 439 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID, false) 440 th.App.JoinUserToTeam(th.BasicTeam, ruser, "") 441 th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, model.TEAM_USER_ROLE_ID+" "+model.TEAM_POST_ALL_ROLE_ID) 442 th.App.InvalidateAllCaches() 443 444 Client.Login(user.Email, user.Password) 445 446 post.ChannelId = th.BasicPrivateChannel.Id 447 _, resp = Client.CreatePost(post) 448 CheckNoError(t, resp) 449 450 post.ChannelId = th.BasicChannel.Id 451 _, resp = Client.CreatePost(post) 452 CheckNoError(t, resp) 453 454 post.ChannelId = directChannel.Id 455 _, resp = Client.CreatePost(post) 456 CheckForbiddenStatus(t, resp) 457 } 458 459 func TestCreatePostSendOutOfChannelMentions(t *testing.T) { 460 th := Setup().InitBasic() 461 defer th.TearDown() 462 Client := th.Client 463 464 WebSocketClient, err := th.CreateWebSocketClient() 465 if err != nil { 466 t.Fatal(err) 467 } 468 WebSocketClient.Listen() 469 470 inChannelUser := th.CreateUser() 471 th.LinkUserToTeam(inChannelUser, th.BasicTeam) 472 th.App.AddUserToChannel(inChannelUser, th.BasicChannel) 473 474 post1 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "@" + inChannelUser.Username} 475 _, resp := Client.CreatePost(post1) 476 CheckNoError(t, resp) 477 CheckCreatedStatus(t, resp) 478 479 timeout := time.After(300 * time.Millisecond) 480 waiting := true 481 for waiting { 482 select { 483 case event := <-WebSocketClient.EventChannel: 484 if event.Event == model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE { 485 t.Fatal("should not have ephemeral message event") 486 } 487 488 case <-timeout: 489 waiting = false 490 } 491 } 492 493 outOfChannelUser := th.CreateUser() 494 th.LinkUserToTeam(outOfChannelUser, th.BasicTeam) 495 496 post2 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "@" + outOfChannelUser.Username} 497 _, resp = Client.CreatePost(post2) 498 CheckNoError(t, resp) 499 CheckCreatedStatus(t, resp) 500 501 timeout = time.After(300 * time.Millisecond) 502 waiting = true 503 for waiting { 504 select { 505 case event := <-WebSocketClient.EventChannel: 506 if event.Event != model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE { 507 // Ignore any other events 508 continue 509 } 510 511 wpost := model.PostFromJson(strings.NewReader(event.Data["post"].(string))) 512 if acm, ok := wpost.Props[model.PROPS_ADD_CHANNEL_MEMBER].(map[string]interface{}); !ok { 513 t.Fatal("should have received ephemeral post with 'add_channel_member' in props") 514 } else { 515 if acm["post_id"] == nil || acm["user_ids"] == nil || acm["usernames"] == nil { 516 t.Fatal("should not be nil") 517 } 518 } 519 waiting = false 520 case <-timeout: 521 t.Fatal("timed out waiting for ephemeral message event") 522 } 523 } 524 } 525 526 func TestUpdatePost(t *testing.T) { 527 th := Setup().InitBasic() 528 defer th.TearDown() 529 Client := th.Client 530 channel := th.BasicChannel 531 532 th.App.SetLicense(model.NewTestLicense()) 533 534 post := &model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a"} 535 rpost, resp := Client.CreatePost(post) 536 CheckNoError(t, resp) 537 538 if rpost.Message != post.Message { 539 t.Fatal("full name didn't match") 540 } 541 542 if rpost.EditAt != 0 { 543 t.Fatal("Newly created post shouldn't have EditAt set") 544 } 545 546 msg := "zz" + model.NewId() + " update post" 547 rpost.Message = msg 548 rpost.UserId = "" 549 550 rupost, resp := Client.UpdatePost(rpost.Id, rpost) 551 CheckNoError(t, resp) 552 553 if rupost.Message != msg { 554 t.Fatal("failed to updates") 555 } 556 if rupost.EditAt == 0 { 557 t.Fatal("EditAt not updated for post") 558 } 559 560 msg1 := "#hashtag a" + model.NewId() + " update post again" 561 rpost.Message = msg1 562 rpost.Props[model.PROPS_ADD_CHANNEL_MEMBER] = "no good" 563 rrupost, resp := Client.UpdatePost(rpost.Id, rpost) 564 CheckNoError(t, resp) 565 566 if rrupost.Message != msg1 && rrupost.Hashtags != "#hashtag" { 567 t.Fatal("failed to updates") 568 } 569 570 if rrupost.Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 571 t.Fatal("failed to sanitize Props['add_channel_member'], should be nil") 572 } 573 574 rpost2, err := th.App.CreatePost(&model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a", Type: model.POST_JOIN_LEAVE, UserId: th.BasicUser.Id}, channel, false) 575 if err != nil { 576 t.Fatal(err) 577 } 578 579 up2 := &model.Post{Id: rpost2.Id, ChannelId: channel.Id, Message: "zz" + model.NewId() + " update post 2"} 580 _, resp = Client.UpdatePost(rpost2.Id, up2) 581 CheckBadRequestStatus(t, resp) 582 583 rpost3, err := th.App.CreatePost(&model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a", UserId: th.BasicUser.Id}, channel, false) 584 if err != nil { 585 t.Fatal(err) 586 } 587 588 fileIds := model.StringArray{"abcdef", "geh"} 589 up3 := &model.Post{Id: rpost3.Id, ChannelId: channel.Id, Message: "zz" + model.NewId() + " update post 3", FileIds: fileIds} 590 rrupost3, resp := Client.UpdatePost(rpost3.Id, up3) 591 CheckNoError(t, resp) 592 assert.Empty(t, rrupost3.FileIds) 593 594 up4 := &model.Post{Id: rpost3.Id, ChannelId: channel.Id, Message: "zz" + model.NewId() + " update post 3"} 595 up4.AddProp("attachments", []model.SlackAttachment{ 596 { 597 Text: "Hello World", 598 }, 599 }) 600 rrupost3, resp = Client.UpdatePost(rpost3.Id, up4) 601 CheckNoError(t, resp) 602 assert.NotEqual(t, rpost3.EditAt, rrupost3.EditAt) 603 assert.NotEqual(t, rpost3.Attachments(), rrupost3.Attachments()) 604 605 606 Client.Logout() 607 _, resp = Client.UpdatePost(rpost.Id, rpost) 608 CheckUnauthorizedStatus(t, resp) 609 610 th.LoginBasic2() 611 _, resp = Client.UpdatePost(rpost.Id, rpost) 612 CheckForbiddenStatus(t, resp) 613 614 Client.Logout() 615 616 th.LoginTeamAdmin() 617 _, resp = Client.UpdatePost(rpost.Id, rpost) 618 CheckForbiddenStatus(t, resp) 619 620 Client.Logout() 621 622 _, resp = th.SystemAdminClient.UpdatePost(rpost.Id, rpost) 623 CheckNoError(t, resp) 624 } 625 626 func TestUpdateOthersPostInDirectMessageChannel(t *testing.T) { 627 // This test checks that a sysadmin with the "EDIT_OTHERS_POSTS" permission can edit someone else's post in a 628 // channel without a team (DM/GM). This indirectly checks for the proper cascading all the way to system-wide roles 629 // on the user object of permissions based on a post in a channel with no team ID. 630 th := Setup().InitBasic() 631 defer th.TearDown() 632 633 dmChannel := th.CreateDmChannel(th.SystemAdminUser) 634 635 post := &model.Post{ 636 Message: "asd", 637 ChannelId: dmChannel.Id, 638 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 639 UserId: th.BasicUser.Id, 640 CreateAt: 0, 641 } 642 643 post, resp := th.Client.CreatePost(post) 644 CheckNoError(t, resp) 645 646 post.Message = "changed" 647 post, resp = th.SystemAdminClient.UpdatePost(post.Id, post) 648 CheckNoError(t, resp) 649 } 650 651 func TestPatchPost(t *testing.T) { 652 th := Setup().InitBasic() 653 defer th.TearDown() 654 Client := th.Client 655 channel := th.BasicChannel 656 657 th.App.SetLicense(model.NewTestLicense()) 658 659 post := &model.Post{ 660 ChannelId: channel.Id, 661 IsPinned: true, 662 Message: "#hashtag a message", 663 Props: model.StringInterface{"channel_header": "old_header"}, 664 FileIds: model.StringArray{"file1", "file2"}, 665 HasReactions: true, 666 } 667 post, _ = Client.CreatePost(post) 668 669 patch := &model.PostPatch{} 670 671 patch.IsPinned = model.NewBool(false) 672 patch.Message = model.NewString("#otherhashtag other message") 673 patch.Props = new(model.StringInterface) 674 *patch.Props = model.StringInterface{"channel_header": "new_header"} 675 patch.FileIds = new(model.StringArray) 676 *patch.FileIds = model.StringArray{"file1", "otherfile2", "otherfile3"} 677 patch.HasReactions = model.NewBool(false) 678 679 rpost, resp := Client.PatchPost(post.Id, patch) 680 CheckNoError(t, resp) 681 682 if rpost.IsPinned { 683 t.Fatal("IsPinned did not update properly") 684 } 685 if rpost.Message != "#otherhashtag other message" { 686 t.Fatal("Message did not update properly") 687 } 688 if len(rpost.Props) != 1 { 689 t.Fatal("Props did not update properly") 690 } 691 if !reflect.DeepEqual(rpost.Props, *patch.Props) { 692 t.Fatal("Props did not update properly") 693 } 694 if rpost.Hashtags != "#otherhashtag" { 695 t.Fatal("Message did not update properly") 696 } 697 if len(rpost.FileIds) == 3 { 698 t.Fatal("FileIds should not update properly") 699 } 700 if reflect.DeepEqual(rpost.FileIds, *patch.FileIds) { 701 t.Fatal("FileIds should not update") 702 } 703 if rpost.HasReactions { 704 t.Fatal("HasReactions did not update properly") 705 } 706 707 patch2 := &model.PostPatch{} 708 attachments := []model.SlackAttachment{ 709 { 710 Text: "Hello World", 711 }, 712 } 713 patch2.Props = new(model.StringInterface) 714 *patch2.Props = model.StringInterface{"attachments": attachments} 715 716 rpost2, resp := Client.PatchPost(post.Id, patch2) 717 CheckNoError(t, resp) 718 assert.NotEmpty(t, rpost2.Props["attachments"]) 719 assert.NotEqual(t, rpost.EditAt, rpost2.EditAt) 720 721 if r, err := Client.DoApiPut("/posts/"+post.Id+"/patch", "garbage"); err == nil { 722 t.Fatal("should have errored") 723 } else { 724 if r.StatusCode != http.StatusBadRequest { 725 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 726 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 727 t.Fatal("wrong status code") 728 } 729 } 730 731 _, resp = Client.PatchPost("junk", patch) 732 CheckBadRequestStatus(t, resp) 733 734 _, resp = Client.PatchPost(GenerateTestId(), patch) 735 CheckForbiddenStatus(t, resp) 736 737 Client.Logout() 738 _, resp = Client.PatchPost(post.Id, patch) 739 CheckUnauthorizedStatus(t, resp) 740 741 th.LoginBasic2() 742 _, resp = Client.PatchPost(post.Id, patch) 743 CheckForbiddenStatus(t, resp) 744 745 th.LoginTeamAdmin() 746 _, resp = Client.PatchPost(post.Id, patch) 747 CheckForbiddenStatus(t, resp) 748 749 _, resp = th.SystemAdminClient.PatchPost(post.Id, patch) 750 CheckNoError(t, resp) 751 } 752 753 func TestPinPost(t *testing.T) { 754 th := Setup().InitBasic() 755 defer th.TearDown() 756 Client := th.Client 757 758 post := th.BasicPost 759 pass, resp := Client.PinPost(post.Id) 760 CheckNoError(t, resp) 761 762 if !pass { 763 t.Fatal("should have passed") 764 } 765 766 if rpost, err := th.App.GetSinglePost(post.Id); err != nil && !rpost.IsPinned { 767 t.Fatal("failed to pin post") 768 } 769 770 pass, resp = Client.PinPost("junk") 771 CheckBadRequestStatus(t, resp) 772 773 if pass { 774 t.Fatal("should have failed") 775 } 776 777 _, resp = Client.PinPost(GenerateTestId()) 778 CheckForbiddenStatus(t, resp) 779 780 t.Run("unable-to-pin-post-in-read-only-town-square", func(t *testing.T) { 781 townSquareIsReadOnly := *th.App.Config().TeamSettings.ExperimentalTownSquareIsReadOnly 782 th.App.SetLicense(model.NewTestLicense()) 783 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) 784 785 defer th.App.RemoveLicense() 786 defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = townSquareIsReadOnly }) 787 788 channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true) 789 assert.Nil(t, err) 790 adminPost := th.CreatePostWithClient(th.SystemAdminClient, channel) 791 792 _, resp = Client.PinPost(adminPost.Id) 793 CheckForbiddenStatus(t, resp) 794 }) 795 796 Client.Logout() 797 _, resp = Client.PinPost(post.Id) 798 CheckUnauthorizedStatus(t, resp) 799 800 _, resp = th.SystemAdminClient.PinPost(post.Id) 801 CheckNoError(t, resp) 802 } 803 804 func TestUnpinPost(t *testing.T) { 805 th := Setup().InitBasic() 806 defer th.TearDown() 807 Client := th.Client 808 809 pinnedPost := th.CreatePinnedPost() 810 pass, resp := Client.UnpinPost(pinnedPost.Id) 811 CheckNoError(t, resp) 812 813 if !pass { 814 t.Fatal("should have passed") 815 } 816 817 if rpost, err := th.App.GetSinglePost(pinnedPost.Id); err != nil && rpost.IsPinned { 818 t.Fatal("failed to pin post") 819 } 820 821 pass, resp = Client.UnpinPost("junk") 822 CheckBadRequestStatus(t, resp) 823 824 if pass { 825 t.Fatal("should have failed") 826 } 827 828 _, resp = Client.UnpinPost(GenerateTestId()) 829 CheckForbiddenStatus(t, resp) 830 831 Client.Logout() 832 _, resp = Client.UnpinPost(pinnedPost.Id) 833 CheckUnauthorizedStatus(t, resp) 834 835 _, resp = th.SystemAdminClient.UnpinPost(pinnedPost.Id) 836 CheckNoError(t, resp) 837 } 838 839 func TestGetPostsForChannel(t *testing.T) { 840 th := Setup().InitBasic() 841 defer th.TearDown() 842 Client := th.Client 843 844 post1 := th.CreatePost() 845 post2 := th.CreatePost() 846 post3 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 847 post3, _ = Client.CreatePost(post3) 848 849 time.Sleep(300 * time.Millisecond) 850 since := model.GetMillis() 851 time.Sleep(300 * time.Millisecond) 852 853 post4 := th.CreatePost() 854 855 posts, resp := Client.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 856 CheckNoError(t, resp) 857 858 if posts.Order[0] != post4.Id { 859 t.Fatal("wrong order") 860 } 861 862 if posts.Order[1] != post3.Id { 863 t.Fatal("wrong order") 864 } 865 866 if posts.Order[2] != post2.Id { 867 t.Fatal("wrong order") 868 } 869 870 if posts.Order[3] != post1.Id { 871 t.Fatal("wrong order") 872 } 873 874 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, resp.Etag) 875 CheckEtag(t, posts, resp) 876 877 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, "") 878 CheckNoError(t, resp) 879 880 if len(posts.Order) != 3 { 881 t.Fatal("wrong number returned") 882 } 883 884 if _, ok := posts.Posts[post3.Id]; !ok { 885 t.Fatal("missing comment") 886 } 887 888 if _, ok := posts.Posts[post1.Id]; !ok { 889 t.Fatal("missing root post") 890 } 891 892 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 1, 1, "") 893 CheckNoError(t, resp) 894 895 if posts.Order[0] != post3.Id { 896 t.Fatal("wrong order") 897 } 898 899 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 10000, 10000, "") 900 CheckNoError(t, resp) 901 902 if len(posts.Order) != 0 { 903 t.Fatal("should be no posts") 904 } 905 906 post5 := th.CreatePost() 907 908 posts, resp = Client.GetPostsSince(th.BasicChannel.Id, since) 909 CheckNoError(t, resp) 910 911 if len(posts.Posts) != 2 { 912 t.Log(posts.Posts) 913 t.Fatal("should return 2 posts") 914 } 915 916 found := make([]bool, 2) 917 for _, p := range posts.Posts { 918 if p.CreateAt < since { 919 t.Fatal("bad create at for post returned") 920 } 921 if p.Id == post4.Id { 922 found[0] = true 923 } else if p.Id == post5.Id { 924 found[1] = true 925 } 926 } 927 928 for _, f := range found { 929 if !f { 930 t.Fatal("missing post") 931 } 932 } 933 934 _, resp = Client.GetPostsForChannel("", 0, 60, "") 935 CheckBadRequestStatus(t, resp) 936 937 _, resp = Client.GetPostsForChannel("junk", 0, 60, "") 938 CheckBadRequestStatus(t, resp) 939 940 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 941 CheckForbiddenStatus(t, resp) 942 943 Client.Logout() 944 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 945 CheckUnauthorizedStatus(t, resp) 946 947 _, resp = th.SystemAdminClient.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 948 CheckNoError(t, resp) 949 } 950 951 func TestGetFlaggedPostsForUser(t *testing.T) { 952 th := Setup().InitBasic() 953 defer th.TearDown() 954 Client := th.Client 955 user := th.BasicUser 956 team1 := th.BasicTeam 957 channel1 := th.BasicChannel 958 post1 := th.CreatePost() 959 channel2 := th.CreatePublicChannel() 960 post2 := th.CreatePostWithClient(Client, channel2) 961 962 preference := model.Preference{ 963 UserId: user.Id, 964 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 965 Name: post1.Id, 966 Value: "true", 967 } 968 _, resp := Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 969 CheckNoError(t, resp) 970 preference.Name = post2.Id 971 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 972 CheckNoError(t, resp) 973 974 opl := model.NewPostList() 975 opl.AddPost(post1) 976 opl.AddOrder(post1.Id) 977 978 rpl, resp := Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 979 CheckNoError(t, resp) 980 981 if len(rpl.Posts) != 1 { 982 t.Fatal("should have returned 1 post") 983 } 984 985 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 986 t.Fatal("posts should have matched") 987 } 988 989 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 1) 990 CheckNoError(t, resp) 991 992 if len(rpl.Posts) != 1 { 993 t.Fatal("should have returned 1 post") 994 } 995 996 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 1, 1) 997 CheckNoError(t, resp) 998 999 if len(rpl.Posts) != 0 { 1000 t.Fatal("should be empty") 1001 } 1002 1003 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, GenerateTestId(), 0, 10) 1004 CheckNoError(t, resp) 1005 1006 if len(rpl.Posts) != 0 { 1007 t.Fatal("should be empty") 1008 } 1009 1010 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, "junk", 0, 10) 1011 CheckBadRequestStatus(t, resp) 1012 1013 if rpl != nil { 1014 t.Fatal("should be nil") 1015 } 1016 1017 opl.AddPost(post2) 1018 opl.AddOrder(post2.Id) 1019 1020 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1021 CheckNoError(t, resp) 1022 1023 if len(rpl.Posts) != 2 { 1024 t.Fatal("should have returned 2 posts") 1025 } 1026 1027 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1028 t.Fatal("posts should have matched") 1029 } 1030 1031 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 1) 1032 CheckNoError(t, resp) 1033 1034 if len(rpl.Posts) != 1 { 1035 t.Fatal("should have returned 1 post") 1036 } 1037 1038 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1, 1) 1039 CheckNoError(t, resp) 1040 1041 if len(rpl.Posts) != 1 { 1042 t.Fatal("should have returned 1 post") 1043 } 1044 1045 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1000, 10) 1046 CheckNoError(t, resp) 1047 1048 if len(rpl.Posts) != 0 { 1049 t.Fatal("should be empty") 1050 } 1051 1052 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, GenerateTestId(), 0, 10) 1053 CheckNoError(t, resp) 1054 1055 if len(rpl.Posts) != 0 { 1056 t.Fatal("should be empty") 1057 } 1058 1059 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, "junk", 0, 10) 1060 CheckBadRequestStatus(t, resp) 1061 1062 if rpl != nil { 1063 t.Fatal("should be nil") 1064 } 1065 1066 channel3 := th.CreatePrivateChannel() 1067 post4 := th.CreatePostWithClient(Client, channel3) 1068 1069 preference.Name = post4.Id 1070 Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1071 1072 opl.AddPost(post4) 1073 opl.AddOrder(post4.Id) 1074 1075 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1076 CheckNoError(t, resp) 1077 1078 if len(rpl.Posts) != 3 { 1079 t.Fatal("should have returned 3 posts") 1080 } 1081 1082 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1083 t.Fatal("posts should have matched") 1084 } 1085 1086 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 2) 1087 CheckNoError(t, resp) 1088 1089 if len(rpl.Posts) != 2 { 1090 t.Fatal("should have returned 2 posts") 1091 } 1092 1093 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 2, 2) 1094 CheckNoError(t, resp) 1095 1096 if len(rpl.Posts) != 1 { 1097 t.Fatal("should have returned 1 post") 1098 } 1099 1100 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 1000, 10) 1101 CheckNoError(t, resp) 1102 1103 if len(rpl.Posts) != 0 { 1104 t.Fatal("should be empty") 1105 } 1106 1107 channel4 := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE) 1108 post5 := th.CreatePostWithClient(th.SystemAdminClient, channel4) 1109 1110 preference.Name = post5.Id 1111 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1112 CheckForbiddenStatus(t, resp) 1113 1114 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1115 CheckNoError(t, resp) 1116 1117 if len(rpl.Posts) != 3 { 1118 t.Fatal("should have returned 3 posts") 1119 } 1120 1121 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1122 t.Fatal("posts should have matched") 1123 } 1124 1125 th.AddUserToChannel(user, channel4) 1126 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1127 CheckNoError(t, resp) 1128 1129 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1130 CheckNoError(t, resp) 1131 1132 opl.AddPost(post5) 1133 opl.AddOrder(post5.Id) 1134 1135 if len(rpl.Posts) != 4 { 1136 t.Fatal("should have returned 4 posts") 1137 } 1138 1139 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1140 t.Fatal("posts should have matched") 1141 } 1142 1143 err := th.App.RemoveUserFromChannel(user.Id, "", channel4) 1144 if err != nil { 1145 t.Error("Unable to remove user from channel") 1146 } 1147 1148 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1149 CheckNoError(t, resp) 1150 1151 opl2 := model.NewPostList() 1152 opl2.AddPost(post1) 1153 opl2.AddOrder(post1.Id) 1154 opl2.AddPost(post2) 1155 opl2.AddOrder(post2.Id) 1156 opl2.AddPost(post4) 1157 opl2.AddOrder(post4.Id) 1158 1159 if len(rpl.Posts) != 3 { 1160 t.Fatal("should have returned 3 posts") 1161 } 1162 1163 if !reflect.DeepEqual(rpl.Posts, opl2.Posts) { 1164 t.Fatal("posts should have matched") 1165 } 1166 1167 _, resp = Client.GetFlaggedPostsForUser("junk", 0, 10) 1168 CheckBadRequestStatus(t, resp) 1169 1170 _, resp = Client.GetFlaggedPostsForUser(GenerateTestId(), 0, 10) 1171 CheckForbiddenStatus(t, resp) 1172 1173 Client.Logout() 1174 1175 _, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 1176 CheckUnauthorizedStatus(t, resp) 1177 1178 _, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1179 CheckUnauthorizedStatus(t, resp) 1180 1181 _, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1182 CheckUnauthorizedStatus(t, resp) 1183 1184 _, resp = th.SystemAdminClient.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 1185 CheckNoError(t, resp) 1186 1187 _, resp = th.SystemAdminClient.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1188 CheckNoError(t, resp) 1189 1190 _, resp = th.SystemAdminClient.GetFlaggedPostsForUser(user.Id, 0, 10) 1191 CheckNoError(t, resp) 1192 } 1193 1194 func TestGetPostsAfterAndBefore(t *testing.T) { 1195 th := Setup().InitBasic() 1196 defer th.TearDown() 1197 Client := th.Client 1198 1199 post1 := th.CreatePost() 1200 post2 := th.CreatePost() 1201 post3 := th.CreatePost() 1202 post4 := th.CreatePost() 1203 post5 := th.CreatePost() 1204 1205 posts, resp := Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 0, 100, "") 1206 CheckNoError(t, resp) 1207 1208 found := make([]bool, 2) 1209 for _, p := range posts.Posts { 1210 if p.Id == post1.Id { 1211 found[0] = true 1212 } else if p.Id == post2.Id { 1213 found[1] = true 1214 } 1215 1216 if p.Id == post4.Id || p.Id == post5.Id { 1217 t.Fatal("returned posts after") 1218 } 1219 } 1220 1221 for _, f := range found { 1222 if !f { 1223 t.Fatal("missing post") 1224 } 1225 } 1226 1227 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 1, 1, "") 1228 CheckNoError(t, resp) 1229 1230 if len(posts.Posts) != 1 { 1231 t.Fatal("too many posts returned") 1232 } 1233 1234 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, "junk", 1, 1, "") 1235 CheckNoError(t, resp) 1236 1237 if len(posts.Posts) != 0 { 1238 t.Fatal("should have no posts") 1239 } 1240 1241 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 0, 100, "") 1242 CheckNoError(t, resp) 1243 1244 found = make([]bool, 2) 1245 for _, p := range posts.Posts { 1246 if p.Id == post4.Id { 1247 found[0] = true 1248 } else if p.Id == post5.Id { 1249 found[1] = true 1250 } 1251 1252 if p.Id == post1.Id || p.Id == post2.Id { 1253 t.Fatal("returned posts before") 1254 } 1255 } 1256 1257 for _, f := range found { 1258 if !f { 1259 t.Fatal("missing post") 1260 } 1261 } 1262 1263 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 1, 1, "") 1264 CheckNoError(t, resp) 1265 1266 if len(posts.Posts) != 1 { 1267 t.Fatal("too many posts returned") 1268 } 1269 1270 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, "junk", 1, 1, "") 1271 CheckNoError(t, resp) 1272 1273 if len(posts.Posts) != 0 { 1274 t.Fatal("should have no posts") 1275 } 1276 } 1277 1278 func TestGetPost(t *testing.T) { 1279 th := Setup().InitBasic() 1280 defer th.TearDown() 1281 Client := th.Client 1282 1283 post, resp := Client.GetPost(th.BasicPost.Id, "") 1284 CheckNoError(t, resp) 1285 1286 if post.Id != th.BasicPost.Id { 1287 t.Fatal("post ids don't match") 1288 } 1289 1290 post, resp = Client.GetPost(th.BasicPost.Id, resp.Etag) 1291 CheckEtag(t, post, resp) 1292 1293 _, resp = Client.GetPost("", "") 1294 CheckNotFoundStatus(t, resp) 1295 1296 _, resp = Client.GetPost("junk", "") 1297 CheckBadRequestStatus(t, resp) 1298 1299 _, resp = Client.GetPost(model.NewId(), "") 1300 CheckNotFoundStatus(t, resp) 1301 1302 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1303 1304 // Channel is public, should be able to read post 1305 _, resp = Client.GetPost(th.BasicPost.Id, "") 1306 CheckNoError(t, resp) 1307 1308 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1309 1310 _, resp = Client.GetPost(privatePost.Id, "") 1311 CheckNoError(t, resp) 1312 1313 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1314 1315 // Channel is private, should not be able to read post 1316 _, resp = Client.GetPost(privatePost.Id, "") 1317 CheckForbiddenStatus(t, resp) 1318 1319 Client.Logout() 1320 _, resp = Client.GetPost(model.NewId(), "") 1321 CheckUnauthorizedStatus(t, resp) 1322 1323 _, resp = th.SystemAdminClient.GetPost(th.BasicPost.Id, "") 1324 CheckNoError(t, resp) 1325 } 1326 1327 func TestDeletePost(t *testing.T) { 1328 th := Setup().InitBasic() 1329 defer th.TearDown() 1330 Client := th.Client 1331 1332 _, resp := Client.DeletePost("") 1333 CheckNotFoundStatus(t, resp) 1334 1335 _, resp = Client.DeletePost("junk") 1336 CheckBadRequestStatus(t, resp) 1337 1338 _, resp = Client.DeletePost(th.BasicPost.Id) 1339 CheckForbiddenStatus(t, resp) 1340 1341 Client.Login(th.TeamAdminUser.Email, th.TeamAdminUser.Password) 1342 _, resp = Client.DeletePost(th.BasicPost.Id) 1343 CheckNoError(t, resp) 1344 1345 post := th.CreatePost() 1346 user := th.CreateUser() 1347 1348 Client.Logout() 1349 Client.Login(user.Email, user.Password) 1350 1351 _, resp = Client.DeletePost(post.Id) 1352 CheckForbiddenStatus(t, resp) 1353 1354 Client.Logout() 1355 _, resp = Client.DeletePost(model.NewId()) 1356 CheckUnauthorizedStatus(t, resp) 1357 1358 status, resp := th.SystemAdminClient.DeletePost(post.Id) 1359 if !status { 1360 t.Fatal("post should return status OK") 1361 } 1362 CheckNoError(t, resp) 1363 } 1364 1365 func TestGetPostThread(t *testing.T) { 1366 th := Setup().InitBasic() 1367 defer th.TearDown() 1368 Client := th.Client 1369 1370 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: th.BasicPost.Id} 1371 post, _ = Client.CreatePost(post) 1372 1373 list, resp := Client.GetPostThread(th.BasicPost.Id, "") 1374 CheckNoError(t, resp) 1375 1376 var list2 *model.PostList 1377 list2, resp = Client.GetPostThread(th.BasicPost.Id, resp.Etag) 1378 CheckEtag(t, list2, resp) 1379 1380 if list.Order[0] != th.BasicPost.Id { 1381 t.Fatal("wrong order") 1382 } 1383 1384 if _, ok := list.Posts[th.BasicPost.Id]; !ok { 1385 t.Fatal("should have had post") 1386 } 1387 1388 if _, ok := list.Posts[post.Id]; !ok { 1389 t.Fatal("should have had post") 1390 } 1391 1392 _, resp = Client.GetPostThread("junk", "") 1393 CheckBadRequestStatus(t, resp) 1394 1395 _, resp = Client.GetPostThread(model.NewId(), "") 1396 CheckNotFoundStatus(t, resp) 1397 1398 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1399 1400 // Channel is public, should be able to read post 1401 _, resp = Client.GetPostThread(th.BasicPost.Id, "") 1402 CheckNoError(t, resp) 1403 1404 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1405 1406 _, resp = Client.GetPostThread(privatePost.Id, "") 1407 CheckNoError(t, resp) 1408 1409 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1410 1411 // Channel is private, should not be able to read post 1412 _, resp = Client.GetPostThread(privatePost.Id, "") 1413 CheckForbiddenStatus(t, resp) 1414 1415 Client.Logout() 1416 _, resp = Client.GetPostThread(model.NewId(), "") 1417 CheckUnauthorizedStatus(t, resp) 1418 1419 _, resp = th.SystemAdminClient.GetPostThread(th.BasicPost.Id, "") 1420 CheckNoError(t, resp) 1421 } 1422 1423 func TestSearchPosts(t *testing.T) { 1424 th := Setup().InitBasic() 1425 defer th.TearDown() 1426 experimentalViewArchivedChannels := *th.App.Config().TeamSettings.ExperimentalViewArchivedChannels 1427 defer func() { 1428 th.App.UpdateConfig(func(cfg *model.Config) { 1429 cfg.TeamSettings.ExperimentalViewArchivedChannels = &experimentalViewArchivedChannels 1430 }) 1431 }() 1432 th.App.UpdateConfig(func(cfg *model.Config) { 1433 *cfg.TeamSettings.ExperimentalViewArchivedChannels = true 1434 }) 1435 1436 th.LoginBasic() 1437 Client := th.Client 1438 1439 message := "search for post1" 1440 _ = th.CreateMessagePost(message) 1441 1442 message = "search for post2" 1443 post2 := th.CreateMessagePost(message) 1444 1445 message = "#hashtag search for post3" 1446 post3 := th.CreateMessagePost(message) 1447 1448 message = "hashtag for post4" 1449 _ = th.CreateMessagePost(message) 1450 1451 archivedChannel := th.CreatePublicChannel() 1452 _ = th.CreateMessagePostWithClient(th.Client, archivedChannel, "#hashtag for post3") 1453 th.Client.DeleteChannel(archivedChannel.Id) 1454 1455 terms := "search" 1456 isOrSearch := false 1457 timezoneOffset := 5 1458 searchParams := model.SearchParameter{ 1459 Terms: &terms, 1460 IsOrSearch: &isOrSearch, 1461 TimeZoneOffset: &timezoneOffset, 1462 } 1463 posts, resp := Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1464 CheckNoError(t, resp) 1465 if len(posts.Order) != 3 { 1466 t.Fatal("wrong search") 1467 } 1468 1469 terms = "search" 1470 page := 0 1471 perPage := 2 1472 searchParams = model.SearchParameter{ 1473 Terms: &terms, 1474 IsOrSearch: &isOrSearch, 1475 TimeZoneOffset: &timezoneOffset, 1476 Page: &page, 1477 PerPage: &perPage, 1478 } 1479 posts2, resp := Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1480 CheckNoError(t, resp) 1481 if len(posts2.Order) != 3 { // We don't support paging for DB search yet, modify this when we do. 1482 t.Fatal("Wrong number of posts", len(posts2.Order)) 1483 } 1484 assert.Equal(t, posts.Order[0], posts2.Order[0]) 1485 assert.Equal(t, posts.Order[1], posts2.Order[1]) 1486 1487 page = 1 1488 searchParams = model.SearchParameter{ 1489 Terms: &terms, 1490 IsOrSearch: &isOrSearch, 1491 TimeZoneOffset: &timezoneOffset, 1492 Page: &page, 1493 PerPage: &perPage, 1494 } 1495 posts2, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1496 CheckNoError(t, resp) 1497 if len(posts2.Order) != 0 { // We don't support paging for DB search yet, modify this when we do. 1498 t.Fatal("Wrong number of posts", len(posts2.Order)) 1499 } 1500 1501 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "search", false) 1502 CheckNoError(t, resp) 1503 if len(posts.Order) != 3 { 1504 t.Fatal("wrong search") 1505 } 1506 1507 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post2", false) 1508 CheckNoError(t, resp) 1509 if len(posts.Order) != 1 && posts.Order[0] == post2.Id { 1510 t.Fatal("wrong search") 1511 } 1512 1513 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "#hashtag", false) 1514 CheckNoError(t, resp) 1515 if len(posts.Order) != 1 && posts.Order[0] == post3.Id { 1516 t.Fatal("wrong search") 1517 } 1518 1519 terms = "#hashtag" 1520 includeDeletedChannels := true 1521 searchParams = model.SearchParameter{ 1522 Terms: &terms, 1523 IsOrSearch: &isOrSearch, 1524 TimeZoneOffset: &timezoneOffset, 1525 IncludeDeletedChannels: &includeDeletedChannels, 1526 } 1527 posts, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1528 CheckNoError(t, resp) 1529 if len(posts.Order) != 2 { 1530 t.Fatal("wrong search") 1531 } 1532 1533 th.App.UpdateConfig(func(cfg *model.Config) { 1534 *cfg.TeamSettings.ExperimentalViewArchivedChannels = false 1535 }) 1536 1537 posts, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1538 CheckNoError(t, resp) 1539 if len(posts.Order) != 1 { 1540 t.Fatal("wrong search") 1541 } 1542 1543 if posts, _ = Client.SearchPosts(th.BasicTeam.Id, "*", false); len(posts.Order) != 0 { 1544 t.Fatal("searching for just * shouldn't return any results") 1545 } 1546 1547 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post1 post2", true) 1548 CheckNoError(t, resp) 1549 1550 if len(posts.Order) != 2 { 1551 t.Fatal("wrong search results") 1552 } 1553 1554 _, resp = Client.SearchPosts("junk", "#sgtitlereview", false) 1555 CheckBadRequestStatus(t, resp) 1556 1557 _, resp = Client.SearchPosts(model.NewId(), "#sgtitlereview", false) 1558 CheckForbiddenStatus(t, resp) 1559 1560 _, resp = Client.SearchPosts(th.BasicTeam.Id, "", false) 1561 CheckBadRequestStatus(t, resp) 1562 1563 Client.Logout() 1564 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1565 CheckUnauthorizedStatus(t, resp) 1566 } 1567 1568 func TestSearchHashtagPosts(t *testing.T) { 1569 th := Setup().InitBasic() 1570 defer th.TearDown() 1571 th.LoginBasic() 1572 Client := th.Client 1573 1574 message := "#sgtitlereview with space" 1575 assert.NotNil(t, th.CreateMessagePost(message)) 1576 1577 message = "#sgtitlereview\n with return" 1578 assert.NotNil(t, th.CreateMessagePost(message)) 1579 1580 message = "no hashtag" 1581 assert.NotNil(t, th.CreateMessagePost(message)) 1582 1583 posts, resp := Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1584 CheckNoError(t, resp) 1585 if len(posts.Order) != 2 { 1586 t.Fatal("wrong search results") 1587 } 1588 1589 Client.Logout() 1590 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1591 CheckUnauthorizedStatus(t, resp) 1592 } 1593 1594 func TestSearchPostsInChannel(t *testing.T) { 1595 th := Setup().InitBasic() 1596 defer th.TearDown() 1597 th.LoginBasic() 1598 Client := th.Client 1599 1600 channel := th.CreatePublicChannel() 1601 1602 message := "sgtitlereview with space" 1603 _ = th.CreateMessagePost(message) 1604 1605 message = "sgtitlereview\n with return" 1606 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1607 1608 message = "other message with no return" 1609 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1610 1611 message = "other message with no return" 1612 _ = th.CreateMessagePostWithClient(Client, channel, message) 1613 1614 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:", false); len(posts.Order) != 0 { 1615 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1616 } 1617 1618 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:", false); len(posts.Order) != 0 { 1619 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1620 } 1621 1622 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel.Name, false); len(posts.Order) != 2 { 1623 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1624 } 1625 1626 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1627 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1628 } 1629 1630 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1631 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1632 } 1633 1634 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "ChAnNeL:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1635 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1636 } 1637 1638 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview", false); len(posts.Order) != 2 { 1639 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1640 } 1641 1642 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1643 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1644 } 1645 1646 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview in: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1647 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1648 } 1649 1650 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1651 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1652 } 1653 1654 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel: "+th.BasicChannel2.Name+" channel: "+channel.Name, false); len(posts.Order) != 3 { 1655 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1656 } 1657 1658 } 1659 1660 func TestSearchPostsFromUser(t *testing.T) { 1661 th := Setup().InitBasic() 1662 defer th.TearDown() 1663 Client := th.Client 1664 1665 th.LoginTeamAdmin() 1666 user := th.CreateUser() 1667 th.LinkUserToTeam(user, th.BasicTeam) 1668 th.App.AddUserToChannel(user, th.BasicChannel) 1669 th.App.AddUserToChannel(user, th.BasicChannel2) 1670 1671 message := "sgtitlereview with space" 1672 _ = th.CreateMessagePost(message) 1673 1674 Client.Logout() 1675 th.LoginBasic2() 1676 1677 message = "sgtitlereview\n with return" 1678 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1679 1680 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.TeamAdminUser.Username, false); len(posts.Order) != 2 { 1681 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1682 } 1683 1684 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 1 { 1685 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1686 } 1687 1688 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" sgtitlereview", false); len(posts.Order) != 1 { 1689 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1690 } 1691 1692 message = "hullo" 1693 _ = th.CreateMessagePost(message) 1694 1695 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" in:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1696 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1697 } 1698 1699 Client.Login(user.Email, user.Password) 1700 1701 // wait for the join/leave messages to be created for user3 since they're done asynchronously 1702 time.Sleep(100 * time.Millisecond) 1703 1704 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 2 { 1705 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1706 } 1707 1708 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username, false); len(posts.Order) != 2 { 1709 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1710 } 1711 1712 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1713 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1714 } 1715 1716 message = "coconut" 1717 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1718 1719 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name+" coconut", false); len(posts.Order) != 1 { 1720 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1721 } 1722 } 1723 1724 func TestSearchPostsWithDateFlags(t *testing.T) { 1725 th := Setup().InitBasic() 1726 defer th.TearDown() 1727 th.LoginBasic() 1728 Client := th.Client 1729 1730 message := "sgtitlereview\n with return" 1731 createDate := time.Date(2018, 8, 1, 5, 0, 0, 0, time.UTC) 1732 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1733 1734 message = "other message with no return" 1735 createDate = time.Date(2018, 8, 2, 5, 0, 0, 0, time.UTC) 1736 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1737 1738 message = "other message with no return" 1739 createDate = time.Date(2018, 8, 3, 5, 0, 0, 0, time.UTC) 1740 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1741 1742 posts, _ := Client.SearchPosts(th.BasicTeam.Id, "return", false) 1743 if len(posts.Order) != 3 { 1744 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1745 } 1746 1747 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:", false) 1748 if len(posts.Order) != 0 { 1749 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1750 } 1751 1752 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:", false) 1753 if len(posts.Order) != 0 { 1754 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1755 } 1756 1757 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:", false) 1758 if len(posts.Order) != 0 { 1759 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1760 } 1761 1762 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:2018-08-01", false) 1763 if len(posts.Order) != 1 { 1764 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1765 } 1766 1767 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:2018-08-01", false) 1768 resultCount := 0 1769 for _, post := range posts.Posts { 1770 if post.UserId == th.BasicUser.Id { 1771 resultCount = resultCount + 1 1772 } 1773 } 1774 if resultCount != 2 { 1775 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1776 } 1777 1778 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-02", false) 1779 if len(posts.Order) != 1 { 1780 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1781 } 1782 1783 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-03 after:2018-08-02", false) 1784 if len(posts.Order) != 0 { 1785 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1786 } 1787 1788 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-03 after:2018-08-01", false) 1789 if len(posts.Order) != 1 { 1790 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1791 } 1792 } 1793 1794 func TestGetFileInfosForPost(t *testing.T) { 1795 th := Setup().InitBasic() 1796 defer th.TearDown() 1797 Client := th.Client 1798 1799 fileIds := make([]string, 3) 1800 if data, err := testutils.ReadTestFile("test.png"); err != nil { 1801 t.Fatal(err) 1802 } else { 1803 for i := 0; i < 3; i++ { 1804 fileResp, _ := Client.UploadFile(data, th.BasicChannel.Id, "test.png") 1805 fileIds[i] = fileResp.FileInfos[0].Id 1806 } 1807 } 1808 1809 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", FileIds: fileIds} 1810 post, _ = Client.CreatePost(post) 1811 1812 infos, resp := Client.GetFileInfosForPost(post.Id, "") 1813 CheckNoError(t, resp) 1814 1815 if len(infos) != 3 { 1816 t.Fatal("missing file infos") 1817 } 1818 1819 found := false 1820 for _, info := range infos { 1821 if info.Id == fileIds[0] { 1822 found = true 1823 } 1824 } 1825 1826 if !found { 1827 t.Fatal("missing file info") 1828 } 1829 1830 infos, resp = Client.GetFileInfosForPost(post.Id, resp.Etag) 1831 CheckEtag(t, infos, resp) 1832 1833 infos, resp = Client.GetFileInfosForPost(th.BasicPost.Id, "") 1834 CheckNoError(t, resp) 1835 1836 if len(infos) != 0 { 1837 t.Fatal("should have no file infos") 1838 } 1839 1840 _, resp = Client.GetFileInfosForPost("junk", "") 1841 CheckBadRequestStatus(t, resp) 1842 1843 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1844 CheckForbiddenStatus(t, resp) 1845 1846 Client.Logout() 1847 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1848 CheckUnauthorizedStatus(t, resp) 1849 1850 _, resp = th.SystemAdminClient.GetFileInfosForPost(th.BasicPost.Id, "") 1851 CheckNoError(t, resp) 1852 }