PLT-3512 adding join/leave channel to the CLI (#3498)

* PLT-3512 adding join/leave channel to the CLI

* PLT-3512 adding list channels to the CLI

* PLT-3512 adding restore channel

* Adding make run-cli command

* Updating txt

* Fixing txt purposed by PMs
Этот коммит содержится в:
Corey Hulen
2016-07-06 10:11:21 -08:00
коммит произвёл Christopher Speller
родитель 26c91e73fe
Коммит b1520d0b94
8 изменённых файлов: 490 добавлений и 3 удалений

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

@@ -309,6 +309,12 @@ run-server: prepare-enterprise start-docker
mkdir -p $(BUILD_WEBAPP_DIR)/dist/files
$(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) *.go &
run-cli: prepare-enterprise start-docker
@echo Running mattermost for development
@echo Example should be like >'make ARGS="-version" run-cli'
$(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) *.go ${ARGS}
run-client:
@echo Running mattermost client for development

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

@@ -135,6 +135,175 @@ func TestCliAssignRole(t *testing.T) {
}
}
func TestCliJoinChannel(t *testing.T) {
if disableCliTests {
return
}
th := Setup().InitBasic()
channel := th.CreateChannel(th.BasicClient, th.BasicTeam)
// These test cannot run since this feature requires an enteprise license
// cmd := exec.Command("bash", "-c", `go run ../mattermost.go -join_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
// output, err := cmd.CombinedOutput()
// if err != nil {
// t.Log(string(output))
// t.Fatal(err)
// }
// // Joining twice should succeed
// cmd1 := exec.Command("bash", "-c", `go run ../mattermost.go -join_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
// output1, err1 := cmd1.CombinedOutput()
// if err1 != nil {
// t.Log(string(output1))
// t.Fatal(err1)
// }
// should fail because channel does not exist
cmd2 := exec.Command("bash", "-c", `go run ../mattermost.go -join_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`asdf" -email="`+th.BasicUser2.Email+`"`)
output2, err2 := cmd2.CombinedOutput()
if err2 == nil {
t.Log(string(output2))
t.Fatal()
}
// should fail because channel does not have license
cmd3 := exec.Command("bash", "-c", `go run ../mattermost.go -join_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
output3, err3 := cmd3.CombinedOutput()
if err3 == nil {
t.Log(string(output3))
t.Fatal()
}
}
func TestCliRemoveChannel(t *testing.T) {
if disableCliTests {
return
}
th := Setup().InitBasic()
channel := th.CreateChannel(th.BasicClient, th.BasicTeam)
// These test cannot run since this feature requires an enteprise license
// cmd := exec.Command("bash", "-c", `go run ../mattermost.go -join_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
// output, err := cmd.CombinedOutput()
// if err != nil {
// t.Log(string(output))
// t.Fatal(err)
// }
// cmd0 := exec.Command("bash", "-c", `go run ../mattermost.go -leave_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
// output0, err0 := cmd0.CombinedOutput()
// if err0 != nil {
// t.Log(string(output0))
// t.Fatal(err0)
// }
// // Leaving twice should succeed
// cmd1 := exec.Command("bash", "-c", `go run ../mattermost.go -leave_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
// output1, err1 := cmd1.CombinedOutput()
// if err1 != nil {
// t.Log(string(output1))
// t.Fatal(err1)
// }
// cannot leave town-square
cmd1a := exec.Command("bash", "-c", `go run ../mattermost.go -leave_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="town-square" -email="`+th.BasicUser2.Email+`"`)
output1a, err1a := cmd1a.CombinedOutput()
if err1a == nil {
t.Log(string(output1a))
t.Fatal()
}
// should fail because channel does not exist
cmd2 := exec.Command("bash", "-c", `go run ../mattermost.go -leave_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`asdf" -email="`+th.BasicUser2.Email+`"`)
output2, err2 := cmd2.CombinedOutput()
if err2 == nil {
t.Log(string(output2))
t.Fatal()
}
// should fail because channel does not have license
cmd3 := exec.Command("bash", "-c", `go run ../mattermost.go -leave_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`" -email="`+th.BasicUser2.Email+`"`)
output3, err3 := cmd3.CombinedOutput()
if err3 == nil {
t.Log(string(output3))
t.Fatal()
}
}
func TestCliListChannels(t *testing.T) {
if disableCliTests {
return
}
th := Setup().InitBasic()
channel := th.CreateChannel(th.BasicClient, th.BasicTeam)
th.BasicClient.Must(th.BasicClient.DeleteChannel(channel.Id))
// These test cannot run since this feature requires an enteprise license
// cmd := exec.Command("bash", "-c", `go run ../mattermost.go -list_channels -team_name="`+th.BasicTeam.Name+`"`)
// output, err := cmd.CombinedOutput()
// if err != nil {
// t.Log(string(output))
// t.Fatal(err)
// }
// if !strings.Contains(string(output), "town-square") {
// t.Fatal("should have channels")
// }
// if !strings.Contains(string(output), channel.Name+" (archived)") {
// t.Fatal("should have archived channel")
// }
// should fail because channel does not have license
cmd3 := exec.Command("bash", "-c", `go run ../mattermost.go -list_channels -team_name="`+th.BasicTeam.Name+``)
output3, err3 := cmd3.CombinedOutput()
if err3 == nil {
t.Log(string(output3))
t.Fatal()
}
}
func TestCliRestoreChannel(t *testing.T) {
if disableCliTests {
return
}
th := Setup().InitBasic()
channel := th.CreateChannel(th.BasicClient, th.BasicTeam)
th.BasicClient.Must(th.BasicClient.DeleteChannel(channel.Id))
// These test cannot run since this feature requires an enteprise license
// cmd := exec.Command("bash", "-c", `go run ../mattermost.go -restore_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`"`)
// output, err := cmd.CombinedOutput()
// if err != nil {
// t.Log(string(output))
// t.Fatal(err)
// }
// // restoring twice should succeed
// cmd1 := exec.Command("bash", "-c", `go run ../mattermost.go -restore_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`"`)
// output1, err1 := cmd1.CombinedOutput()
// if err1 != nil {
// t.Log(string(output1))
// t.Fatal(err1)
// }
// should fail because channel does not have license
cmd3 := exec.Command("bash", "-c", `go run ../mattermost.go -restore_channel -team_name="`+th.BasicTeam.Name+`" -channel_name="`+channel.Name+`"`)
output3, err3 := cmd3.CombinedOutput()
if err3 == nil {
t.Log(string(output3))
t.Fatal()
}
}
func TestCliJoinTeam(t *testing.T) {
if disableCliTests {
return

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

@@ -3171,6 +3171,10 @@
"id": "store.sql.read_replicas_not_licensed.critical",
"translation": "More than 1 read replica functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license."
},
{
"id": "cli.license.critical",
"translation": "Feature requires an enterprise license. Please contact your system administrator about upgrading your enterprise license."
},
{
"id": "store.sql.remove_index.critical",
"translation": "Failed to remove index %v"
@@ -3291,6 +3295,10 @@
"id": "store.sql_channel.get_for_export.app_error",
"translation": "We couldn't get all the channels"
},
{
"id": "store.sql_channel.get_all.app_error",
"translation": "We couldn't get all the channels"
},
{
"id": "store.sql_channel.get_member.app_error",
"translation": "We couldn't get the channel member"

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

@@ -45,6 +45,10 @@ var flagCmdCreateTeam bool
var flagCmdCreateUser bool
var flagCmdInviteUser bool
var flagCmdAssignRole bool
var flagCmdJoinChannel bool
var flagCmdLeaveChannel bool
var flagCmdListChannels bool
var flagCmdRestoreChannel bool
var flagCmdJoinTeam bool
var flagCmdVersion bool
var flagCmdRunWebClientTests bool
@@ -63,6 +67,7 @@ var flagLicenseFile string
var flagEmail string
var flagPassword string
var flagTeamName string
var flagChannelName string
var flagSiteURL string
var flagConfirmBackup string
var flagRole string
@@ -198,6 +203,10 @@ func doSecurityAndDiagnostics() {
v.Set(utils.PROP_DIAGNOSTIC_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
}
if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
v.Set(utils.PROP_DIAGNOSTIC_TEAM_COUNT, strconv.FormatInt(tcr.Data.(int64), 10))
}
res, err := http.Get(utils.DIAGNOSTIC_URL + "/security?" + v.Encode())
if err != nil {
l4g.Error(utils.T("mattermost.security_info.error"))
@@ -262,6 +271,7 @@ func parseCmds() {
flag.StringVar(&flagEmail, "email", "", "")
flag.StringVar(&flagPassword, "password", "", "")
flag.StringVar(&flagTeamName, "team_name", "", "")
flag.StringVar(&flagChannelName, "channel_name", "", "")
flag.StringVar(&flagSiteURL, "site_url", "", "")
flag.StringVar(&flagConfirmBackup, "confirm_backup", "", "")
flag.StringVar(&flagRole, "role", "", "")
@@ -271,6 +281,10 @@ func parseCmds() {
flag.BoolVar(&flagCmdCreateUser, "create_user", false, "")
flag.BoolVar(&flagCmdInviteUser, "invite_user", false, "")
flag.BoolVar(&flagCmdAssignRole, "assign_role", false, "")
flag.BoolVar(&flagCmdJoinChannel, "join_channel", false, "")
flag.BoolVar(&flagCmdLeaveChannel, "leave_channel", false, "")
flag.BoolVar(&flagCmdListChannels, "list_channels", false, "")
flag.BoolVar(&flagCmdRestoreChannel, "restore_channel", false, "")
flag.BoolVar(&flagCmdJoinTeam, "join_team", false, "")
flag.BoolVar(&flagCmdVersion, "version", false, "")
flag.BoolVar(&flagCmdRunWebClientTests, "run_web_client_tests", false, "")
@@ -290,6 +304,10 @@ func parseCmds() {
flagCmdCreateUser ||
flagCmdInviteUser ||
flagCmdAssignRole ||
flagCmdJoinChannel ||
flagCmdLeaveChannel ||
flagCmdListChannels ||
flagCmdRestoreChannel ||
flagCmdJoinTeam ||
flagCmdResetPassword ||
flagCmdResetMfa ||
@@ -311,6 +329,10 @@ func runCmds() {
cmdCreateUser()
cmdInviteUser()
cmdAssignRole()
cmdJoinChannel()
cmdLeaveChannel()
cmdListChannels()
cmdRestoreChannel()
cmdJoinTeam()
cmdResetPassword()
cmdResetMfa()
@@ -905,10 +927,230 @@ func cmdAssignRole() {
}
}
func cmdJoinChannel() {
if flagCmdJoinChannel {
if len(flagTeamName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
flag.Usage()
os.Exit(1)
}
if len(flagEmail) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -email")
flag.Usage()
os.Exit(1)
}
if len(flagChannelName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -channel_name")
flag.Usage()
os.Exit(1)
}
if !utils.IsLicensed {
fmt.Fprintln(os.Stderr, utils.T("cli.license.critical"))
flag.Usage()
os.Exit(1)
}
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var user *model.User
if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
var channel *model.Channel
if result := <-api.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
channel = result.Data.(*model.Channel)
}
_, err := api.AddUserToChannel(user, channel)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
}
os.Exit(0)
}
}
func cmdLeaveChannel() {
if flagCmdLeaveChannel {
if len(flagTeamName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
flag.Usage()
os.Exit(1)
}
if len(flagEmail) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -email")
flag.Usage()
os.Exit(1)
}
if len(flagChannelName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -channel_name")
flag.Usage()
os.Exit(1)
}
if flagChannelName == model.DEFAULT_CHANNEL {
fmt.Fprintln(os.Stderr, "flag has invalid argument: -channel_name (cannot leave town-square)")
flag.Usage()
os.Exit(1)
}
if !utils.IsLicensed {
fmt.Fprintln(os.Stderr, utils.T("cli.license.critical"))
flag.Usage()
os.Exit(1)
}
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var user *model.User
if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
user = result.Data.(*model.User)
}
var channel *model.Channel
if result := <-api.Srv.Store.Channel().GetByName(team.Id, flagChannelName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
channel = result.Data.(*model.Channel)
}
err := api.RemoveUserFromChannel(user.Id, user.Id, channel)
if err != nil {
l4g.Error("%v", err)
flushLogAndExit(1)
}
os.Exit(0)
}
}
func cmdListChannels() {
if flagCmdListChannels {
if len(flagTeamName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
flag.Usage()
os.Exit(1)
}
if !utils.IsLicensed {
fmt.Fprintln(os.Stderr, utils.T("cli.license.critical"))
flag.Usage()
os.Exit(1)
}
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
channels := result.Data.([]*model.Channel)
for _, channel := range channels {
if channel.DeleteAt > 0 {
fmt.Fprintln(os.Stdout, channel.Name+" (archived)")
} else {
fmt.Fprintln(os.Stdout, channel.Name)
}
}
}
os.Exit(0)
}
}
func cmdRestoreChannel() {
if flagCmdRestoreChannel {
if len(flagTeamName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
flag.Usage()
os.Exit(1)
}
if len(flagChannelName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -channel_name")
flag.Usage()
os.Exit(1)
}
if !utils.IsLicensed {
fmt.Fprintln(os.Stderr, utils.T("cli.license.critical"))
flag.Usage()
os.Exit(1)
}
var team *model.Team
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
team = result.Data.(*model.Team)
}
var channel *model.Channel
if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
} else {
channels := result.Data.([]*model.Channel)
for _, ctemp := range channels {
if ctemp.Name == flagChannelName {
channel = ctemp
break
}
}
}
if result := <-api.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
l4g.Error("%v", result.Err)
flushLogAndExit(1)
}
os.Exit(0)
}
}
func cmdJoinTeam() {
if flagCmdJoinTeam {
if len(flagTeamName) == 0 {
fmt.Fprintln(os.Stderr, "flag needs an argument: -email")
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
flag.Usage()
os.Exit(1)
}
@@ -1275,7 +1517,7 @@ COMMANDS:
Example:
platform -invite_user -team_name="name" -email="user@example.com" -site_url="https://mattermost.example.com"
-join_team Joins a user to the team. It required the -email and
-join_team Joins a user to the team. It requires the -email and
-team_name. You may need to logout of your current session
for the new team to be applied.
Example:
@@ -1288,6 +1530,30 @@ COMMANDS:
Example:
platform -assign_role -email="user@example.com" -role="system_admin"
-join_channel Joins a user to the channel. It requires the -email, channel_name and
-team_name flags. You may need to logout of your current session
for the new channel to be applied. Requires an enterprise license.
Example:
platform -join_channel -email="user@example.com" -team_name="name" -channel_name="channel_name"
-leave_channel Removes a user from the channel. It requires the -email, channel_name and
-team_name flags. You may need to logout of your current session
for the channel to be removed. Requires an enterprise license.
Example:
platform -leave_channel -email="user@example.com" -team_name="name" -channel_name="channel_name"
-list_channels Lists all public channels and private groups for a given team.
It will append ' (archived)' to the channel name if archived. It requires the
-team_name flag. Requires an enterprise license.
Example:
platform -list_channels -team_name="name"
-restore_channel Restores a previously deleted channel.
It requires the -channel_name and
-team_name flags. Requires an enterprise license.
Example:
platform -restore_channel -team_name="name" -channel_name="channel_name"
-reset_password Resets the password for a user. It requires the
-email and -password flag.
Example:

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

@@ -289,12 +289,16 @@ func (s SqlChannelStore) get(id string, master bool) StoreChannel {
}
func (s SqlChannelStore) Delete(channelId string, time int64) StoreChannel {
return s.SetDeleteAt(channelId, time, time)
}
func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel {
storeChannel := make(StoreChannel)
go func() {
result := StoreResult{}
_, err := s.GetMaster().Exec("Update Channels SET DeleteAt = :Time, UpdateAt = :Time WHERE Id = :ChannelId", map[string]interface{}{"Time": time, "ChannelId": channelId})
_, err := s.GetMaster().Exec("Update Channels SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :ChannelId", map[string]interface{}{"DeleteAt": deleteAt, "UpdateAt": updateAt, "ChannelId": channelId})
if err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.Delete", "store.sql_channel.delete.channel.app_error", nil, "id="+channelId+", err="+err.Error())
}
@@ -948,6 +952,28 @@ func (s SqlChannelStore) GetForExport(teamId string) StoreChannel {
return storeChannel
}
func (s SqlChannelStore) GetAll(teamId string) StoreChannel {
storeChannel := make(StoreChannel)
go func() {
result := StoreResult{}
var data []*model.Channel
_, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Type != 'D' ORDER BY Name", map[string]interface{}{"TeamId": teamId})
if err != nil {
result.Err = model.NewLocAppError("SqlChannelStore.GetAll", "store.sql_channel.get_all.app_error", nil, "teamId="+teamId+", err="+err.Error())
} else {
result.Data = data
}
storeChannel <- result
close(storeChannel)
}()
return storeChannel
}
func (s SqlChannelStore) AnalyticsTypeCount(teamId string, channelType string) StoreChannel {
storeChannel := make(StoreChannel)

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

@@ -200,6 +200,15 @@ func TestChannelStoreGet(t *testing.T) {
t.Fatal("invalid returned channel")
}
}
if r3 := <-store.Channel().GetAll(o1.TeamId); r3.Err != nil {
t.Fatal(r3.Err)
} else {
channels := r3.Data.([]*model.Channel)
if len(channels) == 0 {
t.Fatal("too little")
}
}
}
func TestChannelStoreDelete(t *testing.T) {

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

@@ -77,12 +77,14 @@ type ChannelStore interface {
Get(id string) StoreChannel
GetFromMaster(id string) StoreChannel
Delete(channelId string, time int64) StoreChannel
SetDeleteAt(channelId string, deleteAt int64, updateAt int64) StoreChannel
PermanentDeleteByTeam(teamId string) StoreChannel
GetByName(team_id string, domain string) StoreChannel
GetChannels(teamId string, userId string) StoreChannel
GetMoreChannels(teamId string, userId string) StoreChannel
GetChannelCounts(teamId string, userId string) StoreChannel
GetForExport(teamId string) StoreChannel
GetAll(teamId string) StoreChannel
SaveMember(member *model.ChannelMember) StoreChannel
UpdateMember(member *model.ChannelMember) StoreChannel

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

@@ -19,6 +19,7 @@ const (
PROP_DIAGNOSTIC_DATABASE = "db"
PROP_DIAGNOSTIC_OS = "os"
PROP_DIAGNOSTIC_USER_COUNT = "uc"
PROP_DIAGNOSTIC_TEAM_COUNT = "tc"
PROP_DIAGNOSTIC_ACTIVE_USER_COUNT = "auc"
PROP_DIAGNOSTIC_UNIT_TESTS = "ut"
)