github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+incompatible/api4/command_test.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/mattermost/mattermost-server/model"
    12  )
    13  
    14  func TestCreateCommand(t *testing.T) {
    15  	th := Setup().InitBasic().InitSystemAdmin()
    16  	defer th.TearDown()
    17  	Client := th.Client
    18  
    19  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
    20  	defer func() {
    21  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
    22  	}()
    23  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
    24  
    25  	newCmd := &model.Command{
    26  		CreatorId: th.BasicUser.Id,
    27  		TeamId:    th.BasicTeam.Id,
    28  		URL:       "http://nowhere.com",
    29  		Method:    model.COMMAND_METHOD_POST,
    30  		Trigger:   "trigger"}
    31  
    32  	_, resp := Client.CreateCommand(newCmd)
    33  	CheckForbiddenStatus(t, resp)
    34  
    35  	createdCmd, resp := th.SystemAdminClient.CreateCommand(newCmd)
    36  	CheckNoError(t, resp)
    37  	CheckCreatedStatus(t, resp)
    38  	if createdCmd.CreatorId != th.SystemAdminUser.Id {
    39  		t.Fatal("user ids didn't match")
    40  	}
    41  	if createdCmd.TeamId != th.BasicTeam.Id {
    42  		t.Fatal("team ids didn't match")
    43  	}
    44  
    45  	_, resp = th.SystemAdminClient.CreateCommand(newCmd)
    46  	CheckBadRequestStatus(t, resp)
    47  	CheckErrorMessage(t, resp, "api.command.duplicate_trigger.app_error")
    48  
    49  	newCmd.Method = "Wrong"
    50  	newCmd.Trigger = "testcommand"
    51  	_, resp = th.SystemAdminClient.CreateCommand(newCmd)
    52  	CheckBadRequestStatus(t, resp)
    53  	CheckErrorMessage(t, resp, "model.command.is_valid.method.app_error")
    54  
    55  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = false })
    56  	newCmd.Method = "P"
    57  	newCmd.Trigger = "testcommand"
    58  	_, resp = th.SystemAdminClient.CreateCommand(newCmd)
    59  	CheckNotImplementedStatus(t, resp)
    60  	CheckErrorMessage(t, resp, "api.command.disabled.app_error")
    61  }
    62  
    63  func TestUpdateCommand(t *testing.T) {
    64  	th := Setup().InitBasic().InitSystemAdmin()
    65  	defer th.TearDown()
    66  	Client := th.SystemAdminClient
    67  	user := th.SystemAdminUser
    68  	team := th.BasicTeam
    69  
    70  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
    71  	defer func() {
    72  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
    73  	}()
    74  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
    75  
    76  	cmd1 := &model.Command{
    77  		CreatorId: user.Id,
    78  		TeamId:    team.Id,
    79  		URL:       "http://nowhere.com",
    80  		Method:    model.COMMAND_METHOD_POST,
    81  		Trigger:   "trigger1",
    82  	}
    83  
    84  	cmd1, _ = th.App.CreateCommand(cmd1)
    85  
    86  	cmd2 := &model.Command{
    87  		CreatorId: GenerateTestId(),
    88  		TeamId:    team.Id,
    89  		URL:       "http://nowhere.com/change",
    90  		Method:    model.COMMAND_METHOD_GET,
    91  		Trigger:   "trigger2",
    92  		Id:        cmd1.Id,
    93  		Token:     "tokenchange",
    94  	}
    95  
    96  	rcmd, resp := Client.UpdateCommand(cmd2)
    97  	CheckNoError(t, resp)
    98  
    99  	if rcmd.Trigger != cmd2.Trigger {
   100  		t.Fatal("Trigger should have updated")
   101  	}
   102  
   103  	if rcmd.Method != cmd2.Method {
   104  		t.Fatal("Method should have updated")
   105  	}
   106  
   107  	if rcmd.URL != cmd2.URL {
   108  		t.Fatal("URL should have updated")
   109  	}
   110  
   111  	if rcmd.CreatorId != cmd1.CreatorId {
   112  		t.Fatal("CreatorId should have not updated")
   113  	}
   114  
   115  	if rcmd.Token != cmd1.Token {
   116  		t.Fatal("Token should have not updated")
   117  	}
   118  
   119  	cmd2.Id = GenerateTestId()
   120  
   121  	rcmd, resp = Client.UpdateCommand(cmd2)
   122  	CheckNotFoundStatus(t, resp)
   123  
   124  	if rcmd != nil {
   125  		t.Fatal("should be empty")
   126  	}
   127  
   128  	cmd2.Id = "junk"
   129  
   130  	_, resp = Client.UpdateCommand(cmd2)
   131  	CheckBadRequestStatus(t, resp)
   132  
   133  	cmd2.Id = cmd1.Id
   134  	cmd2.TeamId = GenerateTestId()
   135  
   136  	_, resp = Client.UpdateCommand(cmd2)
   137  	CheckBadRequestStatus(t, resp)
   138  
   139  	cmd2.TeamId = team.Id
   140  
   141  	_, resp = th.Client.UpdateCommand(cmd2)
   142  	CheckForbiddenStatus(t, resp)
   143  
   144  	Client.Logout()
   145  	_, resp = Client.UpdateCommand(cmd2)
   146  	CheckUnauthorizedStatus(t, resp)
   147  }
   148  
   149  func TestDeleteCommand(t *testing.T) {
   150  	th := Setup().InitBasic().InitSystemAdmin()
   151  	defer th.TearDown()
   152  	Client := th.SystemAdminClient
   153  	user := th.SystemAdminUser
   154  	team := th.BasicTeam
   155  
   156  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   157  	defer func() {
   158  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   159  	}()
   160  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   161  
   162  	cmd1 := &model.Command{
   163  		CreatorId: user.Id,
   164  		TeamId:    team.Id,
   165  		URL:       "http://nowhere.com",
   166  		Method:    model.COMMAND_METHOD_POST,
   167  		Trigger:   "trigger1",
   168  	}
   169  
   170  	rcmd1, _ := th.App.CreateCommand(cmd1)
   171  
   172  	ok, resp := Client.DeleteCommand(rcmd1.Id)
   173  	CheckNoError(t, resp)
   174  
   175  	if !ok {
   176  		t.Fatal("should have returned true")
   177  	}
   178  
   179  	rcmd1, _ = th.App.GetCommand(rcmd1.Id)
   180  	if rcmd1 != nil {
   181  		t.Fatal("should be nil")
   182  	}
   183  
   184  	ok, resp = Client.DeleteCommand("junk")
   185  	CheckBadRequestStatus(t, resp)
   186  
   187  	if ok {
   188  		t.Fatal("should have returned false")
   189  	}
   190  
   191  	_, resp = Client.DeleteCommand(GenerateTestId())
   192  	CheckNotFoundStatus(t, resp)
   193  
   194  	cmd2 := &model.Command{
   195  		CreatorId: user.Id,
   196  		TeamId:    team.Id,
   197  		URL:       "http://nowhere.com",
   198  		Method:    model.COMMAND_METHOD_POST,
   199  		Trigger:   "trigger2",
   200  	}
   201  
   202  	rcmd2, _ := th.App.CreateCommand(cmd2)
   203  
   204  	_, resp = th.Client.DeleteCommand(rcmd2.Id)
   205  	CheckForbiddenStatus(t, resp)
   206  
   207  	Client.Logout()
   208  	_, resp = Client.DeleteCommand(rcmd2.Id)
   209  	CheckUnauthorizedStatus(t, resp)
   210  }
   211  
   212  func TestListCommands(t *testing.T) {
   213  	th := Setup().InitBasic().InitSystemAdmin()
   214  	defer th.TearDown()
   215  	Client := th.Client
   216  
   217  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   218  	enableOnlyAdminIntegrations := *th.App.Config().ServiceSettings.EnableOnlyAdminIntegrations
   219  	defer func() {
   220  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   221  		th.App.UpdateConfig(func(cfg *model.Config) {
   222  			cfg.ServiceSettings.EnableOnlyAdminIntegrations = &enableOnlyAdminIntegrations
   223  		})
   224  	}()
   225  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   226  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOnlyAdminIntegrations = true })
   227  
   228  	newCmd := &model.Command{
   229  		CreatorId: th.BasicUser.Id,
   230  		TeamId:    th.BasicTeam.Id,
   231  		URL:       "http://nowhere.com",
   232  		Method:    model.COMMAND_METHOD_POST,
   233  		Trigger:   "custom_command"}
   234  
   235  	_, resp := th.SystemAdminClient.CreateCommand(newCmd)
   236  	CheckNoError(t, resp)
   237  
   238  	t.Run("ListSystemAndCustomCommands", func(t *testing.T) {
   239  		listCommands, resp := th.SystemAdminClient.ListCommands(th.BasicTeam.Id, false)
   240  		CheckNoError(t, resp)
   241  
   242  		foundEcho := false
   243  		foundCustom := false
   244  		for _, command := range listCommands {
   245  			if command.Trigger == "echo" {
   246  				foundEcho = true
   247  			}
   248  			if command.Trigger == "custom_command" {
   249  				foundCustom = true
   250  			}
   251  		}
   252  		if !foundEcho {
   253  			t.Fatal("Couldn't find echo command")
   254  		}
   255  		if !foundCustom {
   256  			t.Fatal("Should list the custom command")
   257  		}
   258  	})
   259  
   260  	t.Run("ListCustomOnlyCommands", func(t *testing.T) {
   261  		listCommands, resp := th.SystemAdminClient.ListCommands(th.BasicTeam.Id, true)
   262  		CheckNoError(t, resp)
   263  
   264  		if len(listCommands) > 1 {
   265  			t.Fatal("Should list just one custom command")
   266  		}
   267  		if listCommands[0].Trigger != "custom_command" {
   268  			t.Fatal("Wrong custom command trigger")
   269  		}
   270  	})
   271  
   272  	t.Run("UserWithNoPermissionForCustomCommands", func(t *testing.T) {
   273  		_, resp := Client.ListCommands(th.BasicTeam.Id, true)
   274  		CheckForbiddenStatus(t, resp)
   275  	})
   276  
   277  	t.Run("RegularUserCanListOnlySystemCommands", func(t *testing.T) {
   278  		listCommands, resp := Client.ListCommands(th.BasicTeam.Id, false)
   279  		CheckNoError(t, resp)
   280  
   281  		foundEcho := false
   282  		foundCustom := false
   283  		for _, command := range listCommands {
   284  			if command.Trigger == "echo" {
   285  				foundEcho = true
   286  			}
   287  			if command.Trigger == "custom_command" {
   288  				foundCustom = true
   289  			}
   290  		}
   291  		if !foundEcho {
   292  			t.Fatal("Couldn't find echo command")
   293  		}
   294  		if foundCustom {
   295  			t.Fatal("Should not list the custom command")
   296  		}
   297  	})
   298  }
   299  
   300  func TestListAutocompleteCommands(t *testing.T) {
   301  	th := Setup().InitBasic().InitSystemAdmin()
   302  	defer th.TearDown()
   303  	Client := th.Client
   304  
   305  	newCmd := &model.Command{
   306  		CreatorId: th.BasicUser.Id,
   307  		TeamId:    th.BasicTeam.Id,
   308  		URL:       "http://nowhere.com",
   309  		Method:    model.COMMAND_METHOD_POST,
   310  		Trigger:   "custom_command"}
   311  
   312  	_, resp := th.SystemAdminClient.CreateCommand(newCmd)
   313  	CheckNoError(t, resp)
   314  
   315  	t.Run("ListAutocompleteCommandsOnly", func(t *testing.T) {
   316  		listCommands, resp := th.SystemAdminClient.ListAutocompleteCommands(th.BasicTeam.Id)
   317  		CheckNoError(t, resp)
   318  
   319  		foundEcho := false
   320  		foundCustom := false
   321  		for _, command := range listCommands {
   322  			if command.Trigger == "echo" {
   323  				foundEcho = true
   324  			}
   325  			if command.Trigger == "custom_command" {
   326  				foundCustom = true
   327  			}
   328  		}
   329  		if !foundEcho {
   330  			t.Fatal("Couldn't find echo command")
   331  		}
   332  		if foundCustom {
   333  			t.Fatal("Should not list the custom command")
   334  		}
   335  	})
   336  
   337  	t.Run("RegularUserCanListOnlySystemCommands", func(t *testing.T) {
   338  		listCommands, resp := Client.ListAutocompleteCommands(th.BasicTeam.Id)
   339  		CheckNoError(t, resp)
   340  
   341  		foundEcho := false
   342  		foundCustom := false
   343  		for _, command := range listCommands {
   344  			if command.Trigger == "echo" {
   345  				foundEcho = true
   346  			}
   347  			if command.Trigger == "custom_command" {
   348  				foundCustom = true
   349  			}
   350  		}
   351  		if !foundEcho {
   352  			t.Fatal("Couldn't find echo command")
   353  		}
   354  		if foundCustom {
   355  			t.Fatal("Should not list the custom command")
   356  		}
   357  	})
   358  }
   359  
   360  func TestRegenToken(t *testing.T) {
   361  	th := Setup().InitBasic().InitSystemAdmin()
   362  	defer th.TearDown()
   363  	Client := th.Client
   364  
   365  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   366  	defer func() {
   367  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   368  	}()
   369  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   370  
   371  	newCmd := &model.Command{
   372  		CreatorId: th.BasicUser.Id,
   373  		TeamId:    th.BasicTeam.Id,
   374  		URL:       "http://nowhere.com",
   375  		Method:    model.COMMAND_METHOD_POST,
   376  		Trigger:   "trigger"}
   377  
   378  	createdCmd, resp := th.SystemAdminClient.CreateCommand(newCmd)
   379  	CheckNoError(t, resp)
   380  	CheckCreatedStatus(t, resp)
   381  
   382  	token, resp := th.SystemAdminClient.RegenCommandToken(createdCmd.Id)
   383  	CheckNoError(t, resp)
   384  	if token == createdCmd.Token {
   385  		t.Fatal("should update the token")
   386  	}
   387  
   388  	token, resp = Client.RegenCommandToken(createdCmd.Id)
   389  	CheckForbiddenStatus(t, resp)
   390  	if token != "" {
   391  		t.Fatal("should not return the token")
   392  	}
   393  }
   394  
   395  func TestExecuteCommand(t *testing.T) {
   396  	th := Setup().InitBasic().InitSystemAdmin()
   397  	defer th.TearDown()
   398  	Client := th.Client
   399  	channel := th.BasicChannel
   400  
   401  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   402  	allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
   403  	defer func() {
   404  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   405  		th.App.UpdateConfig(func(cfg *model.Config) {
   406  			cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
   407  		})
   408  	}()
   409  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   410  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
   411  
   412  	postCmd := &model.Command{
   413  		CreatorId: th.BasicUser.Id,
   414  		TeamId:    th.BasicTeam.Id,
   415  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   416  		Method:    model.COMMAND_METHOD_POST,
   417  		Trigger:   "postcommand",
   418  	}
   419  
   420  	if _, err := th.App.CreateCommand(postCmd); err != nil {
   421  		t.Fatal("failed to create post command")
   422  	}
   423  
   424  	commandResponse, resp := Client.ExecuteCommand(channel.Id, "/postcommand")
   425  	CheckNoError(t, resp)
   426  
   427  	if commandResponse == nil {
   428  		t.Fatal("command response should have returned")
   429  	}
   430  
   431  	posts, err := th.App.GetPostsPage(channel.Id, 0, 10)
   432  	if err != nil || posts == nil || len(posts.Order) != 3 {
   433  		t.Fatal("Test command failed to send")
   434  	}
   435  
   436  	cmdPosted := false
   437  	for _, post := range posts.Posts {
   438  		if strings.Contains(post.Message, "test command response") {
   439  			if post.Type != "custom_test" {
   440  				t.Fatal("wrong type set in slash command post")
   441  			}
   442  
   443  			if post.Props["someprop"] != "somevalue" {
   444  				t.Fatal("wrong prop set in slash command post")
   445  			}
   446  
   447  			cmdPosted = true
   448  			break
   449  		}
   450  	}
   451  
   452  	if !cmdPosted {
   453  		t.Fatal("Test command response failed to post")
   454  	}
   455  
   456  	getCmd := &model.Command{
   457  		CreatorId: th.BasicUser.Id,
   458  		TeamId:    th.BasicTeam.Id,
   459  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   460  		Method:    model.COMMAND_METHOD_GET,
   461  		Trigger:   "getcommand",
   462  	}
   463  
   464  	if _, err := th.App.CreateCommand(getCmd); err != nil {
   465  		t.Fatal("failed to create get command")
   466  	}
   467  
   468  	commandResponse, resp = Client.ExecuteCommand(channel.Id, "/getcommand")
   469  	CheckNoError(t, resp)
   470  
   471  	if commandResponse == nil {
   472  		t.Fatal("command response should have returned")
   473  	}
   474  
   475  	posts, err = th.App.GetPostsPage(channel.Id, 0, 10)
   476  	if err != nil || posts == nil || len(posts.Order) != 4 {
   477  		t.Fatal("Test command failed to send")
   478  	}
   479  
   480  	_, resp = Client.ExecuteCommand(channel.Id, "")
   481  	CheckBadRequestStatus(t, resp)
   482  
   483  	_, resp = Client.ExecuteCommand(channel.Id, "/")
   484  	CheckBadRequestStatus(t, resp)
   485  
   486  	_, resp = Client.ExecuteCommand(channel.Id, "getcommand")
   487  	CheckBadRequestStatus(t, resp)
   488  
   489  	_, resp = Client.ExecuteCommand(channel.Id, "/junk")
   490  	CheckNotFoundStatus(t, resp)
   491  
   492  	otherUser := th.CreateUser()
   493  	Client.Login(otherUser.Email, otherUser.Password)
   494  
   495  	_, resp = Client.ExecuteCommand(channel.Id, "/getcommand")
   496  	CheckForbiddenStatus(t, resp)
   497  
   498  	Client.Logout()
   499  
   500  	_, resp = Client.ExecuteCommand(channel.Id, "/getcommand")
   501  	CheckUnauthorizedStatus(t, resp)
   502  
   503  	_, resp = th.SystemAdminClient.ExecuteCommand(channel.Id, "/getcommand")
   504  	CheckNoError(t, resp)
   505  }
   506  
   507  func TestExecuteCommandAgainstChannelOnAnotherTeam(t *testing.T) {
   508  	th := Setup().InitBasic()
   509  	defer th.TearDown()
   510  	Client := th.Client
   511  	channel := th.BasicChannel
   512  
   513  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   514  	allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
   515  	defer func() {
   516  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   517  		th.App.UpdateConfig(func(cfg *model.Config) {
   518  			cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
   519  		})
   520  	}()
   521  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   522  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
   523  
   524  	// create a slash command on some other team where we have permission to do so
   525  	team2 := th.CreateTeam()
   526  	postCmd := &model.Command{
   527  		CreatorId: th.BasicUser.Id,
   528  		TeamId:    team2.Id,
   529  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   530  		Method:    model.COMMAND_METHOD_POST,
   531  		Trigger:   "postcommand",
   532  	}
   533  	if _, err := th.App.CreateCommand(postCmd); err != nil {
   534  		t.Fatal("failed to create post command")
   535  	}
   536  
   537  	// the execute command endpoint will always search for the command by trigger and team id, inferring team id from the
   538  	// channel id, so there is no way to use that slash command on a channel that belongs to some other team
   539  	_, resp := Client.ExecuteCommand(channel.Id, "/postcommand")
   540  	CheckNotFoundStatus(t, resp)
   541  }
   542  
   543  func TestExecuteCommandAgainstChannelUserIsNotIn(t *testing.T) {
   544  	th := Setup().InitBasic()
   545  	defer th.TearDown()
   546  	client := th.Client
   547  
   548  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   549  	allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
   550  	defer func() {
   551  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   552  		th.App.UpdateConfig(func(cfg *model.Config) {
   553  			cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
   554  		})
   555  	}()
   556  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   557  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
   558  
   559  	// create a slash command on some other team where we have permission to do so
   560  	team2 := th.CreateTeam()
   561  	postCmd := &model.Command{
   562  		CreatorId: th.BasicUser.Id,
   563  		TeamId:    team2.Id,
   564  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   565  		Method:    model.COMMAND_METHOD_POST,
   566  		Trigger:   "postcommand",
   567  	}
   568  	if _, err := th.App.CreateCommand(postCmd); err != nil {
   569  		t.Fatal("failed to create post command")
   570  	}
   571  
   572  	// make a channel on that team, ensuring that our test user isn't in it
   573  	channel2 := th.CreateChannelWithClientAndTeam(client, model.CHANNEL_OPEN, team2.Id)
   574  	if success, _ := client.RemoveUserFromChannel(channel2.Id, th.BasicUser.Id); !success {
   575  		t.Fatal("Failed to remove user from channel")
   576  	}
   577  
   578  	// we should not be able to run the slash command in channel2, because we aren't in it
   579  	_, resp := client.ExecuteCommandWithTeam(channel2.Id, team2.Id, "/postcommand")
   580  	CheckForbiddenStatus(t, resp)
   581  }
   582  
   583  func TestExecuteCommandInDirectMessageChannel(t *testing.T) {
   584  	th := Setup().InitBasic()
   585  	defer th.TearDown()
   586  	client := th.Client
   587  
   588  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   589  	allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
   590  	defer func() {
   591  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   592  		th.App.UpdateConfig(func(cfg *model.Config) {
   593  			cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
   594  		})
   595  	}()
   596  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   597  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
   598  
   599  	// create a slash command on some other team where we have permission to do so
   600  	team2 := th.CreateTeam()
   601  	postCmd := &model.Command{
   602  		CreatorId: th.BasicUser.Id,
   603  		TeamId:    team2.Id,
   604  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   605  		Method:    model.COMMAND_METHOD_POST,
   606  		Trigger:   "postcommand",
   607  	}
   608  	if _, err := th.App.CreateCommand(postCmd); err != nil {
   609  		t.Fatal("failed to create post command")
   610  	}
   611  
   612  	// make a direct message channel
   613  	dmChannel, response := client.CreateDirectChannel(th.BasicUser.Id, th.BasicUser2.Id)
   614  	CheckCreatedStatus(t, response)
   615  
   616  	// we should be able to run the slash command in the DM channel
   617  	_, resp := client.ExecuteCommandWithTeam(dmChannel.Id, team2.Id, "/postcommand")
   618  	CheckOKStatus(t, resp)
   619  
   620  	// but we can't run the slash command in the DM channel if we sub in some other team's id
   621  	_, resp = client.ExecuteCommandWithTeam(dmChannel.Id, th.BasicTeam.Id, "/postcommand")
   622  	CheckNotFoundStatus(t, resp)
   623  }
   624  
   625  func TestExecuteCommandInTeamUserIsNotOn(t *testing.T) {
   626  	th := Setup().InitBasic()
   627  	defer th.TearDown()
   628  	client := th.Client
   629  
   630  	enableCommands := *th.App.Config().ServiceSettings.EnableCommands
   631  	allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
   632  	defer func() {
   633  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
   634  		th.App.UpdateConfig(func(cfg *model.Config) {
   635  			cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
   636  		})
   637  	}()
   638  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
   639  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost" })
   640  
   641  	// create a team that the user isn't a part of
   642  	team2 := th.CreateTeam()
   643  
   644  	// create a slash command on that team
   645  	postCmd := &model.Command{
   646  		CreatorId: th.BasicUser.Id,
   647  		TeamId:    team2.Id,
   648  		URL:       fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) + model.API_URL_SUFFIX_V4 + "/teams/command_test",
   649  		Method:    model.COMMAND_METHOD_POST,
   650  		Trigger:   "postcommand",
   651  	}
   652  	if _, err := th.App.CreateCommand(postCmd); err != nil {
   653  		t.Fatal("failed to create post command")
   654  	}
   655  
   656  	// make a direct message channel
   657  	dmChannel, response := client.CreateDirectChannel(th.BasicUser.Id, th.BasicUser2.Id)
   658  	CheckCreatedStatus(t, response)
   659  
   660  	// we should be able to run the slash command in the DM channel
   661  	_, resp := client.ExecuteCommandWithTeam(dmChannel.Id, team2.Id, "/postcommand")
   662  	CheckOKStatus(t, resp)
   663  
   664  	// if the user is removed from the team, they should NOT be able to run the slash command in the DM channel
   665  	if success, _ := client.RemoveTeamMember(team2.Id, th.BasicUser.Id); !success {
   666  		t.Fatal("Failed to remove user from team")
   667  	}
   668  	_, resp = client.ExecuteCommandWithTeam(dmChannel.Id, team2.Id, "/postcommand")
   669  	CheckForbiddenStatus(t, resp)
   670  
   671  	// if we omit the team id from the request, the slash command will fail because this is a DM channel, and the
   672  	// team id can't be inherited from the channel
   673  	_, resp = client.ExecuteCommand(dmChannel.Id, "/postcommand")
   674  	CheckForbiddenStatus(t, resp)
   675  }