mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-03 20:40:00 -05:00
* Support for permissions allowing end users to create and manage their own integrations if sysadmin deems necessary * Adjustments based on new understanding * remove extra functions now that we've consolidated * Fix webapp i18n * Update snapshots * Fix test * Fix some tests, refactor some more, and add a few extra * fix linter * Update snapshots * Fix test * Missed some cleanup * Fix e2e * Fi * Fix * Fixes from PR feedback * Update snapshots * Fix tests * Fix slash command list endpoint per PR feedback. Remove changes around OAuth Apps * Further reversions of oauth stuff * Update tests * Small changes to fix when customOnly=false * Remove extra perm from cypress * Fixes from Eva's feedback * Fix i18n * More fixing * More fixing
1844 lines
63 KiB
Go
1844 lines
63 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
)
|
|
|
|
func TestCreateCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
LocalClient := th.LocalClient
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger",
|
|
}
|
|
|
|
_, resp, err := client.CreateCommand(context.Background(), newCmd)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
createdCmd, resp, err := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.Equal(t, th.SystemAdminUser.Id, createdCmd.CreatorId, "user ids didn't match")
|
|
require.Equal(t, th.BasicTeam.Id, createdCmd.TeamId, "team ids didn't match")
|
|
|
|
_, resp, err = th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
CheckErrorID(t, err, "api.command.duplicate_trigger.app_error")
|
|
|
|
newCmd.Trigger = "Local"
|
|
newCmd.CreatorId = th.BasicUser.Id
|
|
localCreatedCmd, resp, err := LocalClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.Equal(t, th.BasicUser.Id, localCreatedCmd.CreatorId, "local client: user ids didn't match")
|
|
require.Equal(t, th.BasicTeam.Id, localCreatedCmd.TeamId, "local client: team ids didn't match")
|
|
|
|
newCmd.Method = "Wrong"
|
|
newCmd.Trigger = "testcommand"
|
|
_, resp, err = th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
CheckErrorID(t, err, "model.command.is_valid.method.app_error")
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = false })
|
|
newCmd.Method = "P"
|
|
newCmd.Trigger = "testcommand"
|
|
_, resp, err = th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
CheckErrorID(t, err, "api.command.disabled.app_error")
|
|
|
|
// Confirm that local clients can't override disable command setting
|
|
newCmd.Trigger = "LocalOverride"
|
|
_, _, err = LocalClient.CreateCommand(context.Background(), newCmd)
|
|
CheckErrorID(t, err, "api.command.disabled.app_error")
|
|
}
|
|
|
|
func TestCreateCommandForOtherUser(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithOnlyManageOwnCannotCreateForOthers", func(t *testing.T) {
|
|
cmdForOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_for_other_fail",
|
|
}
|
|
|
|
_, resp, err := th.Client.CreateCommand(context.Background(), cmdForOther)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanCreateForOthers", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
cmdForOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_for_other_success",
|
|
}
|
|
|
|
createdCmd, _, err := th.Client.CreateCommand(context.Background(), cmdForOther)
|
|
require.NoError(t, err)
|
|
require.Equal(t, th.BasicUser2.Id, createdCmd.CreatorId, "command should be owned by BasicUser2")
|
|
require.Equal(t, th.BasicTeam.Id, createdCmd.TeamId)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCannotCreateForNonExistentUser", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
cmdForInvalidUser := &model.Command{
|
|
CreatorId: model.NewId(), // Non-existent user ID
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_invalid_user",
|
|
}
|
|
|
|
_, resp, err := th.Client.CreateCommand(context.Background(), cmdForInvalidUser)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
|
|
t.Run("SystemAdminCanCreateForOthers", func(t *testing.T) {
|
|
cmdForOther := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_admin_for_other",
|
|
}
|
|
|
|
createdCmd, _, err := th.SystemAdminClient.CreateCommand(context.Background(), cmdForOther)
|
|
require.NoError(t, err)
|
|
require.Equal(t, th.BasicUser.Id, createdCmd.CreatorId, "command should be owned by BasicUser")
|
|
require.Equal(t, th.BasicTeam.Id, createdCmd.TeamId)
|
|
})
|
|
}
|
|
|
|
func TestUpdateCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
user := th.SystemAdminUser
|
|
team := th.BasicTeam
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
cmd1 := &model.Command{
|
|
CreatorId: user.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger1",
|
|
}
|
|
|
|
cmd1, _ = th.App.CreateCommand(cmd1)
|
|
|
|
cmd2 := &model.Command{
|
|
CreatorId: GenerateTestID(),
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com/change",
|
|
Method: model.CommandMethodGet,
|
|
Trigger: "trigger2",
|
|
Id: cmd1.Id,
|
|
Token: "tokenchange",
|
|
}
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
|
rcmd, _, err := client.UpdateCommand(context.Background(), cmd2)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, cmd2.Trigger, rcmd.Trigger, "Trigger should have updated")
|
|
|
|
require.Equal(t, cmd2.Method, rcmd.Method, "Method should have updated")
|
|
|
|
require.Equal(t, cmd2.URL, rcmd.URL, "URL should have updated")
|
|
|
|
require.Equal(t, cmd1.CreatorId, rcmd.CreatorId, "CreatorId should have not updated")
|
|
|
|
require.Equal(t, cmd1.Token, rcmd.Token, "Token should have not updated")
|
|
|
|
cmd2.Id = GenerateTestID()
|
|
|
|
rcmd, resp, err := client.UpdateCommand(context.Background(), cmd2)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
require.Nil(t, rcmd, "should be empty")
|
|
|
|
cmd2.Id = "junk"
|
|
|
|
_, resp, err = client.UpdateCommand(context.Background(), cmd2)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
cmd2.Id = cmd1.Id
|
|
cmd2.TeamId = GenerateTestID()
|
|
|
|
_, resp, err = client.UpdateCommand(context.Background(), cmd2)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
cmd2.TeamId = team.Id
|
|
|
|
_, resp, err = th.Client.UpdateCommand(context.Background(), cmd2)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
_, err := th.SystemAdminClient.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err := th.SystemAdminClient.UpdateCommand(context.Background(), cmd2)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
// Permission tests
|
|
th.LoginBasic(t)
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserCanUpdateTheirOwnCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own",
|
|
}
|
|
createdCmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// Update the command
|
|
createdCmd.URL = "http://newurl.com"
|
|
updatedCmd, _, err := th.Client.UpdateCommand(context.Background(), createdCmd)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "http://newurl.com", updatedCmd.URL)
|
|
})
|
|
|
|
t.Run("UserWithoutManageOthersCannotUpdateOthersCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other",
|
|
}
|
|
createdCmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// Try to update the command
|
|
createdCmd.URL = "http://newurl.com"
|
|
_, resp, err := th.Client.UpdateCommand(context.Background(), createdCmd)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanUpdateOthersCommand", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other2",
|
|
}
|
|
createdCmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// Update the command
|
|
createdCmd.URL = "http://newurl.com"
|
|
updatedCmd, _, err := th.Client.UpdateCommand(context.Background(), createdCmd)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "http://newurl.com", updatedCmd.URL)
|
|
})
|
|
|
|
t.Run("UserWithOnlyManageOwnCannotUpdateOthersCommand", func(t *testing.T) {
|
|
// BasicUser should only have ManageOwn permission (already set up in the test)
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other3",
|
|
}
|
|
createdCmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// Try to update the command
|
|
createdCmd.URL = "http://newurl.com"
|
|
_, resp, err := th.Client.UpdateCommand(context.Background(), createdCmd)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestMoveCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
user := th.SystemAdminUser
|
|
team := th.BasicTeam
|
|
newTeam := th.CreateTeam(t)
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
cmd1 := &model.Command{
|
|
CreatorId: user.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger1",
|
|
}
|
|
|
|
rcmd1, _ := th.App.CreateCommand(cmd1)
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
|
_, err := client.MoveCommand(context.Background(), newTeam.Id, rcmd1.Id)
|
|
require.NoError(t, err)
|
|
|
|
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
|
require.NotNil(t, rcmd1)
|
|
require.Equal(t, newTeam.Id, rcmd1.TeamId)
|
|
|
|
resp, err := client.MoveCommand(context.Background(), newTeam.Id, "bogus")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
resp, err = client.MoveCommand(context.Background(), GenerateTestID(), rcmd1.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
cmd2 := &model.Command{
|
|
CreatorId: user.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger2",
|
|
}
|
|
|
|
rcmd2, _ := th.App.CreateCommand(cmd2)
|
|
|
|
resp, err := th.Client.MoveCommand(context.Background(), newTeam.Id, rcmd2.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
_, err = th.SystemAdminClient.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
resp, err = th.SystemAdminClient.MoveCommand(context.Background(), newTeam.Id, rcmd2.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
// Set up for permission tests
|
|
th.LoginBasic(t)
|
|
th.LinkUserToTeam(t, th.BasicUser, newTeam)
|
|
th.LinkUserToTeam(t, th.BasicUser2, newTeam)
|
|
|
|
// Give BasicUser permission to manage their own commands on both teams
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithoutManageOthersPermissionCannotMoveOthersCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger3",
|
|
}
|
|
rcmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// BasicUser should not be able to move BasicUser2's command
|
|
resp, err := th.Client.MoveCommand(context.Background(), newTeam.Id, rcmd.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// Verify the command was not moved
|
|
movedCmd, _ := th.App.GetCommand(rcmd.Id)
|
|
require.Equal(t, team.Id, movedCmd.TeamId)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersPermissionCanMoveOthersCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger4",
|
|
}
|
|
rcmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// Give BasicUser the permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Now BasicUser should be able to move BasicUser2's command
|
|
_, err := th.Client.MoveCommand(context.Background(), newTeam.Id, rcmd.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the command was moved
|
|
movedCmd, _ := th.App.GetCommand(rcmd.Id)
|
|
require.Equal(t, newTeam.Id, movedCmd.TeamId)
|
|
})
|
|
|
|
t.Run("CreatorCanMoveTheirOwnCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger5",
|
|
}
|
|
rcmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// BasicUser should be able to move their own command
|
|
_, err := th.Client.MoveCommand(context.Background(), newTeam.Id, rcmd.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the command was moved
|
|
movedCmd, _ := th.App.GetCommand(rcmd.Id)
|
|
require.Equal(t, newTeam.Id, movedCmd.TeamId)
|
|
})
|
|
|
|
t.Run("UserWithOnlyManageOwnCannotMoveOthersCommand", func(t *testing.T) {
|
|
// BasicUser should only have ManageOwn permission (already set up in the test)
|
|
// Create a command owned by BasicUser2
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger6",
|
|
}
|
|
rcmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// BasicUser should not be able to move BasicUser2's command
|
|
resp, err := th.Client.MoveCommand(context.Background(), newTeam.Id, rcmd.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// Verify the command was not moved
|
|
notMovedCmd, _ := th.App.GetCommand(rcmd.Id)
|
|
require.Equal(t, team.Id, notMovedCmd.TeamId)
|
|
})
|
|
|
|
t.Run("CannotMoveCommandWhenCreatorHasNoPermissionToNewTeam", func(t *testing.T) {
|
|
// Create a third team that the command creator (BasicUser2) is NOT a member of
|
|
thirdTeam := th.CreateTeam(t)
|
|
th.LinkUserToTeam(t, th.BasicUser, thirdTeam)
|
|
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser2
|
|
// Note: BasicUser2 is NOT a member of thirdTeam (only member of team and newTeam)
|
|
cmd := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger7",
|
|
}
|
|
rcmd, _ := th.App.CreateCommand(cmd)
|
|
|
|
// BasicUser attempts to move BasicUser2's command to thirdTeam
|
|
// This should fail because BasicUser2 doesn't have permission to thirdTeam
|
|
resp, err := th.Client.MoveCommand(context.Background(), thirdTeam.Id, rcmd.Id)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
// Verify the command was not moved
|
|
notMovedCmd, _ := th.App.GetCommand(rcmd.Id)
|
|
require.Equal(t, team.Id, notMovedCmd.TeamId)
|
|
})
|
|
}
|
|
|
|
func TestDeleteCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
user := th.SystemAdminUser
|
|
team := th.BasicTeam
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
cmd1 := &model.Command{
|
|
CreatorId: user.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger1",
|
|
}
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
|
cmd1.Id = ""
|
|
rcmd1, appErr := th.App.CreateCommand(cmd1)
|
|
require.Nil(t, appErr)
|
|
_, err := client.DeleteCommand(context.Background(), rcmd1.Id)
|
|
require.NoError(t, err)
|
|
|
|
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
|
require.Nil(t, rcmd1)
|
|
|
|
resp, err := client.DeleteCommand(context.Background(), "junk")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
resp, err = client.DeleteCommand(context.Background(), GenerateTestID())
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
cmd2 := &model.Command{
|
|
CreatorId: user.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger2",
|
|
}
|
|
|
|
rcmd2, _ := th.App.CreateCommand(cmd2)
|
|
|
|
resp, err := th.Client.DeleteCommand(context.Background(), rcmd2.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
_, err = th.SystemAdminClient.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
resp, err = th.SystemAdminClient.DeleteCommand(context.Background(), rcmd2.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
// Permission tests for ManageOwn vs ManageOthers
|
|
th.LoginBasic(t)
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithManageOwnCanDeleteOnlyOwnCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_delete",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_delete",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// Should be able to delete own command
|
|
_, err := th.Client.DeleteCommand(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the command was deleted
|
|
deletedCmd, _ := th.App.GetCommand(createdCmdOwn.Id)
|
|
require.Nil(t, deletedCmd)
|
|
|
|
// Should not be able to delete other user's command
|
|
resp, err := th.Client.DeleteCommand(context.Background(), createdCmdOther.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// Verify the command was not deleted
|
|
notDeletedCmd, _ := th.App.GetCommand(createdCmdOther.Id)
|
|
require.NotNil(t, notDeletedCmd)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanDeleteAnyCommand", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_delete2",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: team.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_delete2",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// Should be able to delete own command
|
|
_, err := th.Client.DeleteCommand(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the command was deleted
|
|
deletedCmd, _ := th.App.GetCommand(createdCmdOwn.Id)
|
|
require.Nil(t, deletedCmd)
|
|
|
|
// Should be able to delete other user's command
|
|
_, err = th.Client.DeleteCommand(context.Background(), createdCmdOther.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the command was deleted
|
|
deletedCmd, _ = th.App.GetCommand(createdCmdOther.Id)
|
|
require.Nil(t, deletedCmd)
|
|
})
|
|
}
|
|
|
|
func TestListCommands(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "custom_command",
|
|
}
|
|
_, _, rootErr := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, rootErr)
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
listCommands, _, err := c.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundCustom := false
|
|
for _, command := range listCommands {
|
|
if command.Trigger == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Trigger == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.True(t, foundCustom, "Should list the custom command")
|
|
}, "ListSystemAndCustomCommands")
|
|
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
|
|
listCommands, _, err := c.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, listCommands, 1, "Should list just one custom command")
|
|
require.Equal(t, listCommands[0].Trigger, "custom_command", "Wrong custom command trigger")
|
|
}, "ListCustomOnlyCommands")
|
|
|
|
t.Run("UserWithNoPermissionForCustomCommands", func(t *testing.T) {
|
|
_, resp, err := client.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("RegularUserCanListOnlySystemCommands", func(t *testing.T) {
|
|
listCommands, _, err := client.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundCustom := false
|
|
for _, command := range listCommands {
|
|
if command.Trigger == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Trigger == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.False(t, foundCustom, "Should not list the custom command")
|
|
})
|
|
|
|
t.Run("NoMember", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
user := th.CreateUser(t)
|
|
_, _, err = client.Login(context.Background(), user.Email, user.Password)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
_, resp, err = client.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("NotLoggedIn", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err := client.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
_, resp, err = client.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
|
|
// Permission tests for ManageOwn vs ManageOthers
|
|
th.LoginBasic(t)
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithManageOwnCanListOnlyOwnCustomCommands", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_list",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_list",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// List custom commands only
|
|
listCommands, _, err := th.Client.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.NoError(t, err)
|
|
|
|
foundOwn := false
|
|
foundOther := false
|
|
for _, command := range listCommands {
|
|
if command.Id == createdCmdOwn.Id {
|
|
foundOwn = true
|
|
}
|
|
if command.Id == createdCmdOther.Id {
|
|
foundOther = true
|
|
}
|
|
}
|
|
require.True(t, foundOwn, "Should list own command")
|
|
require.False(t, foundOther, "Should not list other user's command")
|
|
|
|
// List all commands (system + custom)
|
|
listCommandsAll, _, err := th.Client.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.NoError(t, err)
|
|
|
|
foundOwn = false
|
|
foundOther = false
|
|
foundSystem := false
|
|
for _, command := range listCommandsAll {
|
|
if command.Id == createdCmdOwn.Id {
|
|
foundOwn = true
|
|
}
|
|
if command.Id == createdCmdOther.Id {
|
|
foundOther = true
|
|
}
|
|
if command.Trigger == "echo" {
|
|
foundSystem = true
|
|
}
|
|
}
|
|
require.True(t, foundOwn, "Should list own command")
|
|
require.False(t, foundOther, "Should not list other user's command")
|
|
require.True(t, foundSystem, "Should list system commands")
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanListAllCustomCommands", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_list2",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_list2",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// List custom commands only
|
|
listCommands, _, err := th.Client.ListCommands(context.Background(), th.BasicTeam.Id, true)
|
|
require.NoError(t, err)
|
|
|
|
foundOwn := false
|
|
foundOther := false
|
|
for _, command := range listCommands {
|
|
if command.Id == createdCmdOwn.Id {
|
|
foundOwn = true
|
|
}
|
|
if command.Id == createdCmdOther.Id {
|
|
foundOther = true
|
|
}
|
|
}
|
|
require.True(t, foundOwn, "Should list own command")
|
|
require.True(t, foundOther, "Should list other user's command")
|
|
|
|
// List all commands (system + custom)
|
|
listCommandsAll, _, err := th.Client.ListCommands(context.Background(), th.BasicTeam.Id, false)
|
|
require.NoError(t, err)
|
|
|
|
foundOwn = false
|
|
foundOther = false
|
|
for _, command := range listCommandsAll {
|
|
if command.Id == createdCmdOwn.Id {
|
|
foundOwn = true
|
|
}
|
|
if command.Id == createdCmdOther.Id {
|
|
foundOther = true
|
|
}
|
|
}
|
|
require.True(t, foundOwn, "Should list own command")
|
|
require.True(t, foundOther, "Should list other user's command")
|
|
})
|
|
}
|
|
|
|
func TestListAutocompleteCommands(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "custom_command",
|
|
}
|
|
|
|
_, _, err := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("ListAutocompleteCommandsOnly", func(t *testing.T) {
|
|
listCommands, _, err := th.SystemAdminClient.ListAutocompleteCommands(context.Background(), th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundCustom := false
|
|
for _, command := range listCommands {
|
|
if command.Trigger == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Trigger == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.False(t, foundCustom, "Should not list the custom command")
|
|
})
|
|
|
|
t.Run("RegularUserCanListOnlySystemCommands", func(t *testing.T) {
|
|
listCommands, _, err := client.ListAutocompleteCommands(context.Background(), th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundCustom := false
|
|
for _, command := range listCommands {
|
|
if command.Trigger == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Trigger == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.False(t, foundCustom, "Should not list the custom command")
|
|
})
|
|
|
|
t.Run("NoMember", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
user := th.CreateUser(t)
|
|
_, _, err = client.Login(context.Background(), user.Email, user.Password)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.ListAutocompleteCommands(context.Background(), th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("NotLoggedIn", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err := client.ListAutocompleteCommands(context.Background(), th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestListCommandAutocompleteSuggestions(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "custom_command",
|
|
}
|
|
|
|
_, _, err := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("ListAutocompleteSuggestionsOnly", func(t *testing.T) {
|
|
suggestions, _, err := th.SystemAdminClient.ListCommandAutocompleteSuggestions(context.Background(), "/", th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundShrug := false
|
|
foundCustom := false
|
|
for _, command := range suggestions {
|
|
if command.Suggestion == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Suggestion == "shrug" {
|
|
foundShrug = true
|
|
}
|
|
if command.Suggestion == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.True(t, foundShrug, "Couldn't find shrug command")
|
|
require.False(t, foundCustom, "Should not list the custom command")
|
|
})
|
|
|
|
t.Run("ListAutocompleteSuggestionsOnlyWithInput", func(t *testing.T) {
|
|
suggestions, _, err := th.SystemAdminClient.ListCommandAutocompleteSuggestions(context.Background(), "/e", th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundShrug := false
|
|
for _, command := range suggestions {
|
|
if command.Suggestion == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if command.Suggestion == "shrug" {
|
|
foundShrug = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.False(t, foundShrug, "Should not list the shrug command")
|
|
})
|
|
|
|
t.Run("RegularUserCanListOnlySystemCommands", func(t *testing.T) {
|
|
suggestions, _, err := client.ListCommandAutocompleteSuggestions(context.Background(), "/", th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
|
|
foundEcho := false
|
|
foundCustom := false
|
|
for _, suggestion := range suggestions {
|
|
if suggestion.Suggestion == "echo" {
|
|
foundEcho = true
|
|
}
|
|
if suggestion.Suggestion == "custom_command" {
|
|
foundCustom = true
|
|
}
|
|
}
|
|
require.True(t, foundEcho, "Couldn't find echo command")
|
|
require.False(t, foundCustom, "Should not list the custom command")
|
|
})
|
|
|
|
t.Run("NoMember", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
user := th.CreateUser(t)
|
|
_, _, err = client.Login(context.Background(), user.Email, user.Password)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.ListCommandAutocompleteSuggestions(context.Background(), "/", th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("NotLoggedIn", func(t *testing.T) {
|
|
_, err := client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err := client.ListCommandAutocompleteSuggestions(context.Background(), "/", th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
}
|
|
|
|
func TestGetCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "roger",
|
|
}
|
|
newCmd, _, rootErr := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, rootErr)
|
|
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
|
t.Run("ValidId", func(t *testing.T) {
|
|
cmd, _, err := client.GetCommandById(context.Background(), newCmd.Id)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, newCmd.Id, cmd.Id)
|
|
require.Equal(t, newCmd.CreatorId, cmd.CreatorId)
|
|
require.Equal(t, newCmd.TeamId, cmd.TeamId)
|
|
require.Equal(t, newCmd.URL, cmd.URL)
|
|
require.Equal(t, newCmd.Method, cmd.Method)
|
|
require.Equal(t, newCmd.Trigger, cmd.Trigger)
|
|
})
|
|
|
|
t.Run("InvalidId", func(t *testing.T) {
|
|
_, _, err := client.GetCommandById(context.Background(), strings.Repeat("z", len(newCmd.Id)))
|
|
require.Error(t, err)
|
|
})
|
|
})
|
|
t.Run("UserWithNoPermissionForCustomCommands", func(t *testing.T) {
|
|
_, resp, err := th.Client.GetCommandById(context.Background(), newCmd.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
|
|
t.Run("NoMember", func(t *testing.T) {
|
|
_, err := th.Client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
user := th.CreateUser(t)
|
|
_, _, err = th.Client.Login(context.Background(), user.Email, user.Password)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := th.Client.GetCommandById(context.Background(), newCmd.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
|
|
t.Run("NotLoggedIn", func(t *testing.T) {
|
|
_, err := th.Client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err := th.Client.GetCommandById(context.Background(), newCmd.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
})
|
|
|
|
// Permission tests for ManageOwn vs ManageOthers
|
|
th.LoginBasic(t)
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithManageOwnCanGetOnlyOwnCommand", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_get",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_get",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// Should be able to get own command
|
|
cmd, _, err := th.Client.GetCommandById(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, createdCmdOwn.Id, cmd.Id)
|
|
|
|
// Should not be able to get other user's command
|
|
_, resp, err := th.Client.GetCommandById(context.Background(), createdCmdOther.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanGetAnyCommand", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_get2",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_get2",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// Should be able to get own command
|
|
cmd, _, err := th.Client.GetCommandById(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, createdCmdOwn.Id, cmd.Id)
|
|
|
|
// Should be able to get other user's command
|
|
cmd, _, err = th.Client.GetCommandById(context.Background(), createdCmdOther.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, createdCmdOther.Id, cmd.Id)
|
|
})
|
|
}
|
|
|
|
func TestRegenToken(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
|
|
newCmd := &model.Command{
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger",
|
|
}
|
|
|
|
createdCmd, resp, err := th.SystemAdminClient.CreateCommand(context.Background(), newCmd)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
|
|
token, _, err := th.SystemAdminClient.RegenCommandToken(context.Background(), createdCmd.Id)
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, createdCmd.Token, token, "should update the token")
|
|
|
|
token, resp, err = client.RegenCommandToken(context.Background(), createdCmd.Id)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
require.Empty(t, token, "should not return the token")
|
|
|
|
// Permission tests for ManageOwn vs ManageOthers
|
|
th.LoginBasic(t)
|
|
|
|
// Give BasicUser permission to manage their own commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOwnSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
t.Run("UserWithManageOwnCanRegenOnlyOwnCommandToken", func(t *testing.T) {
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_regen",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
oldToken := createdCmdOwn.Token
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_regen",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
|
|
// Should be able to regenerate own command token
|
|
newToken, _, err := th.Client.RegenCommandToken(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, oldToken, newToken)
|
|
|
|
// Should not be able to regenerate other user's command token
|
|
_, resp, err := th.Client.RegenCommandToken(context.Background(), createdCmdOther.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
})
|
|
|
|
t.Run("UserWithManageOthersCanRegenAnyCommandToken", func(t *testing.T) {
|
|
// Give BasicUser permission to manage others' commands
|
|
th.AddPermissionToRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
defer th.RemovePermissionFromRole(t, model.PermissionManageOthersSlashCommands.Id, model.TeamUserRoleId)
|
|
|
|
// Create a command owned by BasicUser
|
|
cmdOwn := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_own_regen2",
|
|
}
|
|
createdCmdOwn, _ := th.App.CreateCommand(cmdOwn)
|
|
oldTokenOwn := createdCmdOwn.Token
|
|
|
|
// Create a command owned by BasicUser2
|
|
cmdOther := &model.Command{
|
|
CreatorId: th.BasicUser2.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: "http://nowhere.com",
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "trigger_other_regen2",
|
|
}
|
|
createdCmdOther, _ := th.App.CreateCommand(cmdOther)
|
|
oldTokenOther := createdCmdOther.Token
|
|
|
|
// Should be able to regenerate own command token
|
|
newToken, _, err := th.Client.RegenCommandToken(context.Background(), createdCmdOwn.Id)
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, oldTokenOwn, newToken)
|
|
|
|
// Should be able to regenerate other user's command token
|
|
newToken, _, err = th.Client.RegenCommandToken(context.Background(), createdCmdOther.Id)
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, oldTokenOther, newToken)
|
|
})
|
|
}
|
|
|
|
func TestExecuteInvalidCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
channel := th.BasicChannel
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
rc := &model.CommandResponse{}
|
|
|
|
if err := json.NewEncoder(w).Encode(rc); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
getCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodGet,
|
|
Trigger: "getcommand",
|
|
}
|
|
|
|
_, appErr := th.App.CreateCommand(getCmd)
|
|
require.Nil(t, appErr, "failed to create get command")
|
|
|
|
_, resp, err := client.ExecuteCommand(context.Background(), channel.Id, "")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = client.ExecuteCommand(context.Background(), channel.Id, "/")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = client.ExecuteCommand(context.Background(), channel.Id, "getcommand")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = client.ExecuteCommand(context.Background(), channel.Id, "/junk")
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
otherUser := th.CreateUser(t)
|
|
_, _, err = client.Login(context.Background(), otherUser.Email, otherUser.Password)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.ExecuteCommand(context.Background(), channel.Id, "/getcommand")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.ExecuteCommand(context.Background(), channel.Id, "/getcommand")
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
_, _, err = th.SystemAdminClient.ExecuteCommand(context.Background(), channel.Id, "/getcommand")
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestExecuteGetCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
channel := th.BasicChannel
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
|
|
|
token := model.NewId()
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test get command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodGet, r.Method)
|
|
|
|
values, err := url.ParseQuery(r.URL.RawQuery)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, token, values.Get("token"))
|
|
require.Equal(t, th.BasicTeam.Name, values.Get("team_domain"))
|
|
require.Equal(t, "ourCommand", values.Get("cmd"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
getCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: ts.URL + "/?cmd=ourCommand",
|
|
Method: model.CommandMethodGet,
|
|
Trigger: "getcommand",
|
|
Token: token,
|
|
}
|
|
|
|
_, appErr := th.App.CreateCommand(getCmd)
|
|
require.Nil(t, appErr, "failed to create get command")
|
|
|
|
commandResponse, _, err := client.ExecuteCommand(context.Background(), channel.Id, "/getcommand")
|
|
require.NoError(t, err)
|
|
assert.True(t, len(commandResponse.TriggerId) == 26)
|
|
|
|
expectedCommandResponse.TriggerId = commandResponse.TriggerId
|
|
require.Equal(t, expectedCommandResponse, commandResponse)
|
|
}
|
|
|
|
func TestExecutePostCommand(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
channel := th.BasicChannel
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.0/8" })
|
|
|
|
token := model.NewId()
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
|
|
err := r.ParseForm()
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, token, r.FormValue("token"))
|
|
require.Equal(t, th.BasicTeam.Name, r.FormValue("team_domain"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
Token: token,
|
|
}
|
|
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create get command")
|
|
|
|
commandResponse, _, err := client.ExecuteCommand(context.Background(), channel.Id, "/postcommand")
|
|
require.NoError(t, err)
|
|
assert.True(t, len(commandResponse.TriggerId) == 26)
|
|
|
|
expectedCommandResponse.TriggerId = commandResponse.TriggerId
|
|
require.Equal(t, expectedCommandResponse, commandResponse)
|
|
}
|
|
|
|
func TestExecuteCommandAgainstChannelOnAnotherTeam(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
channel := th.BasicChannel
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
|
})
|
|
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// create a slash command on some other team where we have permission to do so
|
|
team2 := th.CreateTeam(t)
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team2.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
}
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create post command")
|
|
|
|
// the execute command endpoint will always search for the command by trigger and team id, inferring team id from the
|
|
// channel id, so there is no way to use that slash command on a channel that belongs to some other team
|
|
_, resp, err := client.ExecuteCommand(context.Background(), channel.Id, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
}
|
|
|
|
func TestExecuteCommandAgainstChannelUserIsNotIn(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
|
})
|
|
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// create a slash command on some other team where we have permission to do so
|
|
team2 := th.CreateTeam(t)
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team2.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
}
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create post command")
|
|
|
|
// make a channel on that team, ensuring that our test user isn't in it
|
|
channel2 := th.CreateChannelWithClientAndTeam(t, client, model.ChannelTypeOpen, team2.Id)
|
|
_, err := th.Client.RemoveUserFromChannel(context.Background(), channel2.Id, th.BasicUser.Id)
|
|
require.NoError(t, err, "Failed to remove user from channel")
|
|
|
|
// we should not be able to run the slash command in channel2, because we aren't in it
|
|
_, resp, err := client.ExecuteCommandWithTeam(context.Background(), channel2.Id, team2.Id, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
}
|
|
|
|
func TestExecuteCommandInDirectMessageChannel(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
|
})
|
|
|
|
// create a team that the user isn't a part of
|
|
team2 := th.CreateTeam(t)
|
|
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// create a slash command on some other team where we have permission to do so
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team2.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
}
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create post command")
|
|
|
|
// make a direct message channel
|
|
dmChannel, response, err := client.CreateDirectChannel(context.Background(), th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, response)
|
|
|
|
// we should be able to run the slash command in the DM channel
|
|
_, resp, err := client.ExecuteCommandWithTeam(context.Background(), dmChannel.Id, team2.Id, "/postcommand")
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
// but we can't run the slash command in the DM channel if we sub in some other team's id
|
|
_, resp, err = client.ExecuteCommandWithTeam(context.Background(), dmChannel.Id, th.BasicTeam.Id, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
}
|
|
|
|
func TestExecuteCommandInTeamUserIsNotOn(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
|
})
|
|
|
|
// create a team that the user isn't a part of
|
|
team2 := th.CreateTeam(t)
|
|
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
err := r.ParseForm()
|
|
require.NoError(t, err)
|
|
require.Equal(t, team2.Name, r.FormValue("team_domain"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// create a slash command on that team
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: team2.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
}
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create post command")
|
|
|
|
// make a direct message channel
|
|
dmChannel, response, err := client.CreateDirectChannel(context.Background(), th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, response)
|
|
|
|
// we should be able to run the slash command in the DM channel
|
|
_, resp, err := client.ExecuteCommandWithTeam(context.Background(), dmChannel.Id, team2.Id, "/postcommand")
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
// if the user is removed from the team, they should NOT be able to run the slash command in the DM channel
|
|
_, err = th.Client.RemoveTeamMember(context.Background(), team2.Id, th.BasicUser.Id)
|
|
require.NoError(t, err, "Failed to remove user from team")
|
|
|
|
_, resp, err = client.ExecuteCommandWithTeam(context.Background(), dmChannel.Id, team2.Id, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// if we omit the team id from the request, the slash command will fail because this is a DM channel, and the
|
|
// team id can't be inherited from the channel
|
|
_, resp, err = client.ExecuteCommand(context.Background(), dmChannel.Id, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
}
|
|
|
|
func TestExecuteCommandReadOnly(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
|
allowedInternalConnections := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
|
defer func() {
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableCommands = &enableCommands })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
|
|
})
|
|
}()
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCommands = true })
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost,127.0.0.1"
|
|
})
|
|
|
|
expectedCommandResponse := &model.CommandResponse{
|
|
Text: "test post command response",
|
|
ResponseType: model.CommandResponseTypeInChannel,
|
|
Type: "custom_test",
|
|
Props: map[string]any{"someprop": "somevalue"},
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
err := r.ParseForm()
|
|
require.NoError(t, err)
|
|
require.Equal(t, th.BasicTeam.Name, r.FormValue("team_domain"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(expectedCommandResponse); err != nil {
|
|
th.TestLogger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// create a slash command on that team
|
|
postCmd := &model.Command{
|
|
CreatorId: th.BasicUser.Id,
|
|
TeamId: th.BasicTeam.Id,
|
|
URL: ts.URL,
|
|
Method: model.CommandMethodPost,
|
|
Trigger: "postcommand",
|
|
}
|
|
_, appErr := th.App.CreateCommand(postCmd)
|
|
require.Nil(t, appErr, "failed to create post command")
|
|
|
|
// Confirm that the command works when the channel is not read only
|
|
_, resp, err := client.ExecuteCommandWithTeam(context.Background(), th.BasicChannel.Id, th.BasicChannel.TeamId, "/postcommand")
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
// Enable Enterprise features
|
|
th.App.Srv().SetLicense(model.NewTestLicense())
|
|
|
|
err = th.App.SetPhase2PermissionsMigrationStatus(true)
|
|
require.NoError(t, err)
|
|
|
|
_, appErr = th.App.PatchChannelModerationsForChannel(
|
|
th.Context,
|
|
th.BasicChannel,
|
|
[]*model.ChannelModerationPatch{{
|
|
Name: &model.PermissionCreatePost.Id,
|
|
Roles: &model.ChannelModeratedRolesPatch{
|
|
Guests: model.NewPointer(false),
|
|
Members: model.NewPointer(false),
|
|
},
|
|
}})
|
|
require.Nil(t, appErr)
|
|
|
|
// Confirm that the command fails when the channel is read only
|
|
_, resp, err = client.ExecuteCommandWithTeam(context.Background(), th.BasicChannel.Id, th.BasicChannel.TeamId, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// Confirm that the command works when the channel is not read only - use different channel
|
|
_, resp, err = client.ExecuteCommandWithTeam(context.Background(), th.BasicChannel2.Id, th.BasicChannel2.TeamId, "/postcommand")
|
|
require.NoError(t, err)
|
|
CheckOKStatus(t, resp)
|
|
|
|
appErr = th.App.DeleteChannel(
|
|
th.Context,
|
|
th.BasicChannel2,
|
|
th.SystemAdminUser.Id,
|
|
)
|
|
require.Nil(t, appErr, "failed to delete channel")
|
|
|
|
// Confirm that the command fails when the channel is archived
|
|
_, resp, err = client.ExecuteCommandWithTeam(context.Background(), th.BasicChannel2.Id, th.BasicChannel2.TeamId, "/postcommand")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
}
|