MM-45208: strip post meta for plugins (#20686)
Try two...
* Revert "Revert "Removed the opengraph type dependency for plugins by stripping post Metadata (#20612)" (#20684)"
This reverts commit 32dee6d449.
* Fixed race condition
* PR feedback
* lint
Этот коммит содержится в:
@@ -513,7 +513,7 @@ func (api *PluginAPI) SearchPostsInTeam(teamID string, paramsList []*model.Searc
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return postList.ToSlice(), nil
|
return postList.ForPlugin().ToSlice(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, searchParams model.SearchParameter) (*model.PostSearchResults, *model.AppError) {
|
func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, searchParams model.SearchParameter) (*model.PostSearchResults, *model.AppError) {
|
||||||
@@ -547,7 +547,11 @@ func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, sea
|
|||||||
includeDeletedChannels = *searchParams.IncludeDeletedChannels
|
includeDeletedChannels = *searchParams.IncludeDeletedChannels
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.app.SearchPostsForUser(api.ctx, terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage, model.ModifierMessages)
|
results, appErr := api.app.SearchPostsForUser(api.ctx, terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage, model.ModifierMessages)
|
||||||
|
if results != nil {
|
||||||
|
results = results.ForPlugin()
|
||||||
|
}
|
||||||
|
return results, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) AddChannelMember(channelID, userID string) (*model.ChannelMember, *model.AppError) {
|
func (api *PluginAPI) AddChannelMember(channelID, userID string) (*model.ChannelMember, *model.AppError) {
|
||||||
@@ -627,7 +631,11 @@ func (api *PluginAPI) GetGroupsForUser(userID string) ([]*model.Group, *model.Ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
|
func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
|
||||||
return api.app.CreatePostMissingChannel(api.ctx, post, true)
|
post, appErr := api.app.CreatePostMissingChannel(api.ctx, post, true)
|
||||||
|
if post != nil {
|
||||||
|
post = post.ForPlugin()
|
||||||
|
}
|
||||||
|
return post, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) AddReaction(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
func (api *PluginAPI) AddReaction(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
@@ -643,11 +651,11 @@ func (api *PluginAPI) GetReactions(postID string) ([]*model.Reaction, *model.App
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) SendEphemeralPost(userID string, post *model.Post) *model.Post {
|
func (api *PluginAPI) SendEphemeralPost(userID string, post *model.Post) *model.Post {
|
||||||
return api.app.SendEphemeralPost(api.ctx, userID, post)
|
return api.app.SendEphemeralPost(api.ctx, userID, post).ForPlugin()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) UpdateEphemeralPost(userID string, post *model.Post) *model.Post {
|
func (api *PluginAPI) UpdateEphemeralPost(userID string, post *model.Post) *model.Post {
|
||||||
return api.app.UpdateEphemeralPost(api.ctx, userID, post)
|
return api.app.UpdateEphemeralPost(api.ctx, userID, post).ForPlugin()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) DeleteEphemeralPost(userID, postID string) {
|
func (api *PluginAPI) DeleteEphemeralPost(userID, postID string) {
|
||||||
@@ -660,31 +668,59 @@ func (api *PluginAPI) DeletePost(postID string) *model.AppError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPostThread(postID string) (*model.PostList, *model.AppError) {
|
func (api *PluginAPI) GetPostThread(postID string) (*model.PostList, *model.AppError) {
|
||||||
return api.app.GetPostThread(postID, model.GetPostsOptions{}, "")
|
list, appErr := api.app.GetPostThread(postID, model.GetPostsOptions{}, "")
|
||||||
|
if list != nil {
|
||||||
|
list = list.ForPlugin()
|
||||||
|
}
|
||||||
|
return list, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPost(postID string) (*model.Post, *model.AppError) {
|
func (api *PluginAPI) GetPost(postID string) (*model.Post, *model.AppError) {
|
||||||
return api.app.GetSinglePost(postID, false)
|
post, appErr := api.app.GetSinglePost(postID, false)
|
||||||
|
if post != nil {
|
||||||
|
post = post.ForPlugin()
|
||||||
|
}
|
||||||
|
return post, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPostsSince(channelID string, time int64) (*model.PostList, *model.AppError) {
|
func (api *PluginAPI) GetPostsSince(channelID string, time int64) (*model.PostList, *model.AppError) {
|
||||||
return api.app.GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelID, Time: time})
|
list, appErr := api.app.GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelID, Time: time})
|
||||||
|
if list != nil {
|
||||||
|
list = list.ForPlugin()
|
||||||
|
}
|
||||||
|
return list, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPostsAfter(channelID, postID string, page, perPage int) (*model.PostList, *model.AppError) {
|
func (api *PluginAPI) GetPostsAfter(channelID, postID string, page, perPage int) (*model.PostList, *model.AppError) {
|
||||||
return api.app.GetPostsAfterPost(model.GetPostsOptions{ChannelId: channelID, PostId: postID, Page: page, PerPage: perPage})
|
list, appErr := api.app.GetPostsAfterPost(model.GetPostsOptions{ChannelId: channelID, PostId: postID, Page: page, PerPage: perPage})
|
||||||
|
if list != nil {
|
||||||
|
list = list.ForPlugin()
|
||||||
|
}
|
||||||
|
return list, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPostsBefore(channelID, postID string, page, perPage int) (*model.PostList, *model.AppError) {
|
func (api *PluginAPI) GetPostsBefore(channelID, postID string, page, perPage int) (*model.PostList, *model.AppError) {
|
||||||
return api.app.GetPostsBeforePost(model.GetPostsOptions{ChannelId: channelID, PostId: postID, Page: page, PerPage: perPage})
|
list, appErr := api.app.GetPostsBeforePost(model.GetPostsOptions{ChannelId: channelID, PostId: postID, Page: page, PerPage: perPage})
|
||||||
|
if list != nil {
|
||||||
|
list = list.ForPlugin()
|
||||||
|
}
|
||||||
|
return list, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetPostsForChannel(channelID string, page, perPage int) (*model.PostList, *model.AppError) {
|
func (api *PluginAPI) GetPostsForChannel(channelID string, page, perPage int) (*model.PostList, *model.AppError) {
|
||||||
return api.app.GetPostsPage(model.GetPostsOptions{ChannelId: channelID, Page: page, PerPage: perPage})
|
list, appErr := api.app.GetPostsPage(model.GetPostsOptions{ChannelId: channelID, Page: page, PerPage: perPage})
|
||||||
|
if list != nil {
|
||||||
|
list = list.ForPlugin()
|
||||||
|
}
|
||||||
|
return list, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) {
|
func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) {
|
||||||
return api.app.UpdatePost(api.ctx, post, false)
|
post, appErr := api.app.UpdatePost(api.ctx, post, false)
|
||||||
|
if post != nil {
|
||||||
|
post = post.ForPlugin()
|
||||||
|
}
|
||||||
|
return post, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PluginAPI) GetProfileImage(userID string) ([]byte, *model.AppError) {
|
func (api *PluginAPI) GetProfileImage(userID string) ([]byte, *model.AppError) {
|
||||||
|
|||||||
27
app/post.go
27
app/post.go
@@ -259,7 +259,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
|||||||
var rejectionError *model.AppError
|
var rejectionError *model.AppError
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post)
|
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post.ForPlugin())
|
||||||
if rejectionReason != "" {
|
if rejectionReason != "" {
|
||||||
id := "Post rejected by plugin. " + rejectionReason
|
id := "Post rejected by plugin. " + rejectionReason
|
||||||
if rejectionReason == plugin.DismissPostError {
|
if rejectionReason == plugin.DismissPostError {
|
||||||
@@ -269,6 +269,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if replacementPost != nil {
|
if replacementPost != nil {
|
||||||
|
// the original post's metadata (if there ever was any) is lost, and will be rebuilt.
|
||||||
post = replacementPost
|
post = replacementPost
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,21 +310,14 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
|||||||
// might be duplicating requests.
|
// might be duplicating requests.
|
||||||
a.Srv().seenPendingPostIdsCache.SetWithExpiry(post.PendingPostId, rpost.Id, PendingPostIDsCacheTTL)
|
a.Srv().seenPendingPostIdsCache.SetWithExpiry(post.PendingPostId, rpost.Id, PendingPostIDsCacheTTL)
|
||||||
|
|
||||||
// We make a copy of the post for the plugin hook to avoid a race condition.
|
// We make a copy of the post for the plugin hook to avoid a race condition,
|
||||||
rPostCopy := rpost.Clone()
|
// and to remove the non-GOB-encodable Metadata from it.
|
||||||
|
|
||||||
// FIXME: Removes PreviewPost from the post payload sent to the MessageHasBeenPosted hook so that plugins compiled with older versions of
|
|
||||||
// Mattermost—without the gob registration of the PreviewPost struct—won't crash.
|
|
||||||
if rPostCopy.Metadata != nil {
|
|
||||||
rPostCopy.Metadata = rPostCopy.Metadata.Copy()
|
|
||||||
}
|
|
||||||
rPostCopy.RemovePreviewPost()
|
|
||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
|
pluginPost := rpost.ForPlugin()
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenPosted(pluginContext, rPostCopy)
|
hooks.MessageHasBeenPosted(pluginContext, pluginPost)
|
||||||
return true
|
return true
|
||||||
}, plugin.MessageHasBeenPostedID)
|
}, plugin.MessageHasBeenPostedID)
|
||||||
})
|
})
|
||||||
@@ -650,12 +644,15 @@ func (a *App) UpdatePost(c *request.Context, post *model.Post, safeUpdate bool)
|
|||||||
var rejectionReason string
|
var rejectionReason string
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost, oldPost)
|
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost.ForPlugin(), oldPost.ForPlugin())
|
||||||
return post != nil
|
return post != nil
|
||||||
}, plugin.MessageWillBeUpdatedID)
|
}, plugin.MessageWillBeUpdatedID)
|
||||||
if newPost == nil {
|
if newPost == nil {
|
||||||
return nil, model.NewAppError("UpdatePost", "Post rejected by plugin. "+rejectionReason, nil, "", http.StatusBadRequest)
|
return nil, model.NewAppError("UpdatePost", "Post rejected by plugin. "+rejectionReason, nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
// Restore the post metadata that was stripped by the plugin. Set it to
|
||||||
|
// the last known good.
|
||||||
|
newPost.Metadata = oldPost.Metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
rpost, nErr := a.Srv().Store.Post().Update(newPost, oldPost)
|
rpost, nErr := a.Srv().Store.Post().Update(newPost, oldPost)
|
||||||
@@ -670,10 +667,12 @@ func (a *App) UpdatePost(c *request.Context, post *model.Post, safeUpdate bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
|
pluginOldPost := oldPost.ForPlugin()
|
||||||
|
pluginNewPost := newPost.ForPlugin()
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenUpdated(pluginContext, newPost, oldPost)
|
hooks.MessageHasBeenUpdated(pluginContext, pluginNewPost, pluginOldPost)
|
||||||
return true
|
return true
|
||||||
}, plugin.MessageHasBeenUpdatedID)
|
}, plugin.MessageHasBeenUpdatedID)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -736,18 +736,10 @@ func (o *Post) ToNilIfInvalid() *Post {
|
|||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Post) RemovePreviewPost() {
|
func (o *Post) ForPlugin() *Post {
|
||||||
if o.Metadata == nil || o.Metadata.Embeds == nil {
|
p := o.Clone()
|
||||||
return
|
p.Metadata = nil
|
||||||
}
|
return p
|
||||||
n := 0
|
|
||||||
for _, embed := range o.Metadata.Embeds {
|
|
||||||
if embed.Type != PostEmbedPermalink {
|
|
||||||
o.Metadata.Embeds[n] = embed
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
o.Metadata.Embeds = o.Metadata.Embeds[:n]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Post) GetPreviewPost() *PreviewPost {
|
func (o *Post) GetPreviewPost() *PreviewPost {
|
||||||
|
|||||||
@@ -46,6 +46,14 @@ func (o *PostList) Clone() *PostList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *PostList) ForPlugin() *PostList {
|
||||||
|
copy := o.Clone()
|
||||||
|
for k, p := range copy.Posts {
|
||||||
|
copy.Posts[k] = p.ForPlugin()
|
||||||
|
}
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
|
||||||
func (o *PostList) ToSlice() []*Post {
|
func (o *PostList) ToSlice() []*Post {
|
||||||
var posts []*Post
|
var posts []*Post
|
||||||
|
|
||||||
|
|||||||
@@ -33,3 +33,9 @@ func (o *PostSearchResults) EncodeJSON(w io.Writer) error {
|
|||||||
o.PostList.StripActionIntegrations()
|
o.PostList.StripActionIntegrations()
|
||||||
return json.NewEncoder(w).Encode(o)
|
return json.NewEncoder(w).Encode(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *PostSearchResults) ForPlugin() *PostSearchResults {
|
||||||
|
copy := *o
|
||||||
|
copy.PostList = copy.PostList.ForPlugin()
|
||||||
|
return ©
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/dyatlov/go-opengraph/opengraph"
|
|
||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
@@ -164,7 +163,6 @@ func init() {
|
|||||||
gob.Register(&pq.Error{})
|
gob.Register(&pq.Error{})
|
||||||
gob.Register(&mysql.MySQLError{})
|
gob.Register(&mysql.MySQLError{})
|
||||||
gob.Register(&ErrorString{})
|
gob.Register(&ErrorString{})
|
||||||
gob.Register(&opengraph.OpenGraph{})
|
|
||||||
gob.Register(&model.AutocompleteDynamicListArg{})
|
gob.Register(&model.AutocompleteDynamicListArg{})
|
||||||
gob.Register(&model.AutocompleteStaticListArg{})
|
gob.Register(&model.AutocompleteStaticListArg{})
|
||||||
gob.Register(&model.AutocompleteTextArg{})
|
gob.Register(&model.AutocompleteTextArg{})
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user