github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/api4/post_test.go (about) 1 // Copyright (c) 2017-present Xenia, 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/xzl8028/xenia-server/app" 21 "github.com/xzl8028/xenia-server/model" 22 "github.com/xzl8028/xenia-server/utils" 23 "github.com/xzl8028/xenia-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.xenia.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 Client.Logout() 606 _, resp = Client.UpdatePost(rpost.Id, rpost) 607 CheckUnauthorizedStatus(t, resp) 608 609 th.LoginBasic2() 610 _, resp = Client.UpdatePost(rpost.Id, rpost) 611 CheckForbiddenStatus(t, resp) 612 613 Client.Logout() 614 615 th.LoginTeamAdmin() 616 _, resp = Client.UpdatePost(rpost.Id, rpost) 617 CheckForbiddenStatus(t, resp) 618 619 Client.Logout() 620 621 _, resp = th.SystemAdminClient.UpdatePost(rpost.Id, rpost) 622 CheckNoError(t, resp) 623 } 624 625 func TestUpdateOthersPostInDirectMessageChannel(t *testing.T) { 626 // This test checks that a sysadmin with the "EDIT_OTHERS_POSTS" permission can edit someone else's post in a 627 // channel without a team (DM/GM). This indirectly checks for the proper cascading all the way to system-wide roles 628 // on the user object of permissions based on a post in a channel with no team ID. 629 th := Setup().InitBasic() 630 defer th.TearDown() 631 632 dmChannel := th.CreateDmChannel(th.SystemAdminUser) 633 634 post := &model.Post{ 635 Message: "asd", 636 ChannelId: dmChannel.Id, 637 PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()), 638 UserId: th.BasicUser.Id, 639 CreateAt: 0, 640 } 641 642 post, resp := th.Client.CreatePost(post) 643 CheckNoError(t, resp) 644 645 post.Message = "changed" 646 post, resp = th.SystemAdminClient.UpdatePost(post.Id, post) 647 CheckNoError(t, resp) 648 } 649 650 func TestPatchPost(t *testing.T) { 651 th := Setup().InitBasic() 652 defer th.TearDown() 653 Client := th.Client 654 channel := th.BasicChannel 655 656 th.App.SetLicense(model.NewTestLicense()) 657 658 post := &model.Post{ 659 ChannelId: channel.Id, 660 IsPinned: true, 661 Message: "#hashtag a message", 662 Props: model.StringInterface{"channel_header": "old_header"}, 663 FileIds: model.StringArray{"file1", "file2"}, 664 HasReactions: true, 665 } 666 post, _ = Client.CreatePost(post) 667 668 patch := &model.PostPatch{} 669 670 patch.IsPinned = model.NewBool(false) 671 patch.Message = model.NewString("#otherhashtag other message") 672 patch.Props = new(model.StringInterface) 673 *patch.Props = model.StringInterface{"channel_header": "new_header"} 674 patch.FileIds = new(model.StringArray) 675 *patch.FileIds = model.StringArray{"file1", "otherfile2", "otherfile3"} 676 patch.HasReactions = model.NewBool(false) 677 678 rpost, resp := Client.PatchPost(post.Id, patch) 679 CheckNoError(t, resp) 680 681 if rpost.IsPinned { 682 t.Fatal("IsPinned did not update properly") 683 } 684 if rpost.Message != "#otherhashtag other message" { 685 t.Fatal("Message did not update properly") 686 } 687 if len(rpost.Props) != 1 { 688 t.Fatal("Props did not update properly") 689 } 690 if !reflect.DeepEqual(rpost.Props, *patch.Props) { 691 t.Fatal("Props did not update properly") 692 } 693 if rpost.Hashtags != "#otherhashtag" { 694 t.Fatal("Message did not update properly") 695 } 696 if len(rpost.FileIds) == 3 { 697 t.Fatal("FileIds should not update properly") 698 } 699 if reflect.DeepEqual(rpost.FileIds, *patch.FileIds) { 700 t.Fatal("FileIds should not update") 701 } 702 if rpost.HasReactions { 703 t.Fatal("HasReactions did not update properly") 704 } 705 706 patch2 := &model.PostPatch{} 707 attachments := []model.SlackAttachment{ 708 { 709 Text: "Hello World", 710 }, 711 } 712 patch2.Props = new(model.StringInterface) 713 *patch2.Props = model.StringInterface{"attachments": attachments} 714 715 rpost2, resp := Client.PatchPost(post.Id, patch2) 716 CheckNoError(t, resp) 717 assert.NotEmpty(t, rpost2.Props["attachments"]) 718 assert.NotEqual(t, rpost.EditAt, rpost2.EditAt) 719 720 if r, err := Client.DoApiPut("/posts/"+post.Id+"/patch", "garbage"); err == nil { 721 t.Fatal("should have errored") 722 } else { 723 if r.StatusCode != http.StatusBadRequest { 724 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 725 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 726 t.Fatal("wrong status code") 727 } 728 } 729 730 _, resp = Client.PatchPost("junk", patch) 731 CheckBadRequestStatus(t, resp) 732 733 _, resp = Client.PatchPost(GenerateTestId(), patch) 734 CheckForbiddenStatus(t, resp) 735 736 Client.Logout() 737 _, resp = Client.PatchPost(post.Id, patch) 738 CheckUnauthorizedStatus(t, resp) 739 740 th.LoginBasic2() 741 _, resp = Client.PatchPost(post.Id, patch) 742 CheckForbiddenStatus(t, resp) 743 744 th.LoginTeamAdmin() 745 _, resp = Client.PatchPost(post.Id, patch) 746 CheckForbiddenStatus(t, resp) 747 748 _, resp = th.SystemAdminClient.PatchPost(post.Id, patch) 749 CheckNoError(t, resp) 750 } 751 752 func TestPinPost(t *testing.T) { 753 th := Setup().InitBasic() 754 defer th.TearDown() 755 Client := th.Client 756 757 post := th.BasicPost 758 pass, resp := Client.PinPost(post.Id) 759 CheckNoError(t, resp) 760 761 if !pass { 762 t.Fatal("should have passed") 763 } 764 765 if rpost, err := th.App.GetSinglePost(post.Id); err != nil && !rpost.IsPinned { 766 t.Fatal("failed to pin post") 767 } 768 769 pass, resp = Client.PinPost("junk") 770 CheckBadRequestStatus(t, resp) 771 772 if pass { 773 t.Fatal("should have failed") 774 } 775 776 _, resp = Client.PinPost(GenerateTestId()) 777 CheckForbiddenStatus(t, resp) 778 779 t.Run("unable-to-pin-post-in-read-only-town-square", func(t *testing.T) { 780 townSquareIsReadOnly := *th.App.Config().TeamSettings.ExperimentalTownSquareIsReadOnly 781 th.App.SetLicense(model.NewTestLicense()) 782 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) 783 784 defer th.App.RemoveLicense() 785 defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = townSquareIsReadOnly }) 786 787 channel, err := th.App.GetChannelByName("town-square", th.BasicTeam.Id, true) 788 assert.Nil(t, err) 789 adminPost := th.CreatePostWithClient(th.SystemAdminClient, channel) 790 791 _, resp = Client.PinPost(adminPost.Id) 792 CheckForbiddenStatus(t, resp) 793 }) 794 795 Client.Logout() 796 _, resp = Client.PinPost(post.Id) 797 CheckUnauthorizedStatus(t, resp) 798 799 _, resp = th.SystemAdminClient.PinPost(post.Id) 800 CheckNoError(t, resp) 801 } 802 803 func TestUnpinPost(t *testing.T) { 804 th := Setup().InitBasic() 805 defer th.TearDown() 806 Client := th.Client 807 808 pinnedPost := th.CreatePinnedPost() 809 pass, resp := Client.UnpinPost(pinnedPost.Id) 810 CheckNoError(t, resp) 811 812 if !pass { 813 t.Fatal("should have passed") 814 } 815 816 if rpost, err := th.App.GetSinglePost(pinnedPost.Id); err != nil && rpost.IsPinned { 817 t.Fatal("failed to pin post") 818 } 819 820 pass, resp = Client.UnpinPost("junk") 821 CheckBadRequestStatus(t, resp) 822 823 if pass { 824 t.Fatal("should have failed") 825 } 826 827 _, resp = Client.UnpinPost(GenerateTestId()) 828 CheckForbiddenStatus(t, resp) 829 830 Client.Logout() 831 _, resp = Client.UnpinPost(pinnedPost.Id) 832 CheckUnauthorizedStatus(t, resp) 833 834 _, resp = th.SystemAdminClient.UnpinPost(pinnedPost.Id) 835 CheckNoError(t, resp) 836 } 837 838 func TestGetPostsForChannel(t *testing.T) { 839 th := Setup().InitBasic() 840 defer th.TearDown() 841 Client := th.Client 842 843 post1 := th.CreatePost() 844 post2 := th.CreatePost() 845 post3 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 846 post3, _ = Client.CreatePost(post3) 847 848 time.Sleep(300 * time.Millisecond) 849 since := model.GetMillis() 850 time.Sleep(300 * time.Millisecond) 851 852 post4 := th.CreatePost() 853 854 posts, resp := Client.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 855 CheckNoError(t, resp) 856 857 if posts.Order[0] != post4.Id { 858 t.Fatal("wrong order") 859 } 860 861 if posts.Order[1] != post3.Id { 862 t.Fatal("wrong order") 863 } 864 865 if posts.Order[2] != post2.Id { 866 t.Fatal("wrong order") 867 } 868 869 if posts.Order[3] != post1.Id { 870 t.Fatal("wrong order") 871 } 872 873 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, resp.Etag) 874 CheckEtag(t, posts, resp) 875 876 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, "") 877 CheckNoError(t, resp) 878 879 if len(posts.Order) != 3 { 880 t.Fatal("wrong number returned") 881 } 882 883 if _, ok := posts.Posts[post3.Id]; !ok { 884 t.Fatal("missing comment") 885 } 886 887 if _, ok := posts.Posts[post1.Id]; !ok { 888 t.Fatal("missing root post") 889 } 890 891 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 1, 1, "") 892 CheckNoError(t, resp) 893 894 if posts.Order[0] != post3.Id { 895 t.Fatal("wrong order") 896 } 897 898 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 10000, 10000, "") 899 CheckNoError(t, resp) 900 901 if len(posts.Order) != 0 { 902 t.Fatal("should be no posts") 903 } 904 905 post5 := th.CreatePost() 906 907 posts, resp = Client.GetPostsSince(th.BasicChannel.Id, since) 908 CheckNoError(t, resp) 909 910 if len(posts.Posts) != 2 { 911 t.Log(posts.Posts) 912 t.Fatal("should return 2 posts") 913 } 914 915 found := make([]bool, 2) 916 for _, p := range posts.Posts { 917 if p.CreateAt < since { 918 t.Fatal("bad create at for post returned") 919 } 920 if p.Id == post4.Id { 921 found[0] = true 922 } else if p.Id == post5.Id { 923 found[1] = true 924 } 925 } 926 927 for _, f := range found { 928 if !f { 929 t.Fatal("missing post") 930 } 931 } 932 933 _, resp = Client.GetPostsForChannel("", 0, 60, "") 934 CheckBadRequestStatus(t, resp) 935 936 _, resp = Client.GetPostsForChannel("junk", 0, 60, "") 937 CheckBadRequestStatus(t, resp) 938 939 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 940 CheckForbiddenStatus(t, resp) 941 942 Client.Logout() 943 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 944 CheckUnauthorizedStatus(t, resp) 945 946 _, resp = th.SystemAdminClient.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 947 CheckNoError(t, resp) 948 } 949 950 func TestGetFlaggedPostsForUser(t *testing.T) { 951 th := Setup().InitBasic() 952 defer th.TearDown() 953 Client := th.Client 954 user := th.BasicUser 955 team1 := th.BasicTeam 956 channel1 := th.BasicChannel 957 post1 := th.CreatePost() 958 channel2 := th.CreatePublicChannel() 959 post2 := th.CreatePostWithClient(Client, channel2) 960 961 preference := model.Preference{ 962 UserId: user.Id, 963 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 964 Name: post1.Id, 965 Value: "true", 966 } 967 _, resp := Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 968 CheckNoError(t, resp) 969 preference.Name = post2.Id 970 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 971 CheckNoError(t, resp) 972 973 opl := model.NewPostList() 974 opl.AddPost(post1) 975 opl.AddOrder(post1.Id) 976 977 rpl, resp := Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 978 CheckNoError(t, resp) 979 980 if len(rpl.Posts) != 1 { 981 t.Fatal("should have returned 1 post") 982 } 983 984 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 985 t.Fatal("posts should have matched") 986 } 987 988 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 1) 989 CheckNoError(t, resp) 990 991 if len(rpl.Posts) != 1 { 992 t.Fatal("should have returned 1 post") 993 } 994 995 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 1, 1) 996 CheckNoError(t, resp) 997 998 if len(rpl.Posts) != 0 { 999 t.Fatal("should be empty") 1000 } 1001 1002 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, GenerateTestId(), 0, 10) 1003 CheckNoError(t, resp) 1004 1005 if len(rpl.Posts) != 0 { 1006 t.Fatal("should be empty") 1007 } 1008 1009 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, "junk", 0, 10) 1010 CheckBadRequestStatus(t, resp) 1011 1012 if rpl != nil { 1013 t.Fatal("should be nil") 1014 } 1015 1016 opl.AddPost(post2) 1017 opl.AddOrder(post2.Id) 1018 1019 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1020 CheckNoError(t, resp) 1021 1022 if len(rpl.Posts) != 2 { 1023 t.Fatal("should have returned 2 posts") 1024 } 1025 1026 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1027 t.Fatal("posts should have matched") 1028 } 1029 1030 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 1) 1031 CheckNoError(t, resp) 1032 1033 if len(rpl.Posts) != 1 { 1034 t.Fatal("should have returned 1 post") 1035 } 1036 1037 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1, 1) 1038 CheckNoError(t, resp) 1039 1040 if len(rpl.Posts) != 1 { 1041 t.Fatal("should have returned 1 post") 1042 } 1043 1044 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1000, 10) 1045 CheckNoError(t, resp) 1046 1047 if len(rpl.Posts) != 0 { 1048 t.Fatal("should be empty") 1049 } 1050 1051 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, GenerateTestId(), 0, 10) 1052 CheckNoError(t, resp) 1053 1054 if len(rpl.Posts) != 0 { 1055 t.Fatal("should be empty") 1056 } 1057 1058 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, "junk", 0, 10) 1059 CheckBadRequestStatus(t, resp) 1060 1061 if rpl != nil { 1062 t.Fatal("should be nil") 1063 } 1064 1065 channel3 := th.CreatePrivateChannel() 1066 post4 := th.CreatePostWithClient(Client, channel3) 1067 1068 preference.Name = post4.Id 1069 Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1070 1071 opl.AddPost(post4) 1072 opl.AddOrder(post4.Id) 1073 1074 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1075 CheckNoError(t, resp) 1076 1077 if len(rpl.Posts) != 3 { 1078 t.Fatal("should have returned 3 posts") 1079 } 1080 1081 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1082 t.Fatal("posts should have matched") 1083 } 1084 1085 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 2) 1086 CheckNoError(t, resp) 1087 1088 if len(rpl.Posts) != 2 { 1089 t.Fatal("should have returned 2 posts") 1090 } 1091 1092 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 2, 2) 1093 CheckNoError(t, resp) 1094 1095 if len(rpl.Posts) != 1 { 1096 t.Fatal("should have returned 1 post") 1097 } 1098 1099 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 1000, 10) 1100 CheckNoError(t, resp) 1101 1102 if len(rpl.Posts) != 0 { 1103 t.Fatal("should be empty") 1104 } 1105 1106 channel4 := th.CreateChannelWithClient(th.SystemAdminClient, model.CHANNEL_PRIVATE) 1107 post5 := th.CreatePostWithClient(th.SystemAdminClient, channel4) 1108 1109 preference.Name = post5.Id 1110 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1111 CheckForbiddenStatus(t, resp) 1112 1113 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1114 CheckNoError(t, resp) 1115 1116 if len(rpl.Posts) != 3 { 1117 t.Fatal("should have returned 3 posts") 1118 } 1119 1120 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1121 t.Fatal("posts should have matched") 1122 } 1123 1124 th.AddUserToChannel(user, channel4) 1125 _, resp = Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 1126 CheckNoError(t, resp) 1127 1128 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1129 CheckNoError(t, resp) 1130 1131 opl.AddPost(post5) 1132 opl.AddOrder(post5.Id) 1133 1134 if len(rpl.Posts) != 4 { 1135 t.Fatal("should have returned 4 posts") 1136 } 1137 1138 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 1139 t.Fatal("posts should have matched") 1140 } 1141 1142 err := th.App.RemoveUserFromChannel(user.Id, "", channel4) 1143 if err != nil { 1144 t.Error("Unable to remove user from channel") 1145 } 1146 1147 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1148 CheckNoError(t, resp) 1149 1150 opl2 := model.NewPostList() 1151 opl2.AddPost(post1) 1152 opl2.AddOrder(post1.Id) 1153 opl2.AddPost(post2) 1154 opl2.AddOrder(post2.Id) 1155 opl2.AddPost(post4) 1156 opl2.AddOrder(post4.Id) 1157 1158 if len(rpl.Posts) != 3 { 1159 t.Fatal("should have returned 3 posts") 1160 } 1161 1162 if !reflect.DeepEqual(rpl.Posts, opl2.Posts) { 1163 t.Fatal("posts should have matched") 1164 } 1165 1166 _, resp = Client.GetFlaggedPostsForUser("junk", 0, 10) 1167 CheckBadRequestStatus(t, resp) 1168 1169 _, resp = Client.GetFlaggedPostsForUser(GenerateTestId(), 0, 10) 1170 CheckForbiddenStatus(t, resp) 1171 1172 Client.Logout() 1173 1174 _, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 1175 CheckUnauthorizedStatus(t, resp) 1176 1177 _, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1178 CheckUnauthorizedStatus(t, resp) 1179 1180 _, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 1181 CheckUnauthorizedStatus(t, resp) 1182 1183 _, resp = th.SystemAdminClient.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 1184 CheckNoError(t, resp) 1185 1186 _, resp = th.SystemAdminClient.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 1187 CheckNoError(t, resp) 1188 1189 _, resp = th.SystemAdminClient.GetFlaggedPostsForUser(user.Id, 0, 10) 1190 CheckNoError(t, resp) 1191 } 1192 1193 func TestGetPostsAfterAndBefore(t *testing.T) { 1194 th := Setup().InitBasic() 1195 defer th.TearDown() 1196 Client := th.Client 1197 1198 post1 := th.CreatePost() 1199 post2 := th.CreatePost() 1200 post3 := th.CreatePost() 1201 post4 := th.CreatePost() 1202 post5 := th.CreatePost() 1203 1204 posts, resp := Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 0, 100, "") 1205 CheckNoError(t, resp) 1206 1207 found := make([]bool, 2) 1208 for _, p := range posts.Posts { 1209 if p.Id == post1.Id { 1210 found[0] = true 1211 } else if p.Id == post2.Id { 1212 found[1] = true 1213 } 1214 1215 if p.Id == post4.Id || p.Id == post5.Id { 1216 t.Fatal("returned posts after") 1217 } 1218 } 1219 1220 for _, f := range found { 1221 if !f { 1222 t.Fatal("missing post") 1223 } 1224 } 1225 1226 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 1, 1, "") 1227 CheckNoError(t, resp) 1228 1229 if len(posts.Posts) != 1 { 1230 t.Fatal("too many posts returned") 1231 } 1232 1233 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, "junk", 1, 1, "") 1234 CheckNoError(t, resp) 1235 1236 if len(posts.Posts) != 0 { 1237 t.Fatal("should have no posts") 1238 } 1239 1240 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 0, 100, "") 1241 CheckNoError(t, resp) 1242 1243 found = make([]bool, 2) 1244 for _, p := range posts.Posts { 1245 if p.Id == post4.Id { 1246 found[0] = true 1247 } else if p.Id == post5.Id { 1248 found[1] = true 1249 } 1250 1251 if p.Id == post1.Id || p.Id == post2.Id { 1252 t.Fatal("returned posts before") 1253 } 1254 } 1255 1256 for _, f := range found { 1257 if !f { 1258 t.Fatal("missing post") 1259 } 1260 } 1261 1262 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 1, 1, "") 1263 CheckNoError(t, resp) 1264 1265 if len(posts.Posts) != 1 { 1266 t.Fatal("too many posts returned") 1267 } 1268 1269 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, "junk", 1, 1, "") 1270 CheckNoError(t, resp) 1271 1272 if len(posts.Posts) != 0 { 1273 t.Fatal("should have no posts") 1274 } 1275 } 1276 1277 func TestGetPost(t *testing.T) { 1278 th := Setup().InitBasic() 1279 defer th.TearDown() 1280 Client := th.Client 1281 1282 post, resp := Client.GetPost(th.BasicPost.Id, "") 1283 CheckNoError(t, resp) 1284 1285 if post.Id != th.BasicPost.Id { 1286 t.Fatal("post ids don't match") 1287 } 1288 1289 post, resp = Client.GetPost(th.BasicPost.Id, resp.Etag) 1290 CheckEtag(t, post, resp) 1291 1292 _, resp = Client.GetPost("", "") 1293 CheckNotFoundStatus(t, resp) 1294 1295 _, resp = Client.GetPost("junk", "") 1296 CheckBadRequestStatus(t, resp) 1297 1298 _, resp = Client.GetPost(model.NewId(), "") 1299 CheckNotFoundStatus(t, resp) 1300 1301 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1302 1303 // Channel is public, should be able to read post 1304 _, resp = Client.GetPost(th.BasicPost.Id, "") 1305 CheckNoError(t, resp) 1306 1307 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1308 1309 _, resp = Client.GetPost(privatePost.Id, "") 1310 CheckNoError(t, resp) 1311 1312 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1313 1314 // Channel is private, should not be able to read post 1315 _, resp = Client.GetPost(privatePost.Id, "") 1316 CheckForbiddenStatus(t, resp) 1317 1318 Client.Logout() 1319 _, resp = Client.GetPost(model.NewId(), "") 1320 CheckUnauthorizedStatus(t, resp) 1321 1322 _, resp = th.SystemAdminClient.GetPost(th.BasicPost.Id, "") 1323 CheckNoError(t, resp) 1324 } 1325 1326 func TestDeletePost(t *testing.T) { 1327 th := Setup().InitBasic() 1328 defer th.TearDown() 1329 Client := th.Client 1330 1331 _, resp := Client.DeletePost("") 1332 CheckNotFoundStatus(t, resp) 1333 1334 _, resp = Client.DeletePost("junk") 1335 CheckBadRequestStatus(t, resp) 1336 1337 _, resp = Client.DeletePost(th.BasicPost.Id) 1338 CheckForbiddenStatus(t, resp) 1339 1340 Client.Login(th.TeamAdminUser.Email, th.TeamAdminUser.Password) 1341 _, resp = Client.DeletePost(th.BasicPost.Id) 1342 CheckNoError(t, resp) 1343 1344 post := th.CreatePost() 1345 user := th.CreateUser() 1346 1347 Client.Logout() 1348 Client.Login(user.Email, user.Password) 1349 1350 _, resp = Client.DeletePost(post.Id) 1351 CheckForbiddenStatus(t, resp) 1352 1353 Client.Logout() 1354 _, resp = Client.DeletePost(model.NewId()) 1355 CheckUnauthorizedStatus(t, resp) 1356 1357 status, resp := th.SystemAdminClient.DeletePost(post.Id) 1358 if !status { 1359 t.Fatal("post should return status OK") 1360 } 1361 CheckNoError(t, resp) 1362 } 1363 1364 func TestGetPostThread(t *testing.T) { 1365 th := Setup().InitBasic() 1366 defer th.TearDown() 1367 Client := th.Client 1368 1369 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: th.BasicPost.Id} 1370 post, _ = Client.CreatePost(post) 1371 1372 list, resp := Client.GetPostThread(th.BasicPost.Id, "") 1373 CheckNoError(t, resp) 1374 1375 var list2 *model.PostList 1376 list2, resp = Client.GetPostThread(th.BasicPost.Id, resp.Etag) 1377 CheckEtag(t, list2, resp) 1378 1379 if list.Order[0] != th.BasicPost.Id { 1380 t.Fatal("wrong order") 1381 } 1382 1383 if _, ok := list.Posts[th.BasicPost.Id]; !ok { 1384 t.Fatal("should have had post") 1385 } 1386 1387 if _, ok := list.Posts[post.Id]; !ok { 1388 t.Fatal("should have had post") 1389 } 1390 1391 _, resp = Client.GetPostThread("junk", "") 1392 CheckBadRequestStatus(t, resp) 1393 1394 _, resp = Client.GetPostThread(model.NewId(), "") 1395 CheckNotFoundStatus(t, resp) 1396 1397 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1398 1399 // Channel is public, should be able to read post 1400 _, resp = Client.GetPostThread(th.BasicPost.Id, "") 1401 CheckNoError(t, resp) 1402 1403 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1404 1405 _, resp = Client.GetPostThread(privatePost.Id, "") 1406 CheckNoError(t, resp) 1407 1408 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1409 1410 // Channel is private, should not be able to read post 1411 _, resp = Client.GetPostThread(privatePost.Id, "") 1412 CheckForbiddenStatus(t, resp) 1413 1414 Client.Logout() 1415 _, resp = Client.GetPostThread(model.NewId(), "") 1416 CheckUnauthorizedStatus(t, resp) 1417 1418 _, resp = th.SystemAdminClient.GetPostThread(th.BasicPost.Id, "") 1419 CheckNoError(t, resp) 1420 } 1421 1422 func TestSearchPosts(t *testing.T) { 1423 th := Setup().InitBasic() 1424 defer th.TearDown() 1425 experimentalViewArchivedChannels := *th.App.Config().TeamSettings.ExperimentalViewArchivedChannels 1426 defer func() { 1427 th.App.UpdateConfig(func(cfg *model.Config) { 1428 cfg.TeamSettings.ExperimentalViewArchivedChannels = &experimentalViewArchivedChannels 1429 }) 1430 }() 1431 th.App.UpdateConfig(func(cfg *model.Config) { 1432 *cfg.TeamSettings.ExperimentalViewArchivedChannels = true 1433 }) 1434 1435 th.LoginBasic() 1436 Client := th.Client 1437 1438 message := "search for post1" 1439 _ = th.CreateMessagePost(message) 1440 1441 message = "search for post2" 1442 post2 := th.CreateMessagePost(message) 1443 1444 message = "#hashtag search for post3" 1445 post3 := th.CreateMessagePost(message) 1446 1447 message = "hashtag for post4" 1448 _ = th.CreateMessagePost(message) 1449 1450 archivedChannel := th.CreatePublicChannel() 1451 _ = th.CreateMessagePostWithClient(th.Client, archivedChannel, "#hashtag for post3") 1452 th.Client.DeleteChannel(archivedChannel.Id) 1453 1454 terms := "search" 1455 isOrSearch := false 1456 timezoneOffset := 5 1457 searchParams := model.SearchParameter{ 1458 Terms: &terms, 1459 IsOrSearch: &isOrSearch, 1460 TimeZoneOffset: &timezoneOffset, 1461 } 1462 posts, resp := Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1463 CheckNoError(t, resp) 1464 if len(posts.Order) != 3 { 1465 t.Fatal("wrong search") 1466 } 1467 1468 terms = "search" 1469 page := 0 1470 perPage := 2 1471 searchParams = model.SearchParameter{ 1472 Terms: &terms, 1473 IsOrSearch: &isOrSearch, 1474 TimeZoneOffset: &timezoneOffset, 1475 Page: &page, 1476 PerPage: &perPage, 1477 } 1478 posts2, resp := Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1479 CheckNoError(t, resp) 1480 if len(posts2.Order) != 3 { // We don't support paging for DB search yet, modify this when we do. 1481 t.Fatal("Wrong number of posts", len(posts2.Order)) 1482 } 1483 assert.Equal(t, posts.Order[0], posts2.Order[0]) 1484 assert.Equal(t, posts.Order[1], posts2.Order[1]) 1485 1486 page = 1 1487 searchParams = model.SearchParameter{ 1488 Terms: &terms, 1489 IsOrSearch: &isOrSearch, 1490 TimeZoneOffset: &timezoneOffset, 1491 Page: &page, 1492 PerPage: &perPage, 1493 } 1494 posts2, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1495 CheckNoError(t, resp) 1496 if len(posts2.Order) != 0 { // We don't support paging for DB search yet, modify this when we do. 1497 t.Fatal("Wrong number of posts", len(posts2.Order)) 1498 } 1499 1500 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "search", false) 1501 CheckNoError(t, resp) 1502 if len(posts.Order) != 3 { 1503 t.Fatal("wrong search") 1504 } 1505 1506 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post2", false) 1507 CheckNoError(t, resp) 1508 if len(posts.Order) != 1 && posts.Order[0] == post2.Id { 1509 t.Fatal("wrong search") 1510 } 1511 1512 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "#hashtag", false) 1513 CheckNoError(t, resp) 1514 if len(posts.Order) != 1 && posts.Order[0] == post3.Id { 1515 t.Fatal("wrong search") 1516 } 1517 1518 terms = "#hashtag" 1519 includeDeletedChannels := true 1520 searchParams = model.SearchParameter{ 1521 Terms: &terms, 1522 IsOrSearch: &isOrSearch, 1523 TimeZoneOffset: &timezoneOffset, 1524 IncludeDeletedChannels: &includeDeletedChannels, 1525 } 1526 posts, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1527 CheckNoError(t, resp) 1528 if len(posts.Order) != 2 { 1529 t.Fatal("wrong search") 1530 } 1531 1532 th.App.UpdateConfig(func(cfg *model.Config) { 1533 *cfg.TeamSettings.ExperimentalViewArchivedChannels = false 1534 }) 1535 1536 posts, resp = Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) 1537 CheckNoError(t, resp) 1538 if len(posts.Order) != 1 { 1539 t.Fatal("wrong search") 1540 } 1541 1542 if posts, _ = Client.SearchPosts(th.BasicTeam.Id, "*", false); len(posts.Order) != 0 { 1543 t.Fatal("searching for just * shouldn't return any results") 1544 } 1545 1546 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post1 post2", true) 1547 CheckNoError(t, resp) 1548 1549 if len(posts.Order) != 2 { 1550 t.Fatal("wrong search results") 1551 } 1552 1553 _, resp = Client.SearchPosts("junk", "#sgtitlereview", false) 1554 CheckBadRequestStatus(t, resp) 1555 1556 _, resp = Client.SearchPosts(model.NewId(), "#sgtitlereview", false) 1557 CheckForbiddenStatus(t, resp) 1558 1559 _, resp = Client.SearchPosts(th.BasicTeam.Id, "", false) 1560 CheckBadRequestStatus(t, resp) 1561 1562 Client.Logout() 1563 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1564 CheckUnauthorizedStatus(t, resp) 1565 } 1566 1567 func TestSearchHashtagPosts(t *testing.T) { 1568 th := Setup().InitBasic() 1569 defer th.TearDown() 1570 th.LoginBasic() 1571 Client := th.Client 1572 1573 message := "#sgtitlereview with space" 1574 assert.NotNil(t, th.CreateMessagePost(message)) 1575 1576 message = "#sgtitlereview\n with return" 1577 assert.NotNil(t, th.CreateMessagePost(message)) 1578 1579 message = "no hashtag" 1580 assert.NotNil(t, th.CreateMessagePost(message)) 1581 1582 posts, resp := Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1583 CheckNoError(t, resp) 1584 if len(posts.Order) != 2 { 1585 t.Fatal("wrong search results") 1586 } 1587 1588 Client.Logout() 1589 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1590 CheckUnauthorizedStatus(t, resp) 1591 } 1592 1593 func TestSearchPostsInChannel(t *testing.T) { 1594 th := Setup().InitBasic() 1595 defer th.TearDown() 1596 th.LoginBasic() 1597 Client := th.Client 1598 1599 channel := th.CreatePublicChannel() 1600 1601 message := "sgtitlereview with space" 1602 _ = th.CreateMessagePost(message) 1603 1604 message = "sgtitlereview\n with return" 1605 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1606 1607 message = "other message with no return" 1608 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1609 1610 message = "other message with no return" 1611 _ = th.CreateMessagePostWithClient(Client, channel, message) 1612 1613 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:", false); len(posts.Order) != 0 { 1614 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1615 } 1616 1617 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:", false); len(posts.Order) != 0 { 1618 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1619 } 1620 1621 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel.Name, false); len(posts.Order) != 2 { 1622 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1623 } 1624 1625 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1626 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1627 } 1628 1629 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1630 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1631 } 1632 1633 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "ChAnNeL:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1634 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1635 } 1636 1637 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview", false); len(posts.Order) != 2 { 1638 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1639 } 1640 1641 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1642 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1643 } 1644 1645 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview in: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1646 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1647 } 1648 1649 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1650 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1651 } 1652 1653 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel: "+th.BasicChannel2.Name+" channel: "+channel.Name, false); len(posts.Order) != 3 { 1654 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1655 } 1656 1657 } 1658 1659 func TestSearchPostsFromUser(t *testing.T) { 1660 th := Setup().InitBasic() 1661 defer th.TearDown() 1662 Client := th.Client 1663 1664 th.LoginTeamAdmin() 1665 user := th.CreateUser() 1666 th.LinkUserToTeam(user, th.BasicTeam) 1667 th.App.AddUserToChannel(user, th.BasicChannel) 1668 th.App.AddUserToChannel(user, th.BasicChannel2) 1669 1670 message := "sgtitlereview with space" 1671 _ = th.CreateMessagePost(message) 1672 1673 Client.Logout() 1674 th.LoginBasic2() 1675 1676 message = "sgtitlereview\n with return" 1677 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1678 1679 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.TeamAdminUser.Username, false); len(posts.Order) != 2 { 1680 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1681 } 1682 1683 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 1 { 1684 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1685 } 1686 1687 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" sgtitlereview", false); len(posts.Order) != 1 { 1688 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1689 } 1690 1691 message = "hullo" 1692 _ = th.CreateMessagePost(message) 1693 1694 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" in:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1695 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1696 } 1697 1698 Client.Login(user.Email, user.Password) 1699 1700 // wait for the join/leave messages to be created for user3 since they're done asynchronously 1701 time.Sleep(100 * time.Millisecond) 1702 1703 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 2 { 1704 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1705 } 1706 1707 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username, false); len(posts.Order) != 2 { 1708 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1709 } 1710 1711 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1712 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1713 } 1714 1715 message = "coconut" 1716 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1717 1718 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name+" coconut", false); len(posts.Order) != 1 { 1719 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1720 } 1721 } 1722 1723 func TestSearchPostsWithDateFlags(t *testing.T) { 1724 th := Setup().InitBasic() 1725 defer th.TearDown() 1726 th.LoginBasic() 1727 Client := th.Client 1728 1729 message := "sgtitlereview\n with return" 1730 createDate := time.Date(2018, 8, 1, 5, 0, 0, 0, time.UTC) 1731 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1732 1733 message = "other message with no return" 1734 createDate = time.Date(2018, 8, 2, 5, 0, 0, 0, time.UTC) 1735 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1736 1737 message = "other message with no return" 1738 createDate = time.Date(2018, 8, 3, 5, 0, 0, 0, time.UTC) 1739 _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) 1740 1741 posts, _ := Client.SearchPosts(th.BasicTeam.Id, "return", false) 1742 if len(posts.Order) != 3 { 1743 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1744 } 1745 1746 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:", false) 1747 if len(posts.Order) != 0 { 1748 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1749 } 1750 1751 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:", false) 1752 if len(posts.Order) != 0 { 1753 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1754 } 1755 1756 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:", false) 1757 if len(posts.Order) != 0 { 1758 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1759 } 1760 1761 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:2018-08-01", false) 1762 if len(posts.Order) != 1 { 1763 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1764 } 1765 1766 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:2018-08-01", false) 1767 resultCount := 0 1768 for _, post := range posts.Posts { 1769 if post.UserId == th.BasicUser.Id { 1770 resultCount = resultCount + 1 1771 } 1772 } 1773 if resultCount != 2 { 1774 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1775 } 1776 1777 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-02", false) 1778 if len(posts.Order) != 1 { 1779 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1780 } 1781 1782 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-03 after:2018-08-02", false) 1783 if len(posts.Order) != 0 { 1784 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1785 } 1786 1787 posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-03 after:2018-08-01", false) 1788 if len(posts.Order) != 1 { 1789 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1790 } 1791 } 1792 1793 func TestGetFileInfosForPost(t *testing.T) { 1794 th := Setup().InitBasic() 1795 defer th.TearDown() 1796 Client := th.Client 1797 1798 fileIds := make([]string, 3) 1799 if data, err := testutils.ReadTestFile("test.png"); err != nil { 1800 t.Fatal(err) 1801 } else { 1802 for i := 0; i < 3; i++ { 1803 fileResp, _ := Client.UploadFile(data, th.BasicChannel.Id, "test.png") 1804 fileIds[i] = fileResp.FileInfos[0].Id 1805 } 1806 } 1807 1808 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", FileIds: fileIds} 1809 post, _ = Client.CreatePost(post) 1810 1811 infos, resp := Client.GetFileInfosForPost(post.Id, "") 1812 CheckNoError(t, resp) 1813 1814 if len(infos) != 3 { 1815 t.Fatal("missing file infos") 1816 } 1817 1818 found := false 1819 for _, info := range infos { 1820 if info.Id == fileIds[0] { 1821 found = true 1822 } 1823 } 1824 1825 if !found { 1826 t.Fatal("missing file info") 1827 } 1828 1829 infos, resp = Client.GetFileInfosForPost(post.Id, resp.Etag) 1830 CheckEtag(t, infos, resp) 1831 1832 infos, resp = Client.GetFileInfosForPost(th.BasicPost.Id, "") 1833 CheckNoError(t, resp) 1834 1835 if len(infos) != 0 { 1836 t.Fatal("should have no file infos") 1837 } 1838 1839 _, resp = Client.GetFileInfosForPost("junk", "") 1840 CheckBadRequestStatus(t, resp) 1841 1842 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1843 CheckForbiddenStatus(t, resp) 1844 1845 Client.Logout() 1846 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1847 CheckUnauthorizedStatus(t, resp) 1848 1849 _, resp = th.SystemAdminClient.GetFileInfosForPost(th.BasicPost.Id, "") 1850 CheckNoError(t, resp) 1851 }