github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/file_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "crypto/rand" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "mime/multipart" 13 "net/http" 14 "net/textproto" 15 "net/url" 16 "os" 17 "path/filepath" 18 "strings" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 25 "github.com/masterhung0112/hk_server/v5/app" 26 "github.com/masterhung0112/hk_server/v5/model" 27 "github.com/masterhung0112/hk_server/v5/utils/fileutils" 28 "github.com/masterhung0112/hk_server/v5/utils/testutils" 29 ) 30 31 var testDir = "" 32 33 func init() { 34 testDir, _ = fileutils.FindDir("tests") 35 } 36 37 // File Section 38 var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") 39 40 func escapeQuotes(s string) string { 41 return quoteEscaper.Replace(s) 42 } 43 44 func randomBytes(t *testing.T, n int) []byte { 45 bb := make([]byte, n) 46 _, err := rand.Read(bb) 47 require.NoError(t, err) 48 return bb 49 } 50 51 func fileBytes(t *testing.T, path string) []byte { 52 path = filepath.Join(testDir, path) 53 f, err := os.Open(path) 54 require.NoError(t, err) 55 defer f.Close() 56 bb, err := ioutil.ReadAll(f) 57 require.NoError(t, err) 58 return bb 59 } 60 61 func testDoUploadFileRequest(t testing.TB, c *model.Client4, url string, blob []byte, contentType string, 62 contentLength int64) (*model.FileUploadResponse, *model.Response) { 63 req, err := http.NewRequest("POST", c.ApiUrl+c.GetFilesRoute()+url, bytes.NewReader(blob)) 64 require.NoError(t, err) 65 66 if contentLength != 0 { 67 req.ContentLength = contentLength 68 } 69 req.Header.Set("Content-Type", contentType) 70 if c.AuthToken != "" { 71 req.Header.Set(model.HEADER_AUTH, c.AuthType+" "+c.AuthToken) 72 } 73 74 resp, err := c.HttpClient.Do(req) 75 require.NoError(t, err) 76 require.NotNil(t, resp) 77 defer closeBody(resp) 78 79 if resp.StatusCode >= 300 { 80 return nil, model.BuildErrorResponse(resp, model.AppErrorFromJson(resp.Body)) 81 } 82 83 return model.FileUploadResponseFromJson(resp.Body), model.BuildResponse(resp) 84 } 85 86 func testUploadFilesPost( 87 t testing.TB, 88 c *model.Client4, 89 channelId string, 90 names []string, 91 blobs [][]byte, 92 clientIds []string, 93 useChunked bool, 94 ) (*model.FileUploadResponse, *model.Response) { 95 96 // Do not check len(clientIds), leave it entirely to the user to 97 // provide. The server will error out if it does not match the number 98 // of files, but it's not critical here. 99 require.NotEmpty(t, names) 100 require.NotEmpty(t, blobs) 101 require.Equal(t, len(names), len(blobs)) 102 103 fileUploadResponse := &model.FileUploadResponse{} 104 for i, blob := range blobs { 105 var cl int64 106 if useChunked { 107 cl = -1 108 } else { 109 cl = int64(len(blob)) 110 } 111 ct := http.DetectContentType(blob) 112 113 postURL := fmt.Sprintf("?channel_id=%v", url.QueryEscape(channelId)) + 114 fmt.Sprintf("&filename=%v", url.QueryEscape(names[i])) 115 if len(clientIds) > i { 116 postURL += fmt.Sprintf("&client_id=%v", url.QueryEscape(clientIds[i])) 117 } 118 119 fur, resp := testDoUploadFileRequest(t, c, postURL, blob, ct, cl) 120 if resp.Error != nil { 121 return nil, resp 122 } 123 124 fileUploadResponse.FileInfos = append(fileUploadResponse.FileInfos, fur.FileInfos[0]) 125 if len(clientIds) > 0 { 126 if len(fur.ClientIds) > 0 { 127 fileUploadResponse.ClientIds = append(fileUploadResponse.ClientIds, fur.ClientIds[0]) 128 } else { 129 fileUploadResponse.ClientIds = append(fileUploadResponse.ClientIds, "") 130 } 131 } 132 } 133 134 return fileUploadResponse, nil 135 } 136 137 func testUploadFilesMultipart( 138 t testing.TB, 139 c *model.Client4, 140 channelId string, 141 names []string, 142 blobs [][]byte, 143 clientIds []string, 144 ) ( 145 fileUploadResponse *model.FileUploadResponse, 146 response *model.Response, 147 ) { 148 // Do not check len(clientIds), leave it entirely to the user to 149 // provide. The server will error out if it does not match the number 150 // of files, but it's not critical here. 151 require.NotEmpty(t, names) 152 require.NotEmpty(t, blobs) 153 require.Equal(t, len(names), len(blobs)) 154 155 mwBody := &bytes.Buffer{} 156 mw := multipart.NewWriter(mwBody) 157 158 err := mw.WriteField("channel_id", channelId) 159 require.NoError(t, err) 160 161 for i, blob := range blobs { 162 ct := http.DetectContentType(blob) 163 if len(clientIds) > i { 164 err = mw.WriteField("client_ids", clientIds[i]) 165 require.NoError(t, err) 166 } 167 168 h := textproto.MIMEHeader{} 169 h.Set("Content-Disposition", 170 fmt.Sprintf(`form-data; name="files"; filename="%s"`, escapeQuotes(names[i]))) 171 h.Set("Content-Type", ct) 172 173 // If we error here, writing to mw, the deferred handler 174 part, err := mw.CreatePart(h) 175 require.NoError(t, err) 176 177 _, err = io.Copy(part, bytes.NewReader(blob)) 178 require.NoError(t, err) 179 } 180 181 require.NoError(t, mw.Close()) 182 return testDoUploadFileRequest(t, c, "", mwBody.Bytes(), mw.FormDataContentType(), -1) 183 } 184 185 func TestUploadFiles(t *testing.T) { 186 th := Setup(t).InitBasic() 187 defer th.TearDown() 188 if *th.App.Config().FileSettings.DriverName == "" { 189 t.Skip("skipping because no file driver is enabled") 190 } 191 192 channel := th.BasicChannel 193 date := time.Now().Format("20060102") 194 195 // Get better error messages 196 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableDeveloper = true }) 197 198 tests := []struct { 199 title string 200 client *model.Client4 201 blobs [][]byte 202 names []string 203 clientIds []string 204 205 skipSuccessValidation bool 206 skipPayloadValidation bool 207 skipSimplePost bool 208 skipMultipart bool 209 channelId string 210 useChunkedInSimplePost bool 211 expectedCreatorId string 212 expectedPayloadNames []string 213 expectImage bool 214 expectedImageWidths []int 215 expectedImageHeights []int 216 expectedImageThumbnailNames []string 217 expectedImagePreviewNames []string 218 expectedImageHasPreview []bool 219 expectedImageMiniPreview []bool 220 setupConfig func(a *app.App) func(a *app.App) 221 checkResponse func(t *testing.T, resp *model.Response) 222 }{ 223 // Upload a bunch of files, mixed images and non-images 224 { 225 title: "Happy", 226 names: []string{"test.png", "testgif.gif", "testplugin.tar.gz", "test-search.md", "test.tiff"}, 227 expectedCreatorId: th.BasicUser.Id, 228 expectedImageMiniPreview: []bool{true, true, false, false, true}, 229 }, 230 // Upload a bunch of files, with clientIds 231 { 232 title: "Happy client_ids", 233 names: []string{"test.png", "testgif.gif", "testplugin.tar.gz", "test-search.md", "test.tiff"}, 234 clientIds: []string{"1", "2", "3", "4", "5"}, 235 expectedImageMiniPreview: []bool{true, true, false, false, true}, 236 expectedCreatorId: th.BasicUser.Id, 237 }, 238 // Upload a bunch of images. testgif.gif is an animated GIF, 239 // so it does not have HasPreviewImage set. 240 { 241 title: "Happy images", 242 names: []string{"test.png", "testgif.gif"}, 243 expectImage: true, 244 expectedCreatorId: th.BasicUser.Id, 245 expectedImageWidths: []int{408, 118}, 246 expectedImageHeights: []int{336, 118}, 247 expectedImageHasPreview: []bool{true, false}, 248 expectedImageMiniPreview: []bool{true, true}, 249 }, 250 { 251 title: "Happy invalid image", 252 names: []string{"testgif.gif"}, 253 blobs: [][]byte{fileBytes(t, "test-search.md")}, 254 skipPayloadValidation: true, 255 expectedCreatorId: th.BasicUser.Id, 256 expectedImageMiniPreview: []bool{false}, 257 }, 258 // Simple POST, chunked encoding 259 { 260 title: "Happy image chunked post", 261 skipMultipart: true, 262 useChunkedInSimplePost: true, 263 names: []string{"test.png"}, 264 expectImage: true, 265 expectedImageWidths: []int{408}, 266 expectedImageHeights: []int{336}, 267 expectedImageHasPreview: []bool{true}, 268 expectedCreatorId: th.BasicUser.Id, 269 expectedImageMiniPreview: []bool{true}, 270 }, 271 // Image thumbnail and preview: size and orientation. Note that 272 // the expected image dimensions remain the same regardless of the 273 // orientation - what we save in FileInfo is used by the 274 // clients to size UI elements, so the dimensions are "actual". 275 { 276 title: "Happy image thumbnail/preview 1", 277 names: []string{"orientation_test_1.jpeg"}, 278 expectedImageThumbnailNames: []string{"orientation_test_1_expected_thumb.jpeg"}, 279 expectedImagePreviewNames: []string{"orientation_test_1_expected_preview.jpeg"}, 280 expectImage: true, 281 expectedImageWidths: []int{2860}, 282 expectedImageHeights: []int{1578}, 283 expectedImageHasPreview: []bool{true}, 284 expectedCreatorId: th.BasicUser.Id, 285 expectedImageMiniPreview: []bool{true}, 286 }, 287 { 288 title: "Happy image thumbnail/preview 2", 289 names: []string{"orientation_test_2.jpeg"}, 290 expectedImageThumbnailNames: []string{"orientation_test_2_expected_thumb.jpeg"}, 291 expectedImagePreviewNames: []string{"orientation_test_2_expected_preview.jpeg"}, 292 expectImage: true, 293 expectedImageWidths: []int{2860}, 294 expectedImageHeights: []int{1578}, 295 expectedImageHasPreview: []bool{true}, 296 expectedImageMiniPreview: []bool{true}, 297 expectedCreatorId: th.BasicUser.Id, 298 }, 299 { 300 title: "Happy image thumbnail/preview 3", 301 names: []string{"orientation_test_3.jpeg"}, 302 expectedImageThumbnailNames: []string{"orientation_test_3_expected_thumb.jpeg"}, 303 expectedImagePreviewNames: []string{"orientation_test_3_expected_preview.jpeg"}, 304 expectImage: true, 305 expectedImageWidths: []int{2860}, 306 expectedImageHeights: []int{1578}, 307 expectedImageHasPreview: []bool{true}, 308 expectedImageMiniPreview: []bool{true}, 309 expectedCreatorId: th.BasicUser.Id, 310 }, 311 { 312 title: "Happy image thumbnail/preview 4", 313 names: []string{"orientation_test_4.jpeg"}, 314 expectedImageThumbnailNames: []string{"orientation_test_4_expected_thumb.jpeg"}, 315 expectedImagePreviewNames: []string{"orientation_test_4_expected_preview.jpeg"}, 316 expectImage: true, 317 expectedImageWidths: []int{2860}, 318 expectedImageHeights: []int{1578}, 319 expectedImageHasPreview: []bool{true}, 320 expectedImageMiniPreview: []bool{true}, 321 expectedCreatorId: th.BasicUser.Id, 322 }, 323 { 324 title: "Happy image thumbnail/preview 5", 325 names: []string{"orientation_test_5.jpeg"}, 326 expectedImageThumbnailNames: []string{"orientation_test_5_expected_thumb.jpeg"}, 327 expectedImagePreviewNames: []string{"orientation_test_5_expected_preview.jpeg"}, 328 expectImage: true, 329 expectedImageWidths: []int{2860}, 330 expectedImageHeights: []int{1578}, 331 expectedImageHasPreview: []bool{true}, 332 expectedImageMiniPreview: []bool{true}, 333 expectedCreatorId: th.BasicUser.Id, 334 }, 335 { 336 title: "Happy image thumbnail/preview 6", 337 names: []string{"orientation_test_6.jpeg"}, 338 expectedImageThumbnailNames: []string{"orientation_test_6_expected_thumb.jpeg"}, 339 expectedImagePreviewNames: []string{"orientation_test_6_expected_preview.jpeg"}, 340 expectImage: true, 341 expectedImageWidths: []int{2860}, 342 expectedImageHeights: []int{1578}, 343 expectedImageHasPreview: []bool{true}, 344 expectedImageMiniPreview: []bool{true}, 345 expectedCreatorId: th.BasicUser.Id, 346 }, 347 { 348 title: "Happy image thumbnail/preview 7", 349 names: []string{"orientation_test_7.jpeg"}, 350 expectedImageThumbnailNames: []string{"orientation_test_7_expected_thumb.jpeg"}, 351 expectedImagePreviewNames: []string{"orientation_test_7_expected_preview.jpeg"}, 352 expectImage: true, 353 expectedImageWidths: []int{2860}, 354 expectedImageHeights: []int{1578}, 355 expectedImageHasPreview: []bool{true}, 356 expectedImageMiniPreview: []bool{true}, 357 expectedCreatorId: th.BasicUser.Id, 358 }, 359 { 360 title: "Happy image thumbnail/preview 8", 361 names: []string{"orientation_test_8.jpeg"}, 362 expectedImageThumbnailNames: []string{"orientation_test_8_expected_thumb.jpeg"}, 363 expectedImagePreviewNames: []string{"orientation_test_8_expected_preview.jpeg"}, 364 expectImage: true, 365 expectedImageWidths: []int{2860}, 366 expectedImageHeights: []int{1578}, 367 expectedImageHasPreview: []bool{true}, 368 expectedImageMiniPreview: []bool{true}, 369 expectedCreatorId: th.BasicUser.Id, 370 }, 371 // TIFF preview test 372 { 373 title: "Happy image thumbnail/preview 9", 374 names: []string{"test.tiff"}, 375 expectedImageThumbnailNames: []string{"test_expected_tiff_thumb.jpeg"}, 376 expectedImagePreviewNames: []string{"test_expected_tiff_preview.jpeg"}, 377 expectImage: true, 378 expectedImageWidths: []int{701}, 379 expectedImageHeights: []int{701}, 380 expectedImageHasPreview: []bool{true}, 381 expectedImageMiniPreview: []bool{true}, 382 expectedCreatorId: th.BasicUser.Id, 383 }, 384 // Extremely wide image test 385 { 386 title: "Happy image thumbnail/preview 10", 387 names: []string{"10000x1.png"}, 388 expectedImageThumbnailNames: []string{"10000x1_expected_thumb.jpeg"}, 389 expectedImagePreviewNames: []string{"10000x1_expected_preview.jpeg"}, 390 expectImage: true, 391 expectedImageWidths: []int{10000}, 392 expectedImageHeights: []int{1}, 393 expectedImageHasPreview: []bool{true}, 394 expectedCreatorId: th.BasicUser.Id, 395 }, 396 // Extremely high image test 397 { 398 title: "Happy image thumbnail/preview 11", 399 names: []string{"1x10000.png"}, 400 expectedImageThumbnailNames: []string{"1x10000_expected_thumb.jpeg"}, 401 expectedImagePreviewNames: []string{"1x10000_expected_preview.jpeg"}, 402 expectImage: true, 403 expectedImageWidths: []int{1}, 404 expectedImageHeights: []int{10000}, 405 expectedImageHasPreview: []bool{true}, 406 expectedCreatorId: th.BasicUser.Id, 407 }, 408 // animated GIF 409 { 410 title: "Happy image thumbnail/preview 12", 411 names: []string{"testgif.gif"}, 412 expectedImageThumbnailNames: []string{"testgif_expected_thumbnail.jpg"}, 413 expectedImagePreviewNames: []string{"testgif_expected_preview.jpg"}, 414 expectImage: true, 415 expectedImageWidths: []int{118}, 416 expectedImageHeights: []int{118}, 417 expectedImageHasPreview: []bool{false}, 418 expectedCreatorId: th.BasicUser.Id, 419 }, 420 { 421 title: "Happy admin", 422 client: th.SystemAdminClient, 423 names: []string{"test.png"}, 424 expectedImageMiniPreview: []bool{true}, 425 expectedCreatorId: th.SystemAdminUser.Id, 426 }, 427 { 428 title: "Happy stream", 429 useChunkedInSimplePost: true, 430 skipPayloadValidation: true, 431 names: []string{"1Mb-stream"}, 432 blobs: [][]byte{randomBytes(t, 1024*1024)}, 433 setupConfig: func(a *app.App) func(a *app.App) { 434 maxFileSize := *a.Config().FileSettings.MaxFileSize 435 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = 1024 * 1024 }) 436 return func(a *app.App) { 437 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = maxFileSize }) 438 } 439 }, 440 expectedImageMiniPreview: []bool{false}, 441 expectedCreatorId: th.BasicUser.Id, 442 }, 443 // Error cases 444 { 445 title: "Error channel_id does not exist", 446 channelId: model.NewId(), 447 names: []string{"test.png"}, 448 skipSuccessValidation: true, 449 checkResponse: CheckForbiddenStatus, 450 }, 451 { 452 // on simple post this uploads the last file 453 // successfully, without a ClientId 454 title: "Error too few client_ids", 455 skipSimplePost: true, 456 names: []string{"test.png", "testplugin.tar.gz", "test-search.md"}, 457 clientIds: []string{"1", "4"}, 458 expectedImageMiniPreview: []bool{true, false, false}, 459 skipSuccessValidation: true, 460 checkResponse: CheckBadRequestStatus, 461 }, 462 { 463 title: "Error invalid channel_id", 464 channelId: "../../junk", 465 names: []string{"test.png"}, 466 expectedImageMiniPreview: []bool{true}, 467 skipSuccessValidation: true, 468 checkResponse: CheckBadRequestStatus, 469 }, 470 { 471 title: "Error admin channel_id does not exist", 472 client: th.SystemAdminClient, 473 channelId: model.NewId(), 474 names: []string{"test.png"}, 475 skipSuccessValidation: true, 476 checkResponse: CheckForbiddenStatus, 477 }, 478 { 479 title: "Error admin invalid channel_id", 480 client: th.SystemAdminClient, 481 channelId: "../../junk", 482 names: []string{"test.png"}, 483 skipSuccessValidation: true, 484 checkResponse: CheckBadRequestStatus, 485 }, 486 { 487 title: "Error admin disabled uploads", 488 client: th.SystemAdminClient, 489 names: []string{"test.png"}, 490 skipSuccessValidation: true, 491 checkResponse: CheckNotImplementedStatus, 492 setupConfig: func(a *app.App) func(a *app.App) { 493 enableFileAttachments := *a.Config().FileSettings.EnableFileAttachments 494 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false }) 495 return func(a *app.App) { 496 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = enableFileAttachments }) 497 } 498 }, 499 }, 500 { 501 title: "Error file too large", 502 names: []string{"test.png"}, 503 skipSuccessValidation: true, 504 checkResponse: CheckRequestEntityTooLargeStatus, 505 setupConfig: func(a *app.App) func(a *app.App) { 506 maxFileSize := *a.Config().FileSettings.MaxFileSize 507 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = 279590 }) 508 return func(a *app.App) { 509 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = maxFileSize }) 510 } 511 }, 512 }, 513 // File too large (chunked, simple POST only, multipart would've been redundant with above) 514 { 515 title: "File too large chunked", 516 useChunkedInSimplePost: true, 517 skipMultipart: true, 518 names: []string{"test.png"}, 519 skipSuccessValidation: true, 520 checkResponse: CheckRequestEntityTooLargeStatus, 521 expectedImageMiniPreview: []bool{false}, 522 setupConfig: func(a *app.App) func(a *app.App) { 523 maxFileSize := *a.Config().FileSettings.MaxFileSize 524 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = 279590 }) 525 return func(a *app.App) { 526 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = maxFileSize }) 527 } 528 }, 529 }, 530 { 531 title: "Error stream too large", 532 skipPayloadValidation: true, 533 names: []string{"1Mb-stream"}, 534 blobs: [][]byte{randomBytes(t, 1024*1024)}, 535 skipSuccessValidation: true, 536 checkResponse: CheckRequestEntityTooLargeStatus, 537 setupConfig: func(a *app.App) func(a *app.App) { 538 maxFileSize := *a.Config().FileSettings.MaxFileSize 539 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = 10 * 1024 }) 540 return func(a *app.App) { 541 a.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.MaxFileSize = maxFileSize }) 542 } 543 }, 544 }, 545 } 546 547 for _, useMultipart := range []bool{true, false} { 548 for _, tc := range tests { 549 if tc.skipMultipart && useMultipart || tc.skipSimplePost && !useMultipart { 550 continue 551 } 552 553 title := "" 554 if useMultipart { 555 title = "multipart " 556 } else { 557 title = "simple " 558 } 559 if tc.title != "" { 560 title += tc.title + " " 561 } 562 title += fmt.Sprintf("%v", tc.names) 563 564 t.Run(title, func(t *testing.T) { 565 // Apply any necessary config changes 566 if tc.setupConfig != nil { 567 restoreConfig := tc.setupConfig(th.App) 568 if restoreConfig != nil { 569 defer restoreConfig(th.App) 570 } 571 } 572 573 // Set the default values 574 client := th.Client 575 if tc.client != nil { 576 client = tc.client 577 } 578 channelId := channel.Id 579 if tc.channelId != "" { 580 channelId = tc.channelId 581 } 582 583 blobs := tc.blobs 584 if len(blobs) == 0 { 585 for _, name := range tc.names { 586 blobs = append(blobs, fileBytes(t, name)) 587 } 588 } 589 590 var fileResp *model.FileUploadResponse 591 var resp *model.Response 592 if useMultipart { 593 fileResp, resp = testUploadFilesMultipart(t, client, channelId, tc.names, blobs, tc.clientIds) 594 } else { 595 fileResp, resp = testUploadFilesPost(t, client, channelId, tc.names, blobs, tc.clientIds, tc.useChunkedInSimplePost) 596 } 597 598 if tc.checkResponse != nil { 599 tc.checkResponse(t, resp) 600 } else { 601 if resp != nil { 602 require.Nil(t, resp.Error) 603 } 604 } 605 if tc.skipSuccessValidation { 606 return 607 } 608 609 require.NotNil(t, fileResp, "Nil fileResp") 610 require.NotEqual(t, 0, len(fileResp.FileInfos), "Empty FileInfos") 611 require.Equal(t, len(tc.names), len(fileResp.FileInfos), "Mismatched actual or expected FileInfos") 612 613 for i, ri := range fileResp.FileInfos { 614 // The returned file info from the upload call will be missing some fields that will be stored in the database 615 assert.Equal(t, ri.CreatorId, tc.expectedCreatorId, "File should be assigned to user") 616 assert.Equal(t, ri.PostId, "", "File shouldn't have a post Id") 617 assert.Equal(t, ri.Path, "", "File path should not be set on returned info") 618 assert.Equal(t, ri.ThumbnailPath, "", "File thumbnail path should not be set on returned info") 619 assert.Equal(t, ri.PreviewPath, "", "File preview path should not be set on returned info") 620 if len(tc.expectedImageMiniPreview) == len(fileResp.FileInfos) { 621 assert.Equal(t, ri.MiniPreview != nil, tc.expectedImageMiniPreview[i], "File: %s mini preview state unexpected", tc.names[i]) 622 } 623 if len(tc.clientIds) > i { 624 assert.True(t, len(fileResp.ClientIds) == len(tc.clientIds), 625 fmt.Sprintf("Wrong number of clientIds returned, expected %v, got %v", len(tc.clientIds), len(fileResp.ClientIds))) 626 assert.Equal(t, fileResp.ClientIds[i], tc.clientIds[i], 627 fmt.Sprintf("Wrong clientId returned, expected %v, got %v", tc.clientIds[i], fileResp.ClientIds[i])) 628 } 629 630 dbInfo, err := th.App.Srv().Store.FileInfo().Get(ri.Id) 631 require.NoError(t, err) 632 assert.Equal(t, dbInfo.Id, ri.Id, "File id from response should match one stored in database") 633 assert.Equal(t, dbInfo.CreatorId, tc.expectedCreatorId, "F ile should be assigned to user") 634 assert.Equal(t, dbInfo.PostId, "", "File shouldn't have a post") 635 assert.NotEqual(t, dbInfo.Path, "", "File path should be set in database") 636 _, fname := filepath.Split(dbInfo.Path) 637 ext := filepath.Ext(fname) 638 name := fname[:len(fname)-len(ext)] 639 expectedDir := fmt.Sprintf("%v/teams/%v/channels/%v/users/%s/%s", date, FileTeamId, channel.Id, ri.CreatorId, ri.Id) 640 expectedPath := fmt.Sprintf("%s/%s", expectedDir, fname) 641 assert.Equal(t, dbInfo.Path, expectedPath, 642 fmt.Sprintf("File %v saved to:%q, expected:%q", dbInfo.Name, dbInfo.Path, expectedPath)) 643 644 if tc.expectImage { 645 expectedThumbnailPath := fmt.Sprintf("%s/%s_thumb.jpg", expectedDir, name) 646 expectedPreviewPath := fmt.Sprintf("%s/%s_preview.jpg", expectedDir, name) 647 assert.Equal(t, dbInfo.ThumbnailPath, expectedThumbnailPath, 648 fmt.Sprintf("Thumbnail for %v saved to:%q, expected:%q", dbInfo.Name, dbInfo.ThumbnailPath, expectedThumbnailPath)) 649 assert.Equal(t, dbInfo.PreviewPath, expectedPreviewPath, 650 fmt.Sprintf("Preview for %v saved to:%q, expected:%q", dbInfo.Name, dbInfo.PreviewPath, expectedPreviewPath)) 651 652 assert.True(t, 653 dbInfo.HasPreviewImage == tc.expectedImageHasPreview[i], 654 fmt.Sprintf("Image: HasPreviewImage should be set for %s", dbInfo.Name)) 655 assert.True(t, 656 dbInfo.Width == tc.expectedImageWidths[i] && dbInfo.Height == tc.expectedImageHeights[i], 657 fmt.Sprintf("Image dimensions: expected %dwx%dh, got %vwx%dh", 658 tc.expectedImageWidths[i], tc.expectedImageHeights[i], 659 dbInfo.Width, dbInfo.Height)) 660 } 661 662 if !tc.skipPayloadValidation { 663 compare := func(get func(string) ([]byte, *model.Response), name string) { 664 data, resp := get(ri.Id) 665 require.NotNil(t, resp) 666 require.Nil(t, resp.Error) 667 668 expected, err := ioutil.ReadFile(filepath.Join(testDir, name)) 669 require.NoError(t, err) 670 if !bytes.Equal(data, expected) { 671 tf, err := ioutil.TempFile("", fmt.Sprintf("test_%v_*_%s", i, name)) 672 defer tf.Close() 673 require.NoError(t, err) 674 _, err = io.Copy(tf, bytes.NewReader(data)) 675 require.NoError(t, err) 676 t.Errorf("Actual data mismatched %s, written to %q - expected %d bytes, got %d.", name, tf.Name(), len(expected), len(data)) 677 } 678 } 679 if len(tc.expectedPayloadNames) == 0 { 680 tc.expectedPayloadNames = tc.names 681 } 682 683 compare(client.GetFile, tc.expectedPayloadNames[i]) 684 if len(tc.expectedImageThumbnailNames) > i { 685 compare(client.GetFileThumbnail, tc.expectedImageThumbnailNames[i]) 686 } 687 if len(tc.expectedImageThumbnailNames) > i { 688 compare(client.GetFilePreview, tc.expectedImagePreviewNames[i]) 689 } 690 } 691 692 th.cleanupTestFile(dbInfo) 693 } 694 }) 695 696 } 697 } 698 } 699 700 func TestGetFile(t *testing.T) { 701 th := Setup(t).InitBasic() 702 defer th.TearDown() 703 Client := th.Client 704 channel := th.BasicChannel 705 706 if *th.App.Config().FileSettings.DriverName == "" { 707 t.Skip("skipping because no file driver is enabled") 708 } 709 710 sent, err := testutils.ReadTestFile("test.png") 711 require.NoError(t, err) 712 713 fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png") 714 CheckNoError(t, resp) 715 716 fileId := fileResp.FileInfos[0].Id 717 718 data, resp := Client.GetFile(fileId) 719 CheckNoError(t, resp) 720 require.NotEqual(t, 0, len(data), "should not be empty") 721 722 for i := range data { 723 require.Equal(t, sent[i], data[i], "received file didn't match sent one") 724 } 725 726 _, resp = Client.GetFile("junk") 727 CheckBadRequestStatus(t, resp) 728 729 _, resp = Client.GetFile(model.NewId()) 730 CheckNotFoundStatus(t, resp) 731 732 Client.Logout() 733 _, resp = Client.GetFile(fileId) 734 CheckUnauthorizedStatus(t, resp) 735 736 _, resp = th.SystemAdminClient.GetFile(fileId) 737 CheckNoError(t, resp) 738 } 739 740 func TestGetFileHeaders(t *testing.T) { 741 th := Setup(t).InitBasic() 742 defer th.TearDown() 743 744 Client := th.Client 745 channel := th.BasicChannel 746 747 if *th.App.Config().FileSettings.DriverName == "" { 748 t.Skip("skipping because no file driver is enabled") 749 } 750 751 testHeaders := func(data []byte, filename string, expectedContentType string, getInline bool) func(*testing.T) { 752 return func(t *testing.T) { 753 fileResp, resp := Client.UploadFile(data, channel.Id, filename) 754 CheckNoError(t, resp) 755 756 fileId := fileResp.FileInfos[0].Id 757 758 _, resp = Client.GetFile(fileId) 759 CheckNoError(t, resp) 760 761 CheckStartsWith(t, resp.Header.Get("Content-Type"), expectedContentType, "returned incorrect Content-Type") 762 763 if getInline { 764 CheckStartsWith(t, resp.Header.Get("Content-Disposition"), "inline", "returned incorrect Content-Disposition") 765 } else { 766 CheckStartsWith(t, resp.Header.Get("Content-Disposition"), "attachment", "returned incorrect Content-Disposition") 767 } 768 769 _, resp = Client.DownloadFile(fileId, true) 770 CheckNoError(t, resp) 771 772 CheckStartsWith(t, resp.Header.Get("Content-Type"), expectedContentType, "returned incorrect Content-Type") 773 CheckStartsWith(t, resp.Header.Get("Content-Disposition"), "attachment", "returned incorrect Content-Disposition") 774 } 775 } 776 777 data := []byte("ABC") 778 779 t.Run("png", testHeaders(data, "test.png", "image/png", true)) 780 t.Run("gif", testHeaders(data, "test.gif", "image/gif", true)) 781 t.Run("mp4", testHeaders(data, "test.mp4", "video/mp4", true)) 782 t.Run("mp3", testHeaders(data, "test.mp3", "audio/mpeg", true)) 783 t.Run("pdf", testHeaders(data, "test.pdf", "application/pdf", false)) 784 t.Run("txt", testHeaders(data, "test.txt", "text/plain", false)) 785 t.Run("html", testHeaders(data, "test.html", "text/plain", false)) 786 t.Run("js", testHeaders(data, "test.js", "text/plain", false)) 787 t.Run("go", testHeaders(data, "test.go", "application/octet-stream", false)) 788 t.Run("zip", testHeaders(data, "test.zip", "application/zip", false)) 789 // Not every platform can recognize these 790 //t.Run("exe", testHeaders(data, "test.exe", "application/x-ms", false)) 791 t.Run("no extension", testHeaders(data, "test", "application/octet-stream", false)) 792 t.Run("no extension 2", testHeaders([]byte("<html></html>"), "test", "application/octet-stream", false)) 793 } 794 795 func TestGetFileThumbnail(t *testing.T) { 796 th := Setup(t).InitBasic() 797 defer th.TearDown() 798 Client := th.Client 799 channel := th.BasicChannel 800 801 if *th.App.Config().FileSettings.DriverName == "" { 802 t.Skip("skipping because no file driver is enabled") 803 } 804 805 sent, err := testutils.ReadTestFile("test.png") 806 require.NoError(t, err) 807 808 fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png") 809 CheckNoError(t, resp) 810 811 fileId := fileResp.FileInfos[0].Id 812 813 data, resp := Client.GetFileThumbnail(fileId) 814 CheckNoError(t, resp) 815 require.NotEqual(t, 0, len(data), "should not be empty") 816 817 _, resp = Client.GetFileThumbnail("junk") 818 CheckBadRequestStatus(t, resp) 819 820 _, resp = Client.GetFileThumbnail(model.NewId()) 821 CheckNotFoundStatus(t, resp) 822 823 Client.Logout() 824 _, resp = Client.GetFileThumbnail(fileId) 825 CheckUnauthorizedStatus(t, resp) 826 827 otherUser := th.CreateUser() 828 Client.Login(otherUser.Email, otherUser.Password) 829 _, resp = Client.GetFileThumbnail(fileId) 830 CheckForbiddenStatus(t, resp) 831 832 Client.Logout() 833 _, resp = th.SystemAdminClient.GetFileThumbnail(fileId) 834 CheckNoError(t, resp) 835 } 836 837 func TestGetFileLink(t *testing.T) { 838 th := Setup(t).InitBasic() 839 defer th.TearDown() 840 Client := th.Client 841 channel := th.BasicChannel 842 843 if *th.App.Config().FileSettings.DriverName == "" { 844 t.Skip("skipping because no file driver is enabled") 845 } 846 847 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) 848 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = model.NewRandomString(32) }) 849 850 data, err := testutils.ReadTestFile("test.png") 851 require.NoError(t, err) 852 853 fileResp, uploadResp := Client.UploadFile(data, channel.Id, "test.png") 854 CheckNoError(t, uploadResp) 855 856 fileId := fileResp.FileInfos[0].Id 857 858 _, resp := Client.GetFileLink(fileId) 859 CheckBadRequestStatus(t, resp) 860 861 // Hacky way to assign file to a post (usually would be done by CreatePost call) 862 err = th.App.Srv().Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id, th.BasicUser.Id) 863 require.NoError(t, err) 864 865 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = false }) 866 _, resp = Client.GetFileLink(fileId) 867 CheckNotImplementedStatus(t, resp) 868 869 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) 870 link, resp := Client.GetFileLink(fileId) 871 CheckNoError(t, resp) 872 require.NotEqual(t, "", link, "should've received public link") 873 874 _, resp = Client.GetFileLink("junk") 875 CheckBadRequestStatus(t, resp) 876 877 _, resp = Client.GetFileLink(model.NewId()) 878 CheckNotFoundStatus(t, resp) 879 880 Client.Logout() 881 _, resp = Client.GetFileLink(fileId) 882 CheckUnauthorizedStatus(t, resp) 883 884 otherUser := th.CreateUser() 885 Client.Login(otherUser.Email, otherUser.Password) 886 _, resp = Client.GetFileLink(fileId) 887 CheckForbiddenStatus(t, resp) 888 889 Client.Logout() 890 _, resp = th.SystemAdminClient.GetFileLink(fileId) 891 CheckNoError(t, resp) 892 893 fileInfo, err := th.App.Srv().Store.FileInfo().Get(fileId) 894 require.NoError(t, err) 895 th.cleanupTestFile(fileInfo) 896 } 897 898 func TestGetFilePreview(t *testing.T) { 899 th := Setup(t).InitBasic() 900 defer th.TearDown() 901 Client := th.Client 902 channel := th.BasicChannel 903 904 if *th.App.Config().FileSettings.DriverName == "" { 905 t.Skip("skipping because no file driver is enabled") 906 } 907 908 sent, err := testutils.ReadTestFile("test.png") 909 require.NoError(t, err) 910 911 fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png") 912 CheckNoError(t, resp) 913 fileId := fileResp.FileInfos[0].Id 914 915 data, resp := Client.GetFilePreview(fileId) 916 CheckNoError(t, resp) 917 require.NotEqual(t, 0, len(data), "should not be empty") 918 919 _, resp = Client.GetFilePreview("junk") 920 CheckBadRequestStatus(t, resp) 921 922 _, resp = Client.GetFilePreview(model.NewId()) 923 CheckNotFoundStatus(t, resp) 924 925 Client.Logout() 926 _, resp = Client.GetFilePreview(fileId) 927 CheckUnauthorizedStatus(t, resp) 928 929 otherUser := th.CreateUser() 930 Client.Login(otherUser.Email, otherUser.Password) 931 _, resp = Client.GetFilePreview(fileId) 932 CheckForbiddenStatus(t, resp) 933 934 Client.Logout() 935 _, resp = th.SystemAdminClient.GetFilePreview(fileId) 936 CheckNoError(t, resp) 937 } 938 939 func TestGetFileInfo(t *testing.T) { 940 th := Setup(t).InitBasic() 941 defer th.TearDown() 942 Client := th.Client 943 user := th.BasicUser 944 channel := th.BasicChannel 945 946 if *th.App.Config().FileSettings.DriverName == "" { 947 t.Skip("skipping because no file driver is enabled") 948 } 949 950 sent, err := testutils.ReadTestFile("test.png") 951 require.NoError(t, err) 952 953 fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png") 954 CheckNoError(t, resp) 955 fileId := fileResp.FileInfos[0].Id 956 957 info, resp := Client.GetFileInfo(fileId) 958 CheckNoError(t, resp) 959 960 require.NoError(t, err) 961 require.Equal(t, fileId, info.Id, "got incorrect file") 962 require.Equal(t, user.Id, info.CreatorId, "file should be assigned to user") 963 require.Equal(t, "", info.PostId, "file shouldn't have a post") 964 require.Equal(t, "", info.Path, "file path shouldn't have been returned to client") 965 require.Equal(t, "", info.ThumbnailPath, "file thumbnail path shouldn't have been returned to client") 966 require.Equal(t, "", info.PreviewPath, "file preview path shouldn't have been returned to client") 967 require.Equal(t, "image/png", info.MimeType, "mime type should've been image/png") 968 969 _, resp = Client.GetFileInfo("junk") 970 CheckBadRequestStatus(t, resp) 971 972 _, resp = Client.GetFileInfo(model.NewId()) 973 CheckNotFoundStatus(t, resp) 974 975 Client.Logout() 976 _, resp = Client.GetFileInfo(fileId) 977 CheckUnauthorizedStatus(t, resp) 978 979 otherUser := th.CreateUser() 980 Client.Login(otherUser.Email, otherUser.Password) 981 _, resp = Client.GetFileInfo(fileId) 982 CheckForbiddenStatus(t, resp) 983 984 Client.Logout() 985 _, resp = th.SystemAdminClient.GetFileInfo(fileId) 986 CheckNoError(t, resp) 987 } 988 989 func TestGetPublicFile(t *testing.T) { 990 th := Setup(t).InitBasic() 991 defer th.TearDown() 992 Client := th.Client 993 channel := th.BasicChannel 994 995 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) 996 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = model.NewRandomString(32) }) 997 998 data, err := testutils.ReadTestFile("test.png") 999 require.NoError(t, err) 1000 1001 fileResp, httpResp := Client.UploadFile(data, channel.Id, "test.png") 1002 CheckNoError(t, httpResp) 1003 1004 fileId := fileResp.FileInfos[0].Id 1005 1006 // Hacky way to assign file to a post (usually would be done by CreatePost call) 1007 err = th.App.Srv().Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id, th.BasicUser.Id) 1008 require.NoError(t, err) 1009 1010 info, err := th.App.Srv().Store.FileInfo().Get(fileId) 1011 require.NoError(t, err) 1012 link := th.App.GeneratePublicLink(Client.Url, info) 1013 1014 resp, err := http.Get(link) 1015 require.NoError(t, err) 1016 require.Equal(t, http.StatusOK, resp.StatusCode, "failed to get image with public link") 1017 1018 resp, err = http.Get(link[:strings.LastIndex(link, "?")]) 1019 require.NoError(t, err) 1020 require.Equal(t, http.StatusBadRequest, resp.StatusCode, "should've failed to get image with public link without hash", resp.Status) 1021 1022 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = false }) 1023 1024 resp, err = http.Get(link) 1025 require.NoError(t, err) 1026 require.Equal(t, http.StatusNotImplemented, resp.StatusCode, "should've failed to get image with disabled public link") 1027 1028 // test after the salt has changed 1029 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnablePublicLink = true }) 1030 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = model.NewRandomString(32) }) 1031 1032 resp, err = http.Get(link) 1033 require.NoError(t, err) 1034 require.Equal(t, http.StatusBadRequest, resp.StatusCode, "should've failed to get image with public link after salt changed") 1035 1036 resp, err = http.Get(link) 1037 require.NoError(t, err) 1038 require.Equal(t, http.StatusBadRequest, resp.StatusCode, "should've failed to get image with public link after salt changed") 1039 1040 fileInfo, err := th.App.Srv().Store.FileInfo().Get(fileId) 1041 require.NoError(t, err) 1042 require.NoError(t, th.cleanupTestFile(fileInfo)) 1043 1044 th.cleanupTestFile(info) 1045 link = th.App.GeneratePublicLink(Client.Url, info) 1046 resp, err = http.Get(link) 1047 require.NoError(t, err) 1048 require.Equal(t, http.StatusNotFound, resp.StatusCode, "should've failed to get file after it is deleted") 1049 } 1050 1051 func TestSearchFiles(t *testing.T) { 1052 th := Setup(t).InitBasic() 1053 defer th.TearDown() 1054 experimentalViewArchivedChannels := *th.App.Config().TeamSettings.ExperimentalViewArchivedChannels 1055 defer func() { 1056 th.App.UpdateConfig(func(cfg *model.Config) { 1057 cfg.TeamSettings.ExperimentalViewArchivedChannels = &experimentalViewArchivedChannels 1058 }) 1059 }() 1060 th.App.UpdateConfig(func(cfg *model.Config) { 1061 *cfg.TeamSettings.ExperimentalViewArchivedChannels = true 1062 }) 1063 data, err := testutils.ReadTestFile("test.png") 1064 require.NoError(t, err) 1065 1066 th.LoginBasic() 1067 Client := th.Client 1068 1069 filename := "search for fileInfo1" 1070 fileInfo1, appErr := th.App.UploadFile(th.Context, data, th.BasicChannel.Id, filename) 1071 require.Nil(t, appErr) 1072 err = th.App.Srv().Store.FileInfo().AttachToPost(fileInfo1.Id, th.BasicPost.Id, th.BasicUser.Id) 1073 require.NoError(t, err) 1074 1075 filename = "search for fileInfo2" 1076 fileInfo2, appErr := th.App.UploadFile(th.Context, data, th.BasicChannel.Id, filename) 1077 require.Nil(t, appErr) 1078 err = th.App.Srv().Store.FileInfo().AttachToPost(fileInfo2.Id, th.BasicPost.Id, th.BasicUser.Id) 1079 require.NoError(t, err) 1080 1081 filename = "tagged search for fileInfo3" 1082 fileInfo3, appErr := th.App.UploadFile(th.Context, data, th.BasicChannel.Id, filename) 1083 require.Nil(t, appErr) 1084 err = th.App.Srv().Store.FileInfo().AttachToPost(fileInfo3.Id, th.BasicPost.Id, th.BasicUser.Id) 1085 require.NoError(t, err) 1086 1087 filename = "tagged for fileInfo4" 1088 fileInfo4, appErr := th.App.UploadFile(th.Context, data, th.BasicChannel.Id, filename) 1089 require.Nil(t, appErr) 1090 err = th.App.Srv().Store.FileInfo().AttachToPost(fileInfo4.Id, th.BasicPost.Id, th.BasicUser.Id) 1091 require.NoError(t, err) 1092 1093 archivedChannel := th.CreatePublicChannel() 1094 fileInfo5, appErr := th.App.UploadFile(th.Context, data, archivedChannel.Id, "tagged for fileInfo3") 1095 require.Nil(t, appErr) 1096 post := &model.Post{ChannelId: archivedChannel.Id, Message: model.NewId() + "a"} 1097 rpost, resp := Client.CreatePost(post) 1098 CheckNoError(t, resp) 1099 err = th.App.Srv().Store.FileInfo().AttachToPost(fileInfo5.Id, rpost.Id, th.BasicUser.Id) 1100 require.NoError(t, err) 1101 th.Client.DeleteChannel(archivedChannel.Id) 1102 1103 terms := "search" 1104 isOrSearch := false 1105 timezoneOffset := 5 1106 searchParams := model.SearchParameter{ 1107 Terms: &terms, 1108 IsOrSearch: &isOrSearch, 1109 TimeZoneOffset: &timezoneOffset, 1110 } 1111 fileInfos, resp := Client.SearchFilesWithParams(th.BasicTeam.Id, &searchParams) 1112 CheckNoError(t, resp) 1113 require.Len(t, fileInfos.Order, 3, "wrong search") 1114 1115 terms = "search" 1116 page := 0 1117 perPage := 2 1118 searchParams = model.SearchParameter{ 1119 Terms: &terms, 1120 IsOrSearch: &isOrSearch, 1121 TimeZoneOffset: &timezoneOffset, 1122 Page: &page, 1123 PerPage: &perPage, 1124 } 1125 fileInfos2, resp := Client.SearchFilesWithParams(th.BasicTeam.Id, &searchParams) 1126 CheckNoError(t, resp) 1127 // We don't support paging for DB search yet, modify this when we do. 1128 require.Len(t, fileInfos2.Order, 3, "Wrong number of fileInfos") 1129 assert.Equal(t, fileInfos.Order[0], fileInfos2.Order[0]) 1130 assert.Equal(t, fileInfos.Order[1], fileInfos2.Order[1]) 1131 1132 page = 1 1133 searchParams = model.SearchParameter{ 1134 Terms: &terms, 1135 IsOrSearch: &isOrSearch, 1136 TimeZoneOffset: &timezoneOffset, 1137 Page: &page, 1138 PerPage: &perPage, 1139 } 1140 fileInfos2, resp = Client.SearchFilesWithParams(th.BasicTeam.Id, &searchParams) 1141 CheckNoError(t, resp) 1142 // We don't support paging for DB search yet, modify this when we do. 1143 require.Empty(t, fileInfos2.Order, "Wrong number of fileInfos") 1144 1145 fileInfos, resp = Client.SearchFiles(th.BasicTeam.Id, "search", false) 1146 CheckNoError(t, resp) 1147 require.Len(t, fileInfos.Order, 3, "wrong search") 1148 1149 fileInfos, resp = Client.SearchFiles(th.BasicTeam.Id, "fileInfo2", false) 1150 CheckNoError(t, resp) 1151 require.Len(t, fileInfos.Order, 1, "wrong number of fileInfos") 1152 require.Equal(t, fileInfo2.Id, fileInfos.Order[0], "wrong search") 1153 1154 terms = "tagged" 1155 includeDeletedChannels := true 1156 searchParams = model.SearchParameter{ 1157 Terms: &terms, 1158 IsOrSearch: &isOrSearch, 1159 TimeZoneOffset: &timezoneOffset, 1160 IncludeDeletedChannels: &includeDeletedChannels, 1161 } 1162 fileInfos, resp = Client.SearchFilesWithParams(th.BasicTeam.Id, &searchParams) 1163 CheckNoError(t, resp) 1164 require.Len(t, fileInfos.Order, 3, "wrong search") 1165 1166 th.App.UpdateConfig(func(cfg *model.Config) { 1167 *cfg.TeamSettings.ExperimentalViewArchivedChannels = false 1168 }) 1169 1170 fileInfos, resp = Client.SearchFilesWithParams(th.BasicTeam.Id, &searchParams) 1171 CheckNoError(t, resp) 1172 require.Len(t, fileInfos.Order, 2, "wrong search") 1173 1174 fileInfos, _ = Client.SearchFiles(th.BasicTeam.Id, "*", false) 1175 require.Empty(t, fileInfos.Order, "searching for just * shouldn't return any results") 1176 1177 fileInfos, resp = Client.SearchFiles(th.BasicTeam.Id, "fileInfo1 fileInfo2", true) 1178 CheckNoError(t, resp) 1179 require.Len(t, fileInfos.Order, 2, "wrong search results") 1180 1181 _, resp = Client.SearchFiles("junk", "#sgtitlereview", false) 1182 CheckBadRequestStatus(t, resp) 1183 1184 _, resp = Client.SearchFiles(model.NewId(), "#sgtitlereview", false) 1185 CheckForbiddenStatus(t, resp) 1186 1187 _, resp = Client.SearchFiles(th.BasicTeam.Id, "", false) 1188 CheckBadRequestStatus(t, resp) 1189 1190 Client.Logout() 1191 _, resp = Client.SearchFiles(th.BasicTeam.Id, "#sgtitlereview", false) 1192 CheckUnauthorizedStatus(t, resp) 1193 }