PLT-7216: CLI Command to move channels between teams. (#7149)
* PLT-7216: CLI Command to move channels between teams. * Add comment
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1e78ff831e
Коммит
ba2868775d
@@ -1201,6 +1201,36 @@ func PermanentDeleteChannel(channel *model.Channel) *model.AppError {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is intended for use from the CLI. It is not robust against people joining the channel while the move
|
||||||
|
// is in progress, and therefore should not be used from the API without first fixing this potential race condition.
|
||||||
|
func MoveChannel(team *model.Team, channel *model.Channel) *model.AppError {
|
||||||
|
// Check that all channel members are in the destination team.
|
||||||
|
if channelMembers, err := GetChannelMembersPage(channel.Id, 0, 10000000); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
channelMemberIds := []string{}
|
||||||
|
for _, channelMember := range *channelMembers {
|
||||||
|
channelMemberIds = append(channelMemberIds, channelMember.UserId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if teamMembers, err2 := GetTeamMembersByIds(team.Id, channelMemberIds); err != nil {
|
||||||
|
return err2
|
||||||
|
} else {
|
||||||
|
if len(teamMembers) != len(*channelMembers) {
|
||||||
|
return model.NewAppError("MoveChannel", "app.channel.move_channel.members_do_not_match.error", nil, "", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the Team ID of the channel.
|
||||||
|
channel.TeamId = team.Id
|
||||||
|
if result := <-Srv.Store.Channel().Update(channel); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) {
|
func GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) {
|
||||||
if result := <-Srv.Store.Channel().GetPinnedPosts(channelId); result.Err != nil {
|
if result := <-Srv.Store.Channel().GetPinnedPosts(channelId); result.Err != nil {
|
||||||
return nil, result.Err
|
return nil, result.Err
|
||||||
|
|||||||
@@ -64,3 +64,46 @@ func TestPermanentDeleteChannel(t *testing.T) {
|
|||||||
t.Error("outgoing webhook wasn't deleted")
|
t.Error("outgoing webhook wasn't deleted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMoveChannel(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
|
||||||
|
sourceTeam := th.CreateTeam()
|
||||||
|
targetTeam := th.CreateTeam()
|
||||||
|
channel1 := th.CreateChannel(sourceTeam)
|
||||||
|
defer func() {
|
||||||
|
PermanentDeleteChannel(channel1)
|
||||||
|
PermanentDeleteTeam(sourceTeam)
|
||||||
|
PermanentDeleteTeam(targetTeam)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if _, err := AddUserToTeam(sourceTeam.Id, th.BasicUser.Id, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := AddUserToTeam(sourceTeam.Id, th.BasicUser2.Id, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := AddUserToTeam(targetTeam.Id, th.BasicUser.Id, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := AddUserToChannel(th.BasicUser, channel1); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := AddUserToChannel(th.BasicUser2, channel1); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := MoveChannel(targetTeam, channel1); err == nil {
|
||||||
|
t.Fatal("Should have failed due to mismatched members.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := AddUserToTeam(targetTeam.Id, th.BasicUser2.Id, ""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := MoveChannel(targetTeam, channel1); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,6 +71,16 @@ Archived channels are appended with ' (archived)'.`,
|
|||||||
RunE: listChannelsCmdF,
|
RunE: listChannelsCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var moveChannelsCmd = &cobra.Command{
|
||||||
|
Use: "move [team] [channels]",
|
||||||
|
Short: "Moves channels to the specified team",
|
||||||
|
Long: `Moves the provided channels to the specified team.
|
||||||
|
Validates that all users in the channel belong to the target team. Incoming/Outgoing webhooks are moved along with the channel.
|
||||||
|
Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
|
||||||
|
Example: " channel move newteam oldteam:mychannel",
|
||||||
|
RunE: moveChannelsCmdF,
|
||||||
|
}
|
||||||
|
|
||||||
var restoreChannelsCmd = &cobra.Command{
|
var restoreChannelsCmd = &cobra.Command{
|
||||||
Use: "restore [channels]",
|
Use: "restore [channels]",
|
||||||
Short: "Restore some channels",
|
Short: "Restore some channels",
|
||||||
@@ -109,6 +119,7 @@ func init() {
|
|||||||
archiveChannelsCmd,
|
archiveChannelsCmd,
|
||||||
deleteChannelsCmd,
|
deleteChannelsCmd,
|
||||||
listChannelsCmd,
|
listChannelsCmd,
|
||||||
|
moveChannelsCmd,
|
||||||
restoreChannelsCmd,
|
restoreChannelsCmd,
|
||||||
modifyChannelCmd,
|
modifyChannelCmd,
|
||||||
)
|
)
|
||||||
@@ -300,6 +311,72 @@ func deleteChannel(channel *model.Channel) *model.AppError {
|
|||||||
return app.PermanentDeleteChannel(channel)
|
return app.PermanentDeleteChannel(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func moveChannelsCmdF(cmd *cobra.Command, args []string) error {
|
||||||
|
if err := initDBCommandContextCobra(cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) < 2 {
|
||||||
|
return errors.New("Enter the destination team and at least one channel to move.")
|
||||||
|
}
|
||||||
|
|
||||||
|
team := getTeamFromTeamArg(args[0])
|
||||||
|
if team == nil {
|
||||||
|
return errors.New("Unable to find destination team '" + args[0] + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
channels := getChannelsFromChannelArgs(args[1:])
|
||||||
|
for i, channel := range channels {
|
||||||
|
if channel == nil {
|
||||||
|
CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := moveChannel(team, channel); err != nil {
|
||||||
|
CommandPrintErrorln("Unable to move channel '" + channel.Name + "' error: " + err.Error())
|
||||||
|
} else {
|
||||||
|
CommandPrettyPrintln("Moved channel '" + channel.Name + "'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveChannel(team *model.Team, channel *model.Channel) *model.AppError {
|
||||||
|
oldTeamId := channel.TeamId
|
||||||
|
|
||||||
|
if err := app.MoveChannel(team, channel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if incomingWebhooks, err := app.GetIncomingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, webhook := range incomingWebhooks {
|
||||||
|
if webhook.ChannelId == channel.Id {
|
||||||
|
webhook.TeamId = team.Id
|
||||||
|
if result := <-app.Srv.Store.Webhook().UpdateIncoming(webhook); result.Err != nil {
|
||||||
|
CommandPrintErrorln("Failed to move incoming webhook '" + webhook.Id + "' to new team.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if outgoingWebhooks, err := app.GetOutgoingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, webhook := range outgoingWebhooks {
|
||||||
|
if webhook.ChannelId == channel.Id {
|
||||||
|
webhook.TeamId = team.Id
|
||||||
|
if result := <-app.Srv.Store.Webhook().UpdateOutgoing(webhook); result.Err != nil {
|
||||||
|
CommandPrintErrorln("Failed to move outgoing webhook '" + webhook.Id + "' to new team.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func listChannelsCmdF(cmd *cobra.Command, args []string) error {
|
func listChannelsCmdF(cmd *cobra.Command, args []string) error {
|
||||||
if err := initDBCommandContextCobra(cmd); err != nil {
|
if err := initDBCommandContextCobra(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -3059,6 +3059,10 @@
|
|||||||
"id": "app.channel.create_channel.no_team_id.app_error",
|
"id": "app.channel.create_channel.no_team_id.app_error",
|
||||||
"translation": "Must specify the team ID to create a channel"
|
"translation": "Must specify the team ID to create a channel"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.channel.move_channel.members_do_not_match.error",
|
||||||
|
"translation": "Cannot move a channel unless all its members are already members of the destination team."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.channel.post_update_channel_purpose_message.post.error",
|
"id": "app.channel.post_update_channel_purpose_message.post.error",
|
||||||
"translation": "Failed to post channel purpose message"
|
"translation": "Failed to post channel purpose message"
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user