github.com/wgh-/mattermost-server@v4.8.0-rc2+incompatible/api4/file_test.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/mattermost/mattermost-server/model"
    14  	"github.com/mattermost/mattermost-server/store"
    15  )
    16  
    17  func TestUploadFileAsMultipart(t *testing.T) {
    18  	th := Setup().InitBasic().InitSystemAdmin()
    19  	defer th.TearDown()
    20  	Client := th.Client
    21  
    22  	user := th.BasicUser
    23  	channel := th.BasicChannel
    24  
    25  	var uploadInfo *model.FileInfo
    26  	var data []byte
    27  	var err error
    28  	if data, err = readTestFile("test.png"); err != nil {
    29  		t.Fatal(err)
    30  	} else if fileResp, resp := Client.UploadFile(data, channel.Id, "test.png"); resp.Error != nil {
    31  		t.Fatal(resp.Error)
    32  	} else if len(fileResp.FileInfos) != 1 {
    33  		t.Fatal("should've returned a single file infos")
    34  	} else {
    35  		uploadInfo = fileResp.FileInfos[0]
    36  	}
    37  
    38  	// The returned file info from the upload call will be missing some fields that will be stored in the database
    39  	if uploadInfo.CreatorId != user.Id {
    40  		t.Fatal("file should be assigned to user")
    41  	} else if uploadInfo.PostId != "" {
    42  		t.Fatal("file shouldn't have a post")
    43  	} else if uploadInfo.Path != "" {
    44  		t.Fatal("file path should not be set on returned info")
    45  	} else if uploadInfo.ThumbnailPath != "" {
    46  		t.Fatal("file thumbnail path should not be set on returned info")
    47  	} else if uploadInfo.PreviewPath != "" {
    48  		t.Fatal("file preview path should not be set on returned info")
    49  	}
    50  
    51  	var info *model.FileInfo
    52  	if result := <-th.App.Srv.Store.FileInfo().Get(uploadInfo.Id); result.Err != nil {
    53  		t.Fatal(result.Err)
    54  	} else {
    55  		info = result.Data.(*model.FileInfo)
    56  	}
    57  
    58  	if info.Id != uploadInfo.Id {
    59  		t.Fatal("file id from response should match one stored in database")
    60  	} else if info.CreatorId != user.Id {
    61  		t.Fatal("file should be assigned to user")
    62  	} else if info.PostId != "" {
    63  		t.Fatal("file shouldn't have a post")
    64  	} else if info.Path == "" {
    65  		t.Fatal("file path should be set in database")
    66  	} else if info.ThumbnailPath == "" {
    67  		t.Fatal("file thumbnail path should be set in database")
    68  	} else if info.PreviewPath == "" {
    69  		t.Fatal("file preview path should be set in database")
    70  	}
    71  
    72  	date := time.Now().Format("20060102")
    73  
    74  	// This also makes sure that the relative path provided above is sanitized out
    75  	expectedPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test.png", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
    76  	if info.Path != expectedPath {
    77  		t.Logf("file is saved in %v", info.Path)
    78  		t.Fatalf("file should've been saved in %v", expectedPath)
    79  	}
    80  
    81  	expectedThumbnailPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test_thumb.jpg", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
    82  	if info.ThumbnailPath != expectedThumbnailPath {
    83  		t.Logf("file thumbnail is saved in %v", info.ThumbnailPath)
    84  		t.Fatalf("file thumbnail should've been saved in %v", expectedThumbnailPath)
    85  	}
    86  
    87  	expectedPreviewPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test_preview.jpg", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
    88  	if info.PreviewPath != expectedPreviewPath {
    89  		t.Logf("file preview is saved in %v", info.PreviewPath)
    90  		t.Fatalf("file preview should've been saved in %v", expectedPreviewPath)
    91  	}
    92  
    93  	// Wait a bit for files to ready
    94  	time.Sleep(2 * time.Second)
    95  
    96  	if err := th.cleanupTestFile(info); err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	_, resp := Client.UploadFile(data, model.NewId(), "test.png")
   101  	CheckForbiddenStatus(t, resp)
   102  
   103  	_, resp = Client.UploadFile(data, "../../junk", "test.png")
   104  	CheckForbiddenStatus(t, resp)
   105  
   106  	_, resp = th.SystemAdminClient.UploadFile(data, model.NewId(), "test.png")
   107  	CheckForbiddenStatus(t, resp)
   108  
   109  	_, resp = th.SystemAdminClient.UploadFile(data, "../../junk", "test.png")
   110  	CheckForbiddenStatus(t, resp)
   111  
   112  	_, resp = th.SystemAdminClient.UploadFile(data, channel.Id, "test.png")
   113  	CheckNoError(t, resp)
   114  
   115  	enableFileAttachments := *th.App.Config().FileSettings.EnableFileAttachments
   116  	defer func() {
   117  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = enableFileAttachments })
   118  	}()
   119  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false })
   120  
   121  	_, resp = th.SystemAdminClient.UploadFile(data, channel.Id, "test.png")
   122  	if resp.StatusCode == 0 {
   123  		t.Log("file upload request failed completely")
   124  	} else if resp.StatusCode != http.StatusNotImplemented {
   125  		// This should return an HTTP 501, but it occasionally causes the http client itself to error
   126  		t.Fatalf("should've returned HTTP 501 or failed completely, got %v instead", resp.StatusCode)
   127  	}
   128  }
   129  
   130  func TestUploadFileAsRequestBody(t *testing.T) {
   131  	th := Setup().InitBasic().InitSystemAdmin()
   132  	defer th.TearDown()
   133  	Client := th.Client
   134  
   135  	user := th.BasicUser
   136  	channel := th.BasicChannel
   137  
   138  	var uploadInfo *model.FileInfo
   139  	var data []byte
   140  	var err error
   141  	if data, err = readTestFile("test.png"); err != nil {
   142  		t.Fatal(err)
   143  	} else if fileResp, resp := Client.UploadFileAsRequestBody(data, channel.Id, "test.png"); resp.Error != nil {
   144  		t.Fatal(resp.Error)
   145  	} else if len(fileResp.FileInfos) != 1 {
   146  		t.Fatal("should've returned a single file infos")
   147  	} else {
   148  		uploadInfo = fileResp.FileInfos[0]
   149  	}
   150  
   151  	// The returned file info from the upload call will be missing some fields that will be stored in the database
   152  	if uploadInfo.CreatorId != user.Id {
   153  		t.Fatal("file should be assigned to user")
   154  	} else if uploadInfo.PostId != "" {
   155  		t.Fatal("file shouldn't have a post")
   156  	} else if uploadInfo.Path != "" {
   157  		t.Fatal("file path should not be set on returned info")
   158  	} else if uploadInfo.ThumbnailPath != "" {
   159  		t.Fatal("file thumbnail path should not be set on returned info")
   160  	} else if uploadInfo.PreviewPath != "" {
   161  		t.Fatal("file preview path should not be set on returned info")
   162  	}
   163  
   164  	var info *model.FileInfo
   165  	if result := <-th.App.Srv.Store.FileInfo().Get(uploadInfo.Id); result.Err != nil {
   166  		t.Fatal(result.Err)
   167  	} else {
   168  		info = result.Data.(*model.FileInfo)
   169  	}
   170  
   171  	if info.Id != uploadInfo.Id {
   172  		t.Fatal("file id from response should match one stored in database")
   173  	} else if info.CreatorId != user.Id {
   174  		t.Fatal("file should be assigned to user")
   175  	} else if info.PostId != "" {
   176  		t.Fatal("file shouldn't have a post")
   177  	} else if info.Path == "" {
   178  		t.Fatal("file path should be set in database")
   179  	} else if info.ThumbnailPath == "" {
   180  		t.Fatal("file thumbnail path should be set in database")
   181  	} else if info.PreviewPath == "" {
   182  		t.Fatal("file preview path should be set in database")
   183  	}
   184  
   185  	date := time.Now().Format("20060102")
   186  
   187  	// This also makes sure that the relative path provided above is sanitized out
   188  	expectedPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test.png", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
   189  	if info.Path != expectedPath {
   190  		t.Logf("file is saved in %v", info.Path)
   191  		t.Fatalf("file should've been saved in %v", expectedPath)
   192  	}
   193  
   194  	expectedThumbnailPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test_thumb.jpg", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
   195  	if info.ThumbnailPath != expectedThumbnailPath {
   196  		t.Logf("file thumbnail is saved in %v", info.ThumbnailPath)
   197  		t.Fatalf("file thumbnail should've been saved in %v", expectedThumbnailPath)
   198  	}
   199  
   200  	expectedPreviewPath := fmt.Sprintf("%v/teams/%v/channels/%v/users/%v/%v/test_preview.jpg", date, FILE_TEAM_ID, channel.Id, user.Id, info.Id)
   201  	if info.PreviewPath != expectedPreviewPath {
   202  		t.Logf("file preview is saved in %v", info.PreviewPath)
   203  		t.Fatalf("file preview should've been saved in %v", expectedPreviewPath)
   204  	}
   205  
   206  	// Wait a bit for files to ready
   207  	time.Sleep(2 * time.Second)
   208  
   209  	if err := th.cleanupTestFile(info); err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	_, resp := Client.UploadFileAsRequestBody(data, model.NewId(), "test.png")
   214  	CheckForbiddenStatus(t, resp)
   215  
   216  	_, resp = Client.UploadFileAsRequestBody(data, "../../junk", "test.png")
   217  	if resp.StatusCode == 0 {
   218  		t.Log("file upload request failed completely")
   219  	} else if resp.StatusCode != http.StatusBadRequest {
   220  		// This should return an HTTP 400, but it occasionally causes the http client itself to error
   221  		t.Fatalf("should've returned HTTP 400 or failed completely, got %v instead", resp.StatusCode)
   222  	}
   223  
   224  	_, resp = th.SystemAdminClient.UploadFileAsRequestBody(data, model.NewId(), "test.png")
   225  	CheckForbiddenStatus(t, resp)
   226  
   227  	_, resp = th.SystemAdminClient.UploadFileAsRequestBody(data, "../../junk", "test.png")
   228  	if resp.StatusCode == 0 {
   229  		t.Log("file upload request failed completely")
   230  	} else if resp.StatusCode != http.StatusBadRequest {
   231  		// This should return an HTTP 400, but it occasionally causes the http client itself to error
   232  		t.Fatalf("should've returned HTTP 400 or failed completely, got %v instead", resp.StatusCode)
   233  	}
   234  
   235  	_, resp = th.SystemAdminClient.UploadFileAsRequestBody(data, channel.Id, "test.png")
   236  	CheckNoError(t, resp)
   237  
   238  	enableFileAttachments := *th.App.Config().FileSettings.EnableFileAttachments
   239  	defer func() {
   240  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = enableFileAttachments })
   241  	}()
   242  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false })
   243  
   244  	_, resp = th.SystemAdminClient.UploadFileAsRequestBody(data, channel.Id, "test.png")
   245  	if resp.StatusCode == 0 {
   246  		t.Log("file upload request failed completely")
   247  	} else if resp.StatusCode != http.StatusNotImplemented {
   248  		// This should return an HTTP 501, but it occasionally causes the http client itself to error
   249  		t.Fatalf("should've returned HTTP 501 or failed completely, got %v instead", resp.StatusCode)
   250  	}
   251  }
   252  
   253  func TestGetFile(t *testing.T) {
   254  	th := Setup().InitBasic().InitSystemAdmin()
   255  	defer th.TearDown()
   256  	Client := th.Client
   257  	channel := th.BasicChannel
   258  
   259  	if *th.App.Config().FileSettings.DriverName == "" {
   260  		t.Skip("skipping because no file driver is enabled")
   261  	}
   262  
   263  	fileId := ""
   264  	var sent []byte
   265  	var err error
   266  	if sent, err = readTestFile("test.png"); err != nil {
   267  		t.Fatal(err)
   268  	} else {
   269  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   270  		CheckNoError(t, resp)
   271  
   272  		fileId = fileResp.FileInfos[0].Id
   273  	}
   274  
   275  	data, resp := Client.GetFile(fileId)
   276  	CheckNoError(t, resp)
   277  
   278  	if len(data) == 0 {
   279  		t.Fatal("should not be empty")
   280  	}
   281  
   282  	for i := range data {
   283  		if data[i] != sent[i] {
   284  			t.Fatal("received file didn't match sent one")
   285  		}
   286  	}
   287  
   288  	_, resp = Client.GetFile("junk")
   289  	CheckBadRequestStatus(t, resp)
   290  
   291  	_, resp = Client.GetFile(model.NewId())
   292  	CheckNotFoundStatus(t, resp)
   293  
   294  	Client.Logout()
   295  	_, resp = Client.GetFile(fileId)
   296  	CheckUnauthorizedStatus(t, resp)
   297  
   298  	_, resp = th.SystemAdminClient.GetFile(fileId)
   299  	CheckNoError(t, resp)
   300  }
   301  
   302  func TestGetFileHeaders(t *testing.T) {
   303  	th := Setup().InitBasic()
   304  	defer th.TearDown()
   305  
   306  	Client := th.Client
   307  	channel := th.BasicChannel
   308  
   309  	if *th.App.Config().FileSettings.DriverName == "" {
   310  		t.Skip("skipping because no file driver is enabled")
   311  	}
   312  
   313  	testHeaders := func(data []byte, filename string, expectedContentType string, getInline bool) func(*testing.T) {
   314  		return func(t *testing.T) {
   315  			fileResp, resp := Client.UploadFile(data, channel.Id, filename)
   316  			CheckNoError(t, resp)
   317  
   318  			fileId := fileResp.FileInfos[0].Id
   319  
   320  			_, resp = Client.GetFile(fileId)
   321  			CheckNoError(t, resp)
   322  
   323  			if contentType := resp.Header.Get("Content-Type"); !strings.HasPrefix(contentType, expectedContentType) {
   324  				t.Fatal("returned incorrect Content-Type", contentType)
   325  			}
   326  
   327  			if getInline {
   328  				if contentDisposition := resp.Header.Get("Content-Disposition"); !strings.HasPrefix(contentDisposition, "inline") {
   329  					t.Fatal("returned incorrect Content-Disposition", contentDisposition)
   330  				}
   331  			} else {
   332  				if contentDisposition := resp.Header.Get("Content-Disposition"); !strings.HasPrefix(contentDisposition, "attachment") {
   333  					t.Fatal("returned incorrect Content-Disposition", contentDisposition)
   334  				}
   335  			}
   336  
   337  			_, resp = Client.DownloadFile(fileId, true)
   338  			CheckNoError(t, resp)
   339  
   340  			if contentType := resp.Header.Get("Content-Type"); !strings.HasPrefix(contentType, expectedContentType) {
   341  				t.Fatal("returned incorrect Content-Type", contentType)
   342  			}
   343  
   344  			if contentDisposition := resp.Header.Get("Content-Disposition"); !strings.HasPrefix(contentDisposition, "attachment") {
   345  				t.Fatal("returned incorrect Content-Disposition", contentDisposition)
   346  			}
   347  		}
   348  	}
   349  
   350  	data := []byte("ABC")
   351  
   352  	t.Run("png", testHeaders(data, "test.png", "image/png", true))
   353  	t.Run("gif", testHeaders(data, "test.gif", "image/gif", true))
   354  	t.Run("mp4", testHeaders(data, "test.mp4", "video/mp4", true))
   355  	t.Run("mp3", testHeaders(data, "test.mp3", "audio/mpeg", true))
   356  	t.Run("pdf", testHeaders(data, "test.pdf", "application/pdf", false))
   357  	t.Run("txt", testHeaders(data, "test.txt", "text/plain", false))
   358  	t.Run("html", testHeaders(data, "test.html", "text/plain", false))
   359  	t.Run("js", testHeaders(data, "test.js", "text/plain", false))
   360  	t.Run("go", testHeaders(data, "test.go", "application/octet-stream", false))
   361  	t.Run("zip", testHeaders(data, "test.zip", "application/zip", false))
   362  	t.Run("exe", testHeaders(data, "test.exe", "application/x-ms", false))
   363  	t.Run("no extension", testHeaders(data, "test", "application/octet-stream", false))
   364  	t.Run("no extension 2", testHeaders([]byte("<html></html>"), "test", "application/octet-stream", false))
   365  }
   366  
   367  func TestGetFileThumbnail(t *testing.T) {
   368  	th := Setup().InitBasic().InitSystemAdmin()
   369  	defer th.TearDown()
   370  	Client := th.Client
   371  	channel := th.BasicChannel
   372  
   373  	if *th.App.Config().FileSettings.DriverName == "" {
   374  		t.Skip("skipping because no file driver is enabled")
   375  	}
   376  
   377  	fileId := ""
   378  	var sent []byte
   379  	var err error
   380  	if sent, err = readTestFile("test.png"); err != nil {
   381  		t.Fatal(err)
   382  	} else {
   383  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   384  		CheckNoError(t, resp)
   385  
   386  		fileId = fileResp.FileInfos[0].Id
   387  	}
   388  
   389  	// Wait a bit for files to ready
   390  	time.Sleep(2 * time.Second)
   391  
   392  	data, resp := Client.GetFileThumbnail(fileId)
   393  	CheckNoError(t, resp)
   394  
   395  	if len(data) == 0 {
   396  		t.Fatal("should not be empty")
   397  	}
   398  
   399  	_, resp = Client.GetFileThumbnail("junk")
   400  	CheckBadRequestStatus(t, resp)
   401  
   402  	_, resp = Client.GetFileThumbnail(model.NewId())
   403  	CheckNotFoundStatus(t, resp)
   404  
   405  	Client.Logout()
   406  	_, resp = Client.GetFileThumbnail(fileId)
   407  	CheckUnauthorizedStatus(t, resp)
   408  
   409  	otherUser := th.CreateUser()
   410  	Client.Login(otherUser.Email, otherUser.Password)
   411  	_, resp = Client.GetFileThumbnail(fileId)
   412  	CheckForbiddenStatus(t, resp)
   413  
   414  	Client.Logout()
   415  	_, resp = th.SystemAdminClient.GetFileThumbnail(fileId)
   416  	CheckNoError(t, resp)
   417  }
   418  
   419  func TestGetFileLink(t *testing.T) {
   420  	th := Setup().InitBasic().InitSystemAdmin()
   421  	defer th.TearDown()
   422  	Client := th.Client
   423  	channel := th.BasicChannel
   424  
   425  	if *th.App.Config().FileSettings.DriverName == "" {
   426  		t.Skip("skipping because no file driver is enabled")
   427  	}
   428  
   429  	enablePublicLink := th.App.Config().FileSettings.EnablePublicLink
   430  	publicLinkSalt := *th.App.Config().FileSettings.PublicLinkSalt
   431  	defer func() {
   432  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = enablePublicLink })
   433  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = publicLinkSalt })
   434  	}()
   435  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   436  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = model.NewId() })
   437  
   438  	fileId := ""
   439  	if data, err := readTestFile("test.png"); err != nil {
   440  		t.Fatal(err)
   441  	} else {
   442  		fileResp, resp := Client.UploadFile(data, channel.Id, "test.png")
   443  		CheckNoError(t, resp)
   444  
   445  		fileId = fileResp.FileInfos[0].Id
   446  	}
   447  
   448  	link, resp := Client.GetFileLink(fileId)
   449  	CheckBadRequestStatus(t, resp)
   450  
   451  	// Hacky way to assign file to a post (usually would be done by CreatePost call)
   452  	store.Must(th.App.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
   453  
   454  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = false })
   455  	_, resp = Client.GetFileLink(fileId)
   456  	CheckNotImplementedStatus(t, resp)
   457  
   458  	// Wait a bit for files to ready
   459  	time.Sleep(2 * time.Second)
   460  
   461  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   462  	link, resp = Client.GetFileLink(fileId)
   463  	CheckNoError(t, resp)
   464  	if link == "" {
   465  		t.Fatal("should've received public link")
   466  	}
   467  
   468  	_, resp = Client.GetFileLink("junk")
   469  	CheckBadRequestStatus(t, resp)
   470  
   471  	_, resp = Client.GetFileLink(model.NewId())
   472  	CheckNotFoundStatus(t, resp)
   473  
   474  	Client.Logout()
   475  	_, resp = Client.GetFileLink(fileId)
   476  	CheckUnauthorizedStatus(t, resp)
   477  
   478  	otherUser := th.CreateUser()
   479  	Client.Login(otherUser.Email, otherUser.Password)
   480  	_, resp = Client.GetFileLink(fileId)
   481  	CheckForbiddenStatus(t, resp)
   482  
   483  	Client.Logout()
   484  	_, resp = th.SystemAdminClient.GetFileLink(fileId)
   485  	CheckNoError(t, resp)
   486  
   487  	if result := <-th.App.Srv.Store.FileInfo().Get(fileId); result.Err != nil {
   488  		t.Fatal(result.Err)
   489  	} else {
   490  		th.cleanupTestFile(result.Data.(*model.FileInfo))
   491  	}
   492  }
   493  
   494  func TestGetFilePreview(t *testing.T) {
   495  	th := Setup().InitBasic().InitSystemAdmin()
   496  	defer th.TearDown()
   497  	Client := th.Client
   498  	channel := th.BasicChannel
   499  
   500  	if *th.App.Config().FileSettings.DriverName == "" {
   501  		t.Skip("skipping because no file driver is enabled")
   502  	}
   503  
   504  	fileId := ""
   505  	var sent []byte
   506  	var err error
   507  	if sent, err = readTestFile("test.png"); err != nil {
   508  		t.Fatal(err)
   509  	} else {
   510  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   511  		CheckNoError(t, resp)
   512  
   513  		fileId = fileResp.FileInfos[0].Id
   514  	}
   515  
   516  	// Wait a bit for files to ready
   517  	time.Sleep(2 * time.Second)
   518  
   519  	data, resp := Client.GetFilePreview(fileId)
   520  	CheckNoError(t, resp)
   521  
   522  	if len(data) == 0 {
   523  		t.Fatal("should not be empty")
   524  	}
   525  
   526  	_, resp = Client.GetFilePreview("junk")
   527  	CheckBadRequestStatus(t, resp)
   528  
   529  	_, resp = Client.GetFilePreview(model.NewId())
   530  	CheckNotFoundStatus(t, resp)
   531  
   532  	Client.Logout()
   533  	_, resp = Client.GetFilePreview(fileId)
   534  	CheckUnauthorizedStatus(t, resp)
   535  
   536  	otherUser := th.CreateUser()
   537  	Client.Login(otherUser.Email, otherUser.Password)
   538  	_, resp = Client.GetFilePreview(fileId)
   539  	CheckForbiddenStatus(t, resp)
   540  
   541  	Client.Logout()
   542  	_, resp = th.SystemAdminClient.GetFilePreview(fileId)
   543  	CheckNoError(t, resp)
   544  }
   545  
   546  func TestGetFileInfo(t *testing.T) {
   547  	th := Setup().InitBasic().InitSystemAdmin()
   548  	defer th.TearDown()
   549  	Client := th.Client
   550  	user := th.BasicUser
   551  	channel := th.BasicChannel
   552  
   553  	if *th.App.Config().FileSettings.DriverName == "" {
   554  		t.Skip("skipping because no file driver is enabled")
   555  	}
   556  
   557  	fileId := ""
   558  	var sent []byte
   559  	var err error
   560  	if sent, err = readTestFile("test.png"); err != nil {
   561  		t.Fatal(err)
   562  	} else {
   563  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   564  		CheckNoError(t, resp)
   565  
   566  		fileId = fileResp.FileInfos[0].Id
   567  	}
   568  
   569  	// Wait a bit for files to ready
   570  	time.Sleep(2 * time.Second)
   571  
   572  	info, resp := Client.GetFileInfo(fileId)
   573  	CheckNoError(t, resp)
   574  
   575  	if err != nil {
   576  		t.Fatal(err)
   577  	} else if info.Id != fileId {
   578  		t.Fatal("got incorrect file")
   579  	} else if info.CreatorId != user.Id {
   580  		t.Fatal("file should be assigned to user")
   581  	} else if info.PostId != "" {
   582  		t.Fatal("file shouldn't have a post")
   583  	} else if info.Path != "" {
   584  		t.Fatal("file path shouldn't have been returned to client")
   585  	} else if info.ThumbnailPath != "" {
   586  		t.Fatal("file thumbnail path shouldn't have been returned to client")
   587  	} else if info.PreviewPath != "" {
   588  		t.Fatal("file preview path shouldn't have been returned to client")
   589  	} else if info.MimeType != "image/png" {
   590  		t.Fatal("mime type should've been image/png")
   591  	}
   592  
   593  	_, resp = Client.GetFileInfo("junk")
   594  	CheckBadRequestStatus(t, resp)
   595  
   596  	_, resp = Client.GetFileInfo(model.NewId())
   597  	CheckNotFoundStatus(t, resp)
   598  
   599  	Client.Logout()
   600  	_, resp = Client.GetFileInfo(fileId)
   601  	CheckUnauthorizedStatus(t, resp)
   602  
   603  	otherUser := th.CreateUser()
   604  	Client.Login(otherUser.Email, otherUser.Password)
   605  	_, resp = Client.GetFileInfo(fileId)
   606  	CheckForbiddenStatus(t, resp)
   607  
   608  	Client.Logout()
   609  	_, resp = th.SystemAdminClient.GetFileInfo(fileId)
   610  	CheckNoError(t, resp)
   611  }
   612  
   613  func TestGetPublicFile(t *testing.T) {
   614  	th := Setup().InitBasic().InitSystemAdmin()
   615  	defer th.TearDown()
   616  	Client := th.Client
   617  	channel := th.BasicChannel
   618  
   619  	if *th.App.Config().FileSettings.DriverName == "" {
   620  		t.Skip("skipping because no file driver is enabled")
   621  	}
   622  
   623  	enablePublicLink := th.App.Config().FileSettings.EnablePublicLink
   624  	publicLinkSalt := *th.App.Config().FileSettings.PublicLinkSalt
   625  	defer func() {
   626  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = enablePublicLink })
   627  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = publicLinkSalt })
   628  	}()
   629  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   630  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   631  
   632  	fileId := ""
   633  	if data, err := readTestFile("test.png"); err != nil {
   634  		t.Fatal(err)
   635  	} else {
   636  		fileResp, resp := Client.UploadFile(data, channel.Id, "test.png")
   637  		CheckNoError(t, resp)
   638  
   639  		fileId = fileResp.FileInfos[0].Id
   640  	}
   641  
   642  	// Hacky way to assign file to a post (usually would be done by CreatePost call)
   643  	store.Must(th.App.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
   644  
   645  	result := <-th.App.Srv.Store.FileInfo().Get(fileId)
   646  	info := result.Data.(*model.FileInfo)
   647  	link := th.App.GeneratePublicLink(Client.Url, info)
   648  
   649  	// Wait a bit for files to ready
   650  	time.Sleep(2 * time.Second)
   651  
   652  	if resp, err := http.Get(link); err != nil || resp.StatusCode != http.StatusOK {
   653  		t.Log(link)
   654  		t.Fatal("failed to get image with public link", err)
   655  	}
   656  
   657  	if resp, err := http.Get(link[:strings.LastIndex(link, "?")]); err == nil && resp.StatusCode != http.StatusBadRequest {
   658  		t.Fatal("should've failed to get image with public link without hash", resp.Status)
   659  	}
   660  
   661  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = false })
   662  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusNotImplemented {
   663  		t.Fatal("should've failed to get image with disabled public link")
   664  	}
   665  
   666  	// test after the salt has changed
   667  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   668  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   669  
   670  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   671  		t.Fatal("should've failed to get image with public link after salt changed")
   672  	}
   673  
   674  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   675  		t.Fatal("should've failed to get image with public link after salt changed")
   676  	}
   677  
   678  	if err := th.cleanupTestFile(store.Must(th.App.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
   679  		t.Fatal(err)
   680  	}
   681  
   682  	th.cleanupTestFile(info)
   683  }