add support for exporting and importing props (#14034)

* add support for exporting and importing props

* merge master

* add export test for post props

* add check if postData exists

* add import tests for post props

* fix ci bot issues

Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com>

* fix gofmt errors

* remove test comment and add name instead

* remove uneccessary changes

Co-authored-by: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com>
Этот коммит содержится в:
Sven Hüster
2020-03-23 14:21:05 +01:00
коммит произвёл GitHub
родитель b718618fbc
Коммит 37ac6654f6
5 изменённых файлов: 105 добавлений и 4 удалений

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

@@ -156,6 +156,7 @@ func ImportLineForPost(post *model.PostForExport) *LineImportData {
Channel: &post.ChannelName, Channel: &post.ChannelName,
User: &post.Username, User: &post.Username,
Message: &post.Message, Message: &post.Message,
Props: &post.Props,
CreateAt: &post.CreateAt, CreateAt: &post.CreateAt,
}, },
} }
@@ -172,6 +173,7 @@ func ImportLineForDirectPost(post *model.DirectPostForExport) *LineImportData {
ChannelMembers: &channelMembers, ChannelMembers: &channelMembers,
User: &post.User, User: &post.User,
Message: &post.Message, Message: &post.Message,
Props: &post.Props,
CreateAt: &post.CreateAt, CreateAt: &post.CreateAt,
}, },
} }

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

