MM-24847 MM-24484 MM-24850 MM-24849 - local mode for commands (#14571)
* add unix socket listener for mmctl local mode * First working PoC * Adds the channel list endpoint * Add team list endpoint * Add a LocalClient to the api test helper and start local mode * Add helper to test with both SystemAdmin and Local clients * Add some docs * Adds TestForAllClients test helper * Incorporating @ashishbhate's proposal for adding test names to the helpers * [MM-24146] Add unix socket listener for mmctl local mode (#14296) * add unix socket listener for mmctl local mode * add a constant for local-mode socket path * reflect review comments * Fix init errors after merge * Adds create channel tests * Always init local mode to allow for enabling-disabling it via config * Check the RemoteAddr of the request before marking session as local * Mark the request as errored if it's local and the origin is remote * Set the socket permissions to read/write when initialising * Fix linter * Replace RemoteAddr check to ditch connections with the IP:PORT shape * added update/move/get/delete command in local mode * merge fix * . Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> Co-authored-by: Miguel de la Cruz <miguel@mcrx.me>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d1788cab85
Коммит
2af00f73c0
@@ -283,6 +283,7 @@ func InitLocal(configservice configservice.ConfigService, globalOptionsFunc app.
|
||||
api.BaseRoutes.Plugin = api.BaseRoutes.Plugins.PathPrefix("/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
|
||||
|
||||
api.BaseRoutes.Commands = api.BaseRoutes.ApiRoot.PathPrefix("/commands").Subrouter()
|
||||
api.BaseRoutes.Command = api.BaseRoutes.Commands.PathPrefix("/{command_id:[A-Za-z0-9]+}").Subrouter()
|
||||
|
||||
api.BaseRoutes.License = api.BaseRoutes.ApiRoot.PathPrefix("/license").Subrouter()
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ import (
|
||||
func (api *API) InitCommandLocal() {
|
||||
api.BaseRoutes.Commands.Handle("", api.ApiLocal(localCreateCommand)).Methods("POST")
|
||||
api.BaseRoutes.Commands.Handle("", api.ApiLocal(listCommands)).Methods("GET")
|
||||
|
||||
api.BaseRoutes.Command.Handle("", api.ApiLocal(getCommand)).Methods("GET")
|
||||
api.BaseRoutes.Command.Handle("", api.ApiLocal(updateCommand)).Methods("PUT")
|
||||
api.BaseRoutes.Command.Handle("/move", api.ApiLocal(moveCommand)).Methods("PUT")
|
||||
api.BaseRoutes.Command.Handle("", api.ApiLocal(deleteCommand)).Methods("DELETE")
|
||||
}
|
||||
|
||||
func localCreateCommand(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -77,7 +77,6 @@ func TestCreateCommand(t *testing.T) {
|
||||
func TestUpdateCommand(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
Client := th.SystemAdminClient
|
||||
user := th.SystemAdminUser
|
||||
team := th.BasicTeam
|
||||
|
||||
@@ -107,51 +106,51 @@ func TestUpdateCommand(t *testing.T) {
|
||||
Token: "tokenchange",
|
||||
}
|
||||
|
||||
rcmd, resp := Client.UpdateCommand(cmd2)
|
||||
CheckNoError(t, resp)
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
rcmd, resp := client.UpdateCommand(cmd2)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.Equal(t, cmd2.Trigger, rcmd.Trigger, "Trigger should have updated")
|
||||
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.Method, rcmd.Method, "Method should have updated")
|
||||
|
||||
require.Equal(t, cmd2.URL, rcmd.URL, "URL 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.CreatorId, rcmd.CreatorId, "CreatorId should have not updated")
|
||||
|
||||
require.Equal(t, cmd1.Token, rcmd.Token, "Token should have not updated")
|
||||
require.Equal(t, cmd1.Token, rcmd.Token, "Token should have not updated")
|
||||
|
||||
cmd2.Id = GenerateTestId()
|
||||
cmd2.Id = GenerateTestId()
|
||||
|
||||
rcmd, resp = Client.UpdateCommand(cmd2)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
rcmd, resp = client.UpdateCommand(cmd2)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
|
||||
require.Nil(t, rcmd, "should be empty")
|
||||
require.Nil(t, rcmd, "should be empty")
|
||||
|
||||
cmd2.Id = "junk"
|
||||
cmd2.Id = "junk"
|
||||
|
||||
_, resp = Client.UpdateCommand(cmd2)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
_, resp = client.UpdateCommand(cmd2)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
cmd2.Id = cmd1.Id
|
||||
cmd2.TeamId = GenerateTestId()
|
||||
cmd2.Id = cmd1.Id
|
||||
cmd2.TeamId = GenerateTestId()
|
||||
|
||||
_, resp = Client.UpdateCommand(cmd2)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
_, resp = client.UpdateCommand(cmd2)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
cmd2.TeamId = team.Id
|
||||
cmd2.TeamId = team.Id
|
||||
|
||||
_, resp = th.Client.UpdateCommand(cmd2)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
|
||||
Client.Logout()
|
||||
_, resp = Client.UpdateCommand(cmd2)
|
||||
_, resp = th.Client.UpdateCommand(cmd2)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
th.SystemAdminClient.Logout()
|
||||
_, resp := th.SystemAdminClient.UpdateCommand(cmd2)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
}
|
||||
|
||||
func TestMoveCommand(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
Client := th.SystemAdminClient
|
||||
user := th.SystemAdminUser
|
||||
team := th.BasicTeam
|
||||
newTeam := th.CreateTeam()
|
||||
@@ -171,23 +170,24 @@ func TestMoveCommand(t *testing.T) {
|
||||
}
|
||||
|
||||
rcmd1, _ := th.App.CreateCommand(cmd1)
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
|
||||
ok, resp := Client.MoveCommand(newTeam.Id, rcmd1.Id)
|
||||
CheckNoError(t, resp)
|
||||
require.True(t, ok)
|
||||
ok, resp := client.MoveCommand(newTeam.Id, rcmd1.Id)
|
||||
CheckNoError(t, resp)
|
||||
require.True(t, ok)
|
||||
|
||||
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
||||
require.NotNil(t, rcmd1)
|
||||
require.Equal(t, newTeam.Id, rcmd1.TeamId)
|
||||
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
||||
require.NotNil(t, rcmd1)
|
||||
require.Equal(t, newTeam.Id, rcmd1.TeamId)
|
||||
|
||||
ok, resp = Client.MoveCommand(newTeam.Id, "bogus")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.False(t, ok)
|
||||
|
||||
ok, resp = Client.MoveCommand(GenerateTestId(), rcmd1.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
require.False(t, ok)
|
||||
ok, resp = client.MoveCommand(newTeam.Id, "bogus")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
require.False(t, ok)
|
||||
|
||||
ok, resp = client.MoveCommand(GenerateTestId(), rcmd1.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
require.False(t, ok)
|
||||
})
|
||||
cmd2 := &model.Command{
|
||||
CreatorId: user.Id,
|
||||
TeamId: team.Id,
|
||||
@@ -198,18 +198,17 @@ func TestMoveCommand(t *testing.T) {
|
||||
|
||||
rcmd2, _ := th.App.CreateCommand(cmd2)
|
||||
|
||||
_, resp = th.Client.MoveCommand(newTeam.Id, rcmd2.Id)
|
||||
_, resp := th.Client.MoveCommand(newTeam.Id, rcmd2.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
|
||||
Client.Logout()
|
||||
_, resp = Client.MoveCommand(newTeam.Id, rcmd2.Id)
|
||||
th.SystemAdminClient.Logout()
|
||||
_, resp = th.SystemAdminClient.MoveCommand(newTeam.Id, rcmd2.Id)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
}
|
||||
|
||||
func TestDeleteCommand(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
Client := th.SystemAdminClient
|
||||
user := th.SystemAdminUser
|
||||
team := th.BasicTeam
|
||||
|
||||
@@ -227,24 +226,26 @@ func TestDeleteCommand(t *testing.T) {
|
||||
Trigger: "trigger1",
|
||||
}
|
||||
|
||||
rcmd1, _ := th.App.CreateCommand(cmd1)
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
cmd1.Id = ""
|
||||
rcmd1, err := th.App.CreateCommand(cmd1)
|
||||
require.Nil(t, err)
|
||||
ok, resp := client.DeleteCommand(rcmd1.Id)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
ok, resp := Client.DeleteCommand(rcmd1.Id)
|
||||
CheckNoError(t, resp)
|
||||
require.True(t, ok)
|
||||
|
||||
require.True(t, ok)
|
||||
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
||||
require.Nil(t, rcmd1)
|
||||
|
||||
rcmd1, _ = th.App.GetCommand(rcmd1.Id)
|
||||
require.Nil(t, rcmd1)
|
||||
ok, resp = client.DeleteCommand("junk")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
ok, resp = Client.DeleteCommand("junk")
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
require.False(t, ok)
|
||||
|
||||
_, resp = Client.DeleteCommand(GenerateTestId())
|
||||
CheckNotFoundStatus(t, resp)
|
||||
require.False(t, ok)
|
||||
|
||||
_, resp = client.DeleteCommand(GenerateTestId())
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
cmd2 := &model.Command{
|
||||
CreatorId: user.Id,
|
||||
TeamId: team.Id,
|
||||
@@ -255,11 +256,11 @@ func TestDeleteCommand(t *testing.T) {
|
||||
|
||||
rcmd2, _ := th.App.CreateCommand(cmd2)
|
||||
|
||||
_, resp = th.Client.DeleteCommand(rcmd2.Id)
|
||||
_, resp := th.Client.DeleteCommand(rcmd2.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
|
||||
Client.Logout()
|
||||
_, resp = Client.DeleteCommand(rcmd2.Id)
|
||||
th.SystemAdminClient.Logout()
|
||||
_, resp = th.SystemAdminClient.DeleteCommand(rcmd2.Id)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
}
|
||||
|
||||
@@ -513,7 +514,6 @@ func TestListCommandAutocompleteSuggestions(t *testing.T) {
|
||||
func TestGetCommand(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
Client := th.Client
|
||||
|
||||
enableCommands := *th.App.Config().ServiceSettings.EnableCommands
|
||||
defer func() {
|
||||
@@ -530,41 +530,42 @@ func TestGetCommand(t *testing.T) {
|
||||
|
||||
newCmd, resp := th.SystemAdminClient.CreateCommand(newCmd)
|
||||
CheckNoError(t, resp)
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
|
||||
t.Run("ValidId", func(t *testing.T) {
|
||||
cmd, resp := th.SystemAdminClient.GetCommandById(newCmd.Id)
|
||||
CheckNoError(t, resp)
|
||||
t.Run("ValidId", func(t *testing.T) {
|
||||
cmd, resp := client.GetCommandById(newCmd.Id)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
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)
|
||||
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) {
|
||||
_, resp := client.GetCommandById(strings.Repeat("z", len(newCmd.Id)))
|
||||
require.Error(t, resp.Error)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("InvalidId", func(t *testing.T) {
|
||||
_, resp := th.SystemAdminClient.GetCommandById(strings.Repeat("z", len(newCmd.Id)))
|
||||
require.Error(t, resp.Error)
|
||||
})
|
||||
|
||||
t.Run("UserWithNoPermissionForCustomCommands", func(t *testing.T) {
|
||||
_, resp := Client.GetCommandById(newCmd.Id)
|
||||
_, resp := th.Client.GetCommandById(newCmd.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("NoMember", func(t *testing.T) {
|
||||
Client.Logout()
|
||||
th.Client.Logout()
|
||||
user := th.CreateUser()
|
||||
th.SystemAdminClient.RemoveTeamMember(th.BasicTeam.Id, user.Id)
|
||||
Client.Login(user.Email, user.Password)
|
||||
_, resp := Client.GetCommandById(newCmd.Id)
|
||||
th.Client.Login(user.Email, user.Password)
|
||||
_, resp := th.Client.GetCommandById(newCmd.Id)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("NotLoggedIn", func(t *testing.T) {
|
||||
Client.Logout()
|
||||
_, resp := Client.GetCommandById(newCmd.Id)
|
||||
th.Client.Logout()
|
||||
_, resp := th.Client.GetCommandById(newCmd.Id)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ func (a *App) SessionHasPermissionToTeam(session model.Session, teamId string, p
|
||||
if session.IsUnrestricted() {
|
||||
return true
|
||||
}
|
||||
|
||||
teamMember := session.GetTeamByTeamId(teamId)
|
||||
if teamMember != nil {
|
||||
if a.RolesGrantPermission(teamMember.GetRoles(), permission.Id) {
|
||||
|
||||
Ссылка в новой задаче
Block a user