PLT-4378 Slack import when channel name is deleted (#4649)

This fixes the issue where the channel fails to Import from Slack if
there is already a channel with the same name on Mattermost that has
been deleted.
Этот коммит содержится в:
George Goldberg
2017-01-26 02:14:12 +00:00
коммит произвёл enahum
родитель 57d9d0ad1e
Коммит f7476b2fb6
5 изменённых файлов: 82 добавлений и 7 удалений

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

@@ -470,18 +470,28 @@ func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[str
Header: sChannel.Topic["value"], Header: sChannel.Topic["value"],
} }
newChannel = SlackSanitiseChannelProperties(newChannel) newChannel = SlackSanitiseChannelProperties(newChannel)
mChannel := ImportChannel(&newChannel)
var mChannel *model.Channel
if result := <-Srv.Store.Channel().GetByName(teamId, sChannel.Name); result.Err == nil {
// The channel already exists as an active channel. Merge with the existing one.
mChannel = result.Data.(*model.Channel)
log.WriteString(utils.T("api.slackimport.slack_add_channels.merge", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
} else if result := <-Srv.Store.Channel().GetDeletedByName(teamId, sChannel.Name); result.Err == nil {
// The channel already exists but has been deleted. Generate a random string for the handle instead.
newChannel.Name = model.NewId()
newChannel = SlackSanitiseChannelProperties(newChannel)
}
if mChannel == nil {
// Haven't found an existing channel to merge with. Try importing it as a new one.
mChannel = ImportChannel(&newChannel)
if mChannel == nil { if mChannel == nil {
// Maybe it already exists?
if result := <-Srv.Store.Channel().GetByName(teamId, sChannel.Name); result.Err != nil {
l4g.Warn(utils.T("api.slackimport.slack_add_channels.import_failed.warn"), newChannel.DisplayName) l4g.Warn(utils.T("api.slackimport.slack_add_channels.import_failed.warn"), newChannel.DisplayName)
log.WriteString(utils.T("api.slackimport.slack_add_channels.import_failed", map[string]interface{}{"DisplayName": newChannel.DisplayName})) log.WriteString(utils.T("api.slackimport.slack_add_channels.import_failed", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
continue continue
} else {
mChannel = result.Data.(*model.Channel)
log.WriteString(utils.T("api.slackimport.slack_add_channels.merge", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
} }
} }
addSlackUsersToChannel(sChannel.Members, users, mChannel, log) addSlackUsersToChannel(sChannel.Members, users, mChannel, log)
log.WriteString(newChannel.DisplayName + "\r\n") log.WriteString(newChannel.DisplayName + "\r\n")
addedChannels[sChannel.Id] = mChannel addedChannels[sChannel.Id] = mChannel

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

@@ -4315,6 +4315,14 @@
"id": "store.sql_channel.get_channels.not_found.app_error", "id": "store.sql_channel.get_channels.not_found.app_error",
"translation": "No channels were found" "translation": "No channels were found"
}, },
{
"id": "store.sql_channel.get_deleted_by_name.existing.app_error",
"translation": "We couldn't find the existing deleted channel"
},
{
"id": "store.sql_channel.get_deleted_by_name.missing.app_error",
"translation": "No deleted channel exists with that name"
},
{ {
"id": "store.sql_channel.get_extra_members.app_error", "id": "store.sql_channel.get_extra_members.app_error",
"translation": "We couldn't get the extra info for channel members" "translation": "We couldn't get the extra info for channel members"

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

@@ -579,6 +579,31 @@ func (s SqlChannelStore) getByName(teamId string, name string, includeDeleted bo
return storeChannel return storeChannel
} }
func (s SqlChannelStore) GetDeletedByName(teamId string, name string) StoreChannel {
storeChannel := make(StoreChannel, 1)
go func() {
result := StoreResult{}
channel := model.Channel{}
if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt != 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
if err == sql.ErrNoRows {
result.Err = model.NewLocAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.missing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error())
} else {
result.Err = model.NewLocAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error())
}
} else {
result.Data = &channel
}
storeChannel <- result
close(storeChannel)
}()
return storeChannel
}
func (s SqlChannelStore) SaveMember(member *model.ChannelMember) StoreChannel { func (s SqlChannelStore) SaveMember(member *model.ChannelMember) StoreChannel {
storeChannel := make(StoreChannel, 1) storeChannel := make(StoreChannel, 1)

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

@@ -352,7 +352,8 @@ func TestChannelStoreGetByName(t *testing.T) {
o1.Type = model.CHANNEL_OPEN o1.Type = model.CHANNEL_OPEN
Must(store.Channel().Save(&o1)) Must(store.Channel().Save(&o1))
if r1 := <-store.Channel().GetByName(o1.TeamId, o1.Name); r1.Err != nil { r1 := <-store.Channel().GetByName(o1.TeamId, o1.Name)
if r1.Err != nil {
t.Fatal(r1.Err) t.Fatal(r1.Err)
} else { } else {
if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { if r1.Data.(*model.Channel).ToJson() != o1.ToJson() {
@@ -363,6 +364,36 @@ func TestChannelStoreGetByName(t *testing.T) {
if err := (<-store.Channel().GetByName(o1.TeamId, "")).Err; err == nil { if err := (<-store.Channel().GetByName(o1.TeamId, "")).Err; err == nil {
t.Fatal("Missing id should have failed") t.Fatal("Missing id should have failed")
} }
Must(store.Channel().Delete(r1.Data.(*model.Channel).Id, model.GetMillis()))
if err := (<-store.Channel().GetByName(o1.TeamId, "")).Err; err == nil {
t.Fatal("Deleted channel should not be returned by GetByName()")
}
}
func TestChannelStoreGetDeletedByName(t *testing.T) {
Setup()
o1 := model.Channel{}
o1.TeamId = model.NewId()
o1.DisplayName = "Name"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
o1.DeleteAt = model.GetMillis()
Must(store.Channel().Save(&o1))
if r1 := <-store.Channel().GetDeletedByName(o1.TeamId, o1.Name); r1.Err != nil {
t.Fatal(r1.Err)
} else {
if r1.Data.(*model.Channel).ToJson() != o1.ToJson() {
t.Fatal("invalid returned channel")
}
}
if err := (<-store.Channel().GetDeletedByName(o1.TeamId, "")).Err; err == nil {
t.Fatal("Missing id should have failed")
}
} }
func TestChannelMemberStore(t *testing.T) { func TestChannelMemberStore(t *testing.T) {

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

@@ -93,6 +93,7 @@ type ChannelStore interface {
PermanentDeleteByTeam(teamId string) StoreChannel PermanentDeleteByTeam(teamId string) StoreChannel
GetByName(team_id string, name string) StoreChannel GetByName(team_id string, name string) StoreChannel
GetByNameIncludeDeleted(team_id string, name string) StoreChannel GetByNameIncludeDeleted(team_id string, name string) StoreChannel
GetDeletedByName(team_id string, name string) StoreChannel
GetChannels(teamId string, userId string) StoreChannel GetChannels(teamId string, userId string) StoreChannel
GetMoreChannels(teamId string, userId string, offset int, limit int) StoreChannel GetMoreChannels(teamId string, userId string, offset int, limit int) StoreChannel
GetChannelCounts(teamId string, userId string) StoreChannel GetChannelCounts(teamId string, userId string) StoreChannel