github.com/turgay/mattermost-server@v5.3.2-0.20181002173352-2945e8a2b0ce+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  	_, 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  
   466  	if link == "" {
   467  		t.Fatal("should've received public link")
   468  	}
   469  
   470  	_, resp = Client.GetFileLink("junk")
   471  	CheckBadRequestStatus(t, resp)
   472  
   473  	_, resp = Client.GetFileLink(model.NewId())
   474  	CheckNotFoundStatus(t, resp)
   475  
   476  	Client.Logout()
   477  	_, resp = Client.GetFileLink(fileId)
   478  	CheckUnauthorizedStatus(t, resp)
   479  
   480  	otherUser := th.CreateUser()
   481  	Client.Login(otherUser.Email, otherUser.Password)
   482  	_, resp = Client.GetFileLink(fileId)
   483  	CheckForbiddenStatus(t, resp)
   484  
   485  	Client.Logout()
   486  	_, resp = th.SystemAdminClient.GetFileLink(fileId)
   487  	CheckNoError(t, resp)
   488  
   489  	if result := <-th.App.Srv.Store.FileInfo().Get(fileId); result.Err != nil {
   490  		t.Fatal(result.Err)
   491  	} else {
   492  		th.cleanupTestFile(result.Data.(*model.FileInfo))
   493  	}
   494  }
   495  
   496  func TestGetFilePreview(t *testing.T) {
   497  	th := Setup().InitBasic().InitSystemAdmin()
   498  	defer th.TearDown()
   499  	Client := th.Client
   500  	channel := th.BasicChannel
   501  
   502  	if *th.App.Config().FileSettings.DriverName == "" {
   503  		t.Skip("skipping because no file driver is enabled")
   504  	}
   505  
   506  	fileId := ""
   507  	var sent []byte
   508  	var err error
   509  	if sent, err = readTestFile("test.png"); err != nil {
   510  		t.Fatal(err)
   511  	} else {
   512  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   513  		CheckNoError(t, resp)
   514  
   515  		fileId = fileResp.FileInfos[0].Id
   516  	}
   517  
   518  	// Wait a bit for files to ready
   519  	time.Sleep(2 * time.Second)
   520  
   521  	data, resp := Client.GetFilePreview(fileId)
   522  	CheckNoError(t, resp)
   523  
   524  	if len(data) == 0 {
   525  		t.Fatal("should not be empty")
   526  	}
   527  
   528  	_, resp = Client.GetFilePreview("junk")
   529  	CheckBadRequestStatus(t, resp)
   530  
   531  	_, resp = Client.GetFilePreview(model.NewId())
   532  	CheckNotFoundStatus(t, resp)
   533  
   534  	Client.Logout()
   535  	_, resp = Client.GetFilePreview(fileId)
   536  	CheckUnauthorizedStatus(t, resp)
   537  
   538  	otherUser := th.CreateUser()
   539  	Client.Login(otherUser.Email, otherUser.Password)
   540  	_, resp = Client.GetFilePreview(fileId)
   541  	CheckForbiddenStatus(t, resp)
   542  
   543  	Client.Logout()
   544  	_, resp = th.SystemAdminClient.GetFilePreview(fileId)
   545  	CheckNoError(t, resp)
   546  }
   547  
   548  func TestGetFileInfo(t *testing.T) {
   549  	th := Setup().InitBasic().InitSystemAdmin()
   550  	defer th.TearDown()
   551  	Client := th.Client
   552  	user := th.BasicUser
   553  	channel := th.BasicChannel
   554  
   555  	if *th.App.Config().FileSettings.DriverName == "" {
   556  		t.Skip("skipping because no file driver is enabled")
   557  	}
   558  
   559  	fileId := ""
   560  	var sent []byte
   561  	var err error
   562  	if sent, err = readTestFile("test.png"); err != nil {
   563  		t.Fatal(err)
   564  	} else {
   565  		fileResp, resp := Client.UploadFile(sent, channel.Id, "test.png")
   566  		CheckNoError(t, resp)
   567  
   568  		fileId = fileResp.FileInfos[0].Id
   569  	}
   570  
   571  	// Wait a bit for files to ready
   572  	time.Sleep(2 * time.Second)
   573  
   574  	info, resp := Client.GetFileInfo(fileId)
   575  	CheckNoError(t, resp)
   576  
   577  	if err != nil {
   578  		t.Fatal(err)
   579  	} else if info.Id != fileId {
   580  		t.Fatal("got incorrect file")
   581  	} else if info.CreatorId != user.Id {
   582  		t.Fatal("file should be assigned to user")
   583  	} else if info.PostId != "" {
   584  		t.Fatal("file shouldn't have a post")
   585  	} else if info.Path != "" {
   586  		t.Fatal("file path shouldn't have been returned to client")
   587  	} else if info.ThumbnailPath != "" {
   588  		t.Fatal("file thumbnail path shouldn't have been returned to client")
   589  	} else if info.PreviewPath != "" {
   590  		t.Fatal("file preview path shouldn't have been returned to client")
   591  	} else if info.MimeType != "image/png" {
   592  		t.Fatal("mime type should've been image/png")
   593  	}
   594  
   595  	_, resp = Client.GetFileInfo("junk")
   596  	CheckBadRequestStatus(t, resp)
   597  
   598  	_, resp = Client.GetFileInfo(model.NewId())
   599  	CheckNotFoundStatus(t, resp)
   600  
   601  	Client.Logout()
   602  	_, resp = Client.GetFileInfo(fileId)
   603  	CheckUnauthorizedStatus(t, resp)
   604  
   605  	otherUser := th.CreateUser()
   606  	Client.Login(otherUser.Email, otherUser.Password)
   607  	_, resp = Client.GetFileInfo(fileId)
   608  	CheckForbiddenStatus(t, resp)
   609  
   610  	Client.Logout()
   611  	_, resp = th.SystemAdminClient.GetFileInfo(fileId)
   612  	CheckNoError(t, resp)
   613  }
   614  
   615  func TestGetPublicFile(t *testing.T) {
   616  	th := Setup().InitBasic().InitSystemAdmin()
   617  	defer th.TearDown()
   618  	Client := th.Client
   619  	channel := th.BasicChannel
   620  
   621  	if *th.App.Config().FileSettings.DriverName == "" {
   622  		t.Skip("skipping because no file driver is enabled")
   623  	}
   624  
   625  	enablePublicLink := th.App.Config().FileSettings.EnablePublicLink
   626  	publicLinkSalt := *th.App.Config().FileSettings.PublicLinkSalt
   627  	defer func() {
   628  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = enablePublicLink })
   629  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = publicLinkSalt })
   630  	}()
   631  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   632  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   633  
   634  	fileId := ""
   635  	if data, err := readTestFile("test.png"); err != nil {
   636  		t.Fatal(err)
   637  	} else {
   638  		fileResp, resp := Client.UploadFile(data, channel.Id, "test.png")
   639  		CheckNoError(t, resp)
   640  
   641  		fileId = fileResp.FileInfos[0].Id
   642  	}
   643  
   644  	// Hacky way to assign file to a post (usually would be done by CreatePost call)
   645  	store.Must(th.App.Srv.Store.FileInfo().AttachToPost(fileId, th.BasicPost.Id))
   646  
   647  	result := <-th.App.Srv.Store.FileInfo().Get(fileId)
   648  	info := result.Data.(*model.FileInfo)
   649  	link := th.App.GeneratePublicLink(Client.Url, info)
   650  
   651  	// Wait a bit for files to ready
   652  	time.Sleep(2 * time.Second)
   653  
   654  	if resp, err := http.Get(link); err != nil || resp.StatusCode != http.StatusOK {
   655  		t.Log(link)
   656  		t.Fatal("failed to get image with public link", err)
   657  	}
   658  
   659  	if resp, err := http.Get(link[:strings.LastIndex(link, "?")]); err == nil && resp.StatusCode != http.StatusBadRequest {
   660  		t.Fatal("should've failed to get image with public link without hash", resp.Status)
   661  	}
   662  
   663  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = false })
   664  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusNotImplemented {
   665  		t.Fatal("should've failed to get image with disabled public link")
   666  	}
   667  
   668  	// test after the salt has changed
   669  	th.App.UpdateConfig(func(cfg *model.Config) { cfg.FileSettings.EnablePublicLink = true })
   670  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.PublicLinkSalt = GenerateTestId() })
   671  
   672  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   673  		t.Fatal("should've failed to get image with public link after salt changed")
   674  	}
   675  
   676  	if resp, err := http.Get(link); err == nil && resp.StatusCode != http.StatusBadRequest {
   677  		t.Fatal("should've failed to get image with public link after salt changed")
   678  	}
   679  
   680  	if err := th.cleanupTestFile(store.Must(th.App.Srv.Store.FileInfo().Get(fileId)).(*model.FileInfo)); err != nil {
   681  		t.Fatal(err)
   682  	}
   683  
   684  	th.cleanupTestFile(info)
   685  }