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  }