github.com/dschalla/mattermost-server@v4.8.1-rc1+incompatible/api/post_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package api 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "net/http/httptest" 11 "net/url" 12 "reflect" 13 "strings" 14 15 "testing" 16 "time" 17 18 "github.com/mattermost/mattermost-server/app" 19 "github.com/mattermost/mattermost-server/model" 20 "github.com/mattermost/mattermost-server/store" 21 "github.com/mattermost/mattermost-server/utils" 22 ) 23 24 func TestCreatePost(t *testing.T) { 25 th := Setup().InitBasic() 26 defer th.TearDown() 27 28 Client := th.BasicClient 29 team := th.BasicTeam 30 team2 := th.CreateTeam(th.BasicClient) 31 user3 := th.CreateUser(th.BasicClient) 32 th.LinkUserToTeam(user3, team2) 33 channel1 := th.BasicChannel 34 channel2 := th.CreateChannel(Client, team) 35 36 th.InitSystemAdmin() 37 AdminClient := th.SystemAdminClient 38 adminTeam := th.SystemAdminTeam 39 adminUser := th.CreateUser(th.SystemAdminClient) 40 th.LinkUserToTeam(adminUser, adminTeam) 41 42 post1 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag a" + model.NewId() + "a", Props: model.StringInterface{model.PROPS_ADD_CHANNEL_MEMBER: "no good"}} 43 rpost1, err := Client.CreatePost(post1) 44 if err != nil { 45 t.Fatal(err) 46 } 47 48 if rpost1.Data.(*model.Post).Message != post1.Message { 49 t.Fatal("message didn't match") 50 } 51 52 if rpost1.Data.(*model.Post).Hashtags != "#hashtag" { 53 t.Fatal("hashtag didn't match") 54 } 55 56 if len(rpost1.Data.(*model.Post).FileIds) != 0 { 57 t.Fatal("shouldn't have files") 58 } 59 60 if rpost1.Data.(*model.Post).EditAt != 0 { 61 t.Fatal("Newly craeted post shouldn't have EditAt set") 62 } 63 64 if rpost1.Data.(*model.Post).Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 65 t.Fatal("newly created post shouldn't have Props['add_channel_member'] set") 66 } 67 68 _, err = Client.CreatePost(&model.Post{ChannelId: channel1.Id, Message: "#hashtag a" + model.NewId() + "a", Type: model.POST_SYSTEM_GENERIC}) 69 if err == nil { 70 t.Fatal("should have failed - bad post type") 71 } 72 73 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id} 74 rpost2, err := Client.CreatePost(post2) 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id, ParentId: rpost2.Data.(*model.Post).Id} 80 _, err = Client.CreatePost(post3) 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 post4 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: "junk"} 86 _, err = Client.CreatePost(post4) 87 if err.StatusCode != http.StatusBadRequest { 88 t.Fatal("Should have been invalid param") 89 } 90 91 post5 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id, ParentId: "junk"} 92 _, err = Client.CreatePost(post5) 93 if err.StatusCode != http.StatusBadRequest { 94 t.Fatal("Should have been invalid param") 95 } 96 97 post1c2 := &model.Post{ChannelId: channel2.Id, Message: "zz" + model.NewId() + "a"} 98 rpost1c2, err := Client.CreatePost(post1c2) 99 100 post2c2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1c2.Data.(*model.Post).Id} 101 _, err = Client.CreatePost(post2c2) 102 if err.StatusCode != http.StatusBadRequest { 103 t.Fatal("Should have been invalid param") 104 } 105 106 post6 := &model.Post{ChannelId: "junk", Message: "zz" + model.NewId() + "a"} 107 _, err = Client.CreatePost(post6) 108 if err.StatusCode != http.StatusForbidden { 109 t.Fatal("Should have been forbidden") 110 } 111 112 th.LoginBasic2() 113 114 post7 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 115 _, err = Client.CreatePost(post7) 116 if err.StatusCode != http.StatusForbidden { 117 t.Fatal("Should have been forbidden") 118 } 119 120 Client.Login(user3.Email, user3.Password) 121 Client.SetTeamId(team2.Id) 122 channel3 := th.CreateChannel(Client, team2) 123 124 post8 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 125 _, err = Client.CreatePost(post8) 126 if err.StatusCode != http.StatusForbidden { 127 t.Fatal("Should have been forbidden") 128 } 129 130 if _, err = Client.DoApiPost("/channels/"+channel3.Id+"/create", "garbage"); err == nil { 131 t.Fatal("should have been an error") 132 } 133 134 fileIds := make([]string, 4) 135 if data, err := readTestFile("test.png"); err != nil { 136 t.Fatal(err) 137 } else { 138 for i := 0; i < 3; i++ { 139 fileIds[i] = Client.MustGeneric(Client.UploadPostAttachment(data, channel3.Id, "test.png")).(*model.FileUploadResponse).FileInfos[0].Id 140 } 141 } 142 143 // Make sure duplicated file ids are removed 144 fileIds[3] = fileIds[0] 145 146 post9 := &model.Post{ 147 ChannelId: channel3.Id, 148 Message: "test", 149 FileIds: fileIds, 150 } 151 if resp, err := Client.CreatePost(post9); err != nil { 152 t.Fatal(err) 153 } else if rpost9 := resp.Data.(*model.Post); len(rpost9.FileIds) != 3 { 154 t.Fatal("post should have 3 files") 155 } else { 156 infos := store.Must(th.App.Srv.Store.FileInfo().GetForPost(rpost9.Id, true, true)).([]*model.FileInfo) 157 158 if len(infos) != 3 { 159 t.Fatal("should've attached all 3 files to post") 160 } 161 } 162 163 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly = true }) 164 th.App.SetLicense(model.NewTestLicense()) 165 166 defaultChannel := store.Must(th.App.Srv.Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, true)).(*model.Channel) 167 defaultPost := &model.Post{ 168 ChannelId: defaultChannel.Id, 169 Message: "Default Channel Post", 170 } 171 if _, err = Client.CreatePost(defaultPost); err == nil { 172 t.Fatal("should have failed -- ExperimentalTownSquareIsReadOnly is true and it's a read only channel") 173 } 174 175 adminDefaultChannel := store.Must(th.App.Srv.Store.Channel().GetByName(adminTeam.Id, model.DEFAULT_CHANNEL, true)).(*model.Channel) 176 adminDefaultPost := &model.Post{ 177 ChannelId: adminDefaultChannel.Id, 178 Message: "Admin Default Channel Post", 179 } 180 if _, err = AdminClient.CreatePost(adminDefaultPost); err != nil { 181 t.Fatal("should not have failed -- ExperimentalTownSquareIsReadOnly is true and admin can post to channel") 182 } 183 } 184 185 func TestCreatePostWithCreateAt(t *testing.T) { 186 187 // An ordinary user cannot use CreateAt 188 189 th := Setup().InitBasic() 190 defer th.TearDown() 191 192 Client := th.BasicClient 193 channel1 := th.BasicChannel 194 195 post := &model.Post{ 196 ChannelId: channel1.Id, 197 Message: "PLT-4349", 198 CreateAt: 1234, 199 } 200 if resp, err := Client.CreatePost(post); err != nil { 201 t.Fatal(err) 202 } else if rpost := resp.Data.(*model.Post); rpost.CreateAt == post.CreateAt { 203 t.Fatal("post should be created with default CreateAt timestamp for ordinary user") 204 } 205 206 // But a System Admin user can 207 208 th.InitSystemAdmin() 209 SysClient := th.SystemAdminClient 210 211 if resp, err := SysClient.CreatePost(post); err != nil { 212 t.Fatal(err) 213 } else if rpost := resp.Data.(*model.Post); rpost.CreateAt != post.CreateAt { 214 t.Fatal("post should be created with provided CreateAt timestamp for System Admin user") 215 } 216 } 217 218 func testCreatePostWithOutgoingHook( 219 t *testing.T, 220 hookContentType, expectedContentType, message, triggerWord string, 221 fileIds []string, 222 triggerWhen int, 223 ) { 224 th := Setup().InitSystemAdmin() 225 defer th.TearDown() 226 227 Client := th.SystemAdminClient 228 team := th.SystemAdminTeam 229 user := th.SystemAdminUser 230 channel := th.CreateChannel(Client, team) 231 232 th.App.UpdateConfig(func(cfg *model.Config) { 233 cfg.ServiceSettings.EnableOutgoingWebhooks = true 234 *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1" 235 }) 236 237 var hook *model.OutgoingWebhook 238 var post *model.Post 239 240 // Create a test server that is the target of the outgoing webhook. It will 241 // validate the webhook body fields and write to the success channel on 242 // success/failure. 243 success := make(chan bool) 244 wait := make(chan bool, 1) 245 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 246 <-wait 247 248 requestContentType := r.Header.Get("Content-Type") 249 if requestContentType != expectedContentType { 250 t.Logf("Content-Type is %s, should be %s", requestContentType, expectedContentType) 251 success <- false 252 return 253 } 254 255 expectedPayload := &model.OutgoingWebhookPayload{ 256 Token: hook.Token, 257 TeamId: hook.TeamId, 258 TeamDomain: team.Name, 259 ChannelId: post.ChannelId, 260 ChannelName: channel.Name, 261 Timestamp: post.CreateAt, 262 UserId: post.UserId, 263 UserName: user.Username, 264 PostId: post.Id, 265 Text: post.Message, 266 TriggerWord: triggerWord, 267 FileIds: strings.Join(post.FileIds, ","), 268 } 269 270 // depending on the Content-Type, we expect to find a JSON or form encoded payload 271 if requestContentType == "application/json" { 272 decoder := json.NewDecoder(r.Body) 273 o := &model.OutgoingWebhookPayload{} 274 decoder.Decode(&o) 275 276 if !reflect.DeepEqual(expectedPayload, o) { 277 t.Logf("JSON payload is %+v, should be %+v", o, expectedPayload) 278 success <- false 279 return 280 } 281 } else { 282 err := r.ParseForm() 283 if err != nil { 284 t.Logf("Error parsing form: %q", err) 285 success <- false 286 return 287 } 288 289 expectedFormValues, _ := url.ParseQuery(expectedPayload.ToFormValues()) 290 if !reflect.DeepEqual(expectedFormValues, r.Form) { 291 t.Logf("Form values are %q, should be %q", r.Form, expectedFormValues) 292 success <- false 293 return 294 } 295 } 296 297 resp := &model.OutgoingWebhookResponse{} 298 resp.Text = model.NewString("some test text") 299 resp.Username = "testusername" 300 resp.IconURL = "http://www.mattermost.org/wp-content/uploads/2016/04/icon.png" 301 resp.Props = map[string]interface{}{"someprop": "somevalue"} 302 resp.Type = "custom_test" 303 304 w.Write([]byte(resp.ToJson())) 305 306 success <- true 307 })) 308 defer ts.Close() 309 310 // create an outgoing webhook, passing it the test server URL 311 var triggerWords []string 312 if triggerWord != "" { 313 triggerWords = []string{triggerWord} 314 } 315 316 hook = &model.OutgoingWebhook{ 317 ChannelId: channel.Id, 318 TeamId: team.Id, 319 ContentType: hookContentType, 320 TriggerWords: triggerWords, 321 TriggerWhen: triggerWhen, 322 CallbackURLs: []string{ts.URL}, 323 } 324 325 if result, err := Client.CreateOutgoingWebhook(hook); err != nil { 326 t.Fatal(err) 327 } else { 328 hook = result.Data.(*model.OutgoingWebhook) 329 } 330 331 // create a post to trigger the webhook 332 post = &model.Post{ 333 ChannelId: channel.Id, 334 Message: message, 335 FileIds: fileIds, 336 } 337 338 if result, err := Client.CreatePost(post); err != nil { 339 t.Fatal(err) 340 } else { 341 post = result.Data.(*model.Post) 342 } 343 344 wait <- true 345 346 // We wait for the test server to write to the success channel and we make 347 // the test fail if that doesn't happen before the timeout. 348 select { 349 case ok := <-success: 350 if !ok { 351 t.Fatal("Test server did send an invalid webhook.") 352 } 353 case <-time.After(time.Second): 354 t.Fatal("Timeout, test server did not send the webhook.") 355 } 356 } 357 358 func TestCreatePostWithOutgoingHook_form_urlencoded(t *testing.T) { 359 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH) 360 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH) 361 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH) 362 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH) 363 } 364 365 func TestCreatePostWithOutgoingHook_json(t *testing.T) { 366 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH) 367 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH) 368 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH) 369 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH) 370 } 371 372 // hooks created before we added the ContentType field should be considered as 373 // application/x-www-form-urlencoded 374 func TestCreatePostWithOutgoingHook_no_content_type(t *testing.T) { 375 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH) 376 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH) 377 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH) 378 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH) 379 } 380 381 func TestUpdatePost(t *testing.T) { 382 th := Setup().InitBasic() 383 defer th.TearDown() 384 385 Client := th.BasicClient 386 channel1 := th.BasicChannel 387 388 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = model.ALLOW_EDIT_POST_ALWAYS }) 389 390 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 391 rpost1, err := Client.CreatePost(post1) 392 if err != nil { 393 t.Fatal(err) 394 } 395 396 if rpost1.Data.(*model.Post).Message != post1.Message { 397 t.Fatal("full name didn't match") 398 } 399 400 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id} 401 rpost2, err := Client.CreatePost(post2) 402 if err != nil { 403 t.Fatal(err) 404 } 405 406 if rpost2.Data.(*model.Post).EditAt != 0 { 407 t.Fatal("Newly craeted post shouldn't have EditAt set") 408 } 409 410 msg2 := "zz" + model.NewId() + " update post 1" 411 rpost2.Data.(*model.Post).Message = msg2 412 rpost2.Data.(*model.Post).Props[model.PROPS_ADD_CHANNEL_MEMBER] = "no good" 413 if rupost2, err := Client.UpdatePost(rpost2.Data.(*model.Post)); err != nil { 414 t.Fatal(err) 415 } else { 416 if rupost2.Data.(*model.Post).Message != msg2 { 417 t.Fatal("failed to updates") 418 } 419 if rupost2.Data.(*model.Post).EditAt == 0 { 420 t.Fatal("EditAt not updated for post") 421 } 422 if rupost2.Data.(*model.Post).Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 423 t.Fatal("failed to sanitize Props['add_channel_member'], should be nil") 424 } 425 } 426 427 msg1 := "#hashtag a" + model.NewId() + " update post 2" 428 rpost1.Data.(*model.Post).Message = msg1 429 if rupost1, err := Client.UpdatePost(rpost1.Data.(*model.Post)); err != nil { 430 t.Fatal(err) 431 } else { 432 if rupost1.Data.(*model.Post).Message != msg1 && rupost1.Data.(*model.Post).Hashtags != "#hashtag" { 433 t.Fatal("failed to updates") 434 } 435 } 436 437 up12 := &model.Post{Id: rpost1.Data.(*model.Post).Id, ChannelId: channel1.Id, Message: "zz" + model.NewId() + " updaet post 1 update 2"} 438 if rup12, err := Client.UpdatePost(up12); err != nil { 439 t.Fatal(err) 440 } else { 441 if rup12.Data.(*model.Post).Message != up12.Message { 442 t.Fatal("failed to updates") 443 } 444 } 445 446 rpost3, err := th.App.CreatePost(&model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", Type: model.POST_JOIN_LEAVE, UserId: th.BasicUser.Id}, channel1, false) 447 if err != nil { 448 t.Fatal(err) 449 } 450 451 up3 := &model.Post{Id: rpost3.Id, ChannelId: channel1.Id, Message: "zz" + model.NewId() + " update post 3"} 452 if _, err := Client.UpdatePost(up3); err == nil { 453 t.Fatal("shouldn't have been able to update system message") 454 } 455 456 // Test licensed policy controls for edit post 457 th.App.SetLicense(model.NewTestLicense()) 458 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = model.ALLOW_EDIT_POST_NEVER }) 459 460 post4 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id} 461 rpost4, err := Client.CreatePost(post4) 462 if err != nil { 463 t.Fatal(err) 464 } 465 466 up4 := &model.Post{Id: rpost4.Data.(*model.Post).Id, ChannelId: channel1.Id, Message: "zz" + model.NewId() + " update post 4"} 467 if _, err := Client.UpdatePost(up4); err == nil { 468 t.Fatal("shouldn't have been able to update a message when not allowed") 469 } 470 471 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowEditPost = model.ALLOW_EDIT_POST_TIME_LIMIT }) 472 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.PostEditTimeLimit = 1 }) //seconds 473 474 post5 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id} 475 rpost5, err := Client.CreatePost(post5) 476 if err != nil { 477 t.Fatal(err) 478 } 479 480 msg5 := "zz" + model.NewId() + " update post 5" 481 up5 := &model.Post{Id: rpost5.Data.(*model.Post).Id, ChannelId: channel1.Id, Message: msg5} 482 if rup5, err := Client.UpdatePost(up5); err != nil { 483 t.Fatal(err) 484 } else { 485 if rup5.Data.(*model.Post).Message != up5.Message { 486 t.Fatal("failed to updates") 487 } 488 } 489 490 time.Sleep(1000 * time.Millisecond) 491 492 up6 := &model.Post{Id: rpost5.Data.(*model.Post).Id, ChannelId: channel1.Id, Message: "zz" + model.NewId() + " update post 5"} 493 if _, err := Client.UpdatePost(up6); err == nil { 494 t.Fatal("shouldn't have been able to update a message after time limit") 495 } 496 } 497 498 func TestGetPosts(t *testing.T) { 499 th := Setup().InitBasic() 500 defer th.TearDown() 501 502 Client := th.BasicClient 503 channel1 := th.BasicChannel 504 505 time.Sleep(10 * time.Millisecond) 506 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 507 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 508 509 time.Sleep(10 * time.Millisecond) 510 post1a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 511 post1a1 = Client.Must(Client.CreatePost(post1a1)).Data.(*model.Post) 512 513 time.Sleep(10 * time.Millisecond) 514 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 515 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 516 517 time.Sleep(10 * time.Millisecond) 518 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 519 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 520 521 time.Sleep(10 * time.Millisecond) 522 post3a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post3.Id} 523 post3a1 = Client.Must(Client.CreatePost(post3a1)).Data.(*model.Post) 524 525 r1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList) 526 527 if r1.Order[0] != post3a1.Id { 528 t.Fatal("wrong order") 529 } 530 531 if r1.Order[1] != post3.Id { 532 t.Fatal("wrong order") 533 } 534 535 if len(r1.Posts) != 2 { // 3a1 and 3; 3a1's parent already there 536 t.Fatal("wrong size") 537 } 538 539 r2 := Client.Must(Client.GetPosts(channel1.Id, 2, 2, "")).Data.(*model.PostList) 540 541 if r2.Order[0] != post2.Id { 542 t.Fatal("wrong order") 543 } 544 545 if r2.Order[1] != post1a1.Id { 546 t.Fatal("wrong order") 547 } 548 549 if len(r2.Posts) != 3 { // 2 and 1a1; + 1a1's parent 550 t.Log(r2.Posts) 551 t.Fatal("wrong size") 552 } 553 } 554 555 func TestGetPostsSince(t *testing.T) { 556 th := Setup().InitBasic() 557 defer th.TearDown() 558 559 Client := th.BasicClient 560 channel1 := th.BasicChannel 561 562 time.Sleep(10 * time.Millisecond) 563 post0 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 564 post0 = Client.Must(Client.CreatePost(post0)).Data.(*model.Post) 565 566 time.Sleep(10 * time.Millisecond) 567 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 568 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 569 570 time.Sleep(10 * time.Millisecond) 571 post1a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 572 post1a1 = Client.Must(Client.CreatePost(post1a1)).Data.(*model.Post) 573 574 time.Sleep(10 * time.Millisecond) 575 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 576 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 577 578 time.Sleep(10 * time.Millisecond) 579 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 580 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 581 582 time.Sleep(10 * time.Millisecond) 583 post3a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post3.Id} 584 post3a1 = Client.Must(Client.CreatePost(post3a1)).Data.(*model.Post) 585 586 r1 := Client.Must(Client.GetPostsSince(channel1.Id, post1.CreateAt)).Data.(*model.PostList) 587 588 if r1.Order[0] != post3a1.Id { 589 t.Fatal("wrong order") 590 } 591 592 if r1.Order[1] != post3.Id { 593 t.Fatal("wrong order") 594 } 595 596 if len(r1.Posts) != 5 { 597 t.Fatal("wrong size") 598 } 599 600 now := model.GetMillis() 601 r2 := Client.Must(Client.GetPostsSince(channel1.Id, now)).Data.(*model.PostList) 602 603 if len(r2.Posts) != 0 { 604 t.Fatal("should have been empty") 605 } 606 607 post2.Message = "new message" 608 Client.Must(Client.UpdatePost(post2)) 609 610 r3 := Client.Must(Client.GetPostsSince(channel1.Id, now)).Data.(*model.PostList) 611 612 if len(r3.Order) != 2 { // 2 because deleted post is returned as well 613 t.Fatal("missing post update") 614 } 615 } 616 617 func TestGetPostsBeforeAfter(t *testing.T) { 618 th := Setup().InitBasic() 619 defer th.TearDown() 620 621 Client := th.BasicClient 622 channel1 := th.BasicChannel 623 624 time.Sleep(10 * time.Millisecond) 625 post0 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 626 post0 = Client.Must(Client.CreatePost(post0)).Data.(*model.Post) 627 628 time.Sleep(10 * time.Millisecond) 629 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 630 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 631 632 time.Sleep(10 * time.Millisecond) 633 post1a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 634 post1a1 = Client.Must(Client.CreatePost(post1a1)).Data.(*model.Post) 635 636 time.Sleep(10 * time.Millisecond) 637 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 638 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 639 640 time.Sleep(10 * time.Millisecond) 641 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 642 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 643 644 time.Sleep(10 * time.Millisecond) 645 post3a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post3.Id} 646 post3a1 = Client.Must(Client.CreatePost(post3a1)).Data.(*model.Post) 647 648 r1 := Client.Must(Client.GetPostsBefore(channel1.Id, post1a1.Id, 0, 10, "")).Data.(*model.PostList) 649 650 if r1.Order[0] != post1.Id { 651 t.Fatal("wrong order") 652 } 653 654 if r1.Order[1] != post0.Id { 655 t.Fatal("wrong order") 656 } 657 658 // including created post from test helper and system 'joined' message 659 if len(r1.Posts) != 4 { 660 t.Fatal("wrong size") 661 } 662 663 r2 := Client.Must(Client.GetPostsAfter(channel1.Id, post3a1.Id, 0, 3, "")).Data.(*model.PostList) 664 665 if len(r2.Posts) != 0 { 666 t.Fatal("should have been empty") 667 } 668 669 post2.Message = "new message" 670 Client.Must(Client.UpdatePost(post2)) 671 672 r3 := Client.Must(Client.GetPostsAfter(channel1.Id, post1a1.Id, 0, 2, "")).Data.(*model.PostList) 673 674 if r3.Order[0] != post3.Id { 675 t.Fatal("wrong order") 676 } 677 678 if r3.Order[1] != post2.Id { 679 t.Fatal("wrong order") 680 } 681 682 if len(r3.Order) != 2 { 683 t.Fatal("missing post update") 684 } 685 } 686 687 func TestSearchPosts(t *testing.T) { 688 th := Setup().InitBasic() 689 defer th.TearDown() 690 691 Client := th.BasicClient 692 channel1 := th.BasicChannel 693 694 post1 := &model.Post{ChannelId: channel1.Id, Message: "search for post1"} 695 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 696 697 post2 := &model.Post{ChannelId: channel1.Id, Message: "search for post2"} 698 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 699 700 post3 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag search for post3"} 701 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 702 703 post4 := &model.Post{ChannelId: channel1.Id, Message: "hashtag for post4"} 704 post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) 705 706 r1 := Client.Must(Client.SearchPosts("search", false)).Data.(*model.PostList) 707 708 if len(r1.Order) != 3 { 709 t.Fatal("wrong search") 710 } 711 712 r2 := Client.Must(Client.SearchPosts("post2", false)).Data.(*model.PostList) 713 714 if len(r2.Order) != 1 && r2.Order[0] == post2.Id { 715 t.Fatal("wrong search") 716 } 717 718 r3 := Client.Must(Client.SearchPosts("#hashtag", false)).Data.(*model.PostList) 719 720 if len(r3.Order) != 1 && r3.Order[0] == post3.Id { 721 t.Fatal("wrong search") 722 } 723 724 if r4 := Client.Must(Client.SearchPosts("*", false)).Data.(*model.PostList); len(r4.Order) != 0 { 725 t.Fatal("searching for just * shouldn't return any results") 726 } 727 728 r5 := Client.Must(Client.SearchPosts("post1 post2", true)).Data.(*model.PostList) 729 730 if len(r5.Order) != 2 { 731 t.Fatal("wrong search results") 732 } 733 } 734 735 func TestSearchHashtagPosts(t *testing.T) { 736 th := Setup().InitBasic() 737 defer th.TearDown() 738 739 Client := th.BasicClient 740 channel1 := th.BasicChannel 741 742 post1 := &model.Post{ChannelId: channel1.Id, Message: "#sgtitlereview with space"} 743 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 744 745 post2 := &model.Post{ChannelId: channel1.Id, Message: "#sgtitlereview\n with return"} 746 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 747 748 post3 := &model.Post{ChannelId: channel1.Id, Message: "no hashtag"} 749 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 750 751 r1 := Client.Must(Client.SearchPosts("#sgtitlereview", false)).Data.(*model.PostList) 752 753 if len(r1.Order) != 2 { 754 t.Fatal("wrong search") 755 } 756 } 757 758 func TestSearchPostsInChannel(t *testing.T) { 759 th := Setup().InitBasic() 760 defer th.TearDown() 761 762 Client := th.BasicClient 763 channel1 := th.BasicChannel 764 team := th.BasicTeam 765 766 post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"} 767 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 768 769 channel2 := &model.Channel{DisplayName: "TestGetPosts", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} 770 channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) 771 772 channel3 := &model.Channel{DisplayName: "TestGetPosts", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} 773 channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel) 774 775 post2 := &model.Post{ChannelId: channel2.Id, Message: "sgtitlereview\n with return"} 776 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 777 778 post3 := &model.Post{ChannelId: channel2.Id, Message: "other message with no return"} 779 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 780 781 post4 := &model.Post{ChannelId: channel3.Id, Message: "other message with no return"} 782 post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) 783 784 if result := Client.Must(Client.SearchPosts("channel:", false)).Data.(*model.PostList); len(result.Order) != 0 { 785 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 786 } 787 788 if result := Client.Must(Client.SearchPosts("in:", false)).Data.(*model.PostList); len(result.Order) != 0 { 789 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 790 } 791 792 if result := Client.Must(Client.SearchPosts("channel:"+channel1.Name, false)).Data.(*model.PostList); len(result.Order) != 2 { 793 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 794 } 795 796 if result := Client.Must(Client.SearchPosts("in: "+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 2 { 797 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 798 } 799 800 if result := Client.Must(Client.SearchPosts("channel: "+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 2 { 801 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 802 } 803 804 if result := Client.Must(Client.SearchPosts("ChAnNeL: "+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 2 { 805 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 806 } 807 808 if result := Client.Must(Client.SearchPosts("sgtitlereview", false)).Data.(*model.PostList); len(result.Order) != 2 { 809 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 810 } 811 812 if result := Client.Must(Client.SearchPosts("sgtitlereview channel:"+channel1.Name, false)).Data.(*model.PostList); len(result.Order) != 1 { 813 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 814 } 815 816 if result := Client.Must(Client.SearchPosts("sgtitlereview in: "+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 1 { 817 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 818 } 819 820 if result := Client.Must(Client.SearchPosts("sgtitlereview channel: "+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 1 { 821 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 822 } 823 824 if result := Client.Must(Client.SearchPosts("channel: "+channel2.Name+" channel: "+channel3.Name, false)).Data.(*model.PostList); len(result.Order) != 3 { 825 t.Fatalf("wrong number of posts returned :) %v :) %v", result.Posts, result.Order) 826 } 827 } 828 829 func TestSearchPostsFromUser(t *testing.T) { 830 th := Setup().InitBasic() 831 defer th.TearDown() 832 833 Client := th.BasicClient 834 channel1 := th.BasicChannel 835 team := th.BasicTeam 836 user1 := th.BasicUser 837 user2 := th.BasicUser2 838 channel2 := th.CreateChannel(Client, team) 839 Client.Must(Client.AddChannelMember(channel1.Id, th.BasicUser2.Id)) 840 Client.Must(Client.AddChannelMember(channel2.Id, th.BasicUser2.Id)) 841 user3 := th.CreateUser(Client) 842 th.LinkUserToTeam(user3, team) 843 Client.Must(Client.AddChannelMember(channel1.Id, user3.Id)) 844 Client.Must(Client.AddChannelMember(channel2.Id, user3.Id)) 845 846 post1 := &model.Post{ChannelId: channel1.Id, Message: "sgtitlereview with space"} 847 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 848 849 th.LoginBasic2() 850 851 post2 := &model.Post{ChannelId: channel2.Id, Message: "sgtitlereview\n with return"} 852 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 853 854 if result := Client.Must(Client.SearchPosts("from: "+user1.Username, false)).Data.(*model.PostList); len(result.Order) != 2 { 855 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 856 } 857 858 if result := Client.Must(Client.SearchPosts("from: "+user2.Username, false)).Data.(*model.PostList); len(result.Order) != 1 { 859 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 860 } 861 862 if result := Client.Must(Client.SearchPosts("from: "+user2.Username+" sgtitlereview", false)).Data.(*model.PostList); len(result.Order) != 1 { 863 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 864 } 865 866 post3 := &model.Post{ChannelId: channel1.Id, Message: "hullo"} 867 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 868 869 if result := Client.Must(Client.SearchPosts("from: "+user2.Username+" in:"+channel1.Name, false)).Data.(*model.PostList); len(result.Order) != 1 { 870 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 871 } 872 873 Client.Login(user3.Email, user3.Password) 874 875 // wait for the join/leave messages to be created for user3 since they're done asynchronously 876 time.Sleep(100 * time.Millisecond) 877 878 if result := Client.Must(Client.SearchPosts("from: "+user2.Username, false)).Data.(*model.PostList); len(result.Order) != 2 { 879 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 880 } 881 882 if result := Client.Must(Client.SearchPosts("from: "+user2.Username+" from: "+user3.Username, false)).Data.(*model.PostList); len(result.Order) != 2 { 883 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 884 } 885 886 if result := Client.Must(Client.SearchPosts("from: "+user2.Username+" from: "+user3.Username+" in:"+channel2.Name, false)).Data.(*model.PostList); len(result.Order) != 1 { 887 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 888 } 889 890 post4 := &model.Post{ChannelId: channel2.Id, Message: "coconut"} 891 post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) 892 893 if result := Client.Must(Client.SearchPosts("from: "+user2.Username+" from: "+user3.Username+" in:"+channel2.Name+" coconut", false)).Data.(*model.PostList); len(result.Order) != 1 { 894 t.Fatalf("wrong number of posts returned %v", len(result.Order)) 895 } 896 } 897 898 func TestGetPostsCache(t *testing.T) { 899 th := Setup().InitBasic() 900 defer th.TearDown() 901 902 Client := th.BasicClient 903 channel1 := th.BasicChannel 904 905 time.Sleep(10 * time.Millisecond) 906 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 907 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 908 909 time.Sleep(10 * time.Millisecond) 910 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 911 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 912 913 time.Sleep(10 * time.Millisecond) 914 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 915 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 916 917 etag := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Etag 918 919 // test etag caching 920 if cache_result, err := Client.GetPosts(channel1.Id, 0, 2, etag); err != nil { 921 t.Fatal(err) 922 } else if cache_result.Data.(*model.PostList) != nil { 923 t.Log(cache_result.Data) 924 t.Fatal("cache should be empty") 925 } 926 927 etag = Client.Must(Client.GetPost(channel1.Id, post1.Id, "")).Etag 928 929 // test etag caching 930 if cache_result, err := Client.GetPost(channel1.Id, post1.Id, etag); err != nil { 931 t.Fatal(err) 932 } else if cache_result.Data.(*model.PostList) != nil { 933 t.Log(cache_result.Data) 934 t.Fatal("cache should be empty") 935 } 936 937 } 938 939 func TestDeletePosts(t *testing.T) { 940 th := Setup().InitBasic().InitSystemAdmin() 941 defer th.TearDown() 942 943 Client := th.BasicClient 944 channel1 := th.BasicChannel 945 team1 := th.BasicTeam 946 947 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_ALL }) 948 949 time.Sleep(10 * time.Millisecond) 950 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 951 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 952 953 time.Sleep(10 * time.Millisecond) 954 post1a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 955 post1a1 = Client.Must(Client.CreatePost(post1a1)).Data.(*model.Post) 956 957 time.Sleep(10 * time.Millisecond) 958 post1a2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id, ParentId: post1a1.Id} 959 post1a2 = Client.Must(Client.CreatePost(post1a2)).Data.(*model.Post) 960 961 time.Sleep(10 * time.Millisecond) 962 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 963 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 964 965 time.Sleep(10 * time.Millisecond) 966 post3 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 967 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 968 969 time.Sleep(10 * time.Millisecond) 970 post3a1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a", RootId: post3.Id} 971 post3a1 = Client.Must(Client.CreatePost(post3a1)).Data.(*model.Post) 972 973 time.Sleep(10 * time.Millisecond) 974 Client.Must(Client.DeletePost(channel1.Id, post3.Id)) 975 976 r2 := Client.Must(Client.GetPosts(channel1.Id, 0, 10, "")).Data.(*model.PostList) 977 978 if post := r2.Posts[post3.Id]; post != nil { 979 t.Fatal("should have not returned deleted post") 980 } 981 982 time.Sleep(10 * time.Millisecond) 983 post4a := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 984 post4a = Client.Must(Client.CreatePost(post4a)).Data.(*model.Post) 985 986 time.Sleep(10 * time.Millisecond) 987 post4b := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 988 post4b = Client.Must(Client.CreatePost(post4b)).Data.(*model.Post) 989 990 SystemAdminClient := th.SystemAdminClient 991 th.LinkUserToTeam(th.SystemAdminUser, th.BasicTeam) 992 SystemAdminClient.Must(SystemAdminClient.JoinChannel(channel1.Id)) 993 994 th.LoginBasic2() 995 Client.Must(Client.JoinChannel(channel1.Id)) 996 997 if _, err := Client.DeletePost(channel1.Id, post4a.Id); err == nil { 998 t.Fatal(err) 999 } 1000 1001 // Test licensed policy controls for delete post 1002 th.App.SetLicense(model.NewTestLicense()) 1003 1004 th.UpdateUserToTeamAdmin(th.BasicUser2, th.BasicTeam) 1005 1006 Client.Logout() 1007 th.LoginBasic2() 1008 Client.SetTeamId(team1.Id) 1009 1010 Client.Must(Client.DeletePost(channel1.Id, post4a.Id)) 1011 1012 SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post4b.Id)) 1013 1014 th.App.UpdateConfig(func(cfg *model.Config) { 1015 *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_TEAM_ADMIN 1016 }) 1017 1018 th.LoginBasic() 1019 1020 time.Sleep(10 * time.Millisecond) 1021 post5a := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1022 post5a = Client.Must(Client.CreatePost(post5a)).Data.(*model.Post) 1023 1024 time.Sleep(10 * time.Millisecond) 1025 post5b := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1026 post5b = Client.Must(Client.CreatePost(post5b)).Data.(*model.Post) 1027 1028 if _, err := Client.DeletePost(channel1.Id, post5a.Id); err == nil { 1029 t.Fatal(err) 1030 } 1031 1032 th.LoginBasic2() 1033 1034 Client.Must(Client.DeletePost(channel1.Id, post5a.Id)) 1035 1036 SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post5b.Id)) 1037 1038 th.App.UpdateConfig(func(cfg *model.Config) { 1039 *cfg.ServiceSettings.RestrictPostDelete = model.PERMISSIONS_DELETE_POST_SYSTEM_ADMIN 1040 }) 1041 1042 th.LoginBasic() 1043 1044 time.Sleep(10 * time.Millisecond) 1045 post6a := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1046 post6a = Client.Must(Client.CreatePost(post6a)).Data.(*model.Post) 1047 1048 if _, err := Client.DeletePost(channel1.Id, post6a.Id); err == nil { 1049 t.Fatal(err) 1050 } 1051 1052 th.LoginBasic2() 1053 1054 if _, err := Client.DeletePost(channel1.Id, post6a.Id); err == nil { 1055 t.Fatal(err) 1056 } 1057 1058 // Check that if unlicensed the policy restriction is not enforced. 1059 th.App.SetLicense(nil) 1060 1061 time.Sleep(10 * time.Millisecond) 1062 post7 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1063 post7 = Client.Must(Client.CreatePost(post7)).Data.(*model.Post) 1064 1065 if _, err := Client.DeletePost(channel1.Id, post7.Id); err != nil { 1066 t.Fatal(err) 1067 } 1068 1069 SystemAdminClient.Must(SystemAdminClient.DeletePost(channel1.Id, post6a.Id)) 1070 1071 } 1072 1073 func TestEmailMention(t *testing.T) { 1074 th := Setup().InitBasic() 1075 defer th.TearDown() 1076 1077 Client := th.BasicClient 1078 channel1 := th.BasicChannel 1079 Client.Must(Client.AddChannelMember(channel1.Id, th.BasicUser2.Id)) 1080 1081 th.LoginBasic2() 1082 //Set the notification properties 1083 data := make(map[string]string) 1084 data["user_id"] = th.BasicUser2.Id 1085 data["email"] = "true" 1086 data["desktop"] = "all" 1087 data["desktop_sound"] = "false" 1088 data["comments"] = "any" 1089 Client.Must(Client.UpdateUserNotify(data)) 1090 1091 store.Must(th.App.Srv.Store.Preference().Save(&model.Preferences{{ 1092 UserId: th.BasicUser2.Id, 1093 Category: model.PREFERENCE_CATEGORY_NOTIFICATIONS, 1094 Name: model.PREFERENCE_NAME_EMAIL_INTERVAL, 1095 Value: "0", 1096 }})) 1097 1098 //Delete all the messages before create a mention post 1099 utils.DeleteMailBox(th.BasicUser2.Email) 1100 1101 //Send a mention message from user1 to user2 1102 th.LoginBasic() 1103 time.Sleep(10 * time.Millisecond) 1104 post1 := &model.Post{ChannelId: channel1.Id, Message: "@" + th.BasicUser2.Username + " this is a test"} 1105 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 1106 1107 var resultsMailbox utils.JSONMessageHeaderInbucket 1108 err := utils.RetryInbucket(5, func() error { 1109 var err error 1110 resultsMailbox, err = utils.GetMailBox(th.BasicUser2.Email) 1111 return err 1112 }) 1113 if err != nil { 1114 t.Log(err) 1115 t.Log("No email was received, maybe due load on the server. Disabling this verification") 1116 } 1117 if err == nil && len(resultsMailbox) > 0 { 1118 if !strings.ContainsAny(resultsMailbox[len(resultsMailbox)-1].To[0], th.BasicUser2.Email) { 1119 t.Fatal("Wrong To recipient") 1120 } else { 1121 for i := 0; i < 30; i++ { 1122 for j := len(resultsMailbox) - 1; j >= 0; j-- { 1123 isUser := false 1124 for _, to := range resultsMailbox[j].To { 1125 if to == "<"+th.BasicUser2.Email+">" { 1126 isUser = true 1127 } 1128 } 1129 if !isUser { 1130 continue 1131 } 1132 if resultsEmail, err := utils.GetMessageFromMailbox(th.BasicUser2.Email, resultsMailbox[j].ID); err == nil { 1133 if strings.Contains(resultsEmail.Body.Text, post1.Message) { 1134 return 1135 } else if i == 4 { 1136 t.Log(resultsEmail.Body.Text) 1137 t.Fatal("Received wrong Message") 1138 } 1139 } 1140 } 1141 time.Sleep(100 * time.Millisecond) 1142 } 1143 t.Fatal("Didn't receive message") 1144 } 1145 } 1146 } 1147 1148 func TestFuzzyPosts(t *testing.T) { 1149 th := Setup().InitBasic() 1150 defer th.TearDown() 1151 1152 Client := th.BasicClient 1153 channel1 := th.BasicChannel 1154 1155 for i := 0; i < len(utils.FUZZY_STRINGS_POSTS); i++ { 1156 post := &model.Post{ChannelId: channel1.Id, Message: utils.FUZZY_STRINGS_POSTS[i]} 1157 1158 _, err := Client.CreatePost(post) 1159 if err != nil { 1160 t.Fatal(err) 1161 } 1162 } 1163 } 1164 1165 func TestGetFlaggedPosts(t *testing.T) { 1166 th := Setup().InitBasic() 1167 defer th.TearDown() 1168 1169 Client := th.BasicClient 1170 user1 := th.BasicUser 1171 post1 := th.BasicPost 1172 1173 preferences := &model.Preferences{ 1174 { 1175 UserId: user1.Id, 1176 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 1177 Name: post1.Id, 1178 Value: "true", 1179 }, 1180 } 1181 Client.Must(Client.SetPreferences(preferences)) 1182 1183 r1 := Client.Must(Client.GetFlaggedPosts(0, 2)).Data.(*model.PostList) 1184 1185 if len(r1.Order) == 0 { 1186 t.Fatal("should have gotten a flagged post") 1187 } 1188 1189 if _, ok := r1.Posts[post1.Id]; !ok { 1190 t.Fatal("missing flagged post") 1191 } 1192 1193 Client.DeletePreferences(preferences) 1194 1195 r2 := Client.Must(Client.GetFlaggedPosts(0, 2)).Data.(*model.PostList) 1196 1197 if len(r2.Order) != 0 { 1198 t.Fatal("should not have gotten a flagged post") 1199 } 1200 1201 Client.SetTeamId(model.NewId()) 1202 if _, err := Client.GetFlaggedPosts(0, 2); err == nil { 1203 t.Fatal("should have failed - bad team id") 1204 } 1205 } 1206 1207 func TestGetMessageForNotification(t *testing.T) { 1208 th := Setup().InitBasic() 1209 defer th.TearDown() 1210 1211 testPng := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 1212 CreatorId: model.NewId(), 1213 Path: "test1.png", 1214 Name: "test1.png", 1215 MimeType: "image/png", 1216 })).(*model.FileInfo) 1217 1218 testJpg1 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 1219 CreatorId: model.NewId(), 1220 Path: "test2.jpg", 1221 Name: "test2.jpg", 1222 MimeType: "image/jpeg", 1223 })).(*model.FileInfo) 1224 1225 testFile := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 1226 CreatorId: model.NewId(), 1227 Path: "test1.go", 1228 Name: "test1.go", 1229 MimeType: "text/plain", 1230 })).(*model.FileInfo) 1231 1232 testJpg2 := store.Must(th.App.Srv.Store.FileInfo().Save(&model.FileInfo{ 1233 CreatorId: model.NewId(), 1234 Path: "test3.jpg", 1235 Name: "test3.jpg", 1236 MimeType: "image/jpeg", 1237 })).(*model.FileInfo) 1238 1239 translateFunc := utils.GetUserTranslations("en") 1240 1241 post := &model.Post{ 1242 Id: model.NewId(), 1243 Message: "test", 1244 } 1245 1246 if th.App.GetMessageForNotification(post, translateFunc) != "test" { 1247 t.Fatal("should've returned message text") 1248 } 1249 1250 post.FileIds = model.StringArray{testPng.Id} 1251 store.Must(th.App.Srv.Store.FileInfo().AttachToPost(testPng.Id, post.Id)) 1252 if th.App.GetMessageForNotification(post, translateFunc) != "test" { 1253 t.Fatal("should've returned message text, even with attachments") 1254 } 1255 1256 post.Message = "" 1257 if message := th.App.GetMessageForNotification(post, translateFunc); message != "1 image sent: test1.png" { 1258 t.Fatal("should've returned number of images:", message) 1259 } 1260 1261 post.FileIds = model.StringArray{testPng.Id, testJpg1.Id} 1262 store.Must(th.App.Srv.Store.FileInfo().AttachToPost(testJpg1.Id, post.Id)) 1263 th.App.Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id) 1264 if message := th.App.GetMessageForNotification(post, translateFunc); message != "2 images sent: test1.png, test2.jpg" && message != "2 images sent: test2.jpg, test1.png" { 1265 t.Fatal("should've returned number of images:", message) 1266 } 1267 1268 post.Id = model.NewId() 1269 post.FileIds = model.StringArray{testFile.Id} 1270 store.Must(th.App.Srv.Store.FileInfo().AttachToPost(testFile.Id, post.Id)) 1271 if message := th.App.GetMessageForNotification(post, translateFunc); message != "1 file sent: test1.go" { 1272 t.Fatal("should've returned number of files:", message) 1273 } 1274 1275 store.Must(th.App.Srv.Store.FileInfo().AttachToPost(testJpg2.Id, post.Id)) 1276 th.App.Srv.Store.FileInfo().InvalidateFileInfosForPostCache(post.Id) 1277 post.FileIds = model.StringArray{testFile.Id, testJpg2.Id} 1278 if message := th.App.GetMessageForNotification(post, translateFunc); message != "2 files sent: test1.go, test3.jpg" && message != "2 files sent: test3.jpg, test1.go" { 1279 t.Fatal("should've returned number of mixed files:", message) 1280 } 1281 } 1282 1283 func TestGetFileInfosForPost(t *testing.T) { 1284 th := Setup().InitBasic() 1285 defer th.TearDown() 1286 1287 Client := th.BasicClient 1288 channel1 := th.BasicChannel 1289 1290 fileIds := make([]string, 3) 1291 if data, err := readTestFile("test.png"); err != nil { 1292 t.Fatal(err) 1293 } else { 1294 for i := 0; i < 3; i++ { 1295 fileIds[i] = Client.MustGeneric(Client.UploadPostAttachment(data, channel1.Id, "test.png")).(*model.FileUploadResponse).FileInfos[0].Id 1296 } 1297 } 1298 1299 post1 := Client.Must(Client.CreatePost(&model.Post{ 1300 ChannelId: channel1.Id, 1301 Message: "test", 1302 FileIds: fileIds, 1303 })).Data.(*model.Post) 1304 1305 var etag string 1306 if infos, err := Client.GetFileInfosForPost(channel1.Id, post1.Id, ""); err != nil { 1307 t.Fatal(err) 1308 } else if len(infos) != 3 { 1309 t.Fatal("should've received 3 files") 1310 } else if Client.Etag == "" { 1311 t.Fatal("should've received etag") 1312 } else { 1313 etag = Client.Etag 1314 } 1315 1316 if infos, err := Client.GetFileInfosForPost(channel1.Id, post1.Id, etag); err != nil { 1317 t.Fatal(err) 1318 } else if len(infos) != 0 { 1319 t.Fatal("should've returned nothing because of etag") 1320 } 1321 } 1322 1323 func TestGetPostById(t *testing.T) { 1324 th := Setup().InitBasic() 1325 defer th.TearDown() 1326 1327 Client := th.BasicClient 1328 channel1 := th.BasicChannel 1329 1330 time.Sleep(10 * time.Millisecond) 1331 post1 := &model.Post{ChannelId: channel1.Id, Message: "yommamma" + model.NewId() + "a"} 1332 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 1333 1334 if post, respMetadata := Client.GetPostById(post1.Id, ""); respMetadata.Error != nil { 1335 t.Fatal(respMetadata.Error) 1336 } else { 1337 if len(post.Order) != 1 { 1338 t.Fatal("should be just one post") 1339 } 1340 1341 if post.Order[0] != post1.Id { 1342 t.Fatal("wrong order") 1343 } 1344 1345 if post.Posts[post.Order[0]].Message != post1.Message { 1346 t.Fatal("wrong message from post") 1347 } 1348 } 1349 1350 if _, respMetadata := Client.GetPostById("45345435345345", ""); respMetadata.Error == nil { 1351 t.Fatal(respMetadata.Error) 1352 } 1353 } 1354 1355 func TestGetPermalinkTmp(t *testing.T) { 1356 th := Setup().InitBasic().InitSystemAdmin() 1357 defer th.TearDown() 1358 1359 Client := th.BasicClient 1360 channel1 := th.BasicChannel 1361 team := th.BasicTeam 1362 1363 th.LoginBasic() 1364 1365 time.Sleep(10 * time.Millisecond) 1366 post1 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1367 post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post) 1368 1369 time.Sleep(10 * time.Millisecond) 1370 post2 := &model.Post{ChannelId: channel1.Id, Message: "zz" + model.NewId() + "a"} 1371 post2 = Client.Must(Client.CreatePost(post2)).Data.(*model.Post) 1372 1373 etag := Client.Must(Client.GetPost(channel1.Id, post1.Id, "")).Etag 1374 1375 // test etag caching 1376 if cache_result, respMetadata := Client.GetPermalink(channel1.Id, post1.Id, etag); respMetadata.Error != nil { 1377 t.Fatal(respMetadata.Error) 1378 } else if cache_result != nil { 1379 t.Log(cache_result) 1380 t.Fatal("cache should be empty") 1381 } 1382 1383 if results, respMetadata := Client.GetPermalink(channel1.Id, post1.Id, ""); respMetadata.Error != nil { 1384 t.Fatal(respMetadata.Error) 1385 } else if results == nil { 1386 t.Fatal("should not be empty") 1387 } 1388 1389 // Test permalink to private channels. 1390 channel2 := &model.Channel{DisplayName: "TestGetPermalinkPriv", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_PRIVATE, TeamId: team.Id} 1391 channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel) 1392 time.Sleep(10 * time.Millisecond) 1393 post3 := &model.Post{ChannelId: channel2.Id, Message: "zz" + model.NewId() + "a"} 1394 post3 = Client.Must(Client.CreatePost(post3)).Data.(*model.Post) 1395 1396 if _, md := Client.GetPermalink(channel2.Id, post3.Id, ""); md.Error != nil { 1397 t.Fatal(md.Error) 1398 } 1399 1400 th.LoginBasic2() 1401 1402 if _, md := Client.GetPermalink(channel2.Id, post3.Id, ""); md.Error == nil { 1403 t.Fatal("Expected 403 error") 1404 } 1405 1406 // Test direct channels. 1407 th.LoginBasic() 1408 channel3 := Client.Must(Client.CreateDirectChannel(th.SystemAdminUser.Id)).Data.(*model.Channel) 1409 time.Sleep(10 * time.Millisecond) 1410 post4 := &model.Post{ChannelId: channel3.Id, Message: "zz" + model.NewId() + "a"} 1411 post4 = Client.Must(Client.CreatePost(post4)).Data.(*model.Post) 1412 1413 if _, md := Client.GetPermalink(channel3.Id, post4.Id, ""); md.Error != nil { 1414 t.Fatal(md.Error) 1415 } 1416 1417 th.LoginBasic2() 1418 1419 if _, md := Client.GetPermalink(channel3.Id, post4.Id, ""); md.Error == nil { 1420 t.Fatal("Expected 403 error") 1421 } 1422 } 1423 1424 func TestGetOpenGraphMetadata(t *testing.T) { 1425 th := Setup().InitBasic() 1426 defer th.TearDown() 1427 1428 Client := th.BasicClient 1429 1430 th.App.UpdateConfig(func(cfg *model.Config) { 1431 *cfg.ServiceSettings.EnableLinkPreviews = true 1432 *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1" 1433 }) 1434 1435 ogDataCacheMissCount := 0 1436 1437 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1438 ogDataCacheMissCount++ 1439 1440 if r.URL.Path == "/og-data/" { 1441 fmt.Fprintln(w, ` 1442 <html><head><meta property="og:type" content="article" /> 1443 <meta property="og:title" content="Test Title" /> 1444 <meta property="og:url" content="http://example.com/" /> 1445 </head><body></body></html> 1446 `) 1447 } else if r.URL.Path == "/no-og-data/" { 1448 fmt.Fprintln(w, `<html><head></head><body></body></html>`) 1449 } 1450 })) 1451 1452 for _, data := range [](map[string]interface{}){ 1453 {"path": "/og-data/", "title": "Test Title", "cacheMissCount": 1}, 1454 {"path": "/no-og-data/", "title": "", "cacheMissCount": 2}, 1455 1456 // Data should be cached for following 1457 {"path": "/og-data/", "title": "Test Title", "cacheMissCount": 2}, 1458 {"path": "/no-og-data/", "title": "", "cacheMissCount": 2}, 1459 } { 1460 res, err := Client.DoApiPost( 1461 "/get_opengraph_metadata", 1462 fmt.Sprintf("{\"url\":\"%s\"}", ts.URL+data["path"].(string)), 1463 ) 1464 if err != nil { 1465 t.Fatal(err) 1466 } 1467 1468 ogData := model.StringInterfaceFromJson(res.Body) 1469 if strings.Compare(ogData["title"].(string), data["title"].(string)) != 0 { 1470 t.Fatal(fmt.Sprintf( 1471 "OG data title mismatch for path \"%s\". Expected title: \"%s\". Actual title: \"%s\"", 1472 data["path"].(string), data["title"].(string), ogData["title"].(string), 1473 )) 1474 } 1475 1476 if ogDataCacheMissCount != data["cacheMissCount"].(int) { 1477 t.Fatal(fmt.Sprintf( 1478 "Cache miss count didn't match. Expected value %d. Actual value %d.", 1479 data["cacheMissCount"].(int), ogDataCacheMissCount, 1480 )) 1481 } 1482 } 1483 1484 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableLinkPreviews = false }) 1485 if _, err := Client.DoApiPost("/get_opengraph_metadata", "{\"url\":\"/og-data/\"}"); err == nil || err.StatusCode != http.StatusNotImplemented { 1486 t.Fatal("should have failed with 501 - disabled link previews") 1487 } 1488 } 1489 1490 func TestPinPost(t *testing.T) { 1491 th := Setup().InitBasic() 1492 defer th.TearDown() 1493 1494 Client := th.BasicClient 1495 1496 post := th.BasicPost 1497 if rupost1, err := Client.PinPost(post.ChannelId, post.Id); err != nil { 1498 t.Fatal(err) 1499 } else { 1500 if !rupost1.Data.(*model.Post).IsPinned { 1501 t.Fatal("failed to pin post") 1502 } 1503 } 1504 1505 pinnedPost := th.PinnedPost 1506 if rupost2, err := Client.PinPost(pinnedPost.ChannelId, pinnedPost.Id); err != nil { 1507 t.Fatal(err) 1508 } else { 1509 if !rupost2.Data.(*model.Post).IsPinned { 1510 t.Fatal("pinning a post should be idempotent") 1511 } 1512 } 1513 } 1514 1515 func TestUnpinPost(t *testing.T) { 1516 th := Setup().InitBasic() 1517 defer th.TearDown() 1518 1519 Client := th.BasicClient 1520 1521 pinnedPost := th.PinnedPost 1522 if rupost1, err := Client.UnpinPost(pinnedPost.ChannelId, pinnedPost.Id); err != nil { 1523 t.Fatal(err) 1524 } else { 1525 if rupost1.Data.(*model.Post).IsPinned { 1526 t.Fatal("failed to unpin post") 1527 } 1528 } 1529 1530 post := th.BasicPost 1531 if rupost2, err := Client.UnpinPost(post.ChannelId, post.Id); err != nil { 1532 t.Fatal(err) 1533 } else { 1534 if rupost2.Data.(*model.Post).IsPinned { 1535 t.Fatal("unpinning a post should be idempotent") 1536 } 1537 } 1538 }