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