[MM-62427] Add message attachments validation (#30180)

* Add message attachments validation

* Add props validation

* Validate slack attachment fields

* Update tests and library usage

* Improve interactive dialog error for length checks

* Allow predefined colors for slack attachments

* Fix TestPostAction

* Use const for data source

* Add tests

* Cleanup unused props

* Add happy path tests

* lint fixes

* Add validation for PostActionOptions
Этот коммит содержится в:
Ben Schumacher
2025-03-20 12:53:50 +01:00
коммит произвёл GitHub
родитель 5609489e86
Коммит 9b5d8d52bf
47 изменённых файлов: 1402 добавлений и 355 удалений

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

@@ -223,7 +223,7 @@ func TestPreparePostForClient(t *testing.T) {
ChannelId: th.BasicChannel.Id,
Message: ":" + emoji.Name + ": :taco:",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: ":" + emoji.Name + ":",
},
@@ -267,7 +267,7 @@ func TestPreparePostForClient(t *testing.T) {
ChannelId: th.BasicChannel.Id,
Message: ":" + emoji3.Name + ": :taco:",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: ":" + emoji4.Name + ":",
},
@@ -531,7 +531,7 @@ func TestPreparePostForClient(t *testing.T) {
ChannelId: th.BasicChannel.Id,
Message: `Bla bla bla: ` + fmt.Sprintf(tc.link, noAccessServer.URL),
}
prepost.AddProp(UnsafeLinksPostProp, "true")
prepost.AddProp(model.PostPropsUnsafeLinks, "true")
post, err := th.App.CreatePost(th.Context, prepost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
@@ -569,7 +569,7 @@ func TestPreparePostForClient(t *testing.T) {
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Props: map[string]any{
"attachments": []any{
model.PostPropsAttachments: []any{
map[string]any{
"text": "![icon](" + server.URL + "/test-image1.png)",
},
@@ -1039,7 +1039,7 @@ func TestGetEmbedForPost(t *testing.T) {
t.Run("should return a message attachment when the post has one", func(t *testing.T) {
embed, err := th.App.getEmbedForPost(th.Context, &model.Post{
Props: model.StringInterface{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: "test",
},
@@ -1117,7 +1117,7 @@ func TestGetEmbedForPost(t *testing.T) {
t.Run("should return an embedded message attachment", func(t *testing.T) {
embed, err := th.App.getEmbedForPost(th.Context, &model.Post{
Props: model.StringInterface{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: "test",
},
@@ -1532,7 +1532,7 @@ func TestGetEmojiNamesForPost(t *testing.T) {
Post: &model.Post{
Message: "this is a post",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: ":emoji1:",
Pretext: ":emoji2:",
@@ -1560,7 +1560,7 @@ func TestGetEmojiNamesForPost(t *testing.T) {
Post: &model.Post{
Message: "this is :emoji1",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: ":emoji2:",
Pretext: ":emoji2:",
@@ -1616,7 +1616,7 @@ func TestGetCustomEmojisForPost(t *testing.T) {
post := &model.Post{
Message: ":" + emojis[1].Name + ":",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Pretext: ":" + emojis[2].Name + ":",
Text: ":" + emojis[3].Name + ":",
@@ -1642,7 +1642,7 @@ func TestGetCustomEmojisForPost(t *testing.T) {
post := &model.Post{
Message: ":secret: :" + emojis[0].Name + ":",
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: ":imaginary:",
},
@@ -1838,7 +1838,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "empty attachments",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{},
model.PostPropsAttachments: []*model.SlackAttachment{},
},
},
Expected: []string{},
@@ -1847,7 +1847,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "attachment with no fields that can contain images",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Title: "This is the title",
},
@@ -1860,7 +1860,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "images in text",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: "![logo](https://example.com/logo) and ![icon](https://example.com/icon)",
},
@@ -1873,7 +1873,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "images in pretext",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Pretext: "![logo](https://example.com/logo1) and ![icon](https://example.com/icon1)",
},
@@ -1886,7 +1886,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "images in fields",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Fields: []*model.SlackAttachmentField{
{
@@ -1903,7 +1903,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "image in author_icon",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
AuthorIcon: "https://example.com/icon2",
},
@@ -1916,7 +1916,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "image in image_url",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
ImageURL: "https://example.com/image",
},
@@ -1929,7 +1929,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "image in thumb_url",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
ThumbURL: "https://example.com/image",
},
@@ -1942,7 +1942,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "image in footer_icon",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
FooterIcon: "https://example.com/image",
},
@@ -1955,7 +1955,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "images in multiple fields",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Fields: []*model.SlackAttachmentField{
{
@@ -1975,7 +1975,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "non-string field",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Fields: []*model.SlackAttachmentField{
{
@@ -1992,7 +1992,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "images in multiple locations",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: "![text](https://example.com/text)",
Pretext: "![pretext](https://example.com/pretext)",
@@ -2014,7 +2014,7 @@ func TestGetImagesInMessageAttachments(t *testing.T) {
Name: "multiple attachments",
Post: &model.Post{
Props: map[string]any{
"attachments": []*model.SlackAttachment{
model.PostPropsAttachments: []*model.SlackAttachment{
{
Text: "![logo](https://example.com/logo)",
},