summaryrefslogtreecommitdiffstats
path: root/api/post.go
diff options
context:
space:
mode:
Diffstat (limited to 'api/post.go')
-rw-r--r--api/post.go1176
1 files changed, 31 insertions, 1145 deletions
diff --git a/api/post.go b/api/post.go
index 8d255649e..270ab72ca 100644
--- a/api/post.go
+++ b/api/post.go
@@ -4,33 +4,15 @@
package api
import (
- "crypto/tls"
- "fmt"
- "html"
- "html/template"
- "io"
- "io/ioutil"
"net/http"
- "net/url"
- "path/filepath"
- "regexp"
- "sort"
"strconv"
- "strings"
- "time"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
- "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
- "github.com/nicksnyder/go-i18n/i18n"
-)
-
-const (
- TRIGGERWORDS_FULL = 0
- TRIGGERWORDS_STARTSWITH = 1
)
func InitPost() {
@@ -61,7 +43,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
post.UserId = c.Session.UserId
- cchan := Srv.Store.Channel().Get(post.ChannelId, true)
+ cchan := app.Srv.Store.Channel().Get(post.ChannelId, true)
if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_CREATE_POST) {
return
@@ -82,7 +64,11 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if rp, err := CreatePost(c, post, true); err != nil {
+ if post.CreateAt != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
+ post.CreateAt = 0
+ }
+
+ if rp, err := app.CreatePost(post, c.TeamId, true); err != nil {
c.Err = err
if c.Err.Id == "api.post.create_post.root_id.app_error" ||
@@ -95,7 +81,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
// Update the LastViewAt only if the post does not have from_webhook prop set (eg. Zapier app)
if _, ok := post.Props["from_webhook"]; !ok {
- if result := <-Srv.Store.Channel().UpdateLastViewedAt([]string{post.ChannelId}, c.Session.UserId); result.Err != nil {
+ if result := <-app.Srv.Store.Channel().UpdateLastViewedAt([]string{post.ChannelId}, c.Session.UserId); result.Err != nil {
l4g.Error(utils.T("api.post.create_post.last_viewed.error"), post.ChannelId, c.Session.UserId, result.Err)
}
}
@@ -104,1106 +90,6 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post, *model.AppError) {
- var pchan store.StoreChannel
- if len(post.RootId) > 0 {
- pchan = Srv.Store.Post().Get(post.RootId)
- }
-
- // Verify the parent/child relationships are correct
- if pchan != nil {
- if presult := <-pchan; presult.Err != nil {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.root_id.app_error", nil, "")
- } else {
- list := presult.Data.(*model.PostList)
- if len(list.Posts) == 0 || !list.IsChannelId(post.ChannelId) {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "")
- }
-
- if post.ParentId == "" {
- post.ParentId = post.RootId
- }
-
- if post.RootId != post.ParentId {
- parent := list.Posts[post.ParentId]
- if parent == nil {
- return nil, model.NewLocAppError("createPost", "api.post.create_post.parent_id.app_error", nil, "")
- }
- }
- }
- }
-
- if post.CreateAt != 0 && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) {
- post.CreateAt = 0
- c.Err = nil
- }
-
- post.Hashtags, _ = model.ParseHashtags(post.Message)
-
- var rpost *model.Post
- if result := <-Srv.Store.Post().Save(post); result.Err != nil {
- return nil, result.Err
- } else {
- rpost = result.Data.(*model.Post)
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostCreate()
- }
-
- if len(post.FileIds) > 0 {
- // There's a rare bug where the client sends up duplicate FileIds so protect against that
- post.FileIds = utils.RemoveDuplicatesFromStringArray(post.FileIds)
-
- for _, fileId := range post.FileIds {
- if result := <-Srv.Store.FileInfo().AttachToPost(fileId, post.Id); result.Err != nil {
- l4g.Error(utils.T("api.post.create_post.attach_files.error"), post.Id, post.FileIds, c.Session.UserId, result.Err)
- }
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostFileAttachment(len(post.FileIds))
- }
- }
-
- InvalidateCacheForChannel(rpost.ChannelId)
- InvalidateCacheForChannelPosts(rpost.ChannelId)
-
- handlePostEvents(c, rpost, triggerWebhooks)
-
- return rpost, nil
-}
-
-var linkWithTextRegex *regexp.Regexp = regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`)
-
-func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string) (*model.Post, *model.AppError) {
- post := &model.Post{UserId: c.Session.UserId, ChannelId: channelId, Message: text, Type: postType}
- post.AddProp("from_webhook", "true")
-
- if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
- if len(overrideUsername) != 0 {
- post.AddProp("override_username", overrideUsername)
- } else {
- post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
- }
- }
-
- if utils.Cfg.ServiceSettings.EnablePostIconOverride {
- if len(overrideIconUrl) != 0 {
- post.AddProp("override_icon_url", overrideIconUrl)
- }
- }
-
- post.Message = parseSlackLinksToMarkdown(post.Message)
-
- if len(props) > 0 {
- for key, val := range props {
- if key == "attachments" {
- parseSlackAttachment(post, val)
- } else if key != "override_icon_url" && key != "override_username" && key != "from_webhook" {
- post.AddProp(key, val)
- }
- }
- }
-
- if _, err := CreatePost(c, post, false); err != nil {
- return nil, model.NewLocAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "err="+err.Message)
- }
-
- return post, nil
-}
-
-func CreateCommandPost(c *Context, post *model.Post, response *model.CommandResponse) {
- post.Message = parseSlackLinksToMarkdown(response.Text)
- post.UserId = c.Session.UserId
- post.CreateAt = model.GetMillis()
-
- if response.Attachments != nil {
- parseSlackAttachment(post, response.Attachments)
- }
-
- switch response.ResponseType {
- case model.COMMAND_RESPONSE_TYPE_IN_CHANNEL:
- if _, err := CreatePost(c, post, true); err != nil {
- c.Err = model.NewLocAppError("command", "api.command.execute_command.save.app_error", nil, "")
- }
- case model.COMMAND_RESPONSE_TYPE_EPHEMERAL:
- if response.Text == "" {
- return
- }
-
- post.ParentId = ""
- SendEphemeralPost(c.TeamId, c.Session.UserId, post)
- }
-}
-
-// This method only parses and processes the attachments,
-// all else should be set in the post which is passed
-func parseSlackAttachment(post *model.Post, attachments interface{}) {
- post.Type = model.POST_SLACK_ATTACHMENT
-
- if list, success := attachments.([]interface{}); success {
- for i, aInt := range list {
- attachment := aInt.(map[string]interface{})
- if aText, ok := attachment["text"].(string); ok {
- aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
- attachment["text"] = aText
- list[i] = attachment
- }
- if aText, ok := attachment["pretext"].(string); ok {
- aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
- attachment["pretext"] = aText
- list[i] = attachment
- }
- if fVal, ok := attachment["fields"]; ok {
- if fields, ok := fVal.([]interface{}); ok {
- // parse attachment field links into Markdown format
- for j, fInt := range fields {
- field := fInt.(map[string]interface{})
- if fValue, ok := field["value"].(string); ok {
- fValue = linkWithTextRegex.ReplaceAllString(fValue, "[${2}](${1})")
- field["value"] = fValue
- fields[j] = field
- }
- }
- attachment["fields"] = fields
- list[i] = attachment
- }
- }
- }
- post.AddProp("attachments", list)
- }
-}
-
-func parseSlackLinksToMarkdown(text string) string {
- return linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")
-}
-
-func handlePostEvents(c *Context, post *model.Post, triggerWebhooks bool) {
- tchan := Srv.Store.Team().Get(c.TeamId)
- cchan := Srv.Store.Channel().Get(post.ChannelId, true)
- uchan := Srv.Store.User().Get(post.UserId)
-
- var team *model.Team
- if result := <-tchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.team.error"), c.TeamId, result.Err)
- return
- } else {
- team = result.Data.(*model.Team)
- }
-
- var channel *model.Channel
- if result := <-cchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.channel.error"), post.ChannelId, result.Err)
- return
- } else {
- channel = result.Data.(*model.Channel)
- }
-
- sendNotifications(c, post, team, channel)
-
- var user *model.User
- if result := <-uchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.user.error"), post.UserId, result.Err)
- return
- } else {
- user = result.Data.(*model.User)
- }
-
- if triggerWebhooks {
- go handleWebhookEvents(c, post, team, channel, user)
- }
-
- if channel.Type == model.CHANNEL_DIRECT {
- go makeDirectChannelVisible(post.ChannelId)
- }
-}
-
-func makeDirectChannelVisible(channelId string) {
- var members []model.ChannelMember
- if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.get_members.error"), channelId, result.Err.Message)
- return
- } else {
- members = result.Data.([]model.ChannelMember)
- }
-
- if len(members) != 2 {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.get_2_members.error"), channelId)
- return
- }
-
- // make sure the channel is visible to both members
- for i, member := range members {
- otherUserId := members[1-i].UserId
-
- if result := <-Srv.Store.Preference().Get(member.UserId, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, otherUserId); result.Err != nil {
- // create a new preference since one doesn't exist yet
- preference := &model.Preference{
- UserId: member.UserId,
- Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
- Name: otherUserId,
- Value: "true",
- }
-
- if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.save_pref.error"), member.UserId, otherUserId, saveResult.Err.Message)
- } else {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
- message.Add("preference", preference.ToJson())
-
- go Publish(message)
- }
- } else {
- preference := result.Data.(model.Preference)
-
- if preference.Value != "true" {
- // update the existing preference to make the channel visible
- preference.Value = "true"
-
- if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil {
- l4g.Error(utils.T("api.post.make_direct_channel_visible.update_pref.error"), member.UserId, otherUserId, updateResult.Err.Message)
- } else {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", member.UserId, nil)
- message.Add("preference", preference.ToJson())
-
- go Publish(message)
- }
- }
- }
- }
-}
-
-func handleWebhookEvents(c *Context, post *model.Post, team *model.Team, channel *model.Channel, user *model.User) {
- if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
- return
- }
-
- if channel.Type != model.CHANNEL_OPEN {
- return
- }
-
- hchan := Srv.Store.Webhook().GetOutgoingByTeam(c.TeamId)
- result := <-hchan
- if result.Err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.getting.error"), result.Err)
- return
- }
-
- hooks := result.Data.([]*model.OutgoingWebhook)
- if len(hooks) == 0 {
- return
- }
-
- splitWords := strings.Fields(post.Message)
- if len(splitWords) == 0 {
- return
- }
- firstWord := splitWords[0]
-
- relevantHooks := []*model.OutgoingWebhook{}
- for _, hook := range hooks {
- if hook.ChannelId == post.ChannelId || len(hook.ChannelId) == 0 {
- if hook.ChannelId == post.ChannelId && len(hook.TriggerWords) == 0 {
- relevantHooks = append(relevantHooks, hook)
- } else if hook.TriggerWhen == TRIGGERWORDS_FULL && hook.HasTriggerWord(firstWord) {
- relevantHooks = append(relevantHooks, hook)
- } else if hook.TriggerWhen == TRIGGERWORDS_STARTSWITH && hook.TriggerWordStartsWith(firstWord) {
- relevantHooks = append(relevantHooks, hook)
- }
- }
- }
-
- for _, hook := range relevantHooks {
- go func(hook *model.OutgoingWebhook) {
- payload := &model.OutgoingWebhookPayload{
- Token: hook.Token,
- TeamId: hook.TeamId,
- TeamDomain: team.Name,
- ChannelId: post.ChannelId,
- ChannelName: channel.Name,
- Timestamp: post.CreateAt,
- UserId: post.UserId,
- UserName: user.Username,
- PostId: post.Id,
- Text: post.Message,
- TriggerWord: firstWord,
- }
- var body io.Reader
- var contentType string
- if hook.ContentType == "application/json" {
- body = strings.NewReader(payload.ToJSON())
- contentType = "application/json"
- } else {
- body = strings.NewReader(payload.ToFormValues())
- contentType = "application/x-www-form-urlencoded"
- }
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- client := &http.Client{Transport: tr}
-
- for _, url := range hook.CallbackURLs {
- go func(url string) {
- req, _ := http.NewRequest("POST", url, body)
- req.Header.Set("Content-Type", contentType)
- req.Header.Set("Accept", "application/json")
- if resp, err := client.Do(req); err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.event_post.error"), err.Error())
- } else {
- defer func() {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }()
- respProps := model.MapFromJson(resp.Body)
-
- // copy the context and create a mock session for posting the message
- mockSession := model.Session{
- UserId: hook.CreatorId,
- TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.CreatorId}},
- IsOAuth: false,
- }
-
- newContext := &Context{
- Session: mockSession,
- RequestId: model.NewId(),
- IpAddress: "",
- Path: c.Path,
- Err: nil,
- teamURLValid: c.teamURLValid,
- teamURL: c.teamURL,
- siteURL: c.siteURL,
- T: c.T,
- Locale: c.Locale,
- TeamId: hook.TeamId,
- }
-
- if text, ok := respProps["text"]; ok {
- if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
- l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.create_post.error"), err)
- }
- }
- }
- }(url)
- }
-
- }(hook)
- }
-}
-
-// Given a map of user IDs to profiles, returns a list of mention
-// keywords for all users in the channel.
-func getMentionKeywordsInChannel(profiles map[string]*model.User) map[string][]string {
- keywords := make(map[string][]string)
-
- for id, profile := range profiles {
- userMention := "@" + strings.ToLower(profile.Username)
- keywords[userMention] = append(keywords[userMention], id)
-
- if len(profile.NotifyProps["mention_keys"]) > 0 {
- // Add all the user's mention keys
- splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",")
- for _, k := range splitKeys {
- // note that these are made lower case so that we can do a case insensitive check for them
- key := strings.ToLower(k)
- keywords[key] = append(keywords[key], id)
- }
- }
-
- // If turned on, add the user's case sensitive first name
- if profile.NotifyProps["first_name"] == "true" {
- keywords[profile.FirstName] = append(keywords[profile.FirstName], profile.Id)
- }
-
- // Add @channel and @all to keywords if user has them turned on
- if int64(len(profiles)) < *utils.Cfg.TeamSettings.MaxNotificationsPerChannel && profile.NotifyProps["channel"] == "true" {
- keywords["@channel"] = append(keywords["@channel"], profile.Id)
- keywords["@all"] = append(keywords["@all"], profile.Id)
- }
- }
-
- return keywords
-}
-
-// Given a message and a map mapping mention keywords to the users who use them, returns a map of mentioned
-// users and a slice of potencial mention users not in the channel and whether or not @here was mentioned.
-func getExplicitMentions(message string, keywords map[string][]string) (map[string]bool, []string, bool, bool, bool) {
- mentioned := make(map[string]bool)
- potentialOthersMentioned := make([]string, 0)
- systemMentions := map[string]bool{"@here": true, "@channel": true, "@all": true}
- hereMentioned := false
- allMentioned := false
- channelMentioned := false
-
- addMentionedUsers := func(ids []string) {
- for _, id := range ids {
- mentioned[id] = true
- }
- }
-
- for _, word := range strings.Fields(message) {
- isMention := false
-
- if word == "@here" {
- hereMentioned = true
- }
-
- if word == "@channel" {
- channelMentioned = true
- }
-
- if word == "@all" {
- allMentioned = true
- }
-
- // Non-case-sensitive check for regular keys
- if ids, match := keywords[strings.ToLower(word)]; match {
- addMentionedUsers(ids)
- isMention = true
- }
-
- // Case-sensitive check for first name
- if ids, match := keywords[word]; match {
- addMentionedUsers(ids)
- isMention = true
- }
-
- if !isMention {
- // No matches were found with the string split just on whitespace so try further splitting
- // the message on punctuation
- splitWords := strings.FieldsFunc(word, func(c rune) bool {
- return model.SplitRunes[c]
- })
-
- for _, splitWord := range splitWords {
- if splitWord == "@here" {
- hereMentioned = true
- }
-
- if splitWord == "@all" {
- allMentioned = true
- }
-
- if splitWord == "@channel" {
- channelMentioned = true
- }
-
- // Non-case-sensitive check for regular keys
- if ids, match := keywords[strings.ToLower(splitWord)]; match {
- addMentionedUsers(ids)
- }
-
- // Case-sensitive check for first name
- if ids, match := keywords[splitWord]; match {
- addMentionedUsers(ids)
- } else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
- username := word[1:len(splitWord)]
- potentialOthersMentioned = append(potentialOthersMentioned, username)
- }
- }
- }
- }
-
- return mentioned, potentialOthersMentioned, hereMentioned, channelMentioned, allMentioned
-}
-
-func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *model.Channel) []string {
- mentionedUsersList := make([]string, 0)
- var fchan store.StoreChannel
- var senderUsername string
-
- if post.IsSystemMessage() {
- senderUsername = c.T("system.message.name")
- } else {
- pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
- fchan = Srv.Store.FileInfo().GetForPost(post.Id)
-
- var profileMap map[string]*model.User
- if result := <-pchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.TeamId, result.Err)
- return nil
- } else {
- profileMap = result.Data.(map[string]*model.User)
- }
-
- // If the user who made the post is mention don't send a notification
- if _, ok := profileMap[post.UserId]; !ok {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId)
- return nil
- }
-
- mentionedUserIds := make(map[string]bool)
- allActivityPushUserIds := []string{}
- hereNotification := false
- channelNotification := false
- allNotification := false
- updateMentionChans := []store.StoreChannel{}
-
- if channel.Type == model.CHANNEL_DIRECT {
- var otherUserId string
- if userIds := strings.Split(channel.Name, "__"); userIds[0] == post.UserId {
- otherUserId = userIds[1]
- } else {
- otherUserId = userIds[0]
- }
-
- mentionedUserIds[otherUserId] = true
- if post.Props["from_webhook"] == "true" {
- mentionedUserIds[post.UserId] = true
- }
- } else {
- keywords := getMentionKeywordsInChannel(profileMap)
-
- var potentialOtherMentions []string
- mentionedUserIds, potentialOtherMentions, hereNotification, channelNotification, allNotification = getExplicitMentions(post.Message, keywords)
-
- // get users that have comment thread mentions enabled
- if len(post.RootId) > 0 {
- if result := <-Srv.Store.Post().Get(post.RootId); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.comment_thread.error"), post.RootId, result.Err)
- return nil
- } else {
- list := result.Data.(*model.PostList)
-
- for _, threadPost := range list.Posts {
- if profile, ok := profileMap[threadPost.UserId]; ok {
- if profile.NotifyProps["comments"] == "any" || (profile.NotifyProps["comments"] == "root" && threadPost.Id == list.Order[0]) {
- mentionedUserIds[threadPost.UserId] = true
- }
- }
- }
- }
- }
-
- // prevent the user from mentioning themselves
- if post.Props["from_webhook"] != "true" {
- delete(mentionedUserIds, post.UserId)
- }
-
- if len(potentialOtherMentions) > 0 {
- if result := <-Srv.Store.User().GetProfilesByUsernames(potentialOtherMentions, team.Id); result.Err == nil {
- outOfChannelMentions := result.Data.(map[string]*model.User)
- go sendOutOfChannelMentions(c, post, outOfChannelMentions)
- }
- }
-
- // find which users in the channel are set up to always receive mobile notifications
- for _, profile := range profileMap {
- if profile.NotifyProps["push"] == model.USER_NOTIFY_ALL &&
- (post.UserId != profile.Id || post.Props["from_webhook"] == "true") {
- allActivityPushUserIds = append(allActivityPushUserIds, profile.Id)
- }
- }
- }
-
- mentionedUsersList = make([]string, 0, len(mentionedUserIds))
- for id := range mentionedUserIds {
- mentionedUsersList = append(mentionedUsersList, id)
- updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, id))
- }
-
- var sender *model.User
- senderName := make(map[string]string)
- for _, id := range mentionedUsersList {
- senderName[id] = ""
- if profile, ok := profileMap[post.UserId]; ok {
- if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
- senderName[id] = value.(string)
- } else {
- //Get the Display name preference from the receiver
- if result := <-Srv.Store.Preference().Get(id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format"); result.Err != nil {
- // Show default sender's name if user doesn't set display settings.
- senderName[id] = profile.Username
- } else {
- senderName[id] = profile.GetDisplayNameForPreference(result.Data.(model.Preference).Value)
- }
- }
- sender = profile
- }
- }
-
- if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" {
- senderUsername = value.(string)
- } else {
- senderUsername = profileMap[post.UserId].Username
- }
-
- if utils.Cfg.EmailSettings.SendEmailNotifications {
- for _, id := range mentionedUsersList {
- userAllowsEmails := profileMap[id].NotifyProps["email"] != "false"
-
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{
- UserId: id,
- Status: model.STATUS_OFFLINE,
- Manual: false,
- LastActivityAt: 0,
- ActiveChannel: "",
- }
- }
-
- if userAllowsEmails && status.Status != model.STATUS_ONLINE {
- sendNotificationEmail(c, post, profileMap[id], channel, team, senderName[id], sender)
- }
- }
- }
-
- // If the channel has more than 1K users then @here is disabled
- if hereNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- hereNotification = false
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_here", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- // If the channel has more than 1K users then @channel is disabled
- if channelNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_channel", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- // If the channel has more than 1K users then @all is disabled
- if allNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: c.T("api.post.disabled_all", map[string]interface{}{"Users": *utils.Cfg.TeamSettings.MaxNotificationsPerChannel}),
- CreateAt: post.CreateAt + 1,
- },
- )
- }
-
- if hereNotification {
- statuses := GetAllStatuses()
- for _, status := range statuses {
- if status.UserId == post.UserId {
- continue
- }
-
- _, profileFound := profileMap[status.UserId]
- _, alreadyMentioned := mentionedUserIds[status.UserId]
-
- if status.Status == model.STATUS_ONLINE && profileFound && !alreadyMentioned {
- mentionedUsersList = append(mentionedUsersList, status.UserId)
- updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, status.UserId))
- }
- }
- }
-
- // Make sure all mention updates are complete to prevent race
- // Probably better to batch these DB updates in the future
- // MUST be completed before push notifications send
- for _, uchan := range updateMentionChans {
- if result := <-uchan; result.Err != nil {
- l4g.Warn(utils.T("api.post.update_mention_count_and_forget.update_error"), post.Id, post.ChannelId, result.Err)
- }
- }
-
- sendPushNotifications := false
- if *utils.Cfg.EmailSettings.SendPushNotifications {
- pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
- if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
- l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
- sendPushNotifications = false
- } else {
- sendPushNotifications = true
- }
- }
-
- if sendPushNotifications {
- for _, id := range mentionedUsersList {
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
- }
-
- if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
- sendPushNotification(post, profileMap[id], channel, senderName[id], true)
- }
- }
-
- for _, id := range allActivityPushUserIds {
- if _, ok := mentionedUserIds[id]; !ok {
- var status *model.Status
- var err *model.AppError
- if status, err = GetStatus(id); err != nil {
- status = &model.Status{id, model.STATUS_OFFLINE, false, 0, ""}
- }
-
- if DoesStatusAllowPushNotification(profileMap[id], status, post.ChannelId) {
- sendPushNotification(post, profileMap[id], channel, senderName[id], false)
- }
- }
- }
- }
- }
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POSTED, "", post.ChannelId, "", nil)
- message.Add("post", post.ToJson())
- message.Add("channel_type", channel.Type)
- message.Add("channel_display_name", channel.DisplayName)
- message.Add("channel_name", channel.Name)
- message.Add("sender_name", senderUsername)
- message.Add("team_id", team.Id)
-
- if len(post.FileIds) != 0 && fchan != nil {
- message.Add("otherFile", "true")
-
- var infos []*model.FileInfo
- if result := <-fchan; result.Err != nil {
- l4g.Warn(utils.T("api.post.send_notifications.files.error"), post.Id, result.Err)
- } else {
- infos = result.Data.([]*model.FileInfo)
- }
-
- for _, info := range infos {
- if info.IsImage() {
- message.Add("image", "true")
- break
- }
- }
- }
-
- if len(mentionedUsersList) != 0 {
- message.Add("mentions", model.ArrayToJson(mentionedUsersList))
- }
-
- Publish(message)
- return mentionedUsersList
-}
-
-func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) {
- // skip if inactive
- if user.DeleteAt > 0 {
- return
- }
-
- if channel.Type == model.CHANNEL_DIRECT && channel.TeamId != team.Id {
- // this message is a cross-team DM so it we need to find a team that the recipient is on to use in the link
- if result := <-Srv.Store.Team().GetTeamsByUserId(user.Id); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.get_teams.error"), user.Id, result.Err)
- return
- } else {
- // if the recipient isn't in the current user's team, just pick one
- teams := result.Data.([]*model.Team)
- found := false
-
- for i := range teams {
- if teams[i].Id == team.Id {
- found = true
- team = teams[i]
- break
- }
- }
-
- if !found {
- if len(teams) > 0 {
- team = teams[0]
- } else {
- // in case the user hasn't joined any teams we send them to the select_team page
- team = &model.Team{Name: "select_team", DisplayName: utils.Cfg.TeamSettings.SiteName}
- }
- }
- }
- }
-
- if *utils.Cfg.EmailSettings.EnableEmailBatching {
- var sendBatched bool
-
- if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL); result.Err != nil {
- // if the call fails, assume it hasn't been set and use the default
- sendBatched = false
- } else {
- // default to not using batching if the setting is set to immediate
- sendBatched = result.Data.(model.Preference).Value != model.PREFERENCE_DEFAULT_EMAIL_INTERVAL
- }
-
- if sendBatched {
- if err := AddNotificationEmailToBatch(user, post, team); err == nil {
- return
- }
- }
-
- // fall back to sending a single email if we can't batch it for some reason
- }
-
- var channelName string
- var bodyText string
- var subjectText string
- var mailTemplate string
- var mailParameters map[string]interface{}
-
- teamURL := c.GetSiteURL() + "/" + team.Name
- tm := time.Unix(post.CreateAt/1000, 0)
-
- userLocale := utils.GetUserTranslations(user.Locale)
- month := userLocale(tm.Month().String())
- day := fmt.Sprintf("%d", tm.Day())
- year := fmt.Sprintf("%d", tm.Year())
- zone, _ := tm.Zone()
-
- if channel.Type == model.CHANNEL_DIRECT {
- bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
- subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
-
- senderDisplayName := senderName
-
- mailTemplate = "api.templates.post_subject_in_direct_message"
- mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
- "SenderDisplayName": senderDisplayName, "Month": month, "Day": day, "Year": year}
- } else {
- bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
- subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
- channelName = channel.DisplayName
- mailTemplate = "api.templates.post_subject_in_channel"
- mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
- "ChannelName": channelName, "Month": month, "Day": day, "Year": year}
- }
-
- subject := fmt.Sprintf("[%v] %v", utils.Cfg.TeamSettings.SiteName, userLocale(mailTemplate, mailParameters))
-
- bodyPage := utils.NewHTMLTemplate("post_body", user.Locale)
- bodyPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage.Props["PostMessage"] = getMessageForNotification(post, userLocale)
- if team.Name != "select_team" {
- bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id
- } else {
- bodyPage.Props["TeamLink"] = teamURL
- }
-
- bodyPage.Props["BodyText"] = bodyText
- bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
- bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
- map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
- "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
- "TimeZone": zone, "Month": month, "Day": day}))
-
- if err := utils.SendMail(user.Email, html.UnescapeString(subject), bodyPage.Render()); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err)
- }
-
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostSentEmail()
- }
-}
-
-func getMessageForNotification(post *model.Post, translateFunc i18n.TranslateFunc) string {
- if len(strings.TrimSpace(post.Message)) != 0 || len(post.FileIds) == 0 {
- return post.Message
- }
-
- // extract the filenames from their paths and determine what type of files are attached
- var infos []*model.FileInfo
- if result := <-Srv.Store.FileInfo().GetForPost(post.Id); result.Err != nil {
- l4g.Warn(utils.T("api.post.get_message_for_notification.get_files.error"), post.Id, result.Err)
- } else {
- infos = result.Data.([]*model.FileInfo)
- }
-
- filenames := make([]string, len(infos))
- onlyImages := true
- for i, info := range infos {
- if escaped, err := url.QueryUnescape(filepath.Base(info.Name)); err != nil {
- // this should never error since filepath was escaped using url.QueryEscape
- filenames[i] = escaped
- } else {
- filenames[i] = info.Name
- }
-
- onlyImages = onlyImages && info.IsImage()
- }
-
- props := map[string]interface{}{"Filenames": strings.Join(filenames, ", ")}
-
- if onlyImages {
- return translateFunc("api.post.get_message_for_notification.images_sent", len(filenames), props)
- } else {
- return translateFunc("api.post.get_message_for_notification.files_sent", len(filenames), props)
- }
-}
-
-func sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName string, wasMentioned bool) {
- sessions := getMobileAppSessions(user.Id)
-
- if sessions == nil {
- return
- }
-
- var channelName string
-
- if channel.Type == model.CHANNEL_DIRECT {
- channelName = senderName
- } else {
- channelName = channel.DisplayName
- }
-
- userLocale := utils.GetUserTranslations(user.Locale)
-
- msg := model.PushNotification{}
- if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
- msg.Badge = 1
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
- msg.Type = model.PUSH_TYPE_MESSAGE
- msg.TeamId = channel.TeamId
- msg.ChannelId = channel.Id
- msg.ChannelName = channel.Name
-
- if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
- }
- } else {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
- } else if wasMentioned {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
- }
- }
-
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
-
- for _, session := range sessions {
- tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
- tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
- sendToPushProxy(tmpMessage)
- if einterfaces.GetMetricsInterface() != nil {
- einterfaces.GetMetricsInterface().IncrementPostSentPush()
- }
- }
-}
-
-func clearPushNotification(userId string, channelId string) {
- sessions := getMobileAppSessions(userId)
- if sessions == nil {
- return
- }
-
- msg := model.PushNotification{}
- msg.Type = model.PUSH_TYPE_CLEAR
- msg.ChannelId = channelId
- msg.ContentAvailable = 0
- if badge := <-Srv.Store.User().GetUnreadCount(userId); badge.Err != nil {
- msg.Badge = 0
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), userId, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
-
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.clear_push_notification.debug"), msg.DeviceId, msg.ChannelId)
- for _, session := range sessions {
- tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson()))
- tmpMessage.SetDeviceIdAndPlatform(session.DeviceId)
- sendToPushProxy(tmpMessage)
- }
-}
-
-func sendToPushProxy(msg model.PushNotification) {
- msg.ServerId = utils.CfgDiagnosticId
-
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- httpClient := &http.Client{Transport: tr}
- request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
-
- if resp, err := httpClient.Do(request); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), msg.DeviceId, err)
- } else {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }
-}
-
-func getMobileAppSessions(userId string) []*model.Session {
- if result := <-Srv.Store.Session().GetSessionsWithActiveDeviceIds(userId); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), userId, result.Err)
- return nil
- } else {
- return result.Data.([]*model.Session)
- }
-}
-
-func sendOutOfChannelMentions(c *Context, post *model.Post, profiles map[string]*model.User) {
- if len(profiles) == 0 {
- return
- }
-
- var usernames []string
- for _, user := range profiles {
- usernames = append(usernames, user.Username)
- }
- sort.Strings(usernames)
-
- var message string
- if len(usernames) == 1 {
- message = c.T("api.post.check_for_out_of_channel_mentions.message.one", map[string]interface{}{
- "Username": usernames[0],
- })
- } else {
- message = c.T("api.post.check_for_out_of_channel_mentions.message.multiple", map[string]interface{}{
- "Usernames": strings.Join(usernames[:len(usernames)-1], ", "),
- "LastUsername": usernames[len(usernames)-1],
- })
- }
-
- SendEphemeralPost(
- c.TeamId,
- post.UserId,
- &model.Post{
- ChannelId: post.ChannelId,
- Message: message,
- CreateAt: post.CreateAt + 1,
- },
- )
-}
-
-func SendEphemeralPost(teamId, userId string, post *model.Post) {
- post.Type = model.POST_EPHEMERAL
-
- // fill in fields which haven't been specified which have sensible defaults
- if post.Id == "" {
- post.Id = model.NewId()
- }
- if post.CreateAt == 0 {
- post.CreateAt = model.GetMillis()
- }
- if post.Props == nil {
- post.Props = model.StringInterface{}
- }
-
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE, "", post.ChannelId, userId, nil)
- message.Add("post", post.ToJson())
-
- go Publish(message)
-}
-
func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
post := model.PostFromJson(r.Body)
@@ -1212,7 +98,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(post.Id)
+ pchan := app.Srv.Store.Post().Get(post.Id)
if !HasPermissionToChannelContext(c, post.ChannelId, model.PERMISSION_EDIT_POST) {
return
@@ -1258,7 +144,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
newPost.EditAt = model.GetMillis()
newPost.Hashtags, _ = model.ParseHashtags(post.Message)
- if result := <-Srv.Store.Post().Update(newPost, oldPost); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Update(newPost, oldPost); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1267,9 +153,9 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", rpost.ChannelId, "", nil)
message.Add("post", rpost.ToJson())
- go Publish(message)
+ go app.Publish(message)
- InvalidateCacheForChannelPosts(rpost.ChannelId)
+ app.InvalidateCacheForChannelPosts(rpost.ChannelId)
w.Write([]byte(rpost.ToJson()))
}
@@ -1292,7 +178,7 @@ func getFlaggedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
posts := &model.PostList{}
- if result := <-Srv.Store.Post().GetFlaggedPosts(c.Session.UserId, offset, limit); result.Err != nil {
+ if result := <-app.Srv.Store.Post().GetFlaggedPosts(c.Session.UserId, offset, limit); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1323,7 +209,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- etagChan := Srv.Store.Post().GetEtag(id, true)
+ etagChan := app.Srv.Store.Post().GetEtag(id, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_CREATE_POST) {
return
@@ -1335,7 +221,7 @@ func getPosts(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().GetPosts(id, offset, limit, true)
+ pchan := app.Srv.Store.Post().GetPosts(id, offset, limit, true)
if result := <-pchan; result.Err != nil {
c.Err = result.Err
@@ -1364,7 +250,7 @@ func getPostsSince(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().GetPostsSince(id, time, true)
+ pchan := app.Srv.Store.Post().GetPostsSince(id, time, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
@@ -1396,7 +282,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return
@@ -1430,7 +316,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Post().Get(postId); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(postId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1464,7 +350,7 @@ func getPermalinkTmp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-Srv.Store.Post().Get(postId); result.Err != nil {
+ if result := <-app.Srv.Store.Post().Get(postId); result.Err != nil {
c.Err = result.Err
return
} else {
@@ -1515,7 +401,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
if result := <-pchan; result.Err != nil {
c.Err = result.Err
@@ -1541,7 +427,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if dresult := <-Srv.Store.Post().Delete(postId, model.GetMillis()); dresult.Err != nil {
+ if dresult := <-app.Srv.Store.Post().Delete(postId, model.GetMillis()); dresult.Err != nil {
c.Err = dresult.Err
return
}
@@ -1549,11 +435,11 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_DELETED, "", post.ChannelId, "", nil)
message.Add("post", post.ToJson())
- go Publish(message)
+ go app.Publish(message)
go DeletePostFiles(post)
go DeleteFlaggedPost(c.Session.UserId, post)
- InvalidateCacheForChannelPosts(post.ChannelId)
+ app.InvalidateCacheForChannelPosts(post.ChannelId)
result := make(map[string]string)
result["id"] = postId
@@ -1562,7 +448,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
}
func DeleteFlaggedPost(userId string, post *model.Post) {
- if result := <-Srv.Store.Preference().Delete(userId, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.Preference().Delete(userId, model.PREFERENCE_CATEGORY_FLAGGED_POST, post.Id); result.Err != nil {
l4g.Warn(utils.T("api.post.delete_flagged_post.app_error.warn"), result.Err)
return
}
@@ -1573,7 +459,7 @@ func DeletePostFiles(post *model.Post) {
return
}
- if result := <-Srv.Store.FileInfo().DeleteForPost(post.Id); result.Err != nil {
+ if result := <-app.Srv.Store.FileInfo().DeleteForPost(post.Id); result.Err != nil {
l4g.Warn(utils.T("api.post.delete_post_files.app_error.warn"), post.Id, result.Err)
}
}
@@ -1614,7 +500,7 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
}
// We can do better than this etag in this situation
- etagChan := Srv.Store.Post().GetEtag(id, true)
+ etagChan := app.Srv.Store.Post().GetEtag(id, true)
if !HasPermissionToChannelContext(c, id, model.PERMISSION_READ_CHANNEL) {
return
@@ -1627,9 +513,9 @@ func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, b
var pchan store.StoreChannel
if before {
- pchan = Srv.Store.Post().GetPostsBefore(id, postId, numPosts, offset)
+ pchan = app.Srv.Store.Post().GetPostsBefore(id, postId, numPosts, offset)
} else {
- pchan = Srv.Store.Post().GetPostsAfter(id, postId, numPosts, offset)
+ pchan = app.Srv.Store.Post().GetPostsAfter(id, postId, numPosts, offset)
}
if result := <-pchan; result.Err != nil {
@@ -1664,7 +550,7 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
params.OrTerms = isOrSearch
// don't allow users to search for everything
if params.Terms != "*" {
- channels = append(channels, Srv.Store.Post().Search(c.TeamId, c.Session.UserId, params))
+ channels = append(channels, app.Srv.Store.Post().Search(c.TeamId, c.Session.UserId, params))
}
}
@@ -1698,8 +584,8 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- pchan := Srv.Store.Post().Get(postId)
- fchan := Srv.Store.FileInfo().GetForPost(postId)
+ pchan := app.Srv.Store.Post().Get(postId)
+ fchan := app.Srv.Store.FileInfo().GetForPost(postId)
if !HasPermissionToChannelContext(c, channelId, model.PERMISSION_READ_CHANNEL) {
return