mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 20:57:31 +00:00
feat: add action v2 execution on requests and responses (#7637)
* feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: add execution of targets to grpc calls * feat: split request and response logic to handle the different context information * feat: split request and response logic to handle the different context information * fix: integration test * fix: import alias * fix: refactor execution package * fix: refactor execution interceptor integration and unit tests * fix: refactor execution interceptor integration and unit tests * fix: refactor execution interceptor integration and unit tests * fix: refactor execution interceptor integration and unit tests * fix: refactor execution interceptor integration and unit tests * docs: basic documentation for executions and targets * fix: change order for interceptors * fix: merge back origin/main * fix: change target definition command and query side (#7735) * fix: change target definition command and query side * fix: correct refactoring name changes * fix: correct refactoring name changes * fix: changing execution defintion with target list and type * fix: changing execution definition with target list and type * fix: add back search queries for target and include * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * fix: projections change for execution with targets suffix table * docs: add example to actions v2 * docs: add example to actions v2 * fix: correct integration tests on query for executions * fix: add separate event for execution v2 as content changed * fix: add separate event for execution v2 as content changed * fix: added review comment changes * fix: added review comment changes * fix: added review comment changes --------- Co-authored-by: adlerhurst <silvan.reusser@gmail.com> * fix: added review comment changes * fix: added review comment changes * Update internal/api/grpc/server/middleware/execution_interceptor.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix: added review comment changes * fix: added review comment changes * fix: added review comment changes * fix: added review comment changes * fix: added review comment changes * fix: added review comment changes --------- Co-authored-by: adlerhurst <silvan.reusser@gmail.com> Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/repository/execution"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
||||
)
|
||||
|
||||
@@ -33,46 +34,46 @@ func (s *Server) SetExecution(ctx context.Context, req *action.SetExecutionReque
|
||||
return nil, err
|
||||
}
|
||||
|
||||
targets := make([]*execution.Target, len(req.Targets))
|
||||
for i, target := range req.Targets {
|
||||
switch t := target.GetType().(type) {
|
||||
case *action.ExecutionTargetType_Include:
|
||||
include, err := conditionToInclude(t.Include)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
targets[i] = &execution.Target{Type: domain.ExecutionTargetTypeInclude, Target: include}
|
||||
case *action.ExecutionTargetType_Target:
|
||||
targets[i] = &execution.Target{Type: domain.ExecutionTargetTypeTarget, Target: t.Target}
|
||||
}
|
||||
}
|
||||
set := &command.SetExecution{
|
||||
Targets: req.GetTargets(),
|
||||
Includes: req.GetIncludes(),
|
||||
Targets: targets,
|
||||
}
|
||||
|
||||
var err error
|
||||
var details *domain.ObjectDetails
|
||||
switch t := req.GetCondition().GetConditionType().(type) {
|
||||
case *action.Condition_Request:
|
||||
cond := &command.ExecutionAPICondition{
|
||||
Method: t.Request.GetMethod(),
|
||||
Service: t.Request.GetService(),
|
||||
All: t.Request.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromRequest(t.Request)
|
||||
details, err = s.command.SetExecutionRequest(ctx, cond, set, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Response:
|
||||
cond := &command.ExecutionAPICondition{
|
||||
Method: t.Response.GetMethod(),
|
||||
Service: t.Response.GetService(),
|
||||
All: t.Response.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromResponse(t.Response)
|
||||
details, err = s.command.SetExecutionResponse(ctx, cond, set, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Event:
|
||||
cond := &command.ExecutionEventCondition{
|
||||
Event: t.Event.GetEvent(),
|
||||
Group: t.Event.GetGroup(),
|
||||
All: t.Event.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromEvent(t.Event)
|
||||
details, err = s.command.SetExecutionEvent(ctx, cond, set, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Function:
|
||||
details, err = s.command.SetExecutionFunction(ctx, command.ExecutionFunctionCondition(t.Function), set, authz.GetInstance(ctx).InstanceID())
|
||||
details, err = s.command.SetExecutionFunction(ctx, command.ExecutionFunctionCondition(t.Function.GetName()), set, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -82,6 +83,36 @@ func (s *Server) SetExecution(ctx context.Context, req *action.SetExecutionReque
|
||||
}, nil
|
||||
}
|
||||
|
||||
func conditionToInclude(cond *action.Condition) (string, error) {
|
||||
switch t := cond.GetConditionType().(type) {
|
||||
case *action.Condition_Request:
|
||||
cond := executionConditionFromRequest(t.Request)
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cond.ID(domain.ExecutionTypeRequest), nil
|
||||
case *action.Condition_Response:
|
||||
cond := executionConditionFromResponse(t.Response)
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cond.ID(domain.ExecutionTypeRequest), nil
|
||||
case *action.Condition_Event:
|
||||
cond := executionConditionFromEvent(t.Event)
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cond.ID(), nil
|
||||
case *action.Condition_Function:
|
||||
cond := command.ExecutionFunctionCondition(t.Function.GetName())
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cond.ID(), nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *Server) DeleteExecution(ctx context.Context, req *action.DeleteExecutionRequest) (*action.DeleteExecutionResponse, error) {
|
||||
if err := checkExecutionEnabled(ctx); err != nil {
|
||||
return nil, err
|
||||
@@ -91,37 +122,25 @@ func (s *Server) DeleteExecution(ctx context.Context, req *action.DeleteExecutio
|
||||
var details *domain.ObjectDetails
|
||||
switch t := req.GetCondition().GetConditionType().(type) {
|
||||
case *action.Condition_Request:
|
||||
cond := &command.ExecutionAPICondition{
|
||||
Method: t.Request.GetMethod(),
|
||||
Service: t.Request.GetService(),
|
||||
All: t.Request.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromRequest(t.Request)
|
||||
details, err = s.command.DeleteExecutionRequest(ctx, cond, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Response:
|
||||
cond := &command.ExecutionAPICondition{
|
||||
Method: t.Response.GetMethod(),
|
||||
Service: t.Response.GetService(),
|
||||
All: t.Response.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromResponse(t.Response)
|
||||
details, err = s.command.DeleteExecutionResponse(ctx, cond, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Event:
|
||||
cond := &command.ExecutionEventCondition{
|
||||
Event: t.Event.GetEvent(),
|
||||
Group: t.Event.GetGroup(),
|
||||
All: t.Event.GetAll(),
|
||||
}
|
||||
cond := executionConditionFromEvent(t.Event)
|
||||
details, err = s.command.DeleteExecutionEvent(ctx, cond, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *action.Condition_Function:
|
||||
details, err = s.command.DeleteExecutionFunction(ctx, command.ExecutionFunctionCondition(t.Function), authz.GetInstance(ctx).InstanceID())
|
||||
details, err = s.command.DeleteExecutionFunction(ctx, command.ExecutionFunctionCondition(t.Function.GetName()), authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,3 +149,27 @@ func (s *Server) DeleteExecution(ctx context.Context, req *action.DeleteExecutio
|
||||
Details: object.DomainToDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func executionConditionFromRequest(request *action.RequestExecution) *command.ExecutionAPICondition {
|
||||
return &command.ExecutionAPICondition{
|
||||
Method: request.GetMethod(),
|
||||
Service: request.GetService(),
|
||||
All: request.GetAll(),
|
||||
}
|
||||
}
|
||||
|
||||
func executionConditionFromResponse(response *action.ResponseExecution) *command.ExecutionAPICondition {
|
||||
return &command.ExecutionAPICondition{
|
||||
Method: response.GetMethod(),
|
||||
Service: response.GetService(),
|
||||
All: response.GetAll(),
|
||||
}
|
||||
}
|
||||
|
||||
func executionConditionFromEvent(event *action.EventExecution) *command.ExecutionEventCondition {
|
||||
return &command.ExecutionEventCondition{
|
||||
Event: event.GetEvent(),
|
||||
Group: event.GetGroup(),
|
||||
All: event.GetAll(),
|
||||
}
|
||||
}
|
||||
|
@@ -9,14 +9,23 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
)
|
||||
|
||||
func executionTargetsSingleTarget(id string) []*action.ExecutionTargetType {
|
||||
return []*action.ExecutionTargetType{{Type: &action.ExecutionTargetType_Target{Target: id}}}
|
||||
}
|
||||
|
||||
func executionTargetsSingleInclude(include *action.Condition) []*action.ExecutionTargetType {
|
||||
return []*action.ExecutionTargetType{{Type: &action.ExecutionTargetType_Include{Include: include}}}
|
||||
}
|
||||
|
||||
func TestServer_SetExecution_Request(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -48,7 +57,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
Request: &action.RequestExecution{},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -65,7 +74,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -82,7 +91,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -104,7 +113,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -121,7 +130,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -143,7 +152,7 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -163,27 +172,28 @@ func TestServer_SetExecution_Request(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
// cleanup to not impact other requests
|
||||
Tester.DeleteExecution(tt.ctx, t, tt.req.GetCondition())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
executionCond := "request"
|
||||
Tester.SetExecution(CTX, t,
|
||||
&action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_All{
|
||||
All: true,
|
||||
},
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
executionCond := &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_All{
|
||||
All: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
[]string{targetResp.GetId()},
|
||||
[]string{},
|
||||
}
|
||||
Tester.SetExecution(CTX, t,
|
||||
executionCond,
|
||||
executionTargetsSingleTarget(targetResp.GetId()),
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
@@ -206,7 +216,7 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Includes: []string{executionCond},
|
||||
Targets: executionTargetsSingleInclude(executionCond),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -228,7 +238,7 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Includes: []string{executionCond},
|
||||
Targets: executionTargetsSingleInclude(executionCond),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -237,6 +247,7 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
/* circular
|
||||
{
|
||||
name: "all, ok",
|
||||
ctx: CTX,
|
||||
@@ -250,7 +261,7 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Includes: []string{executionCond},
|
||||
Targets: executionTargetsSingleInclude(executionCond),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -259,6 +270,7 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
*/
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -270,13 +282,16 @@ func TestServer_SetExecution_Request_Include(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
// cleanup to not impact other requests
|
||||
Tester.DeleteExecution(tt.ctx, t, tt.req.GetCondition())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_DeleteExecution_Request(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -332,7 +347,7 @@ func TestServer_DeleteExecution_Request(t *testing.T) {
|
||||
name: "method, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -373,7 +388,7 @@ func TestServer_DeleteExecution_Request(t *testing.T) {
|
||||
name: "service, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -398,7 +413,7 @@ func TestServer_DeleteExecution_Request(t *testing.T) {
|
||||
name: "all, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -441,7 +456,7 @@ func TestServer_DeleteExecution_Request(t *testing.T) {
|
||||
|
||||
func TestServer_SetExecution_Response(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -473,7 +488,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
Response: &action.ResponseExecution{},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -490,7 +505,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -507,7 +522,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -529,7 +544,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -546,7 +561,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -568,7 +583,7 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -588,13 +603,16 @@ func TestServer_SetExecution_Response(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
// cleanup to not impact other requests
|
||||
Tester.DeleteExecution(tt.ctx, t, tt.req.GetCondition())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_DeleteExecution_Response(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -652,7 +670,7 @@ func TestServer_DeleteExecution_Response(t *testing.T) {
|
||||
name: "method, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -693,7 +711,7 @@ func TestServer_DeleteExecution_Response(t *testing.T) {
|
||||
name: "service, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -718,7 +736,7 @@ func TestServer_DeleteExecution_Response(t *testing.T) {
|
||||
name: "all, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -761,7 +779,7 @@ func TestServer_DeleteExecution_Response(t *testing.T) {
|
||||
|
||||
func TestServer_SetExecution_Event(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -795,7 +813,7 @@ func TestServer_SetExecution_Event(t *testing.T) {
|
||||
Event: &action.EventExecution{},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -833,7 +851,7 @@ func TestServer_SetExecution_Event(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -876,7 +894,7 @@ func TestServer_SetExecution_Event(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -898,7 +916,7 @@ func TestServer_SetExecution_Event(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -918,13 +936,16 @@ func TestServer_SetExecution_Event(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
// cleanup to not impact other requests
|
||||
Tester.DeleteExecution(tt.ctx, t, tt.req.GetCondition())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_DeleteExecution_Event(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -985,7 +1006,7 @@ func TestServer_DeleteExecution_Event(t *testing.T) {
|
||||
name: "event, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -1026,7 +1047,7 @@ func TestServer_DeleteExecution_Event(t *testing.T) {
|
||||
name: "group, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -1061,18 +1082,13 @@ func TestServer_DeleteExecution_Event(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &action.DeleteExecutionResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "all, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
@@ -1115,7 +1131,7 @@ func TestServer_DeleteExecution_Event(t *testing.T) {
|
||||
|
||||
func TestServer_SetExecution_Function(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1147,7 +1163,7 @@ func TestServer_SetExecution_Function(t *testing.T) {
|
||||
Response: &action.ResponseExecution{},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -1157,10 +1173,10 @@ func TestServer_SetExecution_Function(t *testing.T) {
|
||||
req: &action.SetExecutionRequest{
|
||||
Condition: &action.Condition{
|
||||
ConditionType: &action.Condition_Function{
|
||||
Function: "xxx",
|
||||
Function: &action.FunctionExecution{Name: "xxx"},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -1170,10 +1186,10 @@ func TestServer_SetExecution_Function(t *testing.T) {
|
||||
req: &action.SetExecutionRequest{
|
||||
Condition: &action.Condition{
|
||||
ConditionType: &action.Condition_Function{
|
||||
Function: "Action.Flow.Type.ExternalAuthentication.Action.TriggerType.PostAuthentication",
|
||||
Function: &action.FunctionExecution{Name: "Action.Flow.Type.ExternalAuthentication.Action.TriggerType.PostAuthentication"},
|
||||
},
|
||||
},
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
want: &action.SetExecutionResponse{
|
||||
Details: &object.Details{
|
||||
@@ -1193,13 +1209,16 @@ func TestServer_SetExecution_Function(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
// cleanup to not impact other requests
|
||||
Tester.DeleteExecution(tt.ctx, t, tt.req.GetCondition())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_DeleteExecution_Function(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://notexisting", domain.TargetTypeWebhook, false)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1243,7 +1262,7 @@ func TestServer_DeleteExecution_Function(t *testing.T) {
|
||||
req: &action.DeleteExecutionRequest{
|
||||
Condition: &action.Condition{
|
||||
ConditionType: &action.Condition_Function{
|
||||
Function: "xxx",
|
||||
Function: &action.FunctionExecution{Name: "xxx"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1253,13 +1272,13 @@ func TestServer_DeleteExecution_Function(t *testing.T) {
|
||||
name: "function, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.DeleteExecutionRequest) error {
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), []string{targetResp.GetId()}, []string{})
|
||||
Tester.SetExecution(ctx, t, request.GetCondition(), executionTargetsSingleTarget(targetResp.GetId()))
|
||||
return nil
|
||||
},
|
||||
req: &action.DeleteExecutionRequest{
|
||||
Condition: &action.Condition{
|
||||
ConditionType: &action.Condition_Function{
|
||||
Function: "Action.Flow.Type.ExternalAuthentication.Action.TriggerType.PostAuthentication",
|
||||
Function: &action.FunctionExecution{Name: "Action.Flow.Type.ExternalAuthentication.Action.TriggerType.PostAuthentication"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -0,0 +1,323 @@
|
||||
//go:build integration
|
||||
|
||||
package action_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/server/middleware"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
||||
)
|
||||
|
||||
func TestServer_ExecutionTarget(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
|
||||
fullMethod := "/zitadel.action.v3alpha.ActionService/GetTargetByID"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ctx context.Context
|
||||
dep func(context.Context, *action.GetTargetByIDRequest, *action.GetTargetByIDResponse) (func(), error)
|
||||
clean func(context.Context)
|
||||
req *action.GetTargetByIDRequest
|
||||
want *action.GetTargetByIDResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "GetTargetByID, request and response, ok",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) (func(), error) {
|
||||
|
||||
instanceID := Tester.Instance.InstanceID()
|
||||
orgID := Tester.Organisation.ID
|
||||
projectID := ""
|
||||
userID := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.IAMOwner).ID
|
||||
|
||||
// create target for target changes
|
||||
targetCreatedName := fmt.Sprint("GetTargetByID", time.Now().UnixNano()+1)
|
||||
targetCreatedURL := "https://nonexistent"
|
||||
|
||||
targetCreated := Tester.CreateTarget(ctx, t, targetCreatedName, targetCreatedURL, domain.TargetTypeCall, false)
|
||||
|
||||
// request received by target
|
||||
wantRequest := &middleware.ContextInfoRequest{FullMethod: fullMethod, InstanceID: instanceID, OrgID: orgID, ProjectID: projectID, UserID: userID, Request: request}
|
||||
changedRequest := &action.GetTargetByIDRequest{TargetId: targetCreated.GetId()}
|
||||
// replace original request with different targetID
|
||||
urlRequest, closeRequest := testServerCall(wantRequest, 0, http.StatusOK, changedRequest)
|
||||
targetRequest := Tester.CreateTarget(ctx, t, "", urlRequest, domain.TargetTypeCall, false)
|
||||
Tester.SetExecution(ctx, t, conditionRequestFullMethod(fullMethod), executionTargetsSingleTarget(targetRequest.GetId()))
|
||||
// GetTargetByID with used target
|
||||
request.TargetId = targetRequest.GetId()
|
||||
|
||||
// expected response from the GetTargetByID
|
||||
expectedResponse := &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
TargetId: targetCreated.GetId(),
|
||||
Details: targetCreated.GetDetails(),
|
||||
Name: targetCreatedName,
|
||||
Endpoint: targetCreatedURL,
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
}
|
||||
// has to be set separately because of the pointers
|
||||
response.Target = &action.Target{
|
||||
TargetId: targetCreated.GetId(),
|
||||
Details: targetCreated.GetDetails(),
|
||||
Name: targetCreatedName,
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
}
|
||||
|
||||
// content for partial update
|
||||
changedResponse := &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
TargetId: "changed",
|
||||
},
|
||||
}
|
||||
// change partial updated content on returned response
|
||||
response.Target.TargetId = changedResponse.Target.TargetId
|
||||
|
||||
// response received by target
|
||||
wantResponse := &middleware.ContextInfoResponse{
|
||||
FullMethod: fullMethod,
|
||||
InstanceID: instanceID,
|
||||
OrgID: orgID,
|
||||
ProjectID: projectID,
|
||||
UserID: userID,
|
||||
Request: changedRequest,
|
||||
Response: expectedResponse,
|
||||
}
|
||||
// after request with different targetID, return changed response
|
||||
targetResponseURL, closeResponse := testServerCall(wantResponse, 0, http.StatusOK, changedResponse)
|
||||
targetResponse := Tester.CreateTarget(ctx, t, "", targetResponseURL, domain.TargetTypeCall, false)
|
||||
Tester.SetExecution(ctx, t, conditionResponseFullMethod(fullMethod), executionTargetsSingleTarget(targetResponse.GetId()))
|
||||
|
||||
return func() {
|
||||
closeRequest()
|
||||
closeResponse()
|
||||
}, nil
|
||||
},
|
||||
clean: func(ctx context.Context) {
|
||||
Tester.DeleteExecution(ctx, t, conditionRequestFullMethod(fullMethod))
|
||||
Tester.DeleteExecution(ctx, t, conditionResponseFullMethod(fullMethod))
|
||||
},
|
||||
req: &action.GetTargetByIDRequest{},
|
||||
want: &action.GetTargetByIDResponse{},
|
||||
},
|
||||
/*{
|
||||
name: "GetTargetByID, request, interrupt",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) (func(), error) {
|
||||
|
||||
fullMethod := "/zitadel.action.v3alpha.ActionService/GetTargetByID"
|
||||
instanceID := Tester.Instance.InstanceID()
|
||||
orgID := Tester.Organisation.ID
|
||||
projectID := ""
|
||||
userID := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.IAMOwner).ID
|
||||
|
||||
// request received by target
|
||||
wantRequest := &middleware.ContextInfoRequest{FullMethod: fullMethod, InstanceID: instanceID, OrgID: orgID, ProjectID: projectID, UserID: userID, Request: request}
|
||||
urlRequest, closeRequest := testServerCall(wantRequest, 0, http.StatusInternalServerError, &action.GetTargetByIDRequest{TargetId: "notchanged"})
|
||||
|
||||
targetRequest := Tester.CreateTarget(ctx, t, "", urlRequest, domain.TargetTypeCall, true)
|
||||
Tester.SetExecution(ctx, t, conditionRequestFullMethod(fullMethod), executionTargetsSingleTarget(targetRequest.GetId()))
|
||||
// GetTargetByID with used target
|
||||
request.TargetId = targetRequest.GetId()
|
||||
|
||||
return func() {
|
||||
closeRequest()
|
||||
}, nil
|
||||
},
|
||||
clean: func(ctx context.Context) {
|
||||
Tester.DeleteExecution(ctx, t, conditionRequestFullMethod(fullMethod))
|
||||
},
|
||||
req: &action.GetTargetByIDRequest{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "GetTargetByID, response, interrupt",
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) (func(), error) {
|
||||
|
||||
fullMethod := "/zitadel.action.v3alpha.ActionService/GetTargetByID"
|
||||
instanceID := Tester.Instance.InstanceID()
|
||||
orgID := Tester.Organisation.ID
|
||||
projectID := ""
|
||||
userID := Tester.Users.Get(integration.FirstInstanceUsersKey, integration.IAMOwner).ID
|
||||
|
||||
// create target for target changes
|
||||
targetCreatedName := fmt.Sprint("GetTargetByID", time.Now().UnixNano()+1)
|
||||
targetCreatedURL := "https://nonexistent"
|
||||
|
||||
targetCreated := Tester.CreateTarget(ctx, t, targetCreatedName, targetCreatedURL, domain.TargetTypeCall, false)
|
||||
|
||||
// GetTargetByID with used target
|
||||
request.TargetId = targetCreated.GetId()
|
||||
|
||||
// expected response from the GetTargetByID
|
||||
expectedResponse := &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
TargetId: targetCreated.GetId(),
|
||||
Details: targetCreated.GetDetails(),
|
||||
Name: targetCreatedName,
|
||||
Endpoint: targetCreatedURL,
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
}
|
||||
|
||||
// content for partial update
|
||||
changedResponse := &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
TargetId: "changed",
|
||||
},
|
||||
}
|
||||
|
||||
// response received by target
|
||||
wantResponse := &middleware.ContextInfoResponse{
|
||||
FullMethod: fullMethod,
|
||||
InstanceID: instanceID,
|
||||
OrgID: orgID,
|
||||
ProjectID: projectID,
|
||||
UserID: userID,
|
||||
Request: request,
|
||||
Response: expectedResponse,
|
||||
}
|
||||
// after request with different targetID, return changed response
|
||||
targetResponseURL, closeResponse := testServerCall(wantResponse, 0, http.StatusInternalServerError, changedResponse)
|
||||
targetResponse := Tester.CreateTarget(ctx, t, "", targetResponseURL, domain.TargetTypeCall, true)
|
||||
Tester.SetExecution(ctx, t, conditionResponseFullMethod(fullMethod), executionTargetsSingleTarget(targetResponse.GetId()))
|
||||
|
||||
return func() {
|
||||
closeResponse()
|
||||
}, nil
|
||||
},
|
||||
clean: func(ctx context.Context) {
|
||||
Tester.DeleteExecution(ctx, t, conditionResponseFullMethod(fullMethod))
|
||||
},
|
||||
req: &action.GetTargetByIDRequest{},
|
||||
wantErr: true,
|
||||
},*/
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.dep != nil {
|
||||
close, err := tt.dep(tt.ctx, tt.req, tt.want)
|
||||
require.NoError(t, err)
|
||||
defer close()
|
||||
}
|
||||
|
||||
got, err := Client.GetTargetByID(tt.ctx, tt.req)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
integration.AssertDetails(t, tt.want.GetTarget(), got.GetTarget())
|
||||
|
||||
assert.Equal(t, tt.want.Target.TargetId, got.Target.TargetId)
|
||||
|
||||
if tt.clean != nil {
|
||||
tt.clean(tt.ctx)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func conditionRequestFullMethod(fullMethod string) *action.Condition {
|
||||
return &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_Method{
|
||||
Method: fullMethod,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func conditionResponseFullMethod(fullMethod string) *action.Condition {
|
||||
return &action.Condition{
|
||||
ConditionType: &action.Condition_Response{
|
||||
Response: &action.ResponseExecution{
|
||||
Condition: &action.ResponseExecution_Method{
|
||||
Method: fullMethod,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testServerCall(
|
||||
reqBody interface{},
|
||||
sleep time.Duration,
|
||||
statusCode int,
|
||||
respBody interface{},
|
||||
) (string, func()) {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
http.Error(w, "error, marshall: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
sentBody, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, "error, read body: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(data, sentBody) {
|
||||
http.Error(w, "error, equal:\n"+string(data)+"\nsent:\n"+string(sentBody), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if statusCode != http.StatusOK {
|
||||
http.Error(w, "error, statusCode", statusCode)
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(sleep)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
resp, err := json.Marshal(respBody)
|
||||
if err != nil {
|
||||
http.Error(w, "error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if _, err := io.WriteString(w, string(resp)); err != nil {
|
||||
http.Error(w, "error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(handler))
|
||||
|
||||
return server.URL, server.Close
|
||||
}
|
@@ -2,6 +2,7 @@ package action
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
@@ -67,8 +68,6 @@ func targetFieldNameToSortingColumn(field action.TargetFieldName) query.Column {
|
||||
return query.TargetColumnURL
|
||||
case action.TargetFieldName_FIELD_NAME_TIMEOUT:
|
||||
return query.TargetColumnTimeout
|
||||
case action.TargetFieldName_FIELD_NAME_ASYNC:
|
||||
return query.TargetColumnAsync
|
||||
case action.TargetFieldName_FIELD_NAME_INTERRUPT_ON_ERROR:
|
||||
return query.TargetColumnInterruptOnError
|
||||
default:
|
||||
@@ -134,19 +133,16 @@ func targetToPb(t *query.Target) *action.Target {
|
||||
TargetId: t.ID,
|
||||
Name: t.Name,
|
||||
Timeout: durationpb.New(t.Timeout),
|
||||
}
|
||||
if t.Async {
|
||||
target.ExecutionType = &action.Target_IsAsync{IsAsync: t.Async}
|
||||
}
|
||||
if t.InterruptOnError {
|
||||
target.ExecutionType = &action.Target_InterruptOnError{InterruptOnError: t.InterruptOnError}
|
||||
Endpoint: t.Endpoint,
|
||||
}
|
||||
|
||||
switch t.TargetType {
|
||||
case domain.TargetTypeWebhook:
|
||||
target.TargetType = &action.Target_RestWebhook{RestWebhook: &action.SetRESTWebhook{Url: t.URL}}
|
||||
case domain.TargetTypeRequestResponse:
|
||||
target.TargetType = &action.Target_RestRequestResponse{RestRequestResponse: &action.SetRESTRequestResponse{Url: t.URL}}
|
||||
target.TargetType = &action.Target_RestWebhook{RestWebhook: &action.SetRESTWebhook{InterruptOnError: t.InterruptOnError}}
|
||||
case domain.TargetTypeCall:
|
||||
target.TargetType = &action.Target_RestCall{RestCall: &action.SetRESTCall{InterruptOnError: t.InterruptOnError}}
|
||||
case domain.TargetTypeAsync:
|
||||
target.TargetType = &action.Target_RestAsync{RestAsync: &action.SetRESTAsync{}}
|
||||
default:
|
||||
target.TargetType = nil
|
||||
}
|
||||
@@ -205,10 +201,14 @@ func executionQueryToQuery(searchQuery *action.SearchQuery) (query.SearchQuery,
|
||||
return inConditionsQueryToQuery(q.InConditionsQuery)
|
||||
case *action.SearchQuery_ExecutionTypeQuery:
|
||||
return executionTypeToQuery(q.ExecutionTypeQuery)
|
||||
case *action.SearchQuery_TargetQuery:
|
||||
return query.NewExecutionTargetSearchQuery(q.TargetQuery.GetTargetId())
|
||||
case *action.SearchQuery_IncludeQuery:
|
||||
return query.NewExecutionIncludeSearchQuery(q.IncludeQuery.GetInclude())
|
||||
include, err := conditionToInclude(q.IncludeQuery.GetInclude())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return query.NewIncludeSearchQuery(include)
|
||||
case *action.SearchQuery_TargetQuery:
|
||||
return query.NewTargetSearchQuery(q.TargetQuery.GetTargetId())
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
||||
}
|
||||
@@ -267,7 +267,7 @@ func conditionToID(q *action.Condition) (string, error) {
|
||||
}
|
||||
return cond.ID(), nil
|
||||
case *action.Condition_Function:
|
||||
return t.Function, nil
|
||||
return command.ExecutionFunctionCondition(t.Function.GetName()).ID(), nil
|
||||
default:
|
||||
return "", zerrors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
||||
}
|
||||
@@ -282,17 +282,83 @@ func executionsToPb(executions []*query.Execution) []*action.Execution {
|
||||
}
|
||||
|
||||
func executionToPb(e *query.Execution) *action.Execution {
|
||||
var targets, includes []string
|
||||
if len(e.Targets) > 0 {
|
||||
targets = e.Targets
|
||||
}
|
||||
if len(e.Includes) > 0 {
|
||||
includes = e.Includes
|
||||
targets := make([]*action.ExecutionTargetType, len(e.Targets))
|
||||
for i := range e.Targets {
|
||||
switch e.Targets[i].Type {
|
||||
case domain.ExecutionTargetTypeInclude:
|
||||
targets[i] = &action.ExecutionTargetType{Type: &action.ExecutionTargetType_Include{Include: executionIDToCondition(e.Targets[i].Target)}}
|
||||
case domain.ExecutionTargetTypeTarget:
|
||||
targets[i] = &action.ExecutionTargetType{Type: &action.ExecutionTargetType_Target{Target: e.Targets[i].Target}}
|
||||
case domain.ExecutionTargetTypeUnspecified:
|
||||
continue
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return &action.Execution{
|
||||
Details: object.DomainToDetailsPb(&e.ObjectDetails),
|
||||
ExecutionId: e.ID,
|
||||
Targets: targets,
|
||||
Includes: includes,
|
||||
Details: object.DomainToDetailsPb(&e.ObjectDetails),
|
||||
Condition: executionIDToCondition(e.ID),
|
||||
Targets: targets,
|
||||
}
|
||||
}
|
||||
|
||||
func executionIDToCondition(include string) *action.Condition {
|
||||
if strings.HasPrefix(include, domain.ExecutionTypeRequest.String()) {
|
||||
return includeRequestToCondition(strings.TrimPrefix(include, domain.ExecutionTypeRequest.String()))
|
||||
}
|
||||
if strings.HasPrefix(include, domain.ExecutionTypeResponse.String()) {
|
||||
return includeResponseToCondition(strings.TrimPrefix(include, domain.ExecutionTypeResponse.String()))
|
||||
}
|
||||
if strings.HasPrefix(include, domain.ExecutionTypeEvent.String()) {
|
||||
return includeEventToCondition(strings.TrimPrefix(include, domain.ExecutionTypeEvent.String()))
|
||||
}
|
||||
if strings.HasPrefix(include, domain.ExecutionTypeFunction.String()) {
|
||||
return includeFunctionToCondition(strings.TrimPrefix(include, domain.ExecutionTypeFunction.String()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func includeRequestToCondition(id string) *action.Condition {
|
||||
switch strings.Count(id, "/") {
|
||||
case 2:
|
||||
return &action.Condition{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_Method{Method: id}}}}
|
||||
case 1:
|
||||
return &action.Condition{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_Service{Service: strings.TrimPrefix(id, "/")}}}}
|
||||
case 0:
|
||||
return &action.Condition{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_All{All: true}}}}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func includeResponseToCondition(id string) *action.Condition {
|
||||
switch strings.Count(id, "/") {
|
||||
case 2:
|
||||
return &action.Condition{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_Method{Method: id}}}}
|
||||
case 1:
|
||||
return &action.Condition{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_Service{Service: strings.TrimPrefix(id, "/")}}}}
|
||||
case 0:
|
||||
return &action.Condition{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_All{All: true}}}}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func includeEventToCondition(id string) *action.Condition {
|
||||
switch strings.Count(id, "/") {
|
||||
case 1:
|
||||
if strings.HasSuffix(id, command.EventGroupSuffix) {
|
||||
return &action.Condition{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_Group{Group: strings.TrimSuffix(strings.TrimPrefix(id, "/"), command.EventGroupSuffix)}}}}
|
||||
} else {
|
||||
return &action.Condition{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_Event{Event: strings.TrimPrefix(id, "/")}}}}
|
||||
}
|
||||
case 0:
|
||||
return &action.Condition{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_All{All: true}}}}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func includeFunctionToCondition(id string) *action.Condition {
|
||||
return &action.Condition{ConditionType: &action.Condition_Function{Function: &action.FunctionExecution{Name: strings.TrimPrefix(id, "/")}}}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ package action_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
@@ -52,7 +54,7 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTargetWithNameAndType(ctx, t, name, false, false)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeWebhook, false)
|
||||
request.TargetId = resp.GetId()
|
||||
|
||||
response.Target.TargetId = resp.GetId()
|
||||
@@ -69,10 +71,9 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
},
|
||||
RestWebhook: &action.SetRESTWebhook{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
@@ -84,7 +85,7 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTargetWithNameAndType(ctx, t, name, true, false)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeAsync, false)
|
||||
request.TargetId = resp.GetId()
|
||||
|
||||
response.Target.TargetId = resp.GetId()
|
||||
@@ -101,23 +102,21 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.Target_IsAsync{IsAsync: true},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get, interruptOnError, ok",
|
||||
name: "get, webhook interruptOnError, ok",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTargetWithNameAndType(ctx, t, name, false, true)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeWebhook, true)
|
||||
request.TargetId = resp.GetId()
|
||||
|
||||
response.Target.TargetId = resp.GetId()
|
||||
@@ -134,13 +133,79 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.Target_InterruptOnError{InterruptOnError: true},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get, call, ok",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeCall, false)
|
||||
request.TargetId = resp.GetId()
|
||||
|
||||
response.Target.TargetId = resp.GetId()
|
||||
response.Target.Name = name
|
||||
response.Target.Details.ResourceOwner = resp.GetDetails().GetResourceOwner()
|
||||
response.Target.Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Target.Details.Sequence = resp.GetDetails().GetSequence()
|
||||
return nil
|
||||
},
|
||||
req: &action.GetTargetByIDRequest{},
|
||||
},
|
||||
want: &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get, call interruptOnError, ok",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.GetTargetByIDRequest, response *action.GetTargetByIDResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeCall, true)
|
||||
request.TargetId = resp.GetId()
|
||||
|
||||
response.Target.TargetId = resp.GetId()
|
||||
response.Target.Name = name
|
||||
response.Target.Details.ResourceOwner = resp.GetDetails().GetResourceOwner()
|
||||
response.Target.Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Target.Details.Sequence = resp.GetDetails().GetSequence()
|
||||
return nil
|
||||
},
|
||||
req: &action.GetTargetByIDRequest{},
|
||||
},
|
||||
want: &action.GetTargetByIDResponse{
|
||||
Target: &action.Target{
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -163,15 +228,11 @@ func TestServer_GetTargetByID(t *testing.T) {
|
||||
assert.Error(ttt, getErr, "Error: "+getErr.Error())
|
||||
} else {
|
||||
assert.NoError(ttt, getErr)
|
||||
}
|
||||
if getErr != nil {
|
||||
fmt.Println("Error: " + getErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
integration.AssertDetails(t, tt.want.GetTarget(), got.GetTarget())
|
||||
integration.AssertDetails(t, tt.want.GetTarget(), got.GetTarget())
|
||||
|
||||
assert.Equal(t, tt.want.Target, got.Target)
|
||||
assert.Equal(t, tt.want.Target, got.Target)
|
||||
}
|
||||
|
||||
}, retryDuration, time.Millisecond*100, "timeout waiting for expected execution result")
|
||||
})
|
||||
@@ -227,14 +288,14 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListTargetsRequest, response *action.ListTargetsResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTargetWithNameAndType(ctx, t, name, false, false)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeWebhook, false)
|
||||
request.Queries[0].Query = &action.TargetSearchQuery_InTargetIdsQuery{
|
||||
InTargetIdsQuery: &action.InTargetIDsQuery{
|
||||
TargetIds: []string{resp.GetId()},
|
||||
},
|
||||
}
|
||||
response.Details.Timestamp = resp.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
//response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
|
||||
response.Result[0].Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Result[0].Details.Sequence = resp.GetDetails().GetSequence()
|
||||
@@ -255,9 +316,10 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
@@ -270,7 +332,7 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListTargetsRequest, response *action.ListTargetsResponse) error {
|
||||
name := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
resp := Tester.CreateTargetWithNameAndType(ctx, t, name, false, false)
|
||||
resp := Tester.CreateTarget(ctx, t, name, "https://example.com", domain.TargetTypeWebhook, false)
|
||||
request.Queries[0].Query = &action.TargetSearchQuery_TargetNameQuery{
|
||||
TargetNameQuery: &action.TargetNameQuery{
|
||||
TargetName: name,
|
||||
@@ -298,9 +360,10 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
@@ -316,9 +379,9 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
name1 := fmt.Sprint(time.Now().UnixNano() + 1)
|
||||
name2 := fmt.Sprint(time.Now().UnixNano() + 3)
|
||||
name3 := fmt.Sprint(time.Now().UnixNano() + 5)
|
||||
resp1 := Tester.CreateTargetWithNameAndType(ctx, t, name1, false, false)
|
||||
resp2 := Tester.CreateTargetWithNameAndType(ctx, t, name2, true, false)
|
||||
resp3 := Tester.CreateTargetWithNameAndType(ctx, t, name3, false, true)
|
||||
resp1 := Tester.CreateTarget(ctx, t, name1, "https://example.com", domain.TargetTypeWebhook, false)
|
||||
resp2 := Tester.CreateTarget(ctx, t, name2, "https://example.com", domain.TargetTypeCall, true)
|
||||
resp3 := Tester.CreateTarget(ctx, t, name3, "https://example.com", domain.TargetTypeAsync, false)
|
||||
request.Queries[0].Query = &action.TargetSearchQuery_InTargetIdsQuery{
|
||||
InTargetIdsQuery: &action.InTargetIDsQuery{
|
||||
TargetIds: []string{resp1.GetId(), resp2.GetId(), resp3.GetId()},
|
||||
@@ -354,9 +417,10 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
@@ -365,25 +429,23 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.Target_IsAsync{IsAsync: true},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
{
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
TargetType: &action.Target_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
},
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.Target_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.Target_InterruptOnError{InterruptOnError: true},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -422,9 +484,9 @@ func TestServer_ListTargets(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
func TestServer_ListExecutions(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
targetResp := Tester.CreateTarget(CTX, t)
|
||||
targetResp := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -446,17 +508,20 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list single condition",
|
||||
name: "list request single condition",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListExecutionsRequest, response *action.ListExecutionsResponse) error {
|
||||
resp := Tester.SetExecution(ctx, t, request.Queries[0].GetInConditionsQuery().GetConditions()[0], []string{targetResp.GetId()}, []string{})
|
||||
cond := request.Queries[0].GetInConditionsQuery().GetConditions()[0]
|
||||
resp := Tester.SetExecution(ctx, t, cond, executionTargetsSingleTarget(targetResp.GetId()))
|
||||
|
||||
response.Details.Timestamp = resp.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
// response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
|
||||
// Set expected response with used values for SetExecution
|
||||
response.Result[0].Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Result[0].Details.Sequence = resp.GetDetails().GetSequence()
|
||||
response.Result[0].Condition = cond
|
||||
return nil
|
||||
},
|
||||
req: &action.ListExecutionsRequest{
|
||||
@@ -471,8 +536,7 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
@@ -487,18 +551,26 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.session.v2beta.SessionService/GetSession",
|
||||
Targets: []string{targetResp.GetId()},
|
||||
Condition: &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_Method{
|
||||
Method: "/zitadel.session.v2beta.SessionService/GetSession",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: executionTargetsSingleTarget(targetResp.GetId()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list single target",
|
||||
name: "list request single target",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListExecutionsRequest, response *action.ListExecutionsResponse) error {
|
||||
target := Tester.CreateTarget(ctx, t)
|
||||
target := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false)
|
||||
// add target as query to the request
|
||||
request.Queries[0] = &action.SearchQuery{
|
||||
Query: &action.SearchQuery_TargetQuery{
|
||||
@@ -507,7 +579,7 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
resp := Tester.SetExecution(ctx, t, &action.Condition{
|
||||
cond := &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_Method{
|
||||
@@ -515,14 +587,17 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, []string{target.GetId()}, []string{})
|
||||
}
|
||||
targets := executionTargetsSingleTarget(target.GetId())
|
||||
resp := Tester.SetExecution(ctx, t, cond, targets)
|
||||
|
||||
response.Details.Timestamp = resp.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
|
||||
response.Result[0].Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Result[0].Details.Sequence = resp.GetDetails().GetSequence()
|
||||
response.Result[0].Targets[0] = target.GetId()
|
||||
response.Result[0].Condition = cond
|
||||
response.Result[0].Targets = targets
|
||||
return nil
|
||||
},
|
||||
req: &action.ListExecutionsRequest{
|
||||
@@ -538,17 +613,17 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.management.v1.ManagementService/UpdateAction",
|
||||
Targets: []string{""},
|
||||
Condition: &action.Condition{},
|
||||
Targets: executionTargetsSingleTarget(""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "list single include",
|
||||
name: "list request single include",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListExecutionsRequest, response *action.ListExecutionsResponse) error {
|
||||
Tester.SetExecution(ctx, t, &action.Condition{
|
||||
cond := &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_Method{
|
||||
@@ -556,8 +631,11 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, []string{targetResp.GetId()}, []string{})
|
||||
resp2 := Tester.SetExecution(ctx, t, &action.Condition{
|
||||
}
|
||||
Tester.SetExecution(ctx, t, cond, executionTargetsSingleTarget(targetResp.GetId()))
|
||||
request.Queries[0].GetIncludeQuery().Include = cond
|
||||
|
||||
includeCond := &action.Condition{
|
||||
ConditionType: &action.Condition_Request{
|
||||
Request: &action.RequestExecution{
|
||||
Condition: &action.RequestExecution_Method{
|
||||
@@ -565,19 +643,23 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, []string{}, []string{"request./zitadel.management.v1.ManagementService/GetAction"})
|
||||
}
|
||||
includeTargets := executionTargetsSingleInclude(cond)
|
||||
resp2 := Tester.SetExecution(ctx, t, includeCond, includeTargets)
|
||||
|
||||
response.Details.Timestamp = resp2.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp2.GetDetails().GetSequence()
|
||||
|
||||
response.Result[0].Details.ChangeDate = resp2.GetDetails().GetChangeDate()
|
||||
response.Result[0].Details.Sequence = resp2.GetDetails().GetSequence()
|
||||
response.Result[0].Condition = includeCond
|
||||
response.Result[0].Targets = includeTargets
|
||||
return nil
|
||||
},
|
||||
req: &action.ListExecutionsRequest{
|
||||
Queries: []*action.SearchQuery{{
|
||||
Query: &action.SearchQuery_IncludeQuery{
|
||||
IncludeQuery: &action.IncludeQuery{Include: "request./zitadel.management.v1.ManagementService/GetAction"},
|
||||
IncludeQuery: &action.IncludeQuery{},
|
||||
},
|
||||
}},
|
||||
},
|
||||
@@ -591,8 +673,6 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.management.v1.ManagementService/ListActions",
|
||||
Includes: []string{"request./zitadel.management.v1.ManagementService/GetAction"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -603,19 +683,32 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListExecutionsRequest, response *action.ListExecutionsResponse) error {
|
||||
|
||||
resp1 := Tester.SetExecution(ctx, t, request.Queries[0].GetInConditionsQuery().GetConditions()[0], []string{targetResp.GetId()}, []string{})
|
||||
cond1 := request.Queries[0].GetInConditionsQuery().GetConditions()[0]
|
||||
targets1 := executionTargetsSingleTarget(targetResp.GetId())
|
||||
resp1 := Tester.SetExecution(ctx, t, cond1, targets1)
|
||||
response.Result[0].Details.ChangeDate = resp1.GetDetails().GetChangeDate()
|
||||
response.Result[0].Details.Sequence = resp1.GetDetails().GetSequence()
|
||||
response.Result[0].Condition = cond1
|
||||
response.Result[0].Targets = targets1
|
||||
|
||||
resp2 := Tester.SetExecution(ctx, t, request.Queries[0].GetInConditionsQuery().GetConditions()[1], []string{targetResp.GetId()}, []string{})
|
||||
cond2 := request.Queries[0].GetInConditionsQuery().GetConditions()[1]
|
||||
targets2 := executionTargetsSingleTarget(targetResp.GetId())
|
||||
resp2 := Tester.SetExecution(ctx, t, cond2, targets2)
|
||||
response.Result[1].Details.ChangeDate = resp2.GetDetails().GetChangeDate()
|
||||
response.Result[1].Details.Sequence = resp2.GetDetails().GetSequence()
|
||||
response.Result[1].Condition = cond2
|
||||
response.Result[1].Targets = targets2
|
||||
|
||||
resp3 := Tester.SetExecution(ctx, t, request.Queries[0].GetInConditionsQuery().GetConditions()[2], []string{targetResp.GetId()}, []string{})
|
||||
response.Details.Timestamp = resp3.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp3.GetDetails().GetSequence()
|
||||
cond3 := request.Queries[0].GetInConditionsQuery().GetConditions()[2]
|
||||
targets3 := executionTargetsSingleTarget(targetResp.GetId())
|
||||
resp3 := Tester.SetExecution(ctx, t, cond3, targets3)
|
||||
response.Result[2].Details.ChangeDate = resp3.GetDetails().GetChangeDate()
|
||||
response.Result[2].Details.Sequence = resp3.GetDetails().GetSequence()
|
||||
response.Result[2].Condition = cond3
|
||||
response.Result[2].Targets = targets3
|
||||
|
||||
response.Details.Timestamp = resp3.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp3.GetDetails().GetSequence()
|
||||
return nil
|
||||
},
|
||||
req: &action.ListExecutionsRequest{
|
||||
@@ -665,24 +758,77 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.session.v2beta.SessionService/GetSession",
|
||||
Targets: []string{targetResp.GetId()},
|
||||
}, {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.session.v2beta.SessionService/CreateSession",
|
||||
Targets: []string{targetResp.GetId()},
|
||||
}, {
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
ExecutionId: "request./zitadel.session.v2beta.SessionService/SetSession",
|
||||
Targets: []string{targetResp.GetId()},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list multiple conditions all types",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(ctx context.Context, request *action.ListExecutionsRequest, response *action.ListExecutionsResponse) error {
|
||||
targets := executionTargetsSingleTarget(targetResp.GetId())
|
||||
for i, cond := range request.Queries[0].GetInConditionsQuery().GetConditions() {
|
||||
resp := Tester.SetExecution(ctx, t, cond, targets)
|
||||
response.Result[i].Details.ChangeDate = resp.GetDetails().GetChangeDate()
|
||||
response.Result[i].Details.Sequence = resp.GetDetails().GetSequence()
|
||||
response.Result[i].Condition = cond
|
||||
response.Result[i].Targets = targets
|
||||
|
||||
// filled with info of last sequence
|
||||
response.Details.Timestamp = resp.GetDetails().GetChangeDate()
|
||||
response.Details.ProcessedSequence = resp.GetDetails().GetSequence()
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
req: &action.ListExecutionsRequest{
|
||||
Queries: []*action.SearchQuery{{
|
||||
Query: &action.SearchQuery_InConditionsQuery{
|
||||
InConditionsQuery: &action.InConditionsQuery{
|
||||
Conditions: []*action.Condition{
|
||||
{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_Method{Method: "/zitadel.session.v2beta.SessionService/GetSession"}}}},
|
||||
{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_Service{Service: "zitadel.session.v2beta.SessionService"}}}},
|
||||
{ConditionType: &action.Condition_Request{Request: &action.RequestExecution{Condition: &action.RequestExecution_All{All: true}}}},
|
||||
{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_Method{Method: "/zitadel.session.v2beta.SessionService/GetSession"}}}},
|
||||
{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_Service{Service: "zitadel.session.v2beta.SessionService"}}}},
|
||||
{ConditionType: &action.Condition_Response{Response: &action.ResponseExecution{Condition: &action.ResponseExecution_All{All: true}}}},
|
||||
{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_Event{Event: "user.added"}}}},
|
||||
{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_Group{Group: "user"}}}},
|
||||
{ConditionType: &action.Condition_Event{Event: &action.EventExecution{Condition: &action.EventExecution_All{All: true}}}},
|
||||
{ConditionType: &action.Condition_Function{Function: &action.FunctionExecution{Name: "Action.Flow.Type.ExternalAuthentication.Action.TriggerType.PostAuthentication"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
want: &action.ListExecutionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 10,
|
||||
},
|
||||
Result: []*action.Execution{
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
{Details: &object.Details{ResourceOwner: Tester.Instance.InstanceID()}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -699,20 +845,33 @@ func TestServer_ListExecutions_Request(t *testing.T) {
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, listErr := Client.ListExecutions(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(ttt, listErr, "Error: "+listErr.Error())
|
||||
assert.Error(t, listErr, "Error: "+listErr.Error())
|
||||
} else {
|
||||
assert.NoError(ttt, listErr)
|
||||
assert.NoError(t, listErr)
|
||||
}
|
||||
if listErr != nil {
|
||||
return
|
||||
}
|
||||
// always first check length, otherwise its failed anyway
|
||||
assert.Len(ttt, got.Result, len(tt.want.Result))
|
||||
assert.Len(t, got.Result, len(tt.want.Result))
|
||||
for i := range tt.want.Result {
|
||||
assert.Contains(ttt, got.Result, tt.want.Result[i])
|
||||
// as not sorted, all elements have to be checked
|
||||
// workaround as oneof elements can only be checked with assert.EqualExportedValues()
|
||||
if j, found := containExecution(got.Result, tt.want.Result[i]); found {
|
||||
assert.EqualExportedValues(t, tt.want.Result[i], got.Result[j])
|
||||
}
|
||||
}
|
||||
integration.AssertListDetails(t, tt.want, got)
|
||||
}, retryDuration, time.Millisecond*100, "timeout waiting for expected execution result")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func containExecution(executionList []*action.Execution, execution *action.Execution) (int, bool) {
|
||||
for i, exec := range executionList {
|
||||
if reflect.DeepEqual(exec.Details, execution.Details) {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
@@ -66,5 +66,5 @@ func checkExecutionEnabled(ctx context.Context) error {
|
||||
if authz.GetInstance(ctx).Features().Actions {
|
||||
return nil
|
||||
}
|
||||
return zerrors.ThrowPreconditionFailed(nil, "SCHEMA-141bwx3lef", "Errors.action.NotEnabled")
|
||||
return zerrors.ThrowPreconditionFailed(nil, "ACTION-8o6pvqfjhs", "Errors.Action.NotEnabled")
|
||||
}
|
||||
|
@@ -58,23 +58,26 @@ func (s *Server) DeleteTarget(ctx context.Context, req *action.DeleteTargetReque
|
||||
}
|
||||
|
||||
func createTargetToCommand(req *action.CreateTargetRequest) *command.AddTarget {
|
||||
var targetType domain.TargetType
|
||||
var url string
|
||||
var (
|
||||
targetType domain.TargetType
|
||||
interruptOnError bool
|
||||
)
|
||||
switch t := req.GetTargetType().(type) {
|
||||
case *action.CreateTargetRequest_RestWebhook:
|
||||
targetType = domain.TargetTypeWebhook
|
||||
url = t.RestWebhook.GetUrl()
|
||||
case *action.CreateTargetRequest_RestRequestResponse:
|
||||
targetType = domain.TargetTypeRequestResponse
|
||||
url = t.RestRequestResponse.GetUrl()
|
||||
interruptOnError = t.RestWebhook.InterruptOnError
|
||||
case *action.CreateTargetRequest_RestCall:
|
||||
targetType = domain.TargetTypeCall
|
||||
interruptOnError = t.RestCall.InterruptOnError
|
||||
case *action.CreateTargetRequest_RestAsync:
|
||||
targetType = domain.TargetTypeAsync
|
||||
}
|
||||
return &command.AddTarget{
|
||||
Name: req.GetName(),
|
||||
TargetType: targetType,
|
||||
URL: url,
|
||||
Endpoint: req.GetEndpoint(),
|
||||
Timeout: req.GetTimeout().AsDuration(),
|
||||
Async: req.GetIsAsync(),
|
||||
InterruptOnError: req.GetInterruptOnError(),
|
||||
InterruptOnError: interruptOnError,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,22 +89,24 @@ func updateTargetToCommand(req *action.UpdateTargetRequest) *command.ChangeTarge
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: req.GetTargetId(),
|
||||
},
|
||||
Name: req.Name,
|
||||
Name: req.Name,
|
||||
Endpoint: req.Endpoint,
|
||||
}
|
||||
switch t := req.GetTargetType().(type) {
|
||||
case *action.UpdateTargetRequest_RestWebhook:
|
||||
target.TargetType = gu.Ptr(domain.TargetTypeWebhook)
|
||||
target.URL = gu.Ptr(t.RestWebhook.GetUrl())
|
||||
case *action.UpdateTargetRequest_RestRequestResponse:
|
||||
target.TargetType = gu.Ptr(domain.TargetTypeRequestResponse)
|
||||
target.URL = gu.Ptr(t.RestRequestResponse.GetUrl())
|
||||
if req.TargetType != nil {
|
||||
switch t := req.GetTargetType().(type) {
|
||||
case *action.UpdateTargetRequest_RestWebhook:
|
||||
target.TargetType = gu.Ptr(domain.TargetTypeWebhook)
|
||||
target.InterruptOnError = gu.Ptr(t.RestWebhook.InterruptOnError)
|
||||
case *action.UpdateTargetRequest_RestCall:
|
||||
target.TargetType = gu.Ptr(domain.TargetTypeCall)
|
||||
target.InterruptOnError = gu.Ptr(t.RestCall.InterruptOnError)
|
||||
case *action.UpdateTargetRequest_RestAsync:
|
||||
target.TargetType = gu.Ptr(domain.TargetTypeAsync)
|
||||
target.InterruptOnError = gu.Ptr(false)
|
||||
}
|
||||
}
|
||||
if req.Timeout != nil {
|
||||
target.Timeout = gu.Ptr(req.GetTimeout().AsDuration())
|
||||
}
|
||||
if req.ExecutionType != nil {
|
||||
target.Async = gu.Ptr(req.GetIsAsync())
|
||||
target.InterruptOnError = gu.Ptr(req.GetInterruptOnError())
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
@@ -69,8 +70,8 @@ func TestServer_CreateTarget(t *testing.T) {
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
TargetType: &action.CreateTargetRequest_RestRequestResponse{
|
||||
RestRequestResponse: &action.SetRESTRequestResponse{},
|
||||
TargetType: &action.CreateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
@@ -79,29 +80,25 @@ func TestServer_CreateTarget(t *testing.T) {
|
||||
name: "empty timeout",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
},
|
||||
RestWebhook: &action.SetRESTWebhook{},
|
||||
},
|
||||
Timeout: nil,
|
||||
ExecutionType: nil,
|
||||
Timeout: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty execution type, ok",
|
||||
name: "async, ok",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
TargetType: &action.CreateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
},
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: nil,
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
want: &action.CreateTargetResponse{
|
||||
Details: &object.Details{
|
||||
@@ -111,19 +108,17 @@ func TestServer_CreateTarget(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "async execution, ok",
|
||||
name: "webhook, ok",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.CreateTargetRequest_IsAsync{
|
||||
IsAsync: true,
|
||||
},
|
||||
},
|
||||
want: &action.CreateTargetResponse{
|
||||
Details: &object.Details{
|
||||
@@ -133,20 +128,59 @@ func TestServer_CreateTarget(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "interrupt on error execution, ok",
|
||||
name: "webhook, interrupt on error, ok",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com",
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.CreateTargetRequest_InterruptOnError{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
want: &action.CreateTargetResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "call, ok",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
want: &action.CreateTargetResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Tester.Instance.InstanceID(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "call, interruptOnError, ok",
|
||||
ctx: CTX,
|
||||
req: &action.CreateTargetRequest{
|
||||
Name: fmt.Sprint(time.Now().UnixNano() + 1),
|
||||
Endpoint: "https://example.com",
|
||||
TargetType: &action.CreateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
},
|
||||
want: &action.CreateTargetResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
@@ -186,7 +220,7 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
{
|
||||
name: "missing permission",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
@@ -215,7 +249,7 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
{
|
||||
name: "change name, ok",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
@@ -235,16 +269,16 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
{
|
||||
name: "change type, ok",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
req: &action.UpdateTargetRequest{
|
||||
TargetType: &action.UpdateTargetRequest_RestRequestResponse{
|
||||
RestRequestResponse: &action.SetRESTRequestResponse{
|
||||
Url: "https://example.com",
|
||||
TargetType: &action.UpdateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -259,18 +293,14 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
{
|
||||
name: "change url, ok",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
req: &action.UpdateTargetRequest{
|
||||
TargetType: &action.UpdateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com/hooks/new",
|
||||
},
|
||||
},
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/new"),
|
||||
},
|
||||
},
|
||||
want: &action.UpdateTargetResponse{
|
||||
@@ -283,7 +313,7 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
{
|
||||
name: "change timeout, ok",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
@@ -301,17 +331,17 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change execution type, ok",
|
||||
name: "change type async, ok",
|
||||
prepare: func(request *action.UpdateTargetRequest) error {
|
||||
targetID := Tester.CreateTarget(CTX, t).GetId()
|
||||
targetID := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeAsync, false).GetId()
|
||||
request.TargetId = targetID
|
||||
return nil
|
||||
},
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
req: &action.UpdateTargetRequest{
|
||||
ExecutionType: &action.UpdateTargetRequest_IsAsync{
|
||||
IsAsync: true,
|
||||
TargetType: &action.UpdateTargetRequest_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -341,7 +371,7 @@ func TestServer_UpdateTarget(t *testing.T) {
|
||||
|
||||
func TestServer_DeleteTarget(t *testing.T) {
|
||||
ensureFeatureEnabled(t)
|
||||
target := Tester.CreateTarget(CTX, t)
|
||||
target := Tester.CreateTarget(CTX, t, "", "https://example.com", domain.TargetTypeWebhook, false)
|
||||
tests := []struct {
|
||||
name string
|
||||
ctx context.Context
|
||||
|
@@ -27,55 +27,64 @@ func Test_createTargetToCommand(t *testing.T) {
|
||||
args: args{nil},
|
||||
want: &command.AddTarget{
|
||||
Name: "",
|
||||
URL: "",
|
||||
Endpoint: "",
|
||||
Timeout: 0,
|
||||
Async: false,
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (async webhook)",
|
||||
name: "all fields (webhook)",
|
||||
args: args{&action.CreateTargetRequest{
|
||||
Name: "target 1",
|
||||
Name: "target 1",
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
TargetType: &action.CreateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com/hooks/1",
|
||||
},
|
||||
RestWebhook: &action.SetRESTWebhook{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.CreateTargetRequest_IsAsync{
|
||||
IsAsync: true,
|
||||
},
|
||||
}},
|
||||
want: &command.AddTarget{
|
||||
Name: "target 1",
|
||||
TargetType: domain.TargetTypeWebhook,
|
||||
URL: "https://example.com/hooks/1",
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
Timeout: 10 * time.Second,
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (async)",
|
||||
args: args{&action.CreateTargetRequest{
|
||||
Name: "target 1",
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
TargetType: &action.CreateTargetRequest_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
}},
|
||||
want: &command.AddTarget{
|
||||
Name: "target 1",
|
||||
TargetType: domain.TargetTypeAsync,
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
Timeout: 10 * time.Second,
|
||||
Async: true,
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (interrupting response)",
|
||||
args: args{&action.CreateTargetRequest{
|
||||
Name: "target 1",
|
||||
TargetType: &action.CreateTargetRequest_RestRequestResponse{
|
||||
RestRequestResponse: &action.SetRESTRequestResponse{
|
||||
Url: "https://example.com/hooks/1",
|
||||
Name: "target 1",
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
TargetType: &action.CreateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.CreateTargetRequest_InterruptOnError{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
}},
|
||||
want: &command.AddTarget{
|
||||
Name: "target 1",
|
||||
TargetType: domain.TargetTypeRequestResponse,
|
||||
URL: "https://example.com/hooks/1",
|
||||
TargetType: domain.TargetTypeCall,
|
||||
Endpoint: "https://example.com/hooks/1",
|
||||
Timeout: 10 * time.Second,
|
||||
Async: false,
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
@@ -105,80 +114,108 @@ func Test_updateTargetToCommand(t *testing.T) {
|
||||
{
|
||||
name: "all fields nil",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: nil,
|
||||
TargetType: nil,
|
||||
Timeout: nil,
|
||||
ExecutionType: nil,
|
||||
Name: nil,
|
||||
TargetType: nil,
|
||||
Timeout: nil,
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: nil,
|
||||
TargetType: nil,
|
||||
URL: nil,
|
||||
Endpoint: nil,
|
||||
Timeout: nil,
|
||||
Async: nil,
|
||||
InterruptOnError: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields empty",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: gu.Ptr(""),
|
||||
TargetType: nil,
|
||||
Timeout: durationpb.New(0),
|
||||
ExecutionType: nil,
|
||||
Name: gu.Ptr(""),
|
||||
TargetType: nil,
|
||||
Timeout: durationpb.New(0),
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: gu.Ptr(""),
|
||||
TargetType: nil,
|
||||
URL: nil,
|
||||
Endpoint: nil,
|
||||
Timeout: gu.Ptr(0 * time.Second),
|
||||
Async: nil,
|
||||
InterruptOnError: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (async webhook)",
|
||||
name: "all fields (webhook)",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: gu.Ptr("target 1"),
|
||||
Name: gu.Ptr("target 1"),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
TargetType: &action.UpdateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
Url: "https://example.com/hooks/1",
|
||||
InterruptOnError: false,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.UpdateTargetRequest_IsAsync{
|
||||
IsAsync: true,
|
||||
},
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: gu.Ptr("target 1"),
|
||||
TargetType: gu.Ptr(domain.TargetTypeWebhook),
|
||||
URL: gu.Ptr("https://example.com/hooks/1"),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
Timeout: gu.Ptr(10 * time.Second),
|
||||
InterruptOnError: gu.Ptr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (webhook interrupt)",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: gu.Ptr("target 1"),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
TargetType: &action.UpdateTargetRequest_RestWebhook{
|
||||
RestWebhook: &action.SetRESTWebhook{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: gu.Ptr("target 1"),
|
||||
TargetType: gu.Ptr(domain.TargetTypeWebhook),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
Timeout: gu.Ptr(10 * time.Second),
|
||||
InterruptOnError: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (async)",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: gu.Ptr("target 1"),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
TargetType: &action.UpdateTargetRequest_RestAsync{
|
||||
RestAsync: &action.SetRESTAsync{},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: gu.Ptr("target 1"),
|
||||
TargetType: gu.Ptr(domain.TargetTypeAsync),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
Timeout: gu.Ptr(10 * time.Second),
|
||||
Async: gu.Ptr(true),
|
||||
InterruptOnError: gu.Ptr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all fields (interrupting response)",
|
||||
args: args{&action.UpdateTargetRequest{
|
||||
Name: gu.Ptr("target 1"),
|
||||
TargetType: &action.UpdateTargetRequest_RestRequestResponse{
|
||||
RestRequestResponse: &action.SetRESTRequestResponse{
|
||||
Url: "https://example.com/hooks/1",
|
||||
Name: gu.Ptr("target 1"),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
TargetType: &action.UpdateTargetRequest_RestCall{
|
||||
RestCall: &action.SetRESTCall{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
},
|
||||
Timeout: durationpb.New(10 * time.Second),
|
||||
ExecutionType: &action.UpdateTargetRequest_InterruptOnError{
|
||||
InterruptOnError: true,
|
||||
},
|
||||
}},
|
||||
want: &command.ChangeTarget{
|
||||
Name: gu.Ptr("target 1"),
|
||||
TargetType: gu.Ptr(domain.TargetTypeRequestResponse),
|
||||
URL: gu.Ptr("https://example.com/hooks/1"),
|
||||
TargetType: gu.Ptr(domain.TargetTypeCall),
|
||||
Endpoint: gu.Ptr("https://example.com/hooks/1"),
|
||||
Timeout: gu.Ptr(10 * time.Second),
|
||||
Async: gu.Ptr(false),
|
||||
InterruptOnError: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user