@@ -446,6 +446,81 @@ func TestExportDMandGMPost(t *testing.T) {
assert.ElementsMatch(t, dmMembers, *posts[3].ChannelMembers) assert.ElementsMatch(t, dmMembers, *posts[3].ChannelMembers)
} }
func TestExportPostWithProps(t *testing.T) {
th1 := Setup(t).InitBasic()
attachments := []*model.SlackAttachment{{Footer: "footer"}}
// DM Channel
dmChannel := th1.CreateDmChannel(th1.BasicUser2)
dmMembers := []string{th1.BasicUser.Username, th1.BasicUser2.Username}
user1 := th1.CreateUser()
th1.LinkUserToTeam(user1, th1.BasicTeam)
user2 := th1.CreateUser()
th1.LinkUserToTeam(user2, th1.BasicTeam)
// GM Channel
gmChannel := th1.CreateGroupChannel(user1, user2)
gmMembers := []string{th1.BasicUser.Username, user1.Username, user2.Username}
// DM posts
p1 := &model.Post{
ChannelId: dmChannel.Id,
Message: "aa" + model.NewId() + "a",
Props: map[string]interface{}{
"attachments": attachments,
},
UserId: th1.BasicUser.Id,
}
th1.App.CreatePost(p1, dmChannel, false)
p2 := &model.Post{
ChannelId: gmChannel.Id,
Message: "dd" + model.NewId() + "a",
Props: map[string]interface{}{
"attachments": attachments,
},
UserId: th1.BasicUser.Id,
}
th1.App.CreatePost(p2, gmChannel, false)
posts, err := th1.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
require.Nil(t, err)
assert.Len(t, posts, 2)
require.NotEmpty(t, posts[0].Props)
require.NotEmpty(t, posts[1].Props)
var b bytes.Buffer
err = th1.App.BulkExport(&b, "somefile", "somePath", "someDir")
require.Nil(t, err)
th1.TearDown()
th2 := Setup(t)
defer th2.TearDown()
posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
require.Nil(t, err)
assert.Len(t, posts, 0)
// import the exported posts
err, i := th2.App.BulkImport(&b, false, 5)
assert.Nil(t, err)
assert.Equal(t, 0, i)
posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
require.Nil(t, err)
// Adding some determinism so its possible to assert on slice index
sort.Slice(posts, func(i, j int) bool { return posts[i].Message > posts[j].Message })
assert.Len(t, posts, 2)
assert.ElementsMatch(t, gmMembers, *posts[0].ChannelMembers)
assert.ElementsMatch(t, dmMembers, *posts[1].ChannelMembers)
assert.Contains(t, posts[0].Props["attachments"].([]interface{})[0], "footer")
assert.Contains(t, posts[1].Props["attachments"].([]interface{})[0], "footer")
}
func TestExportDMPostWithSelf(t *testing.T) { func TestExportDMPostWithSelf(t *testing.T) {
th1 := Setup(t).InitBasic() th1 := Setup(t).InitBasic()

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

@@ -1111,6 +1111,10 @@ func (a *App) importMultiplePosts(data []*PostImportData, dryRun bool) *model.Ap
post.CreateAt = *postData.CreateAt post.CreateAt = *postData.CreateAt
post.Hashtags, _ = model.ParseHashtags(post.Message) post.Hashtags, _ = model.ParseHashtags(post.Message)
if postData.Props != nil {
post.Props = *postData.Props
}
fileIds, err := a.uploadAttachments(postData.Attachments, post, team.Id, dryRun) fileIds, err := a.uploadAttachments(postData.Attachments, post, team.Id, dryRun)
if err != nil { if err != nil {
return err return err
@@ -1382,6 +1386,10 @@ func (a *App) importMultipleDirectPosts(data []*DirectPostImportData, dryRun boo
post.CreateAt = *postData.CreateAt post.CreateAt = *postData.CreateAt
post.Hashtags, _ = model.ParseHashtags(post.Message) post.Hashtags, _ = model.ParseHashtags(post.Message)
if postData.Props != nil {
post.Props = *postData.Props
}
fileIds, err := a.uploadAttachments(postData.Attachments, post, "noteam", dryRun) fileIds, err := a.uploadAttachments(postData.Attachments, post, "noteam", dryRun)
if err != nil { if err != nil {
return err return err

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

@@ -210,6 +210,20 @@ func TestImportBulkImport(t *testing.T) {
require.NotNil(t, err, "Should have failed due to invalid type on line 2.") require.NotNil(t, err, "Should have failed due to invalid type on line 2.")
require.Equal(t, 2, line, "Should have failed due to invalid type on line 2.") require.Equal(t, 2, line, "Should have failed due to invalid type on line 2.")
}) })
t.Run("Posts with prop information", func(t *testing.T) {
data6 := `{"type": "version", "version": 1}
{"type": "team", "team": {"type": "O", "display_name": "lskmw2d7a5ao7ppwqh5ljchvr4", "name": "` + teamName + `"}}
{"type": "channel", "channel": {"type": "O", "display_name": "xr6m6udffngark2uekvr3hoeny", "team": "` + teamName + `", "name": "` + channelName + `"}}
{"type": "user", "user": {"username": "` + username + `", "email": "` + username + `@example.com", "teams": [{"name": "` + teamName + `","theme": "` + teamTheme1 + `", "channels": [{"name": "` + channelName + `"}]}]}}
{"type": "post", "post": {"team": "` + teamName + `", "channel": "` + channelName + `", "user": "` + username + `", "message": "Hello World", "create_at": 123456789012, "attachments":[{"path": "` + testImage + `"}], "props":{"attachments":[{"id":0,"fallback":"[February 4th, 2020 2:46 PM] author: fallback","color":"D0D0D0","pretext":"","author_name":"author","author_link":"","title":"","title_link":"","text":"this post has props","fields":null,"image_url":"","thumb_url":"","footer":"Posted in #general","footer_icon":"","ts":"1580823992.000100"}]}}}
{"type": "direct_channel", "direct_channel": {"members": ["` + username + `", "` + username + `"]}}
{"type": "direct_post", "direct_post": {"channel_members": ["` + username + `", "` + username + `"], "user": "` + username + `", "message": "Hello Direct Channel to myself", "create_at": 123456789014, "props":{"attachments":[{"id":0,"fallback":"[February 4th, 2020 2:46 PM] author: fallback","color":"D0D0D0","pretext":"","author_name":"author","author_link":"","title":"","title_link":"","text":"this post has props","fields":null,"image_url":"","thumb_url":"","footer":"Posted in #general","footer_icon":"","ts":"1580823992.000100"}]}}}}`
err, line := th.App.BulkImport(strings.NewReader(data6), false, 2)
require.Nil(t, err, "BulkImport should have succeeded")
require.Equal(t, 0, line, "BulkImport line should be 0")
})
} }
func TestImportProcessImportDataFileVersionLine(t *testing.T) { func TestImportProcessImportDataFileVersionLine(t *testing.T) {

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

@@ -131,8 +131,9 @@ type PostImportData struct {
Channel *string `json:"channel"` Channel *string `json:"channel"`
User *string `json:"user"` User *string `json:"user"`
Message *string `json:"message"` Message *string `json:"message"`
CreateAt *int64 `json:"create_at"` Props *model.StringInterface `json:"props"`
CreateAt *int64 `json:"create_at"`
FlaggedBy *[]string `json:"flagged_by,omitempty"` FlaggedBy *[]string `json:"flagged_by,omitempty"`
Reactions *[]ReactionImportData `json:"reactions,omitempty"` Reactions *[]ReactionImportData `json:"reactions,omitempty"`
@@ -151,8 +152,9 @@ type DirectPostImportData struct {
ChannelMembers *[]string `json:"channel_members"` ChannelMembers *[]string `json:"channel_members"`
User *string `json:"user"` User *string `json:"user"`
Message *string `json:"message"` Message *string `json:"message"`
CreateAt *int64 `json:"create_at"` Props *model.StringInterface `json:"props"`
CreateAt *int64 `json:"create_at"`
FlaggedBy *[]string `json:"flagged_by"` FlaggedBy *[]string `json:"flagged_by"`
Reactions *[]ReactionImportData `json:"reactions"` Reactions *[]ReactionImportData `json:"reactions"`