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