github.com/keys-pub/mattermost-server@v4.10.10+incompatible/api/emoji_test.go (about) 1 // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package api 5 6 import ( 7 "bytes" 8 "image" 9 "image/gif" 10 "testing" 11 "time" 12 13 "github.com/mattermost/mattermost-server/app" 14 "github.com/mattermost/mattermost-server/model" 15 "github.com/mattermost/mattermost-server/store" 16 "github.com/mattermost/mattermost-server/utils" 17 ) 18 19 func TestGetEmoji(t *testing.T) { 20 th := Setup().InitBasic() 21 defer th.TearDown() 22 23 Client := th.BasicClient 24 25 EnableCustomEmoji := *th.App.Config().ServiceSettings.EnableCustomEmoji 26 defer func() { 27 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji }) 28 }() 29 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) 30 31 emojis := []*model.Emoji{ 32 { 33 CreatorId: model.NewId(), 34 Name: model.NewId(), 35 }, 36 { 37 CreatorId: model.NewId(), 38 Name: model.NewId(), 39 }, 40 { 41 CreatorId: model.NewId(), 42 Name: model.NewId(), 43 }, 44 } 45 46 for i, emoji := range emojis { 47 emojis[i] = store.Must(th.App.Srv.Store.Emoji().Save(emoji)).(*model.Emoji) 48 } 49 defer func() { 50 for _, emoji := range emojis { 51 store.Must(th.App.Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix())) 52 } 53 }() 54 55 if returnedEmojis, err := Client.ListEmoji(); err != nil { 56 t.Fatal(err) 57 } else { 58 for _, emoji := range emojis { 59 found := false 60 61 for _, savedEmoji := range returnedEmojis { 62 if emoji.Id == savedEmoji.Id { 63 found = true 64 break 65 } 66 } 67 68 if !found { 69 t.Fatalf("failed to get emoji with id %v", emoji.Id) 70 } 71 } 72 } 73 74 deleted := &model.Emoji{ 75 CreatorId: model.NewId(), 76 Name: model.NewId(), 77 DeleteAt: 1, 78 } 79 deleted = store.Must(th.App.Srv.Store.Emoji().Save(deleted)).(*model.Emoji) 80 81 if returnedEmojis, err := Client.ListEmoji(); err != nil { 82 t.Fatal(err) 83 } else { 84 found := false 85 86 for _, savedEmoji := range returnedEmojis { 87 if deleted.Id == savedEmoji.Id { 88 found = true 89 break 90 } 91 } 92 93 if found { 94 t.Fatalf("shouldn't have gotten deleted emoji %v", deleted.Id) 95 } 96 } 97 } 98 99 func TestCreateEmoji(t *testing.T) { 100 th := Setup().InitBasic().InitSystemAdmin() 101 defer th.TearDown() 102 103 Client := th.BasicClient 104 105 EnableCustomEmoji := *th.App.Config().ServiceSettings.EnableCustomEmoji 106 defer func() { 107 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji }) 108 }() 109 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = false }) 110 111 emoji := &model.Emoji{ 112 CreatorId: th.BasicUser.Id, 113 Name: model.NewId(), 114 } 115 116 // try to create an emoji when they're disabled 117 if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil { 118 t.Fatal("shouldn't be able to create an emoji when they're disabled") 119 } 120 121 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) 122 123 // try to create a valid gif emoji when they're enabled 124 if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err != nil { 125 t.Fatal(err) 126 } else { 127 emoji = emojiResult 128 } 129 130 // try to create an emoji with a duplicate name 131 emoji2 := &model.Emoji{ 132 CreatorId: th.BasicUser.Id, 133 Name: emoji.Name, 134 } 135 if _, err := Client.CreateEmoji(emoji2, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil { 136 t.Fatal("shouldn't be able to create an emoji with a duplicate name") 137 } 138 139 Client.MustGeneric(Client.DeleteEmoji(emoji.Id)) 140 141 // try to create a valid animated gif emoji 142 emoji = &model.Emoji{ 143 CreatorId: th.BasicUser.Id, 144 Name: model.NewId(), 145 } 146 if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 10, 10, 10), "image.gif"); err != nil { 147 t.Fatal(err) 148 } else { 149 emoji = emojiResult 150 } 151 Client.MustGeneric(Client.DeleteEmoji(emoji.Id)) 152 153 // try to create a valid jpeg emoji 154 emoji = &model.Emoji{ 155 CreatorId: th.BasicUser.Id, 156 Name: model.NewId(), 157 } 158 if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestJpeg(t, 10, 10), "image.jpeg"); err != nil { 159 t.Fatal(err) 160 } else { 161 emoji = emojiResult 162 } 163 Client.MustGeneric(Client.DeleteEmoji(emoji.Id)) 164 165 // try to create a valid png emoji 166 emoji = &model.Emoji{ 167 CreatorId: th.BasicUser.Id, 168 Name: model.NewId(), 169 } 170 if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestPng(t, 10, 10), "image.png"); err != nil { 171 t.Fatal(err) 172 } else { 173 emoji = emojiResult 174 } 175 Client.MustGeneric(Client.DeleteEmoji(emoji.Id)) 176 177 // try to create an emoji that's too wide 178 emoji = &model.Emoji{ 179 CreatorId: th.BasicUser.Id, 180 Name: model.NewId(), 181 } 182 if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 1000, 10), "image.gif"); err != nil { 183 t.Fatal("should be able to create an emoji that's too wide by resizing it") 184 } 185 186 // try to create an emoji that's too tall 187 emoji = &model.Emoji{ 188 CreatorId: th.BasicUser.Id, 189 Name: model.NewId(), 190 } 191 if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 1000), "image.gif"); err != nil { 192 t.Fatal("should be able to create an emoji that's too tall by resizing it") 193 } 194 195 // try to create an emoji that's too large 196 emoji = &model.Emoji{ 197 CreatorId: th.BasicUser.Id, 198 Name: model.NewId(), 199 } 200 if _, err := Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 100, 100, 10000), "image.gif"); err == nil { 201 t.Fatal("shouldn't be able to create an emoji that's too large") 202 } 203 204 // try to create an emoji with data that isn't an image 205 emoji = &model.Emoji{ 206 CreatorId: th.BasicUser.Id, 207 Name: model.NewId(), 208 } 209 if _, err := Client.CreateEmoji(emoji, make([]byte, 100), "image.gif"); err == nil { 210 t.Fatal("shouldn't be able to create an emoji with non-image data") 211 } 212 213 // try to create an emoji as another user 214 emoji = &model.Emoji{ 215 CreatorId: th.BasicUser2.Id, 216 Name: model.NewId(), 217 } 218 if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil { 219 t.Fatal("shouldn't be able to create an emoji as another user") 220 } 221 } 222 223 func TestDeleteEmoji(t *testing.T) { 224 th := Setup().InitBasic().InitSystemAdmin() 225 defer th.TearDown() 226 227 Client := th.BasicClient 228 229 EnableCustomEmoji := *th.App.Config().ServiceSettings.EnableCustomEmoji 230 defer func() { 231 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji }) 232 }() 233 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = false }) 234 235 emoji1 := createTestEmoji(t, th.App, &model.Emoji{ 236 CreatorId: th.BasicUser.Id, 237 Name: model.NewId(), 238 }, utils.CreateTestGif(t, 10, 10)) 239 240 if _, err := Client.DeleteEmoji(emoji1.Id); err == nil { 241 t.Fatal("shouldn't have been able to delete an emoji when they're disabled") 242 } 243 244 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) 245 246 if deleted, err := Client.DeleteEmoji(emoji1.Id); err != nil { 247 t.Fatal(err) 248 } else if !deleted { 249 t.Fatalf("should be able to delete your own emoji %v", emoji1.Id) 250 } 251 252 if _, err := Client.DeleteEmoji(emoji1.Id); err == nil { 253 t.Fatal("shouldn't be able to delete an already-deleted emoji") 254 } 255 256 emoji2 := createTestEmoji(t, th.App, &model.Emoji{ 257 CreatorId: th.BasicUser2.Id, 258 Name: model.NewId(), 259 }, utils.CreateTestGif(t, 10, 10)) 260 261 if _, err := Client.DeleteEmoji(emoji2.Id); err == nil { 262 t.Fatal("shouldn't be able to delete another user's emoji") 263 } 264 265 if deleted, err := th.SystemAdminClient.DeleteEmoji(emoji2.Id); err != nil { 266 t.Fatal(err) 267 } else if !deleted { 268 t.Fatalf("system admin should be able to delete anyone's emoji %v", emoji2.Id) 269 } 270 } 271 272 func createTestEmoji(t *testing.T, a *app.App, emoji *model.Emoji, imageData []byte) *model.Emoji { 273 emoji = store.Must(a.Srv.Store.Emoji().Save(emoji)).(*model.Emoji) 274 275 if err := a.WriteFile(imageData, "emoji/"+emoji.Id+"/image"); err != nil { 276 store.Must(a.Srv.Store.Emoji().Delete(emoji.Id, time.Now().Unix())) 277 t.Fatalf("failed to write image: %v", err.Error()) 278 } 279 280 return emoji 281 } 282 283 func TestGetEmojiImage(t *testing.T) { 284 th := Setup().InitBasic() 285 defer th.TearDown() 286 287 Client := th.BasicClient 288 289 EnableCustomEmoji := *th.App.Config().ServiceSettings.EnableCustomEmoji 290 RestrictCustomEmojiCreation := *th.App.Config().ServiceSettings.RestrictCustomEmojiCreation 291 defer func() { 292 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji }) 293 th.App.UpdateConfig(func(cfg *model.Config) { 294 *cfg.ServiceSettings.RestrictCustomEmojiCreation = RestrictCustomEmojiCreation 295 }) 296 }() 297 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) 298 th.App.UpdateConfig(func(cfg *model.Config) { 299 *cfg.ServiceSettings.RestrictCustomEmojiCreation = model.RESTRICT_EMOJI_CREATION_ALL 300 }) 301 302 emoji1 := &model.Emoji{ 303 CreatorId: th.BasicUser.Id, 304 Name: model.NewId(), 305 } 306 emoji1 = Client.MustGeneric(Client.CreateEmoji(emoji1, utils.CreateTestGif(t, 10, 10), "image.gif")).(*model.Emoji) 307 defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji1.Id)) }() 308 309 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = false }) 310 311 if _, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji1.Id), "", ""); err == nil { 312 t.Fatal("should've failed to get emoji image when disabled") 313 } 314 315 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) 316 317 if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji1.Id), "", ""); err != nil { 318 t.Fatal(err) 319 } else if resp.Header.Get("Content-Type") != "image/gif" { 320 t.Fatal("should've received a gif") 321 } else if _, imageType, err := image.DecodeConfig(resp.Body); err != nil { 322 t.Fatalf("unable to identify received image: %v", err.Error()) 323 } else if imageType != "gif" { 324 t.Fatal("should've received gif data") 325 } 326 327 emoji2 := &model.Emoji{ 328 CreatorId: th.BasicUser.Id, 329 Name: model.NewId(), 330 } 331 emoji2 = Client.MustGeneric(Client.CreateEmoji(emoji2, utils.CreateTestAnimatedGif(t, 10, 10, 10), "image.gif")).(*model.Emoji) 332 defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji2.Id)) }() 333 334 if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji2.Id), "", ""); err != nil { 335 t.Fatal(err) 336 } else if resp.Header.Get("Content-Type") != "image/gif" { 337 t.Fatal("should've received a gif") 338 } else if _, imageType, err := image.DecodeConfig(resp.Body); err != nil { 339 t.Fatalf("unable to identify received image: %v", err.Error()) 340 } else if imageType != "gif" { 341 t.Fatal("should've received gif data") 342 } 343 344 emoji3 := &model.Emoji{ 345 CreatorId: th.BasicUser.Id, 346 Name: model.NewId(), 347 } 348 emoji3 = Client.MustGeneric(Client.CreateEmoji(emoji3, utils.CreateTestJpeg(t, 10, 10), "image.jpeg")).(*model.Emoji) 349 defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji3.Id)) }() 350 351 if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji3.Id), "", ""); err != nil { 352 t.Fatal(err) 353 } else if resp.Header.Get("Content-Type") != "image/jpeg" { 354 t.Fatal("should've received a jpeg") 355 } else if _, imageType, err := image.DecodeConfig(resp.Body); err != nil { 356 t.Fatalf("unable to identify received image: %v", err.Error()) 357 } else if imageType != "jpeg" { 358 t.Fatal("should've received jpeg data") 359 } 360 361 emoji4 := &model.Emoji{ 362 CreatorId: th.BasicUser.Id, 363 Name: model.NewId(), 364 } 365 emoji4 = Client.MustGeneric(Client.CreateEmoji(emoji4, utils.CreateTestPng(t, 10, 10), "image.png")).(*model.Emoji) 366 defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji4.Id)) }() 367 368 if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji4.Id), "", ""); err != nil { 369 t.Fatal(err) 370 } else if resp.Header.Get("Content-Type") != "image/png" { 371 t.Fatal("should've received a png") 372 } else if _, imageType, err := image.DecodeConfig(resp.Body); err != nil { 373 t.Fatalf("unable to identify received image: %v", err.Error()) 374 } else if imageType != "png" { 375 t.Fatal("should've received png data") 376 } 377 378 emoji5 := &model.Emoji{ 379 CreatorId: th.BasicUser.Id, 380 Name: model.NewId(), 381 } 382 emoji5 = Client.MustGeneric(Client.CreateEmoji(emoji5, utils.CreateTestPng(t, 10, 10), "image.png")).(*model.Emoji) 383 Client.MustGeneric(Client.DeleteEmoji(emoji5.Id)) 384 385 if _, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji5.Id), "", ""); err == nil { 386 t.Fatal("should've failed to get image for deleted emoji") 387 } 388 } 389 390 func TestResizeEmoji(t *testing.T) { 391 // try to resize a jpeg image within MaxEmojiWidth and MaxEmojiHeight 392 small_img_data := utils.CreateTestJpeg(t, app.MaxEmojiWidth, app.MaxEmojiHeight) 393 if small_img, _, err := image.Decode(bytes.NewReader(small_img_data)); err != nil { 394 t.Fatal("failed to decode jpeg bytes to image.Image") 395 } else { 396 resized_img := resizeEmoji(small_img, small_img.Bounds().Dx(), small_img.Bounds().Dy()) 397 if resized_img.Bounds().Dx() > app.MaxEmojiWidth || resized_img.Bounds().Dy() > app.MaxEmojiHeight { 398 t.Fatal("resized jpeg width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight") 399 } 400 if resized_img != small_img { 401 t.Fatal("should've returned small_img itself") 402 } 403 } 404 // try to resize a jpeg image 405 jpeg_data := utils.CreateTestJpeg(t, 256, 256) 406 if jpeg_img, _, err := image.Decode(bytes.NewReader(jpeg_data)); err != nil { 407 t.Fatal("failed to decode jpeg bytes to image.Image") 408 } else { 409 resized_jpeg := resizeEmoji(jpeg_img, jpeg_img.Bounds().Dx(), jpeg_img.Bounds().Dy()) 410 if resized_jpeg.Bounds().Dx() > app.MaxEmojiWidth || resized_jpeg.Bounds().Dy() > app.MaxEmojiHeight { 411 t.Fatal("resized jpeg width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight") 412 } 413 } 414 // try to resize a png image 415 png_data := utils.CreateTestJpeg(t, 256, 256) 416 if png_img, _, err := image.Decode(bytes.NewReader(png_data)); err != nil { 417 t.Fatal("failed to decode png bytes to image.Image") 418 } else { 419 resized_png := resizeEmoji(png_img, png_img.Bounds().Dx(), png_img.Bounds().Dy()) 420 if resized_png.Bounds().Dx() > app.MaxEmojiWidth || resized_png.Bounds().Dy() > app.MaxEmojiHeight { 421 t.Fatal("resized png width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight") 422 } 423 } 424 // try to resize an animated gif 425 gif_data := utils.CreateTestAnimatedGif(t, 256, 256, 10) 426 if gif_img, err := gif.DecodeAll(bytes.NewReader(gif_data)); err != nil { 427 t.Fatal("failed to decode gif bytes to gif.GIF") 428 } else { 429 resized_gif := resizeEmojiGif(gif_img) 430 if resized_gif.Config.Width > app.MaxEmojiWidth || resized_gif.Config.Height > app.MaxEmojiHeight { 431 t.Fatal("resized gif width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight") 432 } 433 if len(resized_gif.Image) != len(gif_img.Image) { 434 t.Fatal("resized gif should have the same number of frames as original gif") 435 } 436 } 437 }