From 51dc5fa36ed2d5afa72bf630d66693bd99acb916 Mon Sep 17 00:00:00 2001 From: Saturnino Abril Date: Sat, 28 Jul 2018 14:27:55 +0800 Subject: [MM-10621] Set createAt timestamp on file upload api call to secure upload order of files (#9170) * set createAt timestamp on file upload api call to secure upload order of files * fix test on plugin hooks --- api4/file.go | 12 +++++++++++- app/file.go | 9 +++++---- app/plugin_hooks_test.go | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/api4/file.go b/api4/file.go index 3c0944b89..f73a54fb4 100644 --- a/api4/file.go +++ b/api4/file.go @@ -10,6 +10,7 @@ import ( "net/url" "strconv" "strings" + "time" "github.com/mattermost/mattermost-server/app" "github.com/mattermost/mattermost-server/model" @@ -69,6 +70,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) { return } + now := time.Now() var resStruct *model.FileUploadResponse var appErr *model.AppError @@ -100,6 +102,7 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) { []io.ReadCloser{r.Body}, []string{filename}, []string{}, + now, ) } else { m := r.MultipartForm @@ -120,7 +123,14 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) { return } - resStruct, appErr = c.App.UploadMultipartFiles(FILE_TEAM_ID, channelId, c.Session.UserId, m.File["files"], m.Value["client_ids"]) + resStruct, appErr = c.App.UploadMultipartFiles( + FILE_TEAM_ID, + channelId, + c.Session.UserId, + m.File["files"], + m.Value["client_ids"], + now, + ) } if appErr != nil { diff --git a/app/file.go b/app/file.go index b0c80da16..7dbcdd394 100644 --- a/app/file.go +++ b/app/file.go @@ -321,7 +321,7 @@ func GeneratePublicLinkHash(fileId, salt string) string { return base64.RawURLEncoding.EncodeToString(hash.Sum(nil)) } -func (a *App) UploadMultipartFiles(teamId string, channelId string, userId string, fileHeaders []*multipart.FileHeader, clientIds []string) (*model.FileUploadResponse, *model.AppError) { +func (a *App) UploadMultipartFiles(teamId string, channelId string, userId string, fileHeaders []*multipart.FileHeader, clientIds []string, now time.Time) (*model.FileUploadResponse, *model.AppError) { files := make([]io.ReadCloser, len(fileHeaders)) filenames := make([]string, len(fileHeaders)) @@ -338,13 +338,13 @@ func (a *App) UploadMultipartFiles(teamId string, channelId string, userId strin filenames[i] = fileHeader.Filename } - return a.UploadFiles(teamId, channelId, userId, files, filenames, clientIds) + return a.UploadFiles(teamId, channelId, userId, files, filenames, clientIds, now) } // Uploads some files to the given team and channel as the given user. files and filenames should have // the same length. clientIds should either not be provided or have the same length as files and filenames. // The provided files should be closed by the caller so that they are not leaked. -func (a *App) UploadFiles(teamId string, channelId string, userId string, files []io.ReadCloser, filenames []string, clientIds []string) (*model.FileUploadResponse, *model.AppError) { +func (a *App) UploadFiles(teamId string, channelId string, userId string, files []io.ReadCloser, filenames []string, clientIds []string, now time.Time) (*model.FileUploadResponse, *model.AppError) { if len(*a.Config().FileSettings.DriverName) == 0 { return nil, model.NewAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "", http.StatusNotImplemented) } @@ -367,7 +367,7 @@ func (a *App) UploadFiles(teamId string, channelId string, userId string, files io.Copy(buf, file) data := buf.Bytes() - info, data, err := a.DoUploadFileExpectModification(time.Now(), teamId, channelId, userId, filenames[i], data) + info, data, err := a.DoUploadFileExpectModification(now, teamId, channelId, userId, filenames[i], data) if err != nil { return nil, err } @@ -417,6 +417,7 @@ func (a *App) DoUploadFileExpectModification(now time.Time, rawTeamId string, ra info.Id = model.NewId() info.CreatorId = userId + info.CreateAt = now.UnixNano() / int64(time.Millisecond) pathPrefix := now.Format("20060102") + "/teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/" + info.Id + "/" info.Path = pathPrefix + filename diff --git a/app/plugin_hooks_test.go b/app/plugin_hooks_test.go index 6e8434cab..488d81757 100644 --- a/app/plugin_hooks_test.go +++ b/app/plugin_hooks_test.go @@ -11,6 +11,7 @@ import ( "os/exec" "path/filepath" "testing" + "time" "github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/plugin" @@ -352,6 +353,7 @@ func TestHookFileWillBeUploaded(t *testing.T) { []io.ReadCloser{ioutil.NopCloser(bytes.NewBufferString("inputfile"))}, []string{"testhook.txt"}, []string{}, + time.Now(), ) assert.Nil(t, err) assert.NotNil(t, response) -- cgit v1.2.3-1-g7c22