[MM-21378] Add mutex to model.Post to guard against race conditions on Post.Props (#13884)

* Add mutex to model.Post to guard against race conditions on Post.Props

* Rename mutex

* Add GetProp() method to Post

* Fix more tests

* Fix flaky test

Benchmarks:

BenchmarkPostPropsGet_indirect
BenchmarkPostPropsGet_indirect-2     	85026746	        13.0 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_indirect-4     	90273747	        13.0 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_indirect-8     	88324293	        13.0 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_indirect-16    	91427720	        13.1 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_direct
BenchmarkPostPropsGet_direct-2       	1000000000	         0.242 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_direct-4       	1000000000	         0.241 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_direct-8       	1000000000	         0.240 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsGet_direct-16      	1000000000	         0.241 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsAdd_indirect
BenchmarkPostPropsAdd_indirect-2     	 5602224	       203 ns/op	     336 B/op	       2 allocs/op
BenchmarkPostPropsAdd_indirect-4     	 5959496	       206 ns/op	     336 B/op	       2 allocs/op
BenchmarkPostPropsAdd_indirect-8     	 5833999	       205 ns/op	     336 B/op	       2 allocs/op
BenchmarkPostPropsAdd_indirect-16    	 5802493	       225 ns/op	     336 B/op	       2 allocs/op
BenchmarkPostPropsAdd_direct
BenchmarkPostPropsAdd_direct-2       	100000000	        11.3 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsAdd_direct-4       	100000000	        11.3 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsAdd_direct-8       	100000000	        11.6 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsAdd_direct-16      	99840794	        11.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsDel_indirect
BenchmarkPostPropsDel_indirect-2     	18824002	        61.9 ns/op	      48 B/op	       1 allocs/op
BenchmarkPostPropsDel_indirect-4     	19470736	        63.8 ns/op	      48 B/op	       1 allocs/op
BenchmarkPostPropsDel_indirect-8     	17640460	        65.3 ns/op	      48 B/op	       1 allocs/op
BenchmarkPostPropsDel_indirect-16    	18692962	        65.4 ns/op	      48 B/op	       1 allocs/op
BenchmarkPostPropsDel_direct
BenchmarkPostPropsDel_direct-2       	516257440	         2.34 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsDel_direct-4       	514865216	         2.43 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsDel_direct-8       	511330477	         2.37 ns/op	       0 B/op	       0 allocs/op
BenchmarkPostPropsDel_direct-16      	499504010	         2.38 ns/op	       0 B/op	       0 allocs/op
Этот коммит содержится в:
Claudio Costa
2020-03-13 21:12:20 +01:00
коммит произвёл GitHub
родитель 9e580361c2
Коммит 1e53fe85ad
28 изменённых файлов: 430 добавлений и 195 удалений

Просмотреть файл

@@ -489,7 +489,7 @@ func TestAddChannelMemberNoUserRequestor(t *testing.T) {
assert.Equal(t, model.POST_JOIN_CHANNEL, post.Type)
assert.Equal(t, user.Id, post.UserId)
assert.Equal(t, user.Username, post.Props["username"])
assert.Equal(t, user.Username, post.GetProp("username"))
}
}

Просмотреть файл

