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