summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/command.go1260
-rw-r--r--api/command_test.go400
-rw-r--r--model/command.go121
-rw-r--r--model/command_test.go90
-rw-r--r--store/sql_command_store.go174
-rw-r--r--store/sql_command_store_test.go155
-rw-r--r--store/sql_store.go8
-rw-r--r--store/store.go10
8 files changed, 1359 insertions, 859 deletions
diff --git a/api/command.go b/api/command.go
index db57f0bae..cff30cdbb 100644
--- a/api/command.go
+++ b/api/command.go
@@ -4,643 +4,643 @@
package api
import (
- "io"
- "net/http"
- "path"
- "strconv"
- "strings"
- "time"
+ // "io"
+ // "net/http"
+ // "path"
+ // "strconv"
+ // "strings"
+ // "time"
l4g "code.google.com/p/log4go"
"github.com/gorilla/mux"
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/utils"
+ // "github.com/mattermost/platform/model"
+ // "github.com/mattermost/platform/utils"
)
-type commandHandler func(c *Context, command *model.Command) bool
-
-var (
- cmds = map[string]string{
- "logoutCommand": "/logout",
- "joinCommand": "/join",
- "loadTestCommand": "/loadtest",
- "echoCommand": "/echo",
- "shrugCommand": "/shrug",
- "meCommand": "/me",
- }
- commands = []commandHandler{
- logoutCommand,
- joinCommand,
- loadTestCommand,
- echoCommand,
- shrugCommand,
- meCommand,
- }
- commandNotImplementedErr = model.NewAppError("checkCommand", "Command not implemented", "")
-)
-var echoSem chan bool
+// type commandHandler func(c *Context, command *model.Command) bool
+
+// var (
+// cmds = map[string]string{
+// "logoutCommand": "/logout",
+// "joinCommand": "/join",
+// "loadTestCommand": "/loadtest",
+// "echoCommand": "/echo",
+// "shrugCommand": "/shrug",
+// "meCommand": "/me",
+// }
+// commands = []commandHandler{
+// logoutCommand,
+// joinCommand,
+// loadTestCommand,
+// echoCommand,
+// shrugCommand,
+// meCommand,
+// }
+// commandNotImplementedErr = model.NewAppError("checkCommand", "Command not implemented", "")
+// )
+// var echoSem chan bool
func InitCommand(r *mux.Router) {
l4g.Debug("Initializing command api routes")
- r.Handle("/command", ApiUserRequired(command)).Methods("POST")
-}
-
-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 {
- if c.Err != commandNotImplementedErr {
- return
- } else {
- c.Err = nil
- command.Response = model.RESP_NOT_IMPLEMENTED
- w.Write([]byte(command.ToJson()))
- 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
- }
- }
-
- if !command.Suggest {
- implemented := false
- for _, cmd := range cmds {
- bounds := len(cmd)
- if len(command.Command) < bounds {
- continue
- }
- if command.Command[:bounds] == cmd {
- implemented = true
- }
- }
- if !implemented {
- c.Err = commandNotImplementedErr
- return false
- }
- }
-
- for _, v := range commands {
-
- if v(c, command) || c.Err != nil {
- return true
- }
- }
-
- return false
-}
-
-func logoutCommand(c *Context, command *model.Command) bool {
-
- cmd := cmds["logoutCommand"]
-
- 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 := cmds["echoCommand"]
- maxThreads := 100
-
- if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
- parameters := strings.SplitN(command.Command, " ", 2)
- if len(parameters) != 2 || len(parameters[1]) == 0 {
- return false
- }
- message := strings.Trim(parameters[1], " ")
- delay := 0
- if endMsg := strings.LastIndex(message, "\""); string(message[0]) == "\"" && endMsg > 1 {
- if checkDelay, err := strconv.Atoi(strings.Trim(message[endMsg:], " \"")); err == nil {
- delay = checkDelay
- }
- message = message[1:endMsg]
- } else if strings.Index(message, " ") > -1 {
- delayIdx := strings.LastIndex(message, " ")
- delayStr := strings.Trim(message[delayIdx:], " ")
-
- if checkDelay, err := strconv.Atoi(delayStr); err == nil {
- delay = checkDelay
- message = message[:delayIdx]
- }
- }
-
- if delay > 10000 {
- c.Err = model.NewAppError("echoCommand", "Delays must be under 10000 seconds", "")
- return false
- }
-
- if echoSem == nil {
- // We want one additional thread allowed so we never reach channel lockup
- echoSem = make(chan bool, maxThreads+1)
- }
-
- if len(echoSem) >= maxThreads {
- c.Err = model.NewAppError("echoCommand", "High volume of echo request, cannot process request", "")
- return false
- }
-
- echoSem <- true
- go func() {
- defer func() { <-echoSem }()
- post := &model.Post{}
- post.ChannelId = command.ChannelId
- post.Message = message
-
- time.Sleep(time.Duration(delay) * time.Second)
-
- if _, err := CreatePost(c, post, true); err != nil {
- l4g.Error("Unable to create /echo post, err=%v", err)
- }
- }()
-
- command.Response = model.RESP_EXECUTED
- return true
-
- } else if strings.Index(cmd, command.Command) == 0 {
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Echo back text from your account, /echo \"message\" [delay in seconds]"})
- }
-
- return false
-}
-
-func meCommand(c *Context, command *model.Command) bool {
- cmd := cmds["meCommand"]
-
- if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
- message := ""
-
- parameters := strings.SplitN(command.Command, " ", 2)
- if len(parameters) > 1 {
- message += "*" + parameters[1] + "*"
- }
-
- post := &model.Post{}
- post.Message = message
- post.ChannelId = command.ChannelId
- if _, err := CreatePost(c, post, false); err != nil {
- l4g.Error("Unable to create /me post post, err=%v", err)
- return false
- }
- command.Response = model.RESP_EXECUTED
- return true
-
- } else if strings.Index(cmd, command.Command) == 0 {
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Do an action, /me [message]"})
- }
-
- return false
+ // r.Handle("/command", ApiUserRequired(command)).Methods("POST")
}
-func shrugCommand(c *Context, command *model.Command) bool {
- cmd := cmds["shrugCommand"]
-
- if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
- message := `¯\\\_(ツ)_/¯`
-
- parameters := strings.SplitN(command.Command, " ", 2)
- if len(parameters) > 1 {
- message += " " + parameters[1]
- }
-
- post := &model.Post{}
- post.Message = message
- post.ChannelId = command.ChannelId
- if _, err := CreatePost(c, post, false); err != nil {
- l4g.Error("Unable to create /shrug post post, err=%v", err)
- return false
- }
- command.Response = model.RESP_EXECUTED
- return true
-
- } else if strings.Index(cmd, command.Command) == 0 {
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Adds ¯\\_(ツ)_/¯ to your message, /shrug [message]"})
- }
-
- return false
-}
-
-func joinCommand(c *Context, command *model.Command) bool {
-
- // looks for "/join channel-name"
- cmd := cmds["joinCommand"]
-
- 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, "")
-
- if c.Err != nil {
- return false
- }
-
- command.GotoLocation = c.GetTeamURL() + "/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 := cmds["loadTestCommand"]
-
- // This command is only available when EnableTesting is true
- if !utils.Cfg.ServiceSettings.EnableTesting {
- 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
- }
- if loadTestUrlCommand(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 := cmds["loadTestCommand"] + " 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.GetSiteURL())
-
- if doTeams {
- if err := CreateBasicUser(client); err != nil {
- l4g.Error("Failed to create testing environment")
- return true
- }
- client.LoginByEmail(BTEST_TEAM_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD)
- environment, err := CreateTestEnvironmentWithTeams(
- 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 environment")
- return true
- } else {
- l4g.Info("Testing environment created")
- for i := 0; i < len(environment.Teams); i++ {
- l4g.Info("Team Created: " + environment.Teams[i].Name)
- l4g.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + USER_PASSWORD)
- }
- }
- } else {
- client.MockSession(c.Session.Token)
- CreateTestEnvironmentInTeam(
- 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 environment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>"})
- }
-
- return false
-}
-
-func loadTestUsersCommand(c *Context, command *model.Command) bool {
- cmd1 := cmds["loadTestCommand"] + " users"
- cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
- 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 <Min Users> <Max Users>"})
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team <Min Users> <Max Users>"})
- } 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 <Min Users> <Max Users>"})
- }
-
- return false
-}
-
-func loadTestChannelsCommand(c *Context, command *model.Command) bool {
- cmd1 := cmds["loadTestCommand"] + " channels"
- cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
- client.MockSession(c.Session.Token)
- 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 <MinChannels> <MaxChannels>"})
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team <Min Channels> <Max Channels>"})
- } 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 <Min Channels> <Max Channels>"})
- }
-
- return false
-}
-
-func loadTestPostsCommand(c *Context, command *model.Command) bool {
- cmd1 := cmds["loadTestCommand"] + " posts"
- cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
- client.MockSession(c.Session.Token)
- 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 <Min Posts> <Max Posts> <Min Images> <Max Images>"})
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel <Min Posts> <Max Posts> <Min Images> <Max Images>"})
- } 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 <Min Posts> <Max Posts> <Min Images> <Max Images>"})
- }
-
- return false
-}
-
-func loadTestUrlCommand(c *Context, command *model.Command) bool {
- cmd := cmds["loadTestCommand"] + " url"
-
- if strings.Index(command.Command, cmd) == 0 && !command.Suggest {
- url := ""
-
- parameters := strings.SplitN(command.Command, " ", 3)
- if len(parameters) != 3 {
- c.Err = model.NewAppError("loadTestUrlCommand", "Command must contain a url", "")
- return true
- } else {
- url = parameters[2]
- }
-
- // provide a shortcut to easily access tests stored in doc/developer/tests
- if !strings.HasPrefix(url, "http") {
- url = "https://raw.githubusercontent.com/mattermost/platform/master/doc/developer/tests/" + url
-
- if path.Ext(url) == "" {
- url += ".md"
- }
- }
-
- var contents io.ReadCloser
- if r, err := http.Get(url); err != nil {
- c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", err.Error())
- return false
- } else if r.StatusCode > 400 {
- c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", r.Status)
- return false
- } else {
- contents = r.Body
- }
-
- bytes := make([]byte, 4000)
-
- // break contents into 4000 byte posts
- for {
- length, err := contents.Read(bytes)
- if err != nil && err != io.EOF {
- c.Err = model.NewAppError("loadTestUrlCommand", "Encountered error reading file", err.Error())
- return false
- }
-
- if length == 0 {
- break
- }
-
- post := &model.Post{}
- post.Message = string(bytes[:length])
- post.ChannelId = command.ChannelId
-
- if _, err := CreatePost(c, post, false); err != nil {
- l4g.Error("Unable to create post, err=%v", err)
- return false
- }
- }
-
- command.Response = model.RESP_EXECUTED
-
- return true
- } else if strings.Index(cmd, command.Command) == 0 && strings.Index(command.Command, "/loadtest posts") != 0 {
- command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Add a post containing the text from a given url to current channel <Url>"})
- }
-
- return false
-}
+// 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 {
+// if c.Err != commandNotImplementedErr {
+// return
+// } else {
+// c.Err = nil
+// command.Response = model.RESP_NOT_IMPLEMENTED
+// w.Write([]byte(command.ToJson()))
+// 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
+// }
+// }
+
+// if !command.Suggest {
+// implemented := false
+// for _, cmd := range cmds {
+// bounds := len(cmd)
+// if len(command.Command) < bounds {
+// continue
+// }
+// if command.Command[:bounds] == cmd {
+// implemented = true
+// }
+// }
+// if !implemented {
+// c.Err = commandNotImplementedErr
+// return false
+// }
+// }
+
+// for _, v := range commands {
+
+// if v(c, command) || c.Err != nil {
+// return true
+// }
+// }
+
+// return false
+// }
+
+// func logoutCommand(c *Context, command *model.Command) bool {
+
+// cmd := cmds["logoutCommand"]
+
+// 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 := cmds["echoCommand"]
+// maxThreads := 100
+
+// if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
+// parameters := strings.SplitN(command.Command, " ", 2)
+// if len(parameters) != 2 || len(parameters[1]) == 0 {
+// return false
+// }
+// message := strings.Trim(parameters[1], " ")
+// delay := 0
+// if endMsg := strings.LastIndex(message, "\""); string(message[0]) == "\"" && endMsg > 1 {
+// if checkDelay, err := strconv.Atoi(strings.Trim(message[endMsg:], " \"")); err == nil {
+// delay = checkDelay
+// }
+// message = message[1:endMsg]
+// } else if strings.Index(message, " ") > -1 {
+// delayIdx := strings.LastIndex(message, " ")
+// delayStr := strings.Trim(message[delayIdx:], " ")
+
+// if checkDelay, err := strconv.Atoi(delayStr); err == nil {
+// delay = checkDelay
+// message = message[:delayIdx]
+// }
+// }
+
+// if delay > 10000 {
+// c.Err = model.NewAppError("echoCommand", "Delays must be under 10000 seconds", "")
+// return false
+// }
+
+// if echoSem == nil {
+// // We want one additional thread allowed so we never reach channel lockup
+// echoSem = make(chan bool, maxThreads+1)
+// }
+
+// if len(echoSem) >= maxThreads {
+// c.Err = model.NewAppError("echoCommand", "High volume of echo request, cannot process request", "")
+// return false
+// }
+
+// echoSem <- true
+// go func() {
+// defer func() { <-echoSem }()
+// post := &model.Post{}
+// post.ChannelId = command.ChannelId
+// post.Message = message
+
+// time.Sleep(time.Duration(delay) * time.Second)
+
+// if _, err := CreatePost(c, post, true); err != nil {
+// l4g.Error("Unable to create /echo post, err=%v", err)
+// }
+// }()
+
+// command.Response = model.RESP_EXECUTED
+// return true
+
+// } else if strings.Index(cmd, command.Command) == 0 {
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Echo back text from your account, /echo \"message\" [delay in seconds]"})
+// }
+
+// return false
+// }
+
+// func meCommand(c *Context, command *model.Command) bool {
+// cmd := cmds["meCommand"]
+
+// if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
+// message := ""
+
+// parameters := strings.SplitN(command.Command, " ", 2)
+// if len(parameters) > 1 {
+// message += "*" + parameters[1] + "*"
+// }
+
+// post := &model.Post{}
+// post.Message = message
+// post.ChannelId = command.ChannelId
+// if _, err := CreatePost(c, post, false); err != nil {
+// l4g.Error("Unable to create /me post post, err=%v", err)
+// return false
+// }
+// command.Response = model.RESP_EXECUTED
+// return true
+
+// } else if strings.Index(cmd, command.Command) == 0 {
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Do an action, /me [message]"})
+// }
+
+// return false
+// }
+
+// func shrugCommand(c *Context, command *model.Command) bool {
+// cmd := cmds["shrugCommand"]
+
+// if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
+// message := `¯\\\_(ツ)_/¯`
+
+// parameters := strings.SplitN(command.Command, " ", 2)
+// if len(parameters) > 1 {
+// message += " " + parameters[1]
+// }
+
+// post := &model.Post{}
+// post.Message = message
+// post.ChannelId = command.ChannelId
+// if _, err := CreatePost(c, post, false); err != nil {
+// l4g.Error("Unable to create /shrug post post, err=%v", err)
+// return false
+// }
+// command.Response = model.RESP_EXECUTED
+// return true
+
+// } else if strings.Index(cmd, command.Command) == 0 {
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Adds ¯\\_(ツ)_/¯ to your message, /shrug [message]"})
+// }
+
+// return false
+// }
+
+// func joinCommand(c *Context, command *model.Command) bool {
+
+// // looks for "/join channel-name"
+// cmd := cmds["joinCommand"]
+
+// 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, "")
+
+// if c.Err != nil {
+// return false
+// }
+
+// command.GotoLocation = c.GetTeamURL() + "/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 := cmds["loadTestCommand"]
+
+// // This command is only available when EnableTesting is true
+// if !utils.Cfg.ServiceSettings.EnableTesting {
+// 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
+// }
+// if loadTestUrlCommand(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 := cmds["loadTestCommand"] + " 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.GetSiteURL())
+
+// if doTeams {
+// if err := CreateBasicUser(client); err != nil {
+// l4g.Error("Failed to create testing environment")
+// return true
+// }
+// client.LoginByEmail(BTEST_TEAM_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD)
+// environment, err := CreateTestEnvironmentWithTeams(
+// 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 environment")
+// return true
+// } else {
+// l4g.Info("Testing environment created")
+// for i := 0; i < len(environment.Teams); i++ {
+// l4g.Info("Team Created: " + environment.Teams[i].Name)
+// l4g.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + USER_PASSWORD)
+// }
+// }
+// } else {
+// client.MockSession(c.Session.Token)
+// CreateTestEnvironmentInTeam(
+// 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 environment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>"})
+// }
+
+// return false
+// }
+
+// func loadTestUsersCommand(c *Context, command *model.Command) bool {
+// cmd1 := cmds["loadTestCommand"] + " users"
+// cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
+// 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 <Min Users> <Max Users>"})
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team <Min Users> <Max Users>"})
+// } 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 <Min Users> <Max Users>"})
+// }
+
+// return false
+// }
+
+// func loadTestChannelsCommand(c *Context, command *model.Command) bool {
+// cmd1 := cmds["loadTestCommand"] + " channels"
+// cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
+// client.MockSession(c.Session.Token)
+// 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 <MinChannels> <MaxChannels>"})
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team <Min Channels> <Max Channels>"})
+// } 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 <Min Channels> <Max Channels>"})
+// }
+
+// return false
+// }
+
+// func loadTestPostsCommand(c *Context, command *model.Command) bool {
+// cmd1 := cmds["loadTestCommand"] + " posts"
+// cmd2 := cmds["loadTestCommand"] + " 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.GetSiteURL())
+// client.MockSession(c.Session.Token)
+// 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 <Min Posts> <Max Posts> <Min Images> <Max Images>"})
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel <Min Posts> <Max Posts> <Min Images> <Max Images>"})
+// } 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 <Min Posts> <Max Posts> <Min Images> <Max Images>"})
+// }
+
+// return false
+// }
+
+// func loadTestUrlCommand(c *Context, command *model.Command) bool {
+// cmd := cmds["loadTestCommand"] + " url"
+
+// if strings.Index(command.Command, cmd) == 0 && !command.Suggest {
+// url := ""
+
+// parameters := strings.SplitN(command.Command, " ", 3)
+// if len(parameters) != 3 {
+// c.Err = model.NewAppError("loadTestUrlCommand", "Command must contain a url", "")
+// return true
+// } else {
+// url = parameters[2]
+// }
+
+// // provide a shortcut to easily access tests stored in doc/developer/tests
+// if !strings.HasPrefix(url, "http") {
+// url = "https://raw.githubusercontent.com/mattermost/platform/master/doc/developer/tests/" + url
+
+// if path.Ext(url) == "" {
+// url += ".md"
+// }
+// }
+
+// var contents io.ReadCloser
+// if r, err := http.Get(url); err != nil {
+// c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", err.Error())
+// return false
+// } else if r.StatusCode > 400 {
+// c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", r.Status)
+// return false
+// } else {
+// contents = r.Body
+// }
+
+// bytes := make([]byte, 4000)
+
+// // break contents into 4000 byte posts
+// for {
+// length, err := contents.Read(bytes)
+// if err != nil && err != io.EOF {
+// c.Err = model.NewAppError("loadTestUrlCommand", "Encountered error reading file", err.Error())
+// return false
+// }
+
+// if length == 0 {
+// break
+// }
+
+// post := &model.Post{}
+// post.Message = string(bytes[:length])
+// post.ChannelId = command.ChannelId
+
+// if _, err := CreatePost(c, post, false); err != nil {
+// l4g.Error("Unable to create post, err=%v", err)
+// return false
+// }
+// }
+
+// command.Response = model.RESP_EXECUTED
+
+// return true
+// } else if strings.Index(cmd, command.Command) == 0 && strings.Index(command.Command, "/loadtest posts") != 0 {
+// command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Add a post containing the text from a given url to current channel <Url>"})
+// }
+
+// return false
+// }
diff --git a/api/command_test.go b/api/command_test.go
index f38cf1397..8b996b9eb 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -3,240 +3,240 @@
package api
-import (
- "strings"
- "testing"
- "time"
+// import (
+// "strings"
+// "testing"
+// "time"
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
- "github.com/mattermost/platform/utils"
-)
+// "github.com/mattermost/platform/model"
+// "github.com/mattermost/platform/store"
+// "github.com/mattermost/platform/utils"
+// )
-func TestSuggestRootCommands(t *testing.T) {
- Setup()
+// func TestSuggestRootCommands(t *testing.T) {
+// Setup()
- team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
- team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+// team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+// team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
- user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+// user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user1.Id))
- Client.LoginByEmail(team.Name, user1.Email, "pwd")
+// Client.LoginByEmail(team.Name, user1.Email, "pwd")
- if _, err := Client.Command("", "", true); err == nil {
- t.Fatal("Should fail")
- }
+// if _, err := Client.Command("", "", true); err == nil {
+// t.Fatal("Should fail")
+// }
- rs1 := Client.Must(Client.Command("", "/", true)).Data.(*model.Command)
+// rs1 := Client.Must(Client.Command("", "/", true)).Data.(*model.Command)
- hasLogout := false
- for _, v := range rs1.Suggestions {
- if v.Suggestion == "/logout" {
- hasLogout = true
- }
- }
+// hasLogout := false
+// for _, v := range rs1.Suggestions {
+// if v.Suggestion == "/logout" {
+// hasLogout = true
+// }
+// }
- if !hasLogout {
- t.Log(rs1.Suggestions)
- t.Fatal("should have logout cmd")
- }
+// if !hasLogout {
+// t.Log(rs1.Suggestions)
+// t.Fatal("should have logout cmd")
+// }
- rs2 := Client.Must(Client.Command("", "/log", true)).Data.(*model.Command)
+// rs2 := Client.Must(Client.Command("", "/log", true)).Data.(*model.Command)
- if rs2.Suggestions[0].Suggestion != "/logout" {
- t.Fatal("should have logout cmd")
- }
+// if rs2.Suggestions[0].Suggestion != "/logout" {
+// t.Fatal("should have logout cmd")
+// }
- rs3 := Client.Must(Client.Command("", "/joi", true)).Data.(*model.Command)
+// rs3 := Client.Must(Client.Command("", "/joi", true)).Data.(*model.Command)
- if rs3.Suggestions[0].Suggestion != "/join" {
- t.Fatal("should have join cmd")
- }
-
- rs4 := Client.Must(Client.Command("", "/ech", true)).Data.(*model.Command)
+// if rs3.Suggestions[0].Suggestion != "/join" {
+// t.Fatal("should have join cmd")
+// }
+
+// rs4 := Client.Must(Client.Command("", "/ech", true)).Data.(*model.Command)
- if rs4.Suggestions[0].Suggestion != "/echo" {
- t.Fatal("should have echo cmd")
- }
-}
+// if rs4.Suggestions[0].Suggestion != "/echo" {
+// t.Fatal("should have echo cmd")
+// }
+// }
-func TestLogoutCommands(t *testing.T) {
- Setup()
+// func TestLogoutCommands(t *testing.T) {
+// Setup()
- team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
- team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+// team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+// team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
- user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+// user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user1.Id))
- Client.LoginByEmail(team.Name, user1.Email, "pwd")
+// Client.LoginByEmail(team.Name, user1.Email, "pwd")
- rs1 := Client.Must(Client.Command("", "/logout", false)).Data.(*model.Command)
- if rs1.GotoLocation != "/logout" {
- t.Fatal("failed to logout")
- }
-}
+// rs1 := Client.Must(Client.Command("", "/logout", false)).Data.(*model.Command)
+// if rs1.GotoLocation != "/logout" {
+// t.Fatal("failed to logout")
+// }
+// }
-func TestJoinCommands(t *testing.T) {
- Setup()
+// func TestJoinCommands(t *testing.T) {
+// Setup()
- team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
- team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+// team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+// team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
- user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+// user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user1.Id))
- Client.LoginByEmail(team.Name, user1.Email, "pwd")
+// Client.LoginByEmail(team.Name, user1.Email, "pwd")
- channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
- channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
- Client.Must(Client.LeaveChannel(channel1.Id))
+// channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+// channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
+// Client.Must(Client.LeaveChannel(channel1.Id))
- channel2 := &model.Channel{DisplayName: "BB", Name: "bb" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
- channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
- Client.Must(Client.LeaveChannel(channel2.Id))
+// channel2 := &model.Channel{DisplayName: "BB", Name: "bb" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+// channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
+// Client.Must(Client.LeaveChannel(channel2.Id))
- user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+// user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user1.Id))
- data := make(map[string]string)
- data["user_id"] = user2.Id
- channel3 := Client.Must(Client.CreateDirectChannel(data)).Data.(*model.Channel)
+// data := make(map[string]string)
+// data["user_id"] = user2.Id
+// channel3 := Client.Must(Client.CreateDirectChannel(data)).Data.(*model.Channel)
- rs1 := Client.Must(Client.Command("", "/join aa", true)).Data.(*model.Command)
- if rs1.Suggestions[0].Suggestion != "/join "+channel1.Name {
- t.Fatal("should have join cmd")
- }
+// rs1 := Client.Must(Client.Command("", "/join aa", true)).Data.(*model.Command)
+// if rs1.Suggestions[0].Suggestion != "/join "+channel1.Name {
+// t.Fatal("should have join cmd")
+// }
- rs2 := Client.Must(Client.Command("", "/join bb", true)).Data.(*model.Command)
- if rs2.Suggestions[0].Suggestion != "/join "+channel2.Name {
- t.Fatal("should have join cmd")
- }
+// rs2 := Client.Must(Client.Command("", "/join bb", true)).Data.(*model.Command)
+// if rs2.Suggestions[0].Suggestion != "/join "+channel2.Name {
+// t.Fatal("should have join cmd")
+// }
- rs3 := Client.Must(Client.Command("", "/join", true)).Data.(*model.Command)
- if len(rs3.Suggestions) != 2 {
- t.Fatal("should have 2 join cmd")
- }
+// rs3 := Client.Must(Client.Command("", "/join", true)).Data.(*model.Command)
+// if len(rs3.Suggestions) != 2 {
+// t.Fatal("should have 2 join cmd")
+// }
- rs4 := Client.Must(Client.Command("", "/join ", true)).Data.(*model.Command)
- if len(rs4.Suggestions) != 2 {
- t.Fatal("should have 2 join cmd")
- }
+// rs4 := Client.Must(Client.Command("", "/join ", true)).Data.(*model.Command)
+// if len(rs4.Suggestions) != 2 {
+// t.Fatal("should have 2 join cmd")
+// }
- rs5 := Client.Must(Client.Command("", "/join "+channel2.Name, false)).Data.(*model.Command)
- if !strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name) {
- t.Fatal("failed to join channel")
- }
+// rs5 := Client.Must(Client.Command("", "/join "+channel2.Name, false)).Data.(*model.Command)
+// if !strings.HasSuffix(rs5.GotoLocation, "/"+team.Name+"/channels/"+channel2.Name) {
+// t.Fatal("failed to join channel")
+// }
- rs6 := Client.Must(Client.Command("", "/join "+channel3.Name, false)).Data.(*model.Command)
- if strings.HasSuffix(rs6.GotoLocation, "/"+team.Name+"/channels/"+channel3.Name) {
- t.Fatal("should not have joined direct message channel")
- }
+// rs6 := Client.Must(Client.Command("", "/join "+channel3.Name, false)).Data.(*model.Command)
+// if strings.HasSuffix(rs6.GotoLocation, "/"+team.Name+"/channels/"+channel3.Name) {
+// t.Fatal("should not have joined direct message channel")
+// }
- c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
+// c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList)
- if len(c1.Channels) != 4 { // 4 because of town-square, off-topic and direct
- t.Fatal("didn't join channel")
- }
+// if len(c1.Channels) != 4 { // 4 because of town-square, off-topic and direct
+// t.Fatal("didn't join channel")
+// }
- found := false
- for _, c := range c1.Channels {
- if c.Name == channel2.Name {
- found = true
- break
- }
- }
- if !found {
- t.Fatal("didn't join channel")
- }
-}
-
-func TestEchoCommand(t *testing.T) {
- Setup()
-
- team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
- team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+// found := false
+// for _, c := range c1.Channels {
+// if c.Name == channel2.Name {
+// found = true
+// break
+// }
+// }
+// if !found {
+// t.Fatal("didn't join channel")
+// }
+// }
+
+// func TestEchoCommand(t *testing.T) {
+// Setup()
+
+// team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+// team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
- user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user1.Id))
-
- Client.LoginByEmail(team.Name, user1.Email, "pwd")
-
- channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
- channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
-
- echoTestString := "/echo test"
-
- r1 := Client.Must(Client.Command(channel1.Id, echoTestString, false)).Data.(*model.Command)
- if r1.Response != model.RESP_EXECUTED {
- t.Fatal("Echo command failed to execute")
- }
-
- time.Sleep(100 * time.Millisecond)
-
- p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList)
- if len(p1.Order) != 1 {
- t.Fatal("Echo command failed to send")
- }
-}
-
-func TestLoadTestUrlCommand(t *testing.T) {
- Setup()
-
- // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
- enableTesting := utils.Cfg.ServiceSettings.EnableTesting
- defer func() {
- utils.Cfg.ServiceSettings.EnableTesting = enableTesting
- }()
-
- utils.Cfg.ServiceSettings.EnableTesting = true
-
- team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
- team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
-
- user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
- user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- store.Must(Srv.Store.User().VerifyEmail(user.Id))
-
- Client.LoginByEmail(team.Name, user.Email, "pwd")
-
- channel := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
- channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
-
- command := "/loadtest url "
- if _, err := Client.Command(channel.Id, command, false); err == nil {
- t.Fatal("/loadtest url with no url should've failed")
- }
-
- command = "/loadtest url http://www.hopefullynonexistent.file/path/asdf/qwerty"
- if _, err := Client.Command(channel.Id, command, false); err == nil {
- t.Fatal("/loadtest url with invalid url should've failed")
- }
-
- command = "/loadtest url https://raw.githubusercontent.com/mattermost/platform/master/README.md"
- if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
- t.Fatal("/loadtest url for README.md should've executed")
- }
-
- command = "/loadtest url test-emoticons.md"
- if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
- t.Fatal("/loadtest url for test-emoticons.md should've executed")
- }
-
- command = "/loadtest url test-emoticons"
- if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
- t.Fatal("/loadtest url for test-emoticons should've executed")
- }
-
- posts := Client.Must(Client.GetPosts(channel.Id, 0, 5, "")).Data.(*model.PostList)
- // note that this may make more than 3 posts if files are too long to fit in an individual post
- if len(posts.Order) < 3 {
- t.Fatal("/loadtest url made too few posts, perhaps there needs to be a delay before GetPosts in the test?")
- }
-}
+// user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+
+// Client.LoginByEmail(team.Name, user1.Email, "pwd")
+
+// channel1 := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+// channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
+
+// echoTestString := "/echo test"
+
+// r1 := Client.Must(Client.Command(channel1.Id, echoTestString, false)).Data.(*model.Command)
+// if r1.Response != model.RESP_EXECUTED {
+// t.Fatal("Echo command failed to execute")
+// }
+
+// time.Sleep(100 * time.Millisecond)
+
+// p1 := Client.Must(Client.GetPosts(channel1.Id, 0, 2, "")).Data.(*model.PostList)
+// if len(p1.Order) != 1 {
+// t.Fatal("Echo command failed to send")
+// }
+// }
+
+// func TestLoadTestUrlCommand(t *testing.T) {
+// Setup()
+
+// // enable testing to use /loadtest but don't save it since we don't want to overwrite config.json
+// enableTesting := utils.Cfg.ServiceSettings.EnableTesting
+// defer func() {
+// utils.Cfg.ServiceSettings.EnableTesting = enableTesting
+// }()
+
+// utils.Cfg.ServiceSettings.EnableTesting = true
+
+// team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+// team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
+
+// user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd"}
+// user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
+// store.Must(Srv.Store.User().VerifyEmail(user.Id))
+
+// Client.LoginByEmail(team.Name, user.Email, "pwd")
+
+// channel := &model.Channel{DisplayName: "AA", Name: "aa" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
+// channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
+
+// command := "/loadtest url "
+// if _, err := Client.Command(channel.Id, command, false); err == nil {
+// t.Fatal("/loadtest url with no url should've failed")
+// }
+
+// command = "/loadtest url http://www.hopefullynonexistent.file/path/asdf/qwerty"
+// if _, err := Client.Command(channel.Id, command, false); err == nil {
+// t.Fatal("/loadtest url with invalid url should've failed")
+// }
+
+// command = "/loadtest url https://raw.githubusercontent.com/mattermost/platform/master/README.md"
+// if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
+// t.Fatal("/loadtest url for README.md should've executed")
+// }
+
+// command = "/loadtest url test-emoticons.md"
+// if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
+// t.Fatal("/loadtest url for test-emoticons.md should've executed")
+// }
+
+// command = "/loadtest url test-emoticons"
+// if r := Client.Must(Client.Command(channel.Id, command, false)).Data.(*model.Command); r.Response != model.RESP_EXECUTED {
+// t.Fatal("/loadtest url for test-emoticons should've executed")
+// }
+
+// posts := Client.Must(Client.GetPosts(channel.Id, 0, 5, "")).Data.(*model.PostList)
+// // note that this may make more than 3 posts if files are too long to fit in an individual post
+// if len(posts.Order) < 3 {
+// t.Fatal("/loadtest url made too few posts, perhaps there needs to be a delay before GetPosts in the test?")
+// }
+// }
diff --git a/model/command.go b/model/command.go
index 5aec5f534..253021896 100644
--- a/model/command.go
+++ b/model/command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -9,28 +9,27 @@ import (
)
const (
- RESP_EXECUTED = "executed"
- RESP_NOT_IMPLEMENTED = "not implemented"
+ COMMAND_METHOD_POST = "P"
+ COMMAND_METHOD_GET = "G"
)
type Command struct {
- Command string `json:"command"`
- Response string `json:"response"`
- GotoLocation string `json:"goto_location"`
- ChannelId string `json:"channel_id"`
- Suggest bool `json:"-"`
- Suggestions []*SuggestCommand `json:"suggestions"`
-}
-
-func (o *Command) AddSuggestion(suggest *SuggestCommand) {
-
- if o.Suggest {
- if o.Suggestions == nil {
- o.Suggestions = make([]*SuggestCommand, 0, 128)
- }
-
- o.Suggestions = append(o.Suggestions, suggest)
- }
+ Id string `json:"id"`
+ Token string `json:"token"`
+ CreateAt int64 `json:"create_at"`
+ UpdateAt int64 `json:"update_at"`
+ DeleteAt int64 `json:"delete_at"`
+ CreatorId string `json:"creator_id"`
+ TeamId string `json:"team_id"`
+ Trigger string `json:"trigger"`
+ Method string `json:"method"`
+ Username string `json:"username"`
+ IconURL string `json:"icon_url"`
+ AutoComplete bool `json:"auto_complete"`
+ AutoCompleteDesc string `json:"auto_complete_desc"`
+ AutoCompleteHint string `json:"auto_complete_hint"`
+ DisplayName string `json:"display_name"`
+ URL string `json:"url"`
}
func (o *Command) ToJson() string {
@@ -52,3 +51,85 @@ func CommandFromJson(data io.Reader) *Command {
return nil
}
}
+
+func CommandListToJson(l []*Command) string {
+ b, err := json.Marshal(l)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func CommandListFromJson(data io.Reader) []*Command {
+ decoder := json.NewDecoder(data)
+ var o []*Command
+ err := decoder.Decode(&o)
+ if err == nil {
+ return o
+ } else {
+ return nil
+ }
+}
+
+func (o *Command) IsValid() *AppError {
+
+ if len(o.Id) != 26 {
+ return NewAppError("Command.IsValid", "Invalid Id", "")
+ }
+
+ if len(o.Token) != 26 {
+ return NewAppError("Command.IsValid", "Invalid token", "")
+ }
+
+ if o.CreateAt == 0 {
+ return NewAppError("Command.IsValid", "Create at must be a valid time", "id="+o.Id)
+ }
+
+ if o.UpdateAt == 0 {
+ return NewAppError("Command.IsValid", "Update at must be a valid time", "id="+o.Id)
+ }
+
+ if len(o.CreatorId) != 26 {
+ return NewAppError("Command.IsValid", "Invalid user id", "")
+ }
+
+ if len(o.TeamId) != 26 {
+ return NewAppError("Command.IsValid", "Invalid team id", "")
+ }
+
+ if len(o.Trigger) > 1024 {
+ return NewAppError("Command.IsValid", "Invalid trigger", "")
+ }
+
+ if len(o.URL) == 0 || len(o.URL) > 1024 {
+ return NewAppError("Command.IsValid", "Invalid url", "")
+ }
+
+ if !IsValidHttpUrl(o.URL) {
+ return NewAppError("Command.IsValid", "Invalid URL. Must be a valid URL and start with http:// or https://", "")
+ }
+
+ if !(o.Method == COMMAND_METHOD_GET || o.Method == COMMAND_METHOD_POST) {
+ return NewAppError("Command.IsValid", "Invalid Method", "")
+ }
+
+ return nil
+}
+
+func (o *Command) PreSave() {
+ if o.Id == "" {
+ o.Id = NewId()
+ }
+
+ if o.Token == "" {
+ o.Token = NewId()
+ }
+
+ o.CreateAt = GetMillis()
+ o.UpdateAt = o.CreateAt
+}
+
+func (o *Command) PreUpdate() {
+ o.UpdateAt = GetMillis()
+}
diff --git a/model/command_test.go b/model/command_test.go
index 61302ea10..0581625d9 100644
--- a/model/command_test.go
+++ b/model/command_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -9,17 +9,89 @@ import (
)
func TestCommandJson(t *testing.T) {
+ o := Command{Id: NewId()}
+ json := o.ToJson()
+ ro := CommandFromJson(strings.NewReader(json))
- command := &Command{Command: NewId(), Suggest: true}
- command.AddSuggestion(&SuggestCommand{Suggestion: NewId()})
- json := command.ToJson()
- result := CommandFromJson(strings.NewReader(json))
-
- if command.Command != result.Command {
+ if o.Id != ro.Id {
t.Fatal("Ids do not match")
}
+}
- if command.Suggestions[0].Suggestion != result.Suggestions[0].Suggestion {
- t.Fatal("Ids do not match")
+func TestCommandIsValid(t *testing.T) {
+ o := Command{}
+
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.Id = NewId()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.CreateAt = GetMillis()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.UpdateAt = GetMillis()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.CreatorId = "123"
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.CreatorId = NewId()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.Token = "123"
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
}
+
+ o.Token = NewId()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.TeamId = "123"
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.TeamId = NewId()
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.URL = "nowhere.com/"
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.URL = "http://nowhere.com/"
+ if err := o.IsValid(); err == nil {
+ t.Fatal("should be invalid")
+ }
+
+ o.Method = COMMAND_METHOD_GET
+ if err := o.IsValid(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCommandPreSave(t *testing.T) {
+ o := Command{}
+ o.PreSave()
+}
+
+func TestCommandPreUpdate(t *testing.T) {
+ o := Command{}
+ o.PreUpdate()
}
diff --git a/store/sql_command_store.go b/store/sql_command_store.go
new file mode 100644
index 000000000..cb817d8f8
--- /dev/null
+++ b/store/sql_command_store.go
@@ -0,0 +1,174 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package store
+
+import (
+ "github.com/mattermost/platform/model"
+)
+
+type SqlCommandStore struct {
+ *SqlStore
+}
+
+func NewSqlCommandStore(sqlStore *SqlStore) CommandStore {
+ s := &SqlCommandStore{sqlStore}
+
+ for _, db := range sqlStore.GetAllConns() {
+ tableo := db.AddTableWithName(model.Command{}, "Commands").SetKeys(false, "Id")
+ tableo.ColMap("Id").SetMaxSize(26)
+ tableo.ColMap("Token").SetMaxSize(26)
+ tableo.ColMap("CreatorId").SetMaxSize(26)
+ tableo.ColMap("TeamId").SetMaxSize(26)
+ tableo.ColMap("Trigger").SetMaxSize(128)
+ tableo.ColMap("URL").SetMaxSize(1024)
+ tableo.ColMap("Method").SetMaxSize(1)
+ tableo.ColMap("Username").SetMaxSize(64)
+ tableo.ColMap("IconURL").SetMaxSize(1024)
+ tableo.ColMap("AutoCompleteDesc").SetMaxSize(1024)
+ tableo.ColMap("AutoCompleteHint").SetMaxSize(1024)
+ tableo.ColMap("DisplayName").SetMaxSize(64)
+ }
+
+ return s
+}
+
+func (s SqlCommandStore) UpgradeSchemaIfNeeded() {
+}
+
+func (s SqlCommandStore) CreateIndexesIfNotExists() {
+ s.CreateIndexIfNotExists("idx_command_team_id", "Commands", "TeamId")
+}
+
+func (s SqlCommandStore) Save(command *model.Command) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ if len(command.Id) > 0 {
+ result.Err = model.NewAppError("SqlCommandStore.Save",
+ "You cannot overwrite an existing Command", "id="+command.Id)
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+
+ command.PreSave()
+ if result.Err = command.IsValid(); result.Err != nil {
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+
+ if err := s.GetMaster().Insert(command); err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.Save", "We couldn't save the Command", "id="+command.Id+", "+err.Error())
+ } else {
+ result.Data = command
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlCommandStore) Get(id string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ var command model.Command
+
+ if err := s.GetReplica().SelectOne(&command, "SELECT * FROM Commands WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": id}); err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.Get", "We couldn't get the command", "id="+id+", err="+err.Error())
+ }
+
+ result.Data = &command
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlCommandStore) GetByTeam(teamId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ var commands []*model.Command
+
+ if _, err := s.GetReplica().Select(&commands, "SELECT * FROM Commands WHERE TeamId = :TeamId AND DeleteAt = 0", map[string]interface{}{"TeamId": teamId}); err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.GetByTeam", "We couldn't get the commands", "teamId="+teamId+", err="+err.Error())
+ }
+
+ result.Data = commands
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlCommandStore) Delete(commandId string, time int64) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := s.GetMaster().Exec("Update Commands SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :Id", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": commandId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.Delete", "We couldn't delete the command", "id="+commandId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlCommandStore) PermanentDeleteByUser(userId string) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ _, err := s.GetMaster().Exec("DELETE FROM Commands WHERE CreatorId = :UserId", map[string]interface{}{"UserId": userId})
+ if err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.DeleteByUser", "We couldn't delete the command", "id="+userId+", err="+err.Error())
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlCommandStore) Update(hook *model.Command) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ hook.UpdateAt = model.GetMillis()
+
+ if _, err := s.GetMaster().Update(hook); err != nil {
+ result.Err = model.NewAppError("SqlCommandStore.Update", "We couldn't update the command", "id="+hook.Id+", "+err.Error())
+ } else {
+ result.Data = hook
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_command_store_test.go b/store/sql_command_store_test.go
new file mode 100644
index 000000000..b4610d4aa
--- /dev/null
+++ b/store/sql_command_store_test.go
@@ -0,0 +1,155 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package store
+
+import (
+ "github.com/mattermost/platform/model"
+ "testing"
+)
+
+func TestCommandStoreSave(t *testing.T) {
+ Setup()
+
+ o1 := model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ if err := (<-store.Command().Save(&o1)).Err; err != nil {
+ t.Fatal("couldn't save item", err)
+ }
+
+ if err := (<-store.Command().Save(&o1)).Err; err == nil {
+ t.Fatal("shouldn't be able to update from save")
+ }
+}
+
+func TestCommandStoreGet(t *testing.T) {
+ Setup()
+
+ o1 := &model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
+
+ if r1 := <-store.Command().Get(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.(*model.Command).CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned command")
+ }
+ }
+
+ if err := (<-store.Command().Get("123")).Err; err == nil {
+ t.Fatal("Missing id should have failed")
+ }
+}
+
+func TestCommandStoreGetByTeam(t *testing.T) {
+ Setup()
+
+ o1 := &model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
+
+ if r1 := <-store.Command().GetByTeam(o1.TeamId); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.([]*model.Command)[0].CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned command")
+ }
+ }
+
+ if result := <-store.Command().GetByTeam("123"); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ if len(result.Data.([]*model.Command)) != 0 {
+ t.Fatal("no commands should have returned")
+ }
+ }
+}
+
+func TestCommandStoreDelete(t *testing.T) {
+ Setup()
+
+ o1 := &model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
+
+ if r1 := <-store.Command().Get(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.(*model.Command).CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned command")
+ }
+ }
+
+ if r2 := <-store.Command().Delete(o1.Id, model.GetMillis()); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Command().Get(o1.Id)); r3.Err == nil {
+ t.Log(r3.Data)
+ t.Fatal("Missing id should have failed")
+ }
+}
+
+func TestCommandStoreDeleteByUser(t *testing.T) {
+ Setup()
+
+ o1 := &model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
+
+ if r1 := <-store.Command().Get(o1.Id); r1.Err != nil {
+ t.Fatal(r1.Err)
+ } else {
+ if r1.Data.(*model.Command).CreateAt != o1.CreateAt {
+ t.Fatal("invalid returned command")
+ }
+ }
+
+ if r2 := <-store.Command().PermanentDeleteByUser(o1.CreatorId); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+
+ if r3 := (<-store.Command().Get(o1.Id)); r3.Err == nil {
+ t.Log(r3.Data)
+ t.Fatal("Missing id should have failed")
+ }
+}
+
+func TestCommandStoreUpdate(t *testing.T) {
+ Setup()
+
+ o1 := &model.Command{}
+ o1.CreatorId = model.NewId()
+ o1.Method = model.COMMAND_METHOD_POST
+ o1.TeamId = model.NewId()
+ o1.URL = "http://nowhere.com/"
+
+ o1 = (<-store.Command().Save(o1)).Data.(*model.Command)
+
+ o1.Token = model.NewId()
+
+ if r2 := <-store.Command().Update(o1); r2.Err != nil {
+ t.Fatal(r2.Err)
+ }
+}
diff --git a/store/sql_store.go b/store/sql_store.go
index d17a3e8c3..30a464586 100644
--- a/store/sql_store.go
+++ b/store/sql_store.go
@@ -47,6 +47,7 @@ type SqlStore struct {
oauth OAuthStore
system SystemStore
webhook WebhookStore
+ command CommandStore
preference PreferenceStore
}
@@ -119,6 +120,7 @@ func NewSqlStore() Store {
sqlStore.oauth = NewSqlOAuthStore(sqlStore)
sqlStore.system = NewSqlSystemStore(sqlStore)
sqlStore.webhook = NewSqlWebhookStore(sqlStore)
+ sqlStore.command = NewSqlCommandStore(sqlStore)
sqlStore.preference = NewSqlPreferenceStore(sqlStore)
err := sqlStore.master.CreateTablesIfNotExists()
@@ -135,6 +137,7 @@ func NewSqlStore() Store {
sqlStore.oauth.(*SqlOAuthStore).UpgradeSchemaIfNeeded()
sqlStore.system.(*SqlSystemStore).UpgradeSchemaIfNeeded()
sqlStore.webhook.(*SqlWebhookStore).UpgradeSchemaIfNeeded()
+ sqlStore.command.(*SqlCommandStore).UpgradeSchemaIfNeeded()
sqlStore.preference.(*SqlPreferenceStore).UpgradeSchemaIfNeeded()
sqlStore.team.(*SqlTeamStore).CreateIndexesIfNotExists()
@@ -146,6 +149,7 @@ func NewSqlStore() Store {
sqlStore.oauth.(*SqlOAuthStore).CreateIndexesIfNotExists()
sqlStore.system.(*SqlSystemStore).CreateIndexesIfNotExists()
sqlStore.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists()
+ sqlStore.command.(*SqlCommandStore).CreateIndexesIfNotExists()
sqlStore.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists()
sqlStore.preference.(*SqlPreferenceStore).DeleteUnusedFeatures()
@@ -530,6 +534,10 @@ func (ss SqlStore) Webhook() WebhookStore {
return ss.webhook
}
+func (ss SqlStore) Command() CommandStore {
+ return ss.command
+}
+
func (ss SqlStore) Preference() PreferenceStore {
return ss.preference
}
diff --git a/store/store.go b/store/store.go
index 8e03c8ee7..b19bba826 100644
--- a/store/store.go
+++ b/store/store.go
@@ -37,6 +37,7 @@ type Store interface {
OAuth() OAuthStore
System() SystemStore
Webhook() WebhookStore
+ Command() CommandStore
Preference() PreferenceStore
MarkSystemRanUnitTests()
Close()
@@ -182,6 +183,15 @@ type WebhookStore interface {
UpdateOutgoing(hook *model.OutgoingWebhook) StoreChannel
}
+type CommandStore interface {
+ Save(webhook *model.Command) StoreChannel
+ Get(id string) StoreChannel
+ GetByTeam(teamId string) StoreChannel
+ Delete(commandId string, time int64) StoreChannel
+ PermanentDeleteByUser(userId string) StoreChannel
+ Update(hook *model.Command) StoreChannel
+}
+
type PreferenceStore interface {
Save(preferences *model.Preferences) StoreChannel
Get(userId string, category string, name string) StoreChannel