From 56e74239d6b34df8f30ef046f0b0ff4ff0866a71 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Sun, 14 Jun 2015 23:53:32 -0800 Subject: first commit --- api/command.go | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 api/command.go (limited to 'api/command.go') diff --git a/api/command.go b/api/command.go new file mode 100644 index 000000000..9efc79b49 --- /dev/null +++ b/api/command.go @@ -0,0 +1,470 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +import ( + l4g "code.google.com/p/log4go" + "github.com/gorilla/mux" + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" + "net/http" + "strconv" + "strings" +) + +type commandHandler func(c *Context, command *model.Command) bool + +var commands = []commandHandler{ + logoutCommand, + joinCommand, + loadTestCommand, + echoCommand, +} + +func InitCommand(r *mux.Router) { + l4g.Debug("Initializing command api routes") + r.Handle("/command", ApiUserRequired(command)).Methods("POST") + hub.Start() +} + +func command(c *Context, w http.ResponseWriter, r *http.Request) { + + props := model.MapFromJson(r.Body) + + command := &model.Command{ + Command: strings.TrimSpace(props["command"]), + ChannelId: strings.TrimSpace(props["channelId"]), + Suggest: props["suggest"] == "true", + Suggestions: make([]*model.SuggestCommand, 0, 128), + } + + checkCommand(c, command) + + if c.Err != nil { + return + } else { + w.Write([]byte(command.ToJson())) + } +} + +func checkCommand(c *Context, command *model.Command) bool { + + if len(command.Command) == 0 || strings.Index(command.Command, "/") != 0 { + c.Err = model.NewAppError("checkCommand", "Command must start with /", "") + return false + } + + if len(command.ChannelId) > 0 { + cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, command.ChannelId, c.Session.UserId) + + if !c.HasPermissionsToChannel(cchan, "checkCommand") { + return true + } + } + + for _, v := range commands { + if v(c, command) { + return true + } else if c.Err != nil { + return true + } + } + + return false +} + +func logoutCommand(c *Context, command *model.Command) bool { + + cmd := "/logout" + + if strings.Index(command.Command, cmd) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"}) + + if !command.Suggest { + command.GotoLocation = "/logout" + command.Response = model.RESP_EXECUTED + return true + } + + } else if strings.Index(cmd, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"}) + } + + return false +} + +func echoCommand(c *Context, command *model.Command) bool { + + cmd := "/echo" + + if strings.Index(command.Command, cmd) == 0 { + parts := strings.SplitN(command.Command, " ", 3) + + channelName := "" + if len(parts) >= 2 { + channelName = parts[1] + } + + message := "" + if len(parts) >= 3 { + message = parts[2] + } + + if result := <-Srv.Store.Channel().GetChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { + c.Err = result.Err + return false + } else { + channels := result.Data.(*model.ChannelList) + + for _, v := range channels.Channels { + if v.Type == model.CHANNEL_DIRECT { + continue + } + + if v.Name == channelName && !command.Suggest { + post := &model.Post{} + post.ChannelId = v.Id + post.Message = message + + if _, err := CreateValetPost(c, post); err != nil { + c.Err = err + return false + } + + command.Response = model.RESP_EXECUTED + return true + } + + if len(channelName) == 0 || (strings.Index(v.Name, channelName) == 0 && len(parts) < 3) { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd + " " + v.Name, Description: "Echo a message using Valet in a channel"}) + } + } + } + + } else if strings.Index(cmd, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Echo a message using Valet in a channel"}) + } + + return false +} + +func joinCommand(c *Context, command *model.Command) bool { + + // looks for "/join channel-name" + cmd := "/join" + + if strings.Index(command.Command, cmd) == 0 { + + parts := strings.Split(command.Command, " ") + + startsWith := "" + + if len(parts) == 2 { + startsWith = parts[1] + } + + if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { + c.Err = result.Err + return false + } else { + channels := result.Data.(*model.ChannelList) + + for _, v := range channels.Channels { + + if v.Name == startsWith && !command.Suggest { + + if v.Type == model.CHANNEL_DIRECT { + return false + } + + JoinChannel(c, v.Id, "/command") + + if c.Err != nil { + return false + } + + command.GotoLocation = "/channels/" + v.Name + command.Response = model.RESP_EXECUTED + return true + } + + if len(startsWith) == 0 || strings.Index(v.Name, startsWith) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd + " " + v.Name, Description: "Join the open channel"}) + } + } + } + } else if strings.Index(cmd, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Join an open channel"}) + } + + return false +} + +func loadTestCommand(c *Context, command *model.Command) bool { + cmd := "/loadtest" + + // This command is only available when AllowTesting is true + if !utils.Cfg.ServiceSettings.AllowTesting { + return false + } + + if strings.Index(command.Command, cmd) == 0 { + if loadTestSetupCommand(c, command) { + return true + } + if loadTestUsersCommand(c, command) { + return true + } + if loadTestChannelsCommand(c, command) { + return true + } + if loadTestPostsCommand(c, command) { + return true + } + } else if strings.Index(cmd, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Debug Load Testing"}) + } + + return false +} + +func parseRange(command string, cmd string) (utils.Range, bool) { + tokens := strings.Fields(strings.TrimPrefix(command, cmd)) + var begin int + var end int + var err1 error + var err2 error + switch { + case len(tokens) == 1: + begin, err1 = strconv.Atoi(tokens[0]) + end = begin + if err1 != nil { + return utils.Range{0, 0}, false + } + case len(tokens) >= 2: + begin, err1 = strconv.Atoi(tokens[0]) + end, err2 = strconv.Atoi(tokens[1]) + if err1 != nil || err2 != nil { + return utils.Range{0, 0}, false + } + default: + return utils.Range{0, 0}, false + } + return utils.Range{begin, end}, true +} + +func contains(items []string, token string) bool { + for _, elem := range items { + if elem == token { + return true + } + } + return false +} + +func loadTestSetupCommand(c *Context, command *model.Command) bool { + cmd := "/loadtest setup" + + if strings.Index(command.Command, cmd) == 0 && !command.Suggest { + tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd)) + doTeams := contains(tokens, "teams") + doFuzz := contains(tokens, "fuzz") + + numArgs := 0 + if doTeams { + numArgs++ + } + if doFuzz { + numArgs++ + } + + var numTeams int + var numChannels int + var numUsers int + var numPosts int + + // Defaults + numTeams = 10 + numChannels = 10 + numUsers = 10 + numPosts = 10 + + if doTeams { + if (len(tokens) - numArgs) >= 4 { + numTeams, _ = strconv.Atoi(tokens[numArgs+0]) + numChannels, _ = strconv.Atoi(tokens[numArgs+1]) + numUsers, _ = strconv.Atoi(tokens[numArgs+2]) + numPosts, _ = strconv.Atoi(tokens[numArgs+3]) + } + } else { + if (len(tokens) - numArgs) >= 3 { + numChannels, _ = strconv.Atoi(tokens[numArgs+0]) + numUsers, _ = strconv.Atoi(tokens[numArgs+1]) + numPosts, _ = strconv.Atoi(tokens[numArgs+2]) + } + } + client := model.NewClient(c.TeamUrl + "/api/v1") + + if doTeams { + if err := CreateBasicUser(client); err != nil { + l4g.Error("Failed to create testing enviroment") + return true + } + client.LoginByEmail(BTEST_TEAM_DOMAIN_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD) + enviroment, err := CreateTestEnviromentWithTeams( + client, + utils.Range{numTeams, numTeams}, + utils.Range{numChannels, numChannels}, + utils.Range{numUsers, numUsers}, + utils.Range{numPosts, numPosts}, + doFuzz) + if err != true { + l4g.Error("Failed to create testing enviroment") + return true + } else { + l4g.Info("Testing enviroment created") + for i := 0; i < len(enviroment.Teams); i++ { + l4g.Info("Team Created: " + enviroment.Teams[i].Domain) + l4g.Info("\t User to login: " + enviroment.Enviroments[i].Users[0].Email + ", " + USER_PASSWORD) + } + } + } else { + client.MockSession(c.Session.Id) + CreateTestEnviromentInTeam( + client, + c.Session.TeamId, + utils.Range{numChannels, numChannels}, + utils.Range{numUsers, numUsers}, + utils.Range{numPosts, numPosts}, + doFuzz) + } + return true + } else if strings.Index(cmd, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{ + Suggestion: cmd, + Description: "Creates a testing enviroment in current team. [teams] [fuzz] "}) + } + + return false +} + +func loadTestUsersCommand(c *Context, command *model.Command) bool { + cmd1 := "/loadtest users" + cmd2 := "/loadtest users fuzz" + + if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { + cmd := cmd1 + doFuzz := false + if strings.Index(command.Command, cmd2) == 0 { + doFuzz = true + cmd = cmd2 + } + usersr, err := parseRange(command.Command, cmd) + if err == false { + usersr = utils.Range{10, 15} + } + client := model.NewClient(c.TeamUrl + "/api/v1") + userCreator := NewAutoUserCreator(client, c.Session.TeamId) + userCreator.Fuzzy = doFuzz + userCreator.CreateTestUsers(usersr) + return true + } else if strings.Index(cmd1, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add a specified number of random users to current team "}) + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team "}) + } else if strings.Index(cmd2, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team "}) + } + + return false +} + +func loadTestChannelsCommand(c *Context, command *model.Command) bool { + cmd1 := "/loadtest channels" + cmd2 := "/loadtest channels fuzz" + + if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { + cmd := cmd1 + doFuzz := false + if strings.Index(command.Command, cmd2) == 0 { + doFuzz = true + cmd = cmd2 + } + channelsr, err := parseRange(command.Command, cmd) + if err == false { + channelsr = utils.Range{20, 30} + } + client := model.NewClient(c.TeamUrl + "/api/v1") + client.MockSession(c.Session.Id) + channelCreator := NewAutoChannelCreator(client, c.Session.TeamId) + channelCreator.Fuzzy = doFuzz + channelCreator.CreateTestChannels(channelsr) + return true + } else if strings.Index(cmd1, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add a specified number of random channels to current team "}) + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team "}) + } else if strings.Index(cmd2, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team "}) + } + + return false +} + +func loadTestPostsCommand(c *Context, command *model.Command) bool { + cmd1 := "/loadtest posts" + cmd2 := "/loadtest posts fuzz" + + if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { + cmd := cmd1 + doFuzz := false + if strings.Index(command.Command, cmd2) == 0 { + cmd = cmd2 + doFuzz = true + } + + postsr, err := parseRange(command.Command, cmd) + if err == false { + postsr = utils.Range{20, 30} + } + + tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd)) + rimages := utils.Range{0, 0} + if len(tokens) >= 3 { + if numImages, err := strconv.Atoi(tokens[2]); err == nil { + rimages = utils.Range{numImages, numImages} + } + } + + var usernames []string + if result := <-Srv.Store.User().GetProfiles(c.Session.TeamId); result.Err == nil { + profileUsers := result.Data.(map[string]*model.User) + usernames = make([]string, len(profileUsers)) + i := 0 + for _, userprof := range profileUsers { + usernames[i] = userprof.Username + i++ + } + } + + client := model.NewClient(c.TeamUrl + "/api/v1") + client.MockSession(c.Session.Id) + testPoster := NewAutoPostCreator(client, command.ChannelId) + testPoster.Fuzzy = doFuzz + testPoster.Users = usernames + + numImages := utils.RandIntFromRange(rimages) + numPosts := utils.RandIntFromRange(postsr) + for i := 0; i < numPosts; i++ { + testPoster.HasImage = (i < numImages) + testPoster.CreateRandomPost() + } + return true + } else if strings.Index(cmd1, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add some random posts to current channel "}) + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel "}) + } else if strings.Index(cmd2, command.Command) == 0 { + command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel "}) + } + + return false +} -- cgit v1.2.3-1-g7c22