diff --git a/app/post_metadata.go b/app/post_metadata.go index b2868330da..5c14646410 100644 --- a/app/post_metadata.go +++ b/app/post_metadata.go @@ -486,6 +486,14 @@ func looksLikeAPermalink(url, siteURL string) bool { return matched } +func (a *App) containsPermalink(post *model.Post) bool { + link, _ := a.getFirstLinkAndImages(post.Message) + if link == "" { + return false + } + return looksLikeAPermalink(link, a.GetSiteURL()) +} + func (a *App) getLinkMetadata(requestURL string, timestamp int64, isNewPost bool, previewedPostPropVal string) (*opengraph.OpenGraph, *model.PostImage, *model.Permalink, error) { requestURL = resolveMetadataURL(requestURL, a.GetSiteURL()) @@ -530,7 +538,15 @@ func (a *App) getLinkMetadata(requestURL string, timestamp int64, isNewPost bool return nil, nil, nil, appErr } - permalink = &model.Permalink{PreviewPost: model.NewPreviewPost(referencedPost, referencedTeam, referencedChannel)} + // Get metadata for embedded post + if a.containsPermalink(referencedPost) { + // referencedPost contains a permalink: we don't get its metadata + permalink = &model.Permalink{PreviewPost: model.NewPreviewPost(referencedPost, referencedTeam, referencedChannel)} + } else { + // referencedPost does not contain a permalink: we get its metadata + referencedPostWithMetadata := a.PreparePostForClientWithEmbedsAndImages(referencedPost, false, false) + permalink = &model.Permalink{PreviewPost: model.NewPreviewPost(referencedPostWithMetadata, referencedTeam, referencedChannel)} + } } else { var request *http.Request diff --git a/app/post_metadata_test.go b/app/post_metadata_test.go index 8a96604763..08500f90bb 100644 --- a/app/post_metadata_test.go +++ b/app/post_metadata_test.go @@ -585,6 +585,90 @@ func TestPreparePostForClient(t *testing.T) { require.Equal(t, referencedPost.Id, preview.PostID) }) + t.Run("permalink with nested preview should have referenced post metadata", func(t *testing.T) { + th := setup(t) + defer th.TearDown() + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.SiteURL = "http://mymattermost.com" + }) + + th.Context.Session().UserId = th.BasicUser.Id + + referencedPost, err := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: `This is our logo: ` + server.URL + `/test-image2.png`, + }, th.BasicChannel, false, true) + require.Nil(t, err) + referencedPost.Metadata.Embeds = nil + + link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id) + + previewPost, err := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: link, + }, th.BasicChannel, false, true) + require.Nil(t, err) + previewPost.Metadata.Embeds = nil + + clientPost := th.App.PreparePostForClientWithEmbedsAndImages(previewPost, false, false) + firstEmbed := clientPost.Metadata.Embeds[0] + preview := firstEmbed.Data.(*model.PreviewPost) + referencedPostFirstEmbed := preview.Post.Metadata.Embeds[0] + + require.Equal(t, referencedPost.Id, preview.PostID) + require.Equal(t, referencedPostFirstEmbed.URL, serverURL+`/test-image2.png`) + }) + + t.Run("permalink with nested permalink should not have referenced post metadata", func(t *testing.T) { + th := setup(t) + defer th.TearDown() + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.SiteURL = "http://mymattermost.com" + }) + + th.Context.Session().UserId = th.BasicUser.Id + + nestedPermalinkPost, err := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: `This is our logo: ` + server.URL + `/test-image2.png`, + }, th.BasicChannel, false, true) + require.Nil(t, err) + nestedPermalinkPost.Metadata.Embeds = nil + + nestedLink := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, nestedPermalinkPost.Id) + + referencedPost, err := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: nestedLink, + }, th.BasicChannel, false, true) + require.Nil(t, err) + referencedPost.Metadata.Embeds = nil + + link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id) + + previewPost, err := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: th.BasicChannel.Id, + Message: link, + }, th.BasicChannel, false, true) + require.Nil(t, err) + previewPost.Metadata.Embeds = nil + + clientPost := th.App.PreparePostForClientWithEmbedsAndImages(previewPost, false, false) + firstEmbed := clientPost.Metadata.Embeds[0] + preview := firstEmbed.Data.(*model.PreviewPost) + referencedPostMetadata := preview.Post.Metadata + + require.Equal(t, referencedPost.Id, preview.PostID) + require.Equal(t, referencedPostMetadata, (*model.PostMetadata)(nil)) + }) + t.Run("permalink preview renders after toggling off the feature", func(t *testing.T) { th := setup(t) defer th.TearDown() @@ -2482,3 +2566,39 @@ func TestLooksLikeAPermalink(t *testing.T) { }) } } + +func TestContainsPermalink(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + const siteURLWithSubpath = "http://localhost:8065/foo" + + testCases := []struct { + Description string + Post *model.Post + Expected bool + }{ + { + Description: "contains a permalink", + Post: &model.Post{ + Message: fmt.Sprintf("%s/private-core/pl/dppezk51jp8afbhwxf1jpag66r", siteURLWithSubpath), + }, + Expected: true, + }, + { + Description: "does not contain a permalink", + Post: &model.Post{ + Message: "foobar", + }, + Expected: false, + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.Description, func(t *testing.T) { + actual := th.App.containsPermalink(testCase.Post) + assert.Equal(t, testCase.Expected, actual) + }) + } +}