@@ -520,7 +520,7 @@ func (a *App) HandleCommandResponsePost(command *model.Command, args *model.Comm
post.ParentId = args.ParentId
post.UserId = args.UserId
post.Type = response.Type
post.Props = response.Props
post.SetProps(response.Props)
if len(response.ChannelId) != 0 {
_, err := a.GetChannelMember(response.ChannelId, args.UserId)

Просмотреть файл

@@ -104,16 +104,16 @@ func TestHandleCommandResponsePost(t *testing.T) {
assert.Equal(t, args.ParentId, post.ParentId)
assert.Equal(t, args.UserId, post.UserId)
assert.Equal(t, resp.Type, post.Type)
assert.Equal(t, resp.Props, post.Props)
assert.Equal(t, resp.Props, post.GetProps())
assert.Equal(t, resp.Text, post.Message)
assert.Nil(t, post.Props["override_icon_url"])
assert.Nil(t, post.Props["override_username"])
assert.Nil(t, post.Props["from_webhook"])
assert.Nil(t, post.GetProp("override_icon_url"))
assert.Nil(t, post.GetProp("override_username"))
assert.Nil(t, post.GetProp("from_webhook"))
// Command is not built in, so it is a bot command.
builtIn = false
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, "true", post.GetProp("from_webhook"))
builtIn = true
@@ -135,23 +135,23 @@ func TestHandleCommandResponsePost(t *testing.T) {
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Nil(t, post.Props["override_username"])
assert.Nil(t, post.GetProp("override_username"))
*th.App.Config().ServiceSettings.EnablePostUsernameOverride = true
// Override username config is turned on. Override username through command property.
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Equal(t, command.Username, post.Props["override_username"])
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, command.Username, post.GetProp("override_username"))
assert.Equal(t, "true", post.GetProp("from_webhook"))
command.Username = ""
// Override username through response property.
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Equal(t, resp.Username, post.Props["override_username"])
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, resp.Username, post.GetProp("override_username"))
assert.Equal(t, "true", post.GetProp("from_webhook"))
*th.App.Config().ServiceSettings.EnablePostUsernameOverride = false
@@ -162,23 +162,23 @@ func TestHandleCommandResponsePost(t *testing.T) {
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Nil(t, post.Props["override_icon_url"])
assert.Nil(t, post.GetProp("override_icon_url"))
*th.App.Config().ServiceSettings.EnablePostIconOverride = true
// Override icon url config is turned on. Override icon url through command property.
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Equal(t, command.IconURL, post.Props["override_icon_url"])
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, command.IconURL, post.GetProp("override_icon_url"))
assert.Equal(t, "true", post.GetProp("from_webhook"))
command.IconURL = ""
// Override icon url through response property.
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Equal(t, resp.IconURL, post.Props["override_icon_url"])
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, resp.IconURL, post.GetProp("override_icon_url"))
assert.Equal(t, "true", post.GetProp("from_webhook"))
// Test Slack text conversion.
resp.Text = "<!channel>"
@@ -186,7 +186,7 @@ func TestHandleCommandResponsePost(t *testing.T) {
post, err = th.App.HandleCommandResponsePost(command, args, resp, builtIn)
assert.Nil(t, err)
assert.Equal(t, "@channel", post.Message)
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, "true", post.GetProp("from_webhook"))
// Test Slack attachments text conversion.
resp.Attachments = []*model.SlackAttachment{
@@ -201,7 +201,7 @@ func TestHandleCommandResponsePost(t *testing.T) {
if assert.Len(t, post.Attachments(), 1) {
assert.Equal(t, "@here", post.Attachments()[0].Text)
}
assert.Equal(t, "true", post.Props["from_webhook"])
assert.Equal(t, "true", post.GetProp("from_webhook"))
channel = th.CreatePrivateChannel(th.BasicTeam)
resp.ChannelId = channel.Id

Просмотреть файл

@@ -331,7 +331,7 @@ func (a *App) MigrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo {
// Copy and save the updated post
newPost := &model.Post{}
*newPost = *post
newPost = post.Clone()
newPost.Filenames = []string{}
newPost.FileIds = fileIds

Просмотреть файл

@@ -138,14 +138,14 @@ func (a *App) DoPostActionWithCookie(postId, actionId, userId, selectedOption st
// Save the original values that may need to be preserved (including selected
// Props, i.e. override_username, override_icon_url)
for _, key := range model.PostActionRetainPropKeys {
value, ok := post.Props[key]
value, ok := post.GetProps()[key]
if ok {
retain[key] = value
} else {
remove = append(remove, key)
}
}
originalProps = post.Props
originalProps = post.GetProps()
originalIsPinned = post.IsPinned
originalHasReactions = post.HasReactions
@@ -219,14 +219,14 @@ func (a *App) DoPostActionWithCookie(postId, actionId, userId, selectedOption st
response.Update.Id = postId
// Restore the post attributes and Props that need to be preserved
if response.Update.Props == nil {
response.Update.Props = originalProps
if response.Update.GetProps() == nil {
response.Update.SetProps(originalProps)
} else {
for key, value := range retain {
response.Update.AddProp(key, value)
}
for _, key := range remove {
delete(response.Update.Props, key)
response.Update.DelProp(key)
}
}
response.Update.IsPinned = originalIsPinned

Просмотреть файл

@@ -57,7 +57,7 @@ func TestPostActionInvalidURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -158,7 +158,7 @@ func TestPostAction(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
@@ -195,7 +195,7 @@ func TestPostAction(t *testing.T) {
post2, err := th.App.CreatePostAsUser(&menuPost, "")
require.Nil(t, err)
attachments2, ok := post2.Props["attachments"].([]*model.SlackAttachment)
attachments2, ok := post2.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments2[0].Actions)
@@ -253,7 +253,7 @@ func TestPostAction(t *testing.T) {
postplugin, err := th.App.CreatePostAsUser(&interactivePostPlugin, "")
require.Nil(t, err)
attachmentsPlugin, ok := postplugin.Props["attachments"].([]*model.SlackAttachment)
attachmentsPlugin, ok := postplugin.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
_, err = th.App.DoPostAction(postplugin.Id, attachmentsPlugin[0].Actions[0].Id, th.BasicUser.Id, "")
@@ -294,7 +294,7 @@ func TestPostAction(t *testing.T) {
postSiteURL, err := th.App.CreatePostAsUser(&interactivePostSiteURL, "")
require.Nil(t, err)
attachmentsSiteURL, ok := postSiteURL.Props["attachments"].([]*model.SlackAttachment)
attachmentsSiteURL, ok := postSiteURL.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
_, err = th.App.DoPostAction(postSiteURL.Id, attachmentsSiteURL[0].Actions[0].Id, th.BasicUser.Id, "")
@@ -336,7 +336,7 @@ func TestPostAction(t *testing.T) {
postSubpath, err := th.App.CreatePostAsUser(&interactivePostSubpath, "")
require.Nil(t, err)
attachmentsSubpath, ok := postSubpath.Props["attachments"].([]*model.SlackAttachment)
attachmentsSubpath, ok := postSubpath.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
_, err = th.App.DoPostAction(postSubpath.Id, attachmentsSubpath[0].Actions[0].Id, th.BasicUser.Id, "")
@@ -410,7 +410,7 @@ func TestPostActionProps(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
clientTriggerId, err := th.App.DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id, "")
@@ -422,11 +422,11 @@ func TestPostActionProps(t *testing.T) {
assert.True(t, newPost.IsPinned)
assert.False(t, newPost.HasReactions)
assert.Nil(t, newPost.Props["B"])
assert.Nil(t, newPost.Props["override_username"])
assert.Equal(t, "AA", newPost.Props["A"])
assert.Equal(t, "old_override_icon", newPost.Props["override_icon_url"])
assert.Equal(t, false, newPost.Props["from_webhook"])
assert.Nil(t, newPost.GetProp("B"))
assert.Nil(t, newPost.GetProp("override_username"))
assert.Equal(t, "AA", newPost.GetProp("A"))
assert.Equal(t, "old_override_icon", newPost.GetProp("override_icon_url"))
assert.Equal(t, false, newPost.GetProp("from_webhook"))
}
func TestSubmitInteractiveDialog(t *testing.T) {
@@ -578,7 +578,7 @@ func TestPostActionRelativeURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -618,7 +618,7 @@ func TestPostActionRelativeURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -658,7 +658,7 @@ func TestPostActionRelativeURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -699,7 +699,7 @@ func TestPostActionRelativeURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -739,7 +739,7 @@ func TestPostActionRelativeURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -813,7 +813,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -853,7 +853,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -893,7 +893,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)
@@ -933,7 +933,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
post, err := th.App.CreatePostAsUser(&interactivePost, "")
require.Nil(t, err)
attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment)
require.True(t, ok)
require.NotEmpty(t, attachments[0].Actions)
require.NotEmpty(t, attachments[0].Actions[0].Id)

Просмотреть файл

@@ -69,7 +69,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
mentions.addMention(otherUserId, DMMention)
}
if post.Props["from_webhook"] == "true" {
if post.GetProp("from_webhook") == "true" {
mentions.addMention(post.UserId, DMMention)
}
} else {
@@ -81,7 +81,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
// Add an implicit mention when a user is added to a channel
// even if the user has set 'username mentions' to false in account settings.
if post.Type == model.POST_ADD_TO_CHANNEL {
addedUserId, ok := post.Props[model.POST_PROPS_ADDED_USER_ID].(string)
addedUserId, ok := post.GetProp(model.POST_PROPS_ADDED_USER_ID).(string)
if ok {
mentions.addMention(addedUserId, KeywordMention)
}
@@ -103,7 +103,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
}
// prevent the user from mentioning themselves
if post.Props["from_webhook"] != "true" {
if post.GetProp("from_webhook") != "true" {
mentions.removeMention(post.UserId)
}
@@ -118,7 +118,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
for _, profile := range profileMap {
if (profile.NotifyProps[model.PUSH_NOTIFY_PROP] == model.USER_NOTIFY_ALL ||
channelMemberNotifyPropsMap[profile.Id][model.PUSH_NOTIFY_PROP] == model.CHANNEL_NOTIFY_ALL) &&
(post.UserId != profile.Id || post.Props["from_webhook"] == "true") &&
(post.UserId != profile.Id || post.GetProp("from_webhook") == "true") &&
!post.IsSystemMessage() {
allActivityPushUserIds = append(allActivityPushUserIds, profile.Id)
}
@@ -733,7 +733,7 @@ func (n *PostNotification) GetSenderName(userNameFormat string, overridesAllowed
}
if overridesAllowed && n.Channel.Type != model.CHANNEL_DIRECT {
if value, ok := n.Post.Props["override_username"]; ok && n.Post.Props["from_webhook"] == "true" {
if value, ok := n.Post.GetProps()["override_username"]; ok && n.Post.GetProp("from_webhook") == "true" {
return value.(string)
}
}

Просмотреть файл

@@ -425,7 +425,7 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
}
if (userNotify == model.USER_NOTIFY_ALL || channelNotify == model.CHANNEL_NOTIFY_ALL) &&
(post.UserId != user.Id || post.Props["from_webhook"] == "true") {
(post.UserId != user.Id || post.GetProp("from_webhook") == "true") {
return true
}
@@ -521,16 +521,16 @@ func (a *App) buildFullPushNotificationMessage(contentsConfig string, post *mode
}
msg.SenderName = senderName
if ou, ok := post.Props["override_username"].(string); ok && *cfg.ServiceSettings.EnablePostUsernameOverride {
if ou, ok := post.GetProp("override_username").(string); ok && *cfg.ServiceSettings.EnablePostUsernameOverride {
msg.OverrideUsername = ou
msg.SenderName = ou
}
if oi, ok := post.Props["override_icon_url"].(string); ok && *cfg.ServiceSettings.EnablePostIconOverride {
if oi, ok := post.GetProp("override_icon_url").(string); ok && *cfg.ServiceSettings.EnablePostIconOverride {
msg.OverrideIconUrl = oi
}
if fw, ok := post.Props["from_webhook"].(string); ok {
if fw, ok := post.GetProp("from_webhook").(string); ok {
msg.FromWebhook = fw
}

Просмотреть файл

@@ -1613,7 +1613,7 @@ func TestPostNotificationGetSenderName(t *testing.T) {
"overridden username": {
post: overriddenPost,
allowOverrides: true,
expected: overriddenPost.Props["override_username"].(string),
expected: overriddenPost.GetProp("override_username").(string),
},
"overridden username, direct channel": {
channel: &model.Channel{Type: model.CHANNEL_DIRECT},

Просмотреть файл

@@ -46,7 +46,7 @@ func TestPluginDeadlock(t *testing.T) {
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
if _, from_plugin := post.Props["from_plugin"]; from_plugin {
if _, from_plugin := post.GetProps()["from_plugin"]; from_plugin {
return nil, ""
}
@@ -121,7 +121,7 @@ func TestPluginDeadlock(t *testing.T) {
}
func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
if _, from_plugin := post.Props["from_plugin"]; from_plugin {
if _, from_plugin := post.GetProps()["from_plugin"]; from_plugin {
return nil, ""
}

Просмотреть файл

@@ -73,7 +73,7 @@ func (a *App) CreatePostAsUser(post *model.Post, currentSessionId string) (*mode
}
// 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 _, ok := post.GetProps()["from_webhook"]; !ok {
if _, err := a.MarkChannelsAsViewed([]string{post.ChannelId}, post.UserId, currentSessionId); err != nil {
mlog.Error(
"Encountered error updating last viewed",
@@ -241,12 +241,12 @@ func (a *App) CreatePost(post *model.Post, channel *model.Channel, triggerWebhoo
}
// Temporary fix so old plugins don't clobber new fields in SlackAttachment struct, see MM-13088
if attachments, ok := post.Props["attachments"].([]*model.SlackAttachment); ok {
if attachments, ok := post.GetProp("attachments").([]*model.SlackAttachment); ok {
jsonAttachments, err := json.Marshal(attachments)
if err == nil {
attachmentsInterface := []interface{}{}
err = json.Unmarshal(jsonAttachments, &attachmentsInterface)
post.Props["attachments"] = attachmentsInterface
post.AddProp("attachments", attachmentsInterface)
}
if err != nil {
mlog.Error("Could not convert post attachments to map interface.", mlog.Err(err))
@@ -384,8 +384,8 @@ func (a *App) FillInPostProps(post *model.Post, channel *model.Channel) *model.A
if len(channelMentionsProp) > 0 {
post.AddProp("channel_mentions", channelMentionsProp)
} else if post.Props != nil {
delete(post.Props, "channel_mentions")
} else if post.GetProps() != nil {
post.DelProp("channel_mentions")
}
return nil
@@ -439,8 +439,8 @@ func (a *App) SendEphemeralPost(userId string, post *model.Post) *model.Post {
if post.CreateAt == 0 {
post.CreateAt = model.GetMillis()
}
if post.Props == nil {
post.Props = model.StringInterface{}
if post.GetProps() == nil {
post.SetProps(make(model.StringInterface))
}
post.GenerateActionIds()
@@ -457,8 +457,8 @@ func (a *App) UpdateEphemeralPost(userId string, post *model.Post) *model.Post {
post.Type = model.POST_EPHEMERAL
post.UpdateAt = model.GetMillis()
if post.Props == nil {
post.Props = model.StringInterface{}
if post.GetProps() == nil {
post.SetProps(make(model.StringInterface))
}
post.GenerateActionIds()
@@ -526,7 +526,7 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model
}
newPost := &model.Post{}
*newPost = *oldPost
newPost = oldPost.Clone()
if newPost.Message != post.Message {
newPost.Message = post.Message
@@ -538,7 +538,7 @@ func (a *App) UpdatePost(post *model.Post, safeUpdate bool) (*model.Post, *model
newPost.IsPinned = post.IsPinned
newPost.HasReactions = post.HasReactions
newPost.FileIds = post.FileIds
newPost.Props = post.Props
newPost.SetProps(post.GetProps())
}
// Avoid deep-equal checks if EditAt was already modified through message change
@@ -1220,7 +1220,7 @@ func isCommentMention(user *model.User, post *model.Post, otherPosts map[string]
func isPostMention(user *model.User, post *model.Post, keywords map[string][]string, otherPosts map[string]*model.Post, mentionedByThread map[string]bool, checkForCommentMentions bool) bool {
// Prevent the user from mentioning themselves
if post.UserId == user.Id && post.Props["from_webhook"] != "true" {
if post.UserId == user.Id && post.GetProp("from_webhook") != "true" {
return false
}
@@ -1232,7 +1232,7 @@ func isPostMention(user *model.User, post *model.Post, keywords map[string][]str
// Check for mentions caused by being added to the channel
if post.Type == model.POST_ADD_TO_CHANNEL {
if addedUserId, ok := post.Props[model.POST_PROPS_ADDED_USER_ID].(string); ok && addedUserId == user.Id {
if addedUserId, ok := post.GetProp(model.POST_PROPS_ADDED_USER_ID).(string); ok && addedUserId == user.Id {
return true
}
}

Просмотреть файл

@@ -59,7 +59,7 @@ func (a *App) PreparePostListForClient(originalList *model.PostList) *model.Post
// OverrideIconURLIfEmoji changes the post icon override URL prop, if it has an emoji icon,
// so that it points to the URL (relative) of the emoji - static if emoji is default, /api if custom.
func (a *App) OverrideIconURLIfEmoji(post *model.Post) {
prop, ok := post.Props[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
prop, ok := post.GetProps()[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
if !ok || prop == nil {
return
}
@@ -149,7 +149,7 @@ func (a *App) getEmojisAndReactionsForPost(post *model.Post) ([]*model.Emoji, []
}
func (a *App) getEmbedForPost(post *model.Post, firstLink string, isNewPost bool) (*model.PostEmbed, error) {
if _, ok := post.Props["attachments"]; ok {
if _, ok := post.GetProps()["attachments"]; ok {
return &model.PostEmbed{
Type: model.POST_EMBED_MESSAGE_ATTACHMENT,
}, nil

Просмотреть файл

@@ -307,10 +307,10 @@ func TestPreparePostForClient(t *testing.T) {
t.Run("does not override icon URL", func(t *testing.T) {
clientPost := prepare(false, url, emoji)
s, ok := clientPost.Props[model.POST_PROPS_OVERRIDE_ICON_URL]
s, ok := clientPost.GetProps()[model.POST_PROPS_OVERRIDE_ICON_URL]
assert.True(t, ok)
assert.EqualValues(t, url, s)
s, ok = clientPost.Props[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
s, ok = clientPost.GetProps()[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
assert.True(t, ok)
assert.EqualValues(t, emoji, s)
})
@@ -318,10 +318,10 @@ func TestPreparePostForClient(t *testing.T) {
t.Run("overrides icon URL", func(t *testing.T) {
clientPost := prepare(true, url, emoji)
s, ok := clientPost.Props[model.POST_PROPS_OVERRIDE_ICON_URL]
s, ok := clientPost.GetProps()[model.POST_PROPS_OVERRIDE_ICON_URL]
assert.True(t, ok)
assert.EqualValues(t, overridenUrl, s)
s, ok = clientPost.Props[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
s, ok = clientPost.GetProps()[model.POST_PROPS_OVERRIDE_ICON_EMOJI]
assert.True(t, ok)
assert.EqualValues(t, emoji, s)
})

Просмотреть файл

@@ -256,13 +256,13 @@ func TestUpdatePostEditAt(t *testing.T) {
defer th.TearDown()
post := &model.Post{}
*post = *th.BasicPost
post = th.BasicPost.Clone()
post.IsPinned = true
saved, err := th.App.UpdatePost(post, true)
require.Nil(t, err)
assert.Equal(t, saved.EditAt, post.EditAt, "shouldn't have updated post.EditAt when pinning post")
*post = *saved
post = saved.Clone()
time.Sleep(time.Millisecond * 100)
@@ -279,7 +279,7 @@ func TestUpdatePostTimeLimit(t *testing.T) {
defer th.TearDown()
post := &model.Post{}
*post = *th.BasicPost
post = th.BasicPost.Clone()
th.App.SetLicense(model.NewTestLicense())
@@ -433,7 +433,7 @@ func TestPostChannelMentions(t *testing.T) {
"mention-test": map[string]interface{}{
"display_name": "Mention Test",
},
}, result.Props["channel_mentions"])
}, result.GetProp("channel_mentions"))
post.Message = fmt.Sprintf("goodbye, ~%v!", channelToMention.Name)
result, err = th.App.UpdatePost(post, false)
@@ -442,7 +442,7 @@ func TestPostChannelMentions(t *testing.T) {
"mention-test": map[string]interface{}{
"display_name": "Mention Test",
},
}, result.Props["channel_mentions"])
}, result.GetProp("channel_mentions"))
}
func TestImageProxy(t *testing.T) {
@@ -694,7 +694,7 @@ func TestCreatePost(t *testing.T) {
}
rpost, err := th.App.CreatePost(postWithNoMention, th.BasicChannel, false)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
postWithMention := &model.Post{
ChannelId: th.BasicChannel.Id,
@@ -703,7 +703,7 @@ func TestCreatePost(t *testing.T) {
}
rpost, err = th.App.CreatePost(postWithMention, th.BasicChannel, false)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
})
t.Run("Sets prop when post has mentions and user does not have USE_CHANNEL_MENTIONS", func(t *testing.T) {
@@ -716,7 +716,7 @@ func TestCreatePost(t *testing.T) {
}
rpost, err := th.App.CreatePost(postWithNoMention, th.BasicChannel, false)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
postWithMention := &model.Post{
ChannelId: th.BasicChannel.Id,
@@ -725,7 +725,7 @@ func TestCreatePost(t *testing.T) {
}
rpost, err = th.App.CreatePost(postWithMention, th.BasicChannel, false)
require.Nil(t, err)
assert.Equal(t, rpost.Props[model.POST_PROPS_MENTION_HIGHLIGHT_DISABLED], true)
assert.Equal(t, rpost.GetProp(model.POST_PROPS_MENTION_HIGHLIGHT_DISABLED), true)
th.AddPermissionToRole(model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.CHANNEL_USER_ROLE_ID)
})
@@ -787,13 +787,13 @@ func TestPatchPost(t *testing.T) {
rpost, err = th.App.PatchPost(rpost.Id, patchWithNoMention)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
patchWithMention := &model.PostPatch{Message: model.NewString("This patch has a mention now @here")}
rpost, err = th.App.PatchPost(rpost.Id, patchWithMention)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
})
t.Run("Sets prop when user does not have USE_CHANNEL_MENTIONS", func(t *testing.T) {
@@ -802,13 +802,13 @@ func TestPatchPost(t *testing.T) {
patchWithNoMention := &model.PostPatch{Message: model.NewString("This patch still does not have a mention")}
rpost, err = th.App.PatchPost(rpost.Id, patchWithNoMention)
require.Nil(t, err)
assert.Equal(t, rpost.Props, model.StringInterface{})
assert.Equal(t, rpost.GetProps(), model.StringInterface{})
patchWithMention := &model.PostPatch{Message: model.NewString("This patch has a mention now @here")}
rpost, err = th.App.PatchPost(rpost.Id, patchWithMention)
require.Nil(t, err)
assert.Equal(t, rpost.Props[model.POST_PROPS_MENTION_HIGHLIGHT_DISABLED], true)
assert.Equal(t, rpost.GetProp(model.POST_PROPS_MENTION_HIGHLIGHT_DISABLED), true)
th.AddPermissionToRole(model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.CHANNEL_USER_ROLE_ID)
})

Просмотреть файл

@@ -168,20 +168,21 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model.
splits := make([]*model.Post, 0)
remainingText := post.Message
base := *post
base := post.Clone()
base.Message = ""
base.Props = make(map[string]interface{})
for k, v := range post.Props {
base.SetProps(make(map[string]interface{}))
for k, v := range post.GetProps() {
if k != "attachments" {
base.Props[k] = v
base.AddProp(k, v)
}
}
if utf8.RuneCountInString(model.StringInterfaceToJson(base.Props)) > model.POST_PROPS_MAX_USER_RUNES {
if utf8.RuneCountInString(model.StringInterfaceToJson(base.GetProps())) > model.POST_PROPS_MAX_USER_RUNES {
return nil, model.NewAppError("SplitWebhookPost", "web.incoming_webhook.split_props_length.app_error", map[string]interface{}{"Max": model.POST_PROPS_MAX_USER_RUNES}, "", http.StatusBadRequest)
}
for utf8.RuneCountInString(remainingText) > maxPostSize {
split := base
split := base.Clone()
x := 0
for index := range remainingText {
x++
@@ -191,20 +192,20 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model.
break
}
}
splits = append(splits, &split)
splits = append(splits, split)
}
split := base
split := base.Clone()
split.Message = remainingText
splits = append(splits, &split)
splits = append(splits, split)
attachments, _ := post.Props["attachments"].([]*model.SlackAttachment)
attachments, _ := post.GetProp("attachments").([]*model.SlackAttachment)
for _, attachment := range attachments {
newAttachment := *attachment
for {
lastSplit := splits[len(splits)-1]
newProps := make(map[string]interface{})
for k, v := range lastSplit.Props {
for k, v := range lastSplit.GetProps() {
newProps[k] = v
}
origAttachments, _ := newProps["attachments"].([]*model.SlackAttachment)
@@ -213,13 +214,13 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model.
runeCount := utf8.RuneCountInString(newPropsString)
if runeCount <= model.POST_PROPS_MAX_USER_RUNES {
lastSplit.Props = newProps
lastSplit.SetProps(newProps)
break
}
if len(origAttachments) > 0 {
newSplit := base
splits = append(splits, &newSplit)
splits = append(splits, newSplit)
continue
}
@@ -236,7 +237,7 @@ func SplitWebhookPost(post *model.Post, maxPostSize int) ([]*model.Post, *model.
break
}
}
lastSplit.Props = newProps
lastSplit.SetProps(newProps)
break
}
}

Просмотреть файл

@@ -302,9 +302,9 @@ func TestCreateWebhookPost(t *testing.T) {
}, model.POST_SLACK_ATTACHMENT, "")
require.Nil(t, err)
assert.Contains(t, post.Props, "from_webhook", "missing from_webhook prop")
assert.Contains(t, post.Props, "attachments", "missing attachments prop")
assert.Contains(t, post.Props, "webhook_display_name", "missing webhook_display_name prop")
assert.Contains(t, post.GetProps(), "from_webhook", "missing from_webhook prop")
assert.Contains(t, post.GetProps(), "attachments", "missing attachments prop")
assert.Contains(t, post.GetProps(), "webhook_display_name", "missing webhook_display_name prop")
_, err = th.App.CreateWebhookPost(hook.UserId, th.BasicChannel, "foo", "user", "http://iconurl", "", nil, model.POST_SYSTEM_GENERIC, "")
require.NotNil(t, err, "Should have failed - bad post type")
@@ -449,7 +449,7 @@ func TestSplitWebhookPost(t *testing.T) {
for i, split := range splits {
if i < len(tc.Expected) {
assert.Equal(t, tc.Expected[i].Message, split.Message)
assert.Equal(t, tc.Expected[i].Props["attachments"], split.Props["attachments"])
assert.Equal(t, tc.Expected[i].GetProp("attachments"), split.GetProp("attachments"))
}
}
})
@@ -610,17 +610,17 @@ func TestTriggerOutGoingWebhookWithUsernameAndIconURL(t *testing.T) {
select {
case webhookPost := <-createdPost:
assert.Equal(t, webhookPost.Message, "sample response text from test server")
assert.Equal(t, webhookPost.Props["from_webhook"], "true")
assert.Equal(t, webhookPost.GetProp("from_webhook"), "true")
if testCase.ExpectedIconUrl != "" {
assert.Equal(t, webhookPost.Props["override_icon_url"], testCase.ExpectedIconUrl)
assert.Equal(t, webhookPost.GetProp("override_icon_url"), testCase.ExpectedIconUrl)
} else {
assert.Nil(t, webhookPost.Props["override_icon_url"])
assert.Nil(t, webhookPost.GetProp("override_icon_url"))
}
if testCase.ExpectedUsername != "" {
assert.Equal(t, webhookPost.Props["override_username"], testCase.ExpectedUsername)
assert.Equal(t, webhookPost.GetProp("override_username"), testCase.ExpectedUsername)
} else {
assert.Nil(t, webhookPost.Props["override_username"])
assert.Nil(t, webhookPost.GetProp("override_username"))
}
case <-time.After(5 * time.Second):
require.Fail(t, "Timeout, webhook response not created as post")