github.com/mattermost/mattermost-server/v5@v5.39.3/api4/emoji.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  	"io"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"strings"
    11  
    12  	"github.com/mattermost/mattermost-server/v5/app"
    13  	"github.com/mattermost/mattermost-server/v5/audit"
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  	"github.com/mattermost/mattermost-server/v5/web"
    16  )
    17  
    18  const (
    19  	EmojiMaxAutocompleteItems = 100
    20  )
    21  
    22  func (api *API) InitEmoji() {
    23  	api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(createEmoji)).Methods("POST")
    24  	api.BaseRoutes.Emojis.Handle("", api.ApiSessionRequired(getEmojiList)).Methods("GET")
    25  	api.BaseRoutes.Emojis.Handle("/search", api.ApiSessionRequired(searchEmojis)).Methods("POST")
    26  	api.BaseRoutes.Emojis.Handle("/autocomplete", api.ApiSessionRequired(autocompleteEmojis)).Methods("GET")
    27  	api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(deleteEmoji)).Methods("DELETE")
    28  	api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(getEmoji)).Methods("GET")
    29  	api.BaseRoutes.EmojiByName.Handle("", api.ApiSessionRequired(getEmojiByName)).Methods("GET")
    30  	api.BaseRoutes.Emoji.Handle("/image", api.ApiSessionRequiredTrustRequester(getEmojiImage)).Methods("GET")
    31  }
    32  
    33  func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
    34  	defer io.Copy(ioutil.Discard, r.Body)
    35  
    36  	if !*c.App.Config().ServiceSettings.EnableCustomEmoji {
    37  		c.Err = model.NewAppError("createEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
    38  		return
    39  	}
    40  
    41  	if r.ContentLength > app.MaxEmojiFileSize {
    42  		c.Err = model.NewAppError("createEmoji", "api.emoji.create.too_large.app_error", nil, "", http.StatusRequestEntityTooLarge)
    43  		return
    44  	}
    45  
    46  	if err := r.ParseMultipartForm(app.MaxEmojiFileSize); err != nil {
    47  		c.Err = model.NewAppError("createEmoji", "api.emoji.create.parse.app_error", nil, err.Error(), http.StatusBadRequest)
    48  		return
    49  	}
    50  
    51  	auditRec := c.MakeAuditRecord("createEmoji", audit.Fail)
    52  	defer c.LogAuditRec(auditRec)
    53  
    54  	// Allow any user with CREATE_EMOJIS permission at Team level to create emojis at system level
    55  	memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId)
    56  
    57  	if err != nil {
    58  		c.Err = err
    59  		return
    60  	}
    61  
    62  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_CREATE_EMOJIS) {
    63  		hasPermission := false
    64  		for _, membership := range memberships {
    65  			if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), membership.TeamId, model.PERMISSION_CREATE_EMOJIS) {
    66  				hasPermission = true
    67  				break
    68  			}
    69  		}
    70  		if !hasPermission {
    71  			c.SetPermissionError(model.PERMISSION_CREATE_EMOJIS)
    72  			return
    73  		}
    74  	}
    75  
    76  	m := r.MultipartForm
    77  	props := m.Value
    78  
    79  	if len(props["emoji"]) == 0 {
    80  		c.SetInvalidParam("emoji")
    81  		return
    82  	}
    83  
    84  	emoji := model.EmojiFromJson(strings.NewReader(props["emoji"][0]))
    85  	if emoji == nil {
    86  		c.SetInvalidParam("emoji")
    87  		return
    88  	}
    89  
    90  	auditRec.AddMeta("emoji", emoji)
    91  
    92  	newEmoji, err := c.App.CreateEmoji(c.AppContext.Session().UserId, emoji, m)
    93  	if err != nil {
    94  		c.Err = err
    95  		return
    96  	}
    97  
    98  	auditRec.Success()
    99  	w.Write([]byte(newEmoji.ToJson()))
   100  }
   101  
   102  func getEmojiList(c *Context, w http.ResponseWriter, r *http.Request) {
   103  	if !*c.App.Config().ServiceSettings.EnableCustomEmoji {
   104  		c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
   105  		return
   106  	}
   107  
   108  	sort := r.URL.Query().Get("sort")
   109  	if sort != "" && sort != model.EMOJI_SORT_BY_NAME {
   110  		c.SetInvalidUrlParam("sort")
   111  		return
   112  	}
   113  
   114  	listEmoji, err := c.App.GetEmojiList(c.Params.Page, c.Params.PerPage, sort)
   115  	if err != nil {
   116  		c.Err = err
   117  		return
   118  	}
   119  
   120  	w.Write([]byte(model.EmojiListToJson(listEmoji)))
   121  }
   122  
   123  func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
   124  	c.RequireEmojiId()
   125  	if c.Err != nil {
   126  		return
   127  	}
   128  
   129  	auditRec := c.MakeAuditRecord("deleteEmoji", audit.Fail)
   130  	defer c.LogAuditRec(auditRec)
   131  
   132  	emoji, err := c.App.GetEmoji(c.Params.EmojiId)
   133  	if err != nil {
   134  		auditRec.AddMeta("emoji_id", c.Params.EmojiId)
   135  		c.Err = err
   136  		return
   137  	}
   138  	auditRec.AddMeta("emoji", emoji)
   139  
   140  	// Allow any user with DELETE_EMOJIS permission at Team level to delete emojis at system level
   141  	memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId)
   142  
   143  	if err != nil {
   144  		c.Err = err
   145  		return
   146  	}
   147  
   148  	if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_DELETE_EMOJIS) {
   149  		hasPermission := false
   150  		for _, membership := range memberships {
   151  			if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), membership.TeamId, model.PERMISSION_DELETE_EMOJIS) {
   152  				hasPermission = true
   153  				break
   154  			}
   155  		}
   156  		if !hasPermission {
   157  			c.SetPermissionError(model.PERMISSION_DELETE_EMOJIS)
   158  			return
   159  		}
   160  	}
   161  
   162  	if c.AppContext.Session().UserId != emoji.CreatorId {
   163  		if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_DELETE_OTHERS_EMOJIS) {
   164  			hasPermission := false
   165  			for _, membership := range memberships {
   166  				if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), membership.TeamId, model.PERMISSION_DELETE_OTHERS_EMOJIS) {
   167  					hasPermission = true
   168  					break
   169  				}
   170  			}
   171  
   172  			if !hasPermission {
   173  				c.SetPermissionError(model.PERMISSION_DELETE_OTHERS_EMOJIS)
   174  				return
   175  			}
   176  		}
   177  	}
   178  
   179  	err = c.App.DeleteEmoji(emoji)
   180  	if err != nil {
   181  		c.Err = err
   182  		return
   183  	}
   184  
   185  	auditRec.Success()
   186  
   187  	ReturnStatusOK(w)
   188  }
   189  
   190  func getEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
   191  	c.RequireEmojiId()
   192  	if c.Err != nil {
   193  		return
   194  	}
   195  
   196  	if !*c.App.Config().ServiceSettings.EnableCustomEmoji {
   197  		c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
   198  		return
   199  	}
   200  
   201  	emoji, err := c.App.GetEmoji(c.Params.EmojiId)
   202  	if err != nil {
   203  		c.Err = err
   204  		return
   205  	}
   206  
   207  	w.Write([]byte(emoji.ToJson()))
   208  }
   209  
   210  func getEmojiByName(c *Context, w http.ResponseWriter, r *http.Request) {
   211  	c.RequireEmojiName()
   212  	if c.Err != nil {
   213  		return
   214  	}
   215  
   216  	emoji, err := c.App.GetEmojiByName(c.Params.EmojiName)
   217  	if err != nil {
   218  		c.Err = err
   219  		return
   220  	}
   221  
   222  	w.Write([]byte(emoji.ToJson()))
   223  }
   224  
   225  func getEmojiImage(c *Context, w http.ResponseWriter, r *http.Request) {
   226  	c.RequireEmojiId()
   227  	if c.Err != nil {
   228  		return
   229  	}
   230  
   231  	if !*c.App.Config().ServiceSettings.EnableCustomEmoji {
   232  		c.Err = model.NewAppError("getEmojiImage", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
   233  		return
   234  	}
   235  
   236  	image, imageType, err := c.App.GetEmojiImage(c.Params.EmojiId)
   237  	if err != nil {
   238  		c.Err = err
   239  		return
   240  	}
   241  
   242  	w.Header().Set("Content-Type", "image/"+imageType)
   243  	w.Header().Set("Cache-Control", "max-age=2592000, private")
   244  	w.Write(image)
   245  }
   246  
   247  func searchEmojis(c *Context, w http.ResponseWriter, r *http.Request) {
   248  	emojiSearch := model.EmojiSearchFromJson(r.Body)
   249  	if emojiSearch == nil {
   250  		c.SetInvalidParam("term")
   251  		return
   252  	}
   253  
   254  	if emojiSearch.Term == "" {
   255  		c.SetInvalidParam("term")
   256  		return
   257  	}
   258  
   259  	emojis, err := c.App.SearchEmoji(emojiSearch.Term, emojiSearch.PrefixOnly, web.PerPageMaximum)
   260  	if err != nil {
   261  		c.Err = err
   262  		return
   263  	}
   264  
   265  	w.Write([]byte(model.EmojiListToJson(emojis)))
   266  }
   267  
   268  func autocompleteEmojis(c *Context, w http.ResponseWriter, r *http.Request) {
   269  	name := r.URL.Query().Get("name")
   270  
   271  	if name == "" {
   272  		c.SetInvalidUrlParam("name")
   273  		return
   274  	}
   275  
   276  	emojis, err := c.App.SearchEmoji(name, true, EmojiMaxAutocompleteItems)
   277  	if err != nil {
   278  		c.Err = err
   279  		return
   280  	}
   281  
   282  	w.Write([]byte(model.EmojiListToJson(emojis)))
   283  }