github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+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  	// Not every platform can recognize these
   363  	//t.Run("exe", testHeaders(data, "test.exe", "application/x-ms", false))
   364  	t.Run("no extension", testHeaders(data, "test", "application/octet-stream", false))
   365  	t.Run("no extension 2", testHeaders([]byte("<html></html>"), "test", "application/octet-stream", false))
   366  }
   367  
   368  func TestGetFileThumbnail(t *testing.T) {
   369  	th := Setup().InitBasic().InitSystemAdmin()
   370  	defer th.TearDown()
   371  	Client := th.Client
   372  	channel := th.BasicChannel
   373  
   374  	if *th.App.Config().FileSettings.DriverName == "" {
   375  		t.Skip("skipping because no file driver is enabled")
   376  	}
   377  
   378  	fileId := ""
   379  	var sent []byte
   380  	var err error
   381  	if sent, err = readTestFile("test.png"); err != nil {
   382  		t.Fatal(err)
   383  	} else {
   384  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   385  		CheckNoError(t, resp)
   386  
   387  		fileId = fileResp.FileInfos[0].Id
   388  	}
   389  
   390  	// Wait a bit for files to ready
   391  	time.Sleep(2 * time.Second)
   392  
   393  	data, resp := Client.GetFileThumbnail(fileId)
   394  	CheckNoError(t, resp)
   395  
   396  	if len(data) == 0 {
   397  		t.Fatal("should not be empty")
   398  	}
   399  
   400  	_, resp = Client.GetFileThumbnail("junk")
   401  	CheckBadRequestStatus(t, resp)
   402  
   403  	_, resp = Client.GetFileThumbnail(model.NewId())
   404  	CheckNotFoundStatus(t, resp)
   405  
   406  	Client.Logout()
   407  	_, resp = Client.GetFileThumbnail(fileId)
   408  	CheckUnauthorizedStatus(t, resp)
   409  
   410  	otherUser := th.CreateUser()
   411  	Client.Login(otherUser.Email, otherUser.Password)
   412  	_, resp = Client.GetFileThumbnail(fileId)
   413  	CheckForbiddenStatus(t, resp)
   414  
   415  	Client.Logout()
   416  	_, resp = th.SystemAdminClient.GetFileThumbnail(fileId)
   417  	CheckNoError(t, resp)
   418  }
   419  
   420  func TestGetFileLink(t *testing.T) {
   421  	th := Setup().InitBasic().InitSystemAdmin()
   422  	defer th.TearDown()
   423  	Client := th.Client
   424  	channel := th.BasicChannel
   425  
   426  	if *th.App.Config().FileSettings.DriverName == "" {
   427  		t.Skip("skipping because no file driver is enabled")
   428  	}
   429  
   430  	enablePublicLink := th.App.Config().FileSettings.EnablePublicLink
   431  	publicLinkSalt := *th.App.Config().FileSettings.PublicLinkSalt
   432  	defer func() {
   433  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = enablePublicLink })
   434  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = publicLinkSalt })
   435  	}()
   436  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   437  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = model.NewId() })
   438  
   439  	fileId := ""
   440  	if data, err := readTestFile("test.png"); err != nil {
   441  		t.Fatal(err)
   442  	} else {
   443  		fileResp, resp := Client.UploadFile(data, channel.Id, "test.png")
   444  		CheckNoError(t, resp)
   445  
   446  		fileId = fileResp.FileInfos[0].Id
   447  	}
   448  
   449  	link, resp := Client.GetFileLink(fileId)
   450  	CheckBadRequestStatus(t, resp)
   451  
   452  	// Hacky way to assign file to a post (usually would be done by CreatePost call)
   453  	store.Must(th.App.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
   454  
   455  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = false })
   456  	_, resp = Client.GetFileLink(fileId)
   457  	CheckNotImplementedStatus(t, resp)
   458  
   459  	// Wait a bit for files to ready
   460  	time.Sleep(2 * time.Second)
   461  
   462  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   463  	link, resp = Client.GetFileLink(fileId)
   464  	CheckNoError(t, resp)
   465  	if link == "" {
   466  		t.Fatal("should've received public link")
   467  	}
   468  
   469  	_, resp = Client.GetFileLink("junk")
   470  	CheckBadRequestStatus(t, resp)
   471  
   472  	_, resp = Client.GetFileLink(model.NewId())
   473  	CheckNotFoundStatus(t, resp)
   474  
   475  	Client.Logout()
   476  	_, resp = Client.GetFileLink(fileId)
   477  	CheckUnauthorizedStatus(t, resp)
   478  
   479  	otherUser := th.CreateUser()
   480  	Client.Login(otherUser.Email, otherUser.Password)
   481  	_, resp = Client.GetFileLink(fileId)
   482  	CheckForbiddenStatus(t, resp)
   483  
   484  	Client.Logout()
   485  	_, resp = th.SystemAdminClient.GetFileLink(fileId)
   486  	CheckNoError(t, resp)
   487  
   488  	if result := <-th.App.Srv.Store.FileInfo().Get(fileId); result.Err != nil {
   489  		t.Fatal(result.Err)
   490  	} else {
   491  		th.cleanupTestFile(result.Data.(*model.FileInfo))
   492  	}
   493  }
   494  
   495  func TestGetFilePreview(t *testing.T) {
   496  	th := Setup().InitBasic().InitSystemAdmin()
   497  	defer th.TearDown()
   498  	Client := th.Client
   499  	channel := th.BasicChannel
   500  
   501  	if *th.App.Config().FileSettings.DriverName == "" {
   502  		t.Skip("skipping because no file driver is enabled")
   503  	}
   504  
   505  	fileId := ""
   506  	var sent []byte
   507  	var err error
   508  	if sent, err = readTestFile("test.png"); err != nil {
   509  		t.Fatal(err)
   510  	} else {
   511  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   512  		CheckNoError(t, resp)
   513  
   514  		fileId = fileResp.FileInfos[0].Id
   515  	}
   516  
   517  	// Wait a bit for files to ready
   518  	time.Sleep(2 * time.Second)
   519  
   520  	data, resp := Client.GetFilePreview(fileId)
   521  	CheckNoError(t, resp)
   522  
   523  	if len(data) == 0 {
   524  		t.Fatal("should not be empty")
   525  	}
   526  
   527  	_, resp = Client.GetFilePreview("junk")
   528  	CheckBadRequestStatus(t, resp)
   529  
   530  	_, resp = Client.GetFilePreview(model.NewId())
   531  	CheckNotFoundStatus(t, resp)
   532  
   533  	Client.Logout()
   534  	_, resp = Client.GetFilePreview(fileId)
   535  	CheckUnauthorizedStatus(t, resp)
   536  
   537  	otherUser := th.CreateUser()
   538  	Client.Login(otherUser.Email, otherUser.Password)
   539  	_, resp = Client.GetFilePreview(fileId)
   540  	CheckForbiddenStatus(t, resp)
   541  
   542  	Client.Logout()
   543  	_, resp = th.SystemAdminClient.GetFilePreview(fileId)
   544  	CheckNoError(t, resp)
   545  }
   546  
   547  func TestGetFileInfo(t *testing.T) {
   548  	th := Setup().InitBasic().InitSystemAdmin()
   549  	defer th.TearDown()
   550  	Client := th.Client
   551  	user := th.BasicUser
   552  	channel := th.BasicChannel
   553  
   554  	if *th.App.Config().FileSettings.DriverName == "" {
   555  		t.Skip("skipping because no file driver is enabled")
   556  	}
   557  
   558  	fileId := ""
   559  	var sent []byte
   560  	var err error
   561  	if sent, err = readTestFile("test.png"); err != nil {
   562  		t.Fatal(err)
   563  	} else {
   564  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   565  		CheckNoError(t, resp)
   566  
   567  		fileId = fileResp.FileInfos[0].Id
   568  	}
   569  
   570  	// Wait a bit for files to ready
   571  	time.Sleep(2 * time.Second)
   572  
   573  	info, resp := Client.GetFileInfo(fileId)
   574  	CheckNoError(t, resp)
   575  
   576  	if err != nil {
   577  		t.Fatal(err)
   578  	} else if info.Id != fileId {
   579  		t.Fatal("got incorrect file")
   580  	} else if info.CreatorId != user.Id {
   581  		t.Fatal("file should be assigned to user")
   582  	} else if info.PostId != "" {
   583  		t.Fatal("file shouldn't have a post")
   584  	} else if info.Path != "" {
   585  		t.Fatal("file path shouldn't have been returned to client")
   586  	} else if info.ThumbnailPath != "" {
   587  		t.Fatal("file thumbnail path shouldn't have been returned to client")
   588  	} else if info.PreviewPath != "" {
   589  		t.Fatal("file preview path shouldn't have been returned to client")
   590  	} else if info.MimeType != "image/png" {
   591  		t.Fatal("mime type should've been image/png")
   592  	}
   593  
   594  	_, resp = Client.GetFileInfo("junk")
   595  	CheckBadRequestStatus(t, resp)
   596  
   597  	_, resp = Client.GetFileInfo(model.NewId())
   598  	CheckNotFoundStatus(t, resp)
   599  
   600  	Client.Logout()
   601  	_, resp = Client.GetFileInfo(fileId)
   602  	CheckUnauthorizedStatus(t, resp)
   603  
   604  	otherUser := th.CreateUser()
   605  	Client.Login(otherUser.Email, otherUser.Password)
   606  	_, resp = Client.GetFileInfo(fileId)
   607  	CheckForbiddenStatus(t, resp)
   608  
   609  	Client.Logout()
   610  	_, resp = th.SystemAdminClient.GetFileInfo(fileId)
   611  	CheckNoError(t, resp)
   612  }
   613  
   614  func TestGetPublicFile(t *testing.T) {
   615  	th := Setup().InitBasic().InitSystemAdmin()
   616  	defer th.TearDown()
   617  	Client := th.Client
   618  	channel := th.BasicChannel
   619  
   620  	if *th.App.Config().FileSettings.DriverName == "" {
   621  		t.Skip("skipping because no file driver is enabled")
   622  	}
   623  
   624  	enablePublicLink := th.App.Config().FileSettings.EnablePublicLink
   625  	publicLinkSalt := *th.App.Config().FileSettings.PublicLinkSalt
   626  	defer func() {
   627  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = enablePublicLink })
   628  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = publicLinkSalt })
   629  	}()
   630  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   631  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   632  
   633  	fileId := ""
   634  	if data, err := readTestFile("test.png"); err != nil {
   635  		t.Fatal(err)
   636  	} else {
   637  		fileResp, resp := Client.UploadFile(data, channel.Id, "test.png")
   638  		CheckNoError(t, resp)
   639  
   640  		fileId = fileResp.FileInfos[0].Id
   641  	}
   642  
   643  	// Hacky way to assign file to a post (usually would be done by CreatePost call)
   644  	store.Must(th.App.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
   645  
   646  	result := <-th.App.Srv.Store.FileInfo().Get(fileId)
   647  	info := result.Data.(*model.FileInfo)
   648  	link := th.App.GeneratePublicLink(Client.Url, info)
   649  
   650  	// Wait a bit for files to ready
   651  	time.Sleep(2 * time.Second)
   652  
   653  	if resp, err := http.Get(link); err != nil || resp.StatusCode != http.StatusOK {
   654  		t.Log(link)
   655  		t.Fatal("failed to get image with public link", err)
   656  	}
   657  
   658  	if resp, err := http.Get(link[:strings.LastIndex(link, "?")]); err == nil && resp.StatusCode != http.StatusBadRequest {
   659  		t.Fatal("should've failed to get image with public link without hash", resp.Status)
   660  	}
   661  
   662  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = false })
   663  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusNotImplemented {
   664  		t.Fatal("should've failed to get image with disabled public link")
   665  	}
   666  
   667  	// test after the salt has changed
   668  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   669  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   670  
   671  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   672  		t.Fatal("should've failed to get image with public link after salt changed")
   673  	}
   674  
   675  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   676  		t.Fatal("should've failed to get image with public link after salt changed")
   677  	}
   678  
   679  	if err := th.cleanupTestFile(store.Must(th.App.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
   680  		t.Fatal(err)
   681  	}
   682  
   683  	th.cleanupTestFile(info)
   684  }