reaction.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
  2. // See LICENSE.txt for license information.
  3. package app
  4. import (
  5. "net/http"
  6. "github.com/mattermost/mattermost-server/v5/model"
  7. )
  8. func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
  9. post, err := a.GetSinglePost(reaction.PostId)
  10. if err != nil {
  11. return nil, err
  12. }
  13. channel, err := a.GetChannel(post.ChannelId)
  14. if err != nil {
  15. return nil, err
  16. }
  17. if channel.DeleteAt > 0 {
  18. return nil, model.NewAppError("deleteReactionForPost", "api.reaction.save.archived_channel.app_error", nil, "", http.StatusForbidden)
  19. }
  20. if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly && channel.Name == model.DEFAULT_CHANNEL {
  21. var user *model.User
  22. user, err = a.GetUser(reaction.UserId)
  23. if err != nil {
  24. return nil, err
  25. }
  26. if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) {
  27. return nil, model.NewAppError("saveReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden)
  28. }
  29. }
  30. reaction, err = a.Srv.Store.Reaction().Save(reaction)
  31. if err != nil {
  32. return nil, err
  33. }
  34. // The post is always modified since the UpdateAt always changes
  35. a.InvalidateCacheForChannelPosts(post.ChannelId)
  36. a.Srv.Go(func() {
  37. a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_ADDED, reaction, post, true)
  38. })
  39. return reaction, nil
  40. }
  41. func (a *App) GetReactionsForPost(postId string) ([]*model.Reaction, *model.AppError) {
  42. return a.Srv.Store.Reaction().GetForPost(postId, true)
  43. }
  44. func (a *App) GetBulkReactionsForPosts(postIds []string) (map[string][]*model.Reaction, *model.AppError) {
  45. reactions := make(map[string][]*model.Reaction)
  46. allReactions, err := a.Srv.Store.Reaction().BulkGetForPosts(postIds)
  47. if err != nil {
  48. return nil, err
  49. }
  50. for _, reaction := range allReactions {
  51. reactionsForPost := reactions[reaction.PostId]
  52. reactionsForPost = append(reactionsForPost, reaction)
  53. reactions[reaction.PostId] = reactionsForPost
  54. }
  55. reactions = populateEmptyReactions(postIds, reactions)
  56. return reactions, nil
  57. }
  58. func populateEmptyReactions(postIds []string, reactions map[string][]*model.Reaction) map[string][]*model.Reaction {
  59. for _, postId := range postIds {
  60. if _, present := reactions[postId]; !present {
  61. reactions[postId] = []*model.Reaction{}
  62. }
  63. }
  64. return reactions
  65. }
  66. func (a *App) DeleteReactionForPost(reaction *model.Reaction) *model.AppError {
  67. post, err := a.GetSinglePost(reaction.PostId)
  68. if err != nil {
  69. return err
  70. }
  71. channel, err := a.GetChannel(post.ChannelId)
  72. if err != nil {
  73. return err
  74. }
  75. if channel.DeleteAt > 0 {
  76. return model.NewAppError("deleteReactionForPost", "api.reaction.delete.archived_channel.app_error", nil, "", http.StatusForbidden)
  77. }
  78. if a.License() != nil && *a.Config().TeamSettings.ExperimentalTownSquareIsReadOnly && channel.Name == model.DEFAULT_CHANNEL {
  79. user, err := a.GetUser(reaction.UserId)
  80. if err != nil {
  81. return err
  82. }
  83. if !a.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) {
  84. return model.NewAppError("deleteReactionForPost", "api.reaction.town_square_read_only", nil, "", http.StatusForbidden)
  85. }
  86. }
  87. hasReactions := true
  88. if reactions, _ := a.GetReactionsForPost(post.Id); len(reactions) <= 1 {
  89. hasReactions = false
  90. }
  91. if _, err := a.Srv.Store.Reaction().Delete(reaction); err != nil {
  92. return err
  93. }
  94. // The post is always modified since the UpdateAt always changes
  95. a.InvalidateCacheForChannelPosts(post.ChannelId)
  96. a.Srv.Go(func() {
  97. a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions)
  98. })
  99. return nil
  100. }
  101. func (a *App) sendReactionEvent(event string, reaction *model.Reaction, post *model.Post, hasReactions bool) {
  102. // send out that a reaction has been added/removed
  103. message := model.NewWebSocketEvent(event, "", post.ChannelId, "", nil)
  104. message.Add("reaction", reaction.ToJson())
  105. a.Publish(message)
  106. }