github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/file_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 "github.com/mattermost/mattermost-server/v5/model" 17 "github.com/mattermost/mattermost-server/v5/utils/fileutils" 18 ) 19 20 func TestGeneratePublicLinkHash(t *testing.T) { 21 filename1 := model.NewId() + "/" + model.NewRandomString(16) + ".txt" 22 filename2 := model.NewId() + "/" + model.NewRandomString(16) + ".txt" 23 salt1 := model.NewRandomString(32) 24 salt2 := model.NewRandomString(32) 25 26 hash1 := GeneratePublicLinkHash(filename1, salt1) 27 hash2 := GeneratePublicLinkHash(filename2, salt1) 28 hash3 := GeneratePublicLinkHash(filename1, salt2) 29 30 hash := GeneratePublicLinkHash(filename1, salt1) 31 assert.Equal(t, hash, hash1, "hash should be equal for the same file name and salt") 32 33 assert.NotEqual(t, hash1, hash2, "hashes for different files should not be equal") 34 35 assert.NotEqual(t, hash1, hash3, "hashes for the same file with different salts should not be equal") 36 } 37 38 func TestDoUploadFile(t *testing.T) { 39 th := Setup(t) 40 defer th.TearDown() 41 42 teamId := model.NewId() 43 channelId := model.NewId() 44 userId := model.NewId() 45 filename := "test" 46 data := []byte("abcd") 47 48 info1, err := th.App.DoUploadFile(time.Date(2007, 2, 4, 1, 2, 3, 4, time.Local), teamId, channelId, userId, filename, data) 49 require.Nil(t, err, "DoUploadFile should succeed with valid data") 50 defer func() { 51 th.App.Srv().Store.FileInfo().PermanentDelete(info1.Id) 52 th.App.RemoveFile(info1.Path) 53 }() 54 55 value := fmt.Sprintf("20070204/teams/%v/channels/%v/users/%v/%v/%v", teamId, channelId, userId, info1.Id, filename) 56 assert.Equal(t, value, info1.Path, "stored file at incorrect path") 57 58 info2, err := th.App.DoUploadFile(time.Date(2007, 2, 4, 1, 2, 3, 4, time.Local), teamId, channelId, userId, filename, data) 59 require.Nil(t, err, "DoUploadFile should succeed with valid data") 60 defer func() { 61 th.App.Srv().Store.FileInfo().PermanentDelete(info2.Id) 62 th.App.RemoveFile(info2.Path) 63 }() 64 65 value = fmt.Sprintf("20070204/teams/%v/channels/%v/users/%v/%v/%v", teamId, channelId, userId, info2.Id, filename) 66 assert.Equal(t, value, info2.Path, "stored file at incorrect path") 67 68 info3, err := th.App.DoUploadFile(time.Date(2008, 3, 5, 1, 2, 3, 4, time.Local), teamId, channelId, userId, filename, data) 69 require.Nil(t, err, "DoUploadFile should succeed with valid data") 70 defer func() { 71 th.App.Srv().Store.FileInfo().PermanentDelete(info3.Id) 72 th.App.RemoveFile(info3.Path) 73 }() 74 75 value = fmt.Sprintf("20080305/teams/%v/channels/%v/users/%v/%v/%v", teamId, channelId, userId, info3.Id, filename) 76 assert.Equal(t, value, info3.Path, "stored file at incorrect path") 77 78 info4, err := th.App.DoUploadFile(time.Date(2009, 3, 5, 1, 2, 3, 4, time.Local), "../../"+teamId, "../../"+channelId, "../../"+userId, "../../"+filename, data) 79 require.Nil(t, err, "DoUploadFile should succeed with valid data") 80 defer func() { 81 th.App.Srv().Store.FileInfo().PermanentDelete(info4.Id) 82 th.App.RemoveFile(info4.Path) 83 }() 84 85 value = fmt.Sprintf("20090305/teams/%v/channels/%v/users/%v/%v/%v", teamId, channelId, userId, info4.Id, filename) 86 assert.Equal(t, value, info4.Path, "stored file at incorrect path") 87 } 88 89 func TestUploadFile(t *testing.T) { 90 th := Setup(t).InitBasic() 91 defer th.TearDown() 92 93 channelId := th.BasicChannel.Id 94 filename := "test" 95 data := []byte("abcd") 96 97 info1, err := th.App.UploadFile(data, "wrong", filename) 98 require.Error(t, err, "Wrong Channel ID.") 99 require.Nil(t, info1, "Channel ID does not exist.") 100 101 info1, err = th.App.UploadFile(data, "", filename) 102 require.Nil(t, err, "empty channel IDs should be valid") 103 104 info1, err = th.App.UploadFile(data, channelId, filename) 105 require.Nil(t, err, "UploadFile should succeed with valid data") 106 defer func() { 107 th.App.Srv().Store.FileInfo().PermanentDelete(info1.Id) 108 th.App.RemoveFile(info1.Path) 109 }() 110 111 value := fmt.Sprintf("%v/teams/noteam/channels/%v/users/nouser/%v/%v", 112 time.Now().Format("20060102"), channelId, info1.Id, filename) 113 assert.Equal(t, value, info1.Path, "Stored file at incorrect path") 114 } 115 116 func TestParseOldFilenames(t *testing.T) { 117 th := Setup(t).InitBasic() 118 defer th.TearDown() 119 120 fileId := model.NewId() 121 122 tests := []struct { 123 description string 124 filenames []string 125 channelId string 126 userId string 127 expected [][]string 128 }{ 129 { 130 description: "Empty input should result in empty output", 131 filenames: []string{}, 132 channelId: th.BasicChannel.Id, 133 userId: th.BasicUser.Id, 134 expected: [][]string{}, 135 }, 136 { 137 description: "Filename with invalid format should not parse", 138 filenames: []string{"/path/to/some/file.png"}, 139 channelId: th.BasicChannel.Id, 140 userId: th.BasicUser.Id, 141 expected: [][]string{}, 142 }, 143 { 144 description: "ChannelId in Filename should not match", 145 filenames: []string{ 146 fmt.Sprintf("/%v/%v/%v/file.png", model.NewId(), th.BasicUser.Id, fileId), 147 }, 148 channelId: th.BasicChannel.Id, 149 userId: th.BasicUser.Id, 150 expected: [][]string{}, 151 }, 152 { 153 description: "UserId in Filename should not match", 154 filenames: []string{ 155 fmt.Sprintf("/%v/%v/%v/file.png", th.BasicChannel.Id, model.NewId(), fileId), 156 }, 157 channelId: th.BasicChannel.Id, 158 userId: th.BasicUser.Id, 159 expected: [][]string{}, 160 }, 161 { 162 description: "../ in filename should not parse", 163 filenames: []string{ 164 fmt.Sprintf("/%v/%v/%v/../../../file.png", th.BasicChannel.Id, th.BasicUser.Id, fileId), 165 }, 166 channelId: th.BasicChannel.Id, 167 userId: th.BasicUser.Id, 168 expected: [][]string{}, 169 }, 170 { 171 description: "Should only parse valid filenames", 172 filenames: []string{ 173 fmt.Sprintf("/%v/%v/%v/../otherfile.png", th.BasicChannel.Id, th.BasicUser.Id, fileId), 174 fmt.Sprintf("/%v/%v/%v/file.png", th.BasicChannel.Id, th.BasicUser.Id, fileId), 175 }, 176 channelId: th.BasicChannel.Id, 177 userId: th.BasicUser.Id, 178 expected: [][]string{ 179 { 180 th.BasicChannel.Id, 181 th.BasicUser.Id, 182 fileId, 183 "file.png", 184 }, 185 }, 186 }, 187 { 188 description: "Valid Filename should parse", 189 filenames: []string{ 190 fmt.Sprintf("/%v/%v/%v/file.png", th.BasicChannel.Id, th.BasicUser.Id, fileId), 191 }, 192 channelId: th.BasicChannel.Id, 193 userId: th.BasicUser.Id, 194 expected: [][]string{ 195 { 196 th.BasicChannel.Id, 197 th.BasicUser.Id, 198 fileId, 199 "file.png", 200 }, 201 }, 202 }, 203 } 204 205 for _, test := range tests { 206 t.Run(test.description, func(tt *testing.T) { 207 result := parseOldFilenames(test.filenames, test.channelId, test.userId) 208 require.Equal(tt, result, test.expected) 209 }) 210 } 211 } 212 213 func TestGetInfoForFilename(t *testing.T) { 214 th := Setup(t).InitBasic() 215 defer th.TearDown() 216 217 post := th.BasicPost 218 teamId := th.BasicTeam.Id 219 220 info := th.App.getInfoForFilename(post, teamId, post.ChannelId, post.UserId, "someid", "somefile.png") 221 assert.Nil(t, info, "Test non-existent file") 222 } 223 224 func TestFindTeamIdForFilename(t *testing.T) { 225 th := Setup(t).InitBasic() 226 defer th.TearDown() 227 228 teamId := th.App.findTeamIdForFilename(th.BasicPost, "someid", "somefile.png") 229 assert.Equal(t, th.BasicTeam.Id, teamId) 230 231 _, err := th.App.CreateTeamWithUser(&model.Team{Email: th.BasicUser.Email, Name: "zz" + model.NewId(), DisplayName: "Joram's Test Team", Type: model.TEAM_OPEN}, th.BasicUser.Id) 232 require.Nil(t, err) 233 234 teamId = th.App.findTeamIdForFilename(th.BasicPost, "someid", "somefile.png") 235 assert.Equal(t, "", teamId) 236 } 237 238 func TestMigrateFilenamesToFileInfos(t *testing.T) { 239 th := Setup(t).InitBasic() 240 defer th.TearDown() 241 242 post := th.BasicPost 243 infos := th.App.MigrateFilenamesToFileInfos(post) 244 assert.Equal(t, 0, len(infos)) 245 246 post.Filenames = []string{fmt.Sprintf("/%v/%v/%v/blargh.png", th.BasicChannel.Id, th.BasicUser.Id, "someid")} 247 infos = th.App.MigrateFilenamesToFileInfos(post) 248 assert.Equal(t, 0, len(infos)) 249 250 path, _ := fileutils.FindDir("tests") 251 file, fileErr := os.Open(filepath.Join(path, "test.png")) 252 require.Nil(t, fileErr) 253 defer file.Close() 254 255 fileId := model.NewId() 256 fpath := fmt.Sprintf("/teams/%v/channels/%v/users/%v/%v/test.png", th.BasicTeam.Id, th.BasicChannel.Id, th.BasicUser.Id, fileId) 257 _, err := th.App.WriteFile(file, fpath) 258 require.Nil(t, err) 259 rpost, err := th.App.CreatePost(&model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/test.png", th.BasicChannel.Id, th.BasicUser.Id, fileId)}}, th.BasicChannel, false, true) 260 require.Nil(t, err) 261 262 infos = th.App.MigrateFilenamesToFileInfos(rpost) 263 assert.Equal(t, 1, len(infos)) 264 265 rpost, err = th.App.CreatePost(&model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/../../test.png", th.BasicChannel.Id, th.BasicUser.Id, fileId)}}, th.BasicChannel, false, true) 266 require.Nil(t, err) 267 268 infos = th.App.MigrateFilenamesToFileInfos(rpost) 269 assert.Equal(t, 0, len(infos)) 270 } 271 272 func TestCopyFileInfos(t *testing.T) { 273 th := Setup(t) 274 defer th.TearDown() 275 276 teamId := model.NewId() 277 channelId := model.NewId() 278 userId := model.NewId() 279 filename := "test" 280 data := []byte("abcd") 281 282 info1, err := th.App.DoUploadFile(time.Date(2007, 2, 4, 1, 2, 3, 4, time.Local), teamId, channelId, userId, filename, data) 283 require.Nil(t, err) 284 defer func() { 285 th.App.Srv().Store.FileInfo().PermanentDelete(info1.Id) 286 th.App.RemoveFile(info1.Path) 287 }() 288 289 infoIds, err := th.App.CopyFileInfos(userId, []string{info1.Id}) 290 require.Nil(t, err) 291 292 info2, err := th.App.GetFileInfo(infoIds[0]) 293 require.Nil(t, err) 294 defer func() { 295 th.App.Srv().Store.FileInfo().PermanentDelete(info2.Id) 296 th.App.RemoveFile(info2.Path) 297 }() 298 299 assert.NotEqual(t, info1.Id, info2.Id, "should not be equal") 300 assert.Equal(t, info2.PostId, "", "should be empty string") 301 }