github.com/mattermost/mattermost-server/v5@v5.39.3/api4/upload_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "io" 9 "mime/multipart" 10 "net/http" 11 "os" 12 "testing" 13 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 TestCreateUpload(t *testing.T) { 21 th := Setup(t).InitBasic() 22 defer th.TearDown() 23 24 us := &model.UploadSession{ 25 ChannelId: th.BasicChannel.Id, 26 Filename: "upload", 27 FileSize: 8 * 1024 * 1024, 28 } 29 30 t.Run("file attachments disabled", func(t *testing.T) { 31 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false }) 32 defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = true }) 33 u, resp := th.Client.CreateUpload(us) 34 require.Nil(t, u) 35 require.NotNil(t, resp.Error) 36 require.Equal(t, "api.file.attachments.disabled.app_error", resp.Error.Id) 37 require.Equal(t, http.StatusNotImplemented, resp.StatusCode) 38 }) 39 40 t.Run("no permissions", func(t *testing.T) { 41 us.ChannelId = th.BasicPrivateChannel2.Id 42 u, resp := th.Client.CreateUpload(us) 43 require.Nil(t, u) 44 require.NotNil(t, resp.Error) 45 require.Equal(t, "api.context.permissions.app_error", resp.Error.Id) 46 require.Equal(t, http.StatusForbidden, resp.StatusCode) 47 }) 48 49 t.Run("valid", func(t *testing.T) { 50 us.ChannelId = th.BasicChannel.Id 51 u, resp := th.Client.CreateUpload(us) 52 require.Nil(t, resp.Error) 53 require.NotEmpty(t, u) 54 require.Equal(t, http.StatusCreated, resp.StatusCode) 55 }) 56 57 t.Run("import file", func(t *testing.T) { 58 testsDir, _ := fileutils.FindDir("tests") 59 60 importFile, err := os.Open(testsDir + "/import_test.zip") 61 require.NoError(t, err) 62 defer importFile.Close() 63 64 info, err := importFile.Stat() 65 require.NoError(t, err) 66 67 t.Run("permissions error", func(t *testing.T) { 68 us := &model.UploadSession{ 69 Filename: info.Name(), 70 FileSize: info.Size(), 71 Type: model.UploadTypeImport, 72 } 73 u, resp := th.Client.CreateUpload(us) 74 require.Nil(t, u) 75 require.NotNil(t, resp.Error) 76 require.Equal(t, "api.context.permissions.app_error", resp.Error.Id) 77 require.Equal(t, http.StatusForbidden, resp.StatusCode) 78 }) 79 80 t.Run("success", func(t *testing.T) { 81 us := &model.UploadSession{ 82 Filename: info.Name(), 83 FileSize: info.Size(), 84 Type: model.UploadTypeImport, 85 } 86 u, resp := th.SystemAdminClient.CreateUpload(us) 87 require.Nil(t, resp.Error) 88 require.NotEmpty(t, u) 89 }) 90 }) 91 } 92 93 func TestGetUpload(t *testing.T) { 94 th := Setup(t).InitBasic() 95 defer th.TearDown() 96 97 us := &model.UploadSession{ 98 Id: model.NewId(), 99 Type: model.UploadTypeAttachment, 100 CreateAt: model.GetMillis(), 101 UserId: th.BasicUser2.Id, 102 ChannelId: th.BasicChannel.Id, 103 Filename: "upload", 104 FileSize: 8 * 1024 * 1024, 105 } 106 us, err := th.App.CreateUploadSession(us) 107 require.Nil(t, err) 108 require.NotNil(t, us) 109 require.NotEmpty(t, us) 110 111 t.Run("upload not found", func(t *testing.T) { 112 u, resp := th.Client.GetUpload(model.NewId()) 113 require.Nil(t, u) 114 require.NotNil(t, resp.Error) 115 require.Equal(t, "app.upload.get.app_error", resp.Error.Id) 116 require.Equal(t, http.StatusNotFound, resp.StatusCode) 117 }) 118 119 t.Run("no permissions", func(t *testing.T) { 120 u, resp := th.Client.GetUpload(us.Id) 121 require.Nil(t, u) 122 require.NotNil(t, resp.Error) 123 require.Equal(t, "api.upload.get_upload.forbidden.app_error", resp.Error.Id) 124 }) 125 126 t.Run("success", func(t *testing.T) { 127 expected, resp := th.Client.CreateUpload(us) 128 require.Nil(t, resp.Error) 129 require.NotEmpty(t, expected) 130 require.Equal(t, http.StatusCreated, resp.StatusCode) 131 132 u, resp := th.Client.GetUpload(expected.Id) 133 require.Nil(t, resp.Error) 134 require.NotEmpty(t, u) 135 require.Equal(t, expected, u) 136 }) 137 } 138 139 func TestGetUploadsForUser(t *testing.T) { 140 th := Setup(t).InitBasic() 141 defer th.TearDown() 142 143 t.Run("no permissions", func(t *testing.T) { 144 uss, resp := th.Client.GetUploadsForUser(th.BasicUser2.Id) 145 require.NotNil(t, resp.Error) 146 require.Equal(t, "api.user.get_uploads_for_user.forbidden.app_error", resp.Error.Id) 147 require.Nil(t, uss) 148 }) 149 150 t.Run("empty", func(t *testing.T) { 151 uss, resp := th.Client.GetUploadsForUser(th.BasicUser.Id) 152 require.Nil(t, resp.Error) 153 require.Empty(t, uss) 154 }) 155 156 t.Run("success", func(t *testing.T) { 157 uploads := make([]*model.UploadSession, 4) 158 for i := 0; i < len(uploads); i++ { 159 us := &model.UploadSession{ 160 Id: model.NewId(), 161 Type: model.UploadTypeAttachment, 162 CreateAt: model.GetMillis(), 163 UserId: th.BasicUser.Id, 164 ChannelId: th.BasicChannel.Id, 165 Filename: "upload", 166 FileSize: 8 * 1024 * 1024, 167 } 168 us, err := th.App.CreateUploadSession(us) 169 require.Nil(t, err) 170 require.NotNil(t, us) 171 require.NotEmpty(t, us) 172 us.Path = "" 173 uploads[i] = us 174 } 175 176 uss, resp := th.Client.GetUploadsForUser(th.BasicUser.Id) 177 require.Nil(t, resp.Error) 178 require.NotEmpty(t, uss) 179 require.Len(t, uss, len(uploads)) 180 for i := range uploads { 181 require.Contains(t, uss, uploads[i]) 182 } 183 }) 184 } 185 186 func TestUploadData(t *testing.T) { 187 th := Setup(t).InitBasic() 188 defer th.TearDown() 189 if *th.App.Config().FileSettings.DriverName == "" { 190 t.Skip("skipping because no file driver is enabled") 191 } 192 193 us := &model.UploadSession{ 194 Id: model.NewId(), 195 Type: model.UploadTypeAttachment, 196 CreateAt: model.GetMillis(), 197 UserId: th.BasicUser2.Id, 198 ChannelId: th.BasicChannel.Id, 199 Filename: "upload", 200 FileSize: 8 * 1024 * 1024, 201 } 202 us, err := th.App.CreateUploadSession(us) 203 require.Nil(t, err) 204 require.NotNil(t, us) 205 require.NotEmpty(t, us) 206 207 data := randomBytes(t, int(us.FileSize)) 208 209 t.Run("file attachments disabled", func(t *testing.T) { 210 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = false }) 211 defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.FileSettings.EnableFileAttachments = true }) 212 info, resp := th.Client.UploadData(model.NewId(), bytes.NewReader(data)) 213 require.Nil(t, info) 214 require.NotNil(t, resp.Error) 215 require.Equal(t, "api.file.attachments.disabled.app_error", resp.Error.Id) 216 }) 217 218 t.Run("upload not found", func(t *testing.T) { 219 info, resp := th.Client.UploadData(model.NewId(), bytes.NewReader(data)) 220 require.Nil(t, info) 221 require.NotNil(t, resp.Error) 222 require.Equal(t, "app.upload.get.app_error", resp.Error.Id) 223 require.Equal(t, http.StatusNotFound, resp.StatusCode) 224 }) 225 226 t.Run("no permissions", func(t *testing.T) { 227 info, resp := th.Client.UploadData(us.Id, bytes.NewReader(data)) 228 require.Nil(t, info) 229 require.NotNil(t, resp.Error) 230 require.Equal(t, "api.context.permissions.app_error", resp.Error.Id) 231 }) 232 233 t.Run("bad content-length", func(t *testing.T) { 234 u, resp := th.Client.CreateUpload(us) 235 require.Nil(t, resp.Error) 236 require.NotEmpty(t, u) 237 require.Equal(t, http.StatusCreated, resp.StatusCode) 238 239 info, resp := th.Client.UploadData(u.Id, bytes.NewReader(append(data, 0x00))) 240 require.Nil(t, info) 241 require.NotNil(t, resp.Error) 242 require.Equal(t, "api.upload.upload_data.invalid_content_length", resp.Error.Id) 243 }) 244 245 t.Run("success", func(t *testing.T) { 246 u, resp := th.Client.CreateUpload(us) 247 require.Nil(t, resp.Error) 248 require.NotEmpty(t, u) 249 require.Equal(t, http.StatusCreated, resp.StatusCode) 250 251 info, resp := th.Client.UploadData(u.Id, bytes.NewReader(data)) 252 require.Nil(t, resp.Error) 253 require.NotEmpty(t, info) 254 require.Equal(t, u.Filename, info.Name) 255 256 file, resp := th.Client.GetFile(info.Id) 257 require.Nil(t, resp.Error) 258 require.Equal(t, file, data) 259 }) 260 261 t.Run("resume success", func(t *testing.T) { 262 u, resp := th.Client.CreateUpload(us) 263 require.Nil(t, resp.Error) 264 require.NotEmpty(t, u) 265 require.Equal(t, http.StatusCreated, resp.StatusCode) 266 267 rd := &io.LimitedReader{ 268 R: bytes.NewReader(data), 269 N: 5 * 1024 * 1024, 270 } 271 info, resp := th.Client.UploadData(u.Id, rd) 272 require.Nil(t, resp.Error) 273 require.Nil(t, info) 274 require.Equal(t, http.StatusNoContent, resp.StatusCode) 275 276 info, resp = th.Client.UploadData(u.Id, bytes.NewReader(data[5*1024*1024:])) 277 require.Nil(t, resp.Error) 278 require.NotEmpty(t, info) 279 require.Equal(t, u.Filename, info.Name) 280 281 file, resp := th.Client.GetFile(info.Id) 282 require.Nil(t, resp.Error) 283 require.Equal(t, file, data) 284 }) 285 } 286 287 func TestUploadDataMultipart(t *testing.T) { 288 th := Setup(t).InitBasic() 289 defer th.TearDown() 290 if *th.App.Config().FileSettings.DriverName == "" { 291 t.Skip("skipping because no file driver is enabled") 292 } 293 294 us := &model.UploadSession{ 295 Id: model.NewId(), 296 Type: model.UploadTypeAttachment, 297 CreateAt: model.GetMillis(), 298 UserId: th.BasicUser.Id, 299 ChannelId: th.BasicChannel.Id, 300 Filename: "upload", 301 FileSize: 8 * 1024 * 1024, 302 } 303 us, resp := th.Client.CreateUpload(us) 304 require.Nil(t, resp.Error) 305 require.NotNil(t, us) 306 require.NotEmpty(t, us) 307 308 data := randomBytes(t, int(us.FileSize)) 309 310 genMultipartData := func(t *testing.T, data []byte) (io.Reader, string) { 311 mpData := &bytes.Buffer{} 312 mpWriter := multipart.NewWriter(mpData) 313 part, err := mpWriter.CreateFormFile("data", us.Filename) 314 require.NoError(t, err) 315 n, err := part.Write(data) 316 require.NoError(t, err) 317 require.Equal(t, len(data), n) 318 err = mpWriter.Close() 319 require.NoError(t, err) 320 return mpData, mpWriter.FormDataContentType() 321 } 322 323 t.Run("bad content-type", func(t *testing.T) { 324 info, resp := th.Client.DoUploadFile("/uploads/"+us.Id, data, "multipart/form-data;") 325 require.Nil(t, info) 326 require.NotNil(t, resp.Error) 327 require.Equal(t, "api.upload.upload_data.invalid_content_type", resp.Error.Id) 328 }) 329 330 t.Run("success", func(t *testing.T) { 331 mpData, contentType := genMultipartData(t, data) 332 333 req, err := http.NewRequest("POST", th.Client.ApiUrl+"/uploads/"+us.Id, mpData) 334 require.NoError(t, err) 335 req.Header.Set("Content-Type", contentType) 336 req.Header.Set(model.HEADER_AUTH, th.Client.AuthType+" "+th.Client.AuthToken) 337 res, err := th.Client.HttpClient.Do(req) 338 require.NoError(t, err) 339 info := model.FileInfoFromJson(res.Body) 340 res.Body.Close() 341 require.NotEmpty(t, info) 342 require.Equal(t, us.Filename, info.Name) 343 344 file, resp := th.Client.GetFile(info.Id) 345 require.Nil(t, resp.Error) 346 require.Equal(t, file, data) 347 }) 348 349 t.Run("resume success", func(t *testing.T) { 350 mpData, contentType := genMultipartData(t, data[:5*1024*1024]) 351 352 u, resp := th.Client.CreateUpload(us) 353 require.Nil(t, resp.Error) 354 require.NotNil(t, u) 355 require.NotEmpty(t, u) 356 357 req, err := http.NewRequest("POST", th.Client.ApiUrl+"/uploads/"+u.Id, mpData) 358 require.NoError(t, err) 359 req.Header.Set("Content-Type", contentType) 360 req.Header.Set(model.HEADER_AUTH, th.Client.AuthType+" "+th.Client.AuthToken) 361 res, err := th.Client.HttpClient.Do(req) 362 require.NoError(t, err) 363 require.Equal(t, http.StatusNoContent, res.StatusCode) 364 require.Equal(t, int64(0), res.ContentLength) 365 366 mpData, contentType = genMultipartData(t, data[5*1024*1024:]) 367 368 req, err = http.NewRequest("POST", th.Client.ApiUrl+"/uploads/"+u.Id, mpData) 369 require.NoError(t, err) 370 req.Header.Set("Content-Type", contentType) 371 req.Header.Set(model.HEADER_AUTH, th.Client.AuthType+" "+th.Client.AuthToken) 372 res, err = th.Client.HttpClient.Do(req) 373 require.NoError(t, err) 374 info := model.FileInfoFromJson(res.Body) 375 res.Body.Close() 376 require.NotEmpty(t, info) 377 require.Equal(t, u.Filename, info.Name) 378 379 file, resp := th.Client.GetFile(info.Id) 380 require.Nil(t, resp.Error) 381 require.Equal(t, file, data) 382 }) 383 }