mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-14 20:08:02 +00:00
1c5ecba42a
* 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>
365 lines
12 KiB
Go
365 lines
12 KiB
Go
package action
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
|
|
"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/query"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
action "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha"
|
|
)
|
|
|
|
func (s *Server) ListTargets(ctx context.Context, req *action.ListTargetsRequest) (*action.ListTargetsResponse, error) {
|
|
if err := checkExecutionEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
queries, err := listTargetsRequestToModel(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := s.query.SearchTargets(ctx, queries)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &action.ListTargetsResponse{
|
|
Result: targetsToPb(resp.Targets),
|
|
Details: object.ToListDetails(resp.SearchResponse),
|
|
}, nil
|
|
}
|
|
|
|
func listTargetsRequestToModel(req *action.ListTargetsRequest) (*query.TargetSearchQueries, error) {
|
|
offset, limit, asc := object.ListQueryToQuery(req.Query)
|
|
queries, err := targetQueriesToQuery(req.Queries)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &query.TargetSearchQueries{
|
|
SearchRequest: query.SearchRequest{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Asc: asc,
|
|
SortingColumn: targetFieldNameToSortingColumn(req.SortingColumn),
|
|
},
|
|
Queries: queries,
|
|
}, nil
|
|
}
|
|
|
|
func targetFieldNameToSortingColumn(field action.TargetFieldName) query.Column {
|
|
switch field {
|
|
case action.TargetFieldName_FIELD_NAME_UNSPECIFIED:
|
|
return query.TargetColumnID
|
|
case action.TargetFieldName_FIELD_NAME_ID:
|
|
return query.TargetColumnID
|
|
case action.TargetFieldName_FIELD_NAME_CREATION_DATE:
|
|
return query.TargetColumnCreationDate
|
|
case action.TargetFieldName_FIELD_NAME_CHANGE_DATE:
|
|
return query.TargetColumnChangeDate
|
|
case action.TargetFieldName_FIELD_NAME_NAME:
|
|
return query.TargetColumnName
|
|
case action.TargetFieldName_FIELD_NAME_TARGET_TYPE:
|
|
return query.TargetColumnTargetType
|
|
case action.TargetFieldName_FIELD_NAME_URL:
|
|
return query.TargetColumnURL
|
|
case action.TargetFieldName_FIELD_NAME_TIMEOUT:
|
|
return query.TargetColumnTimeout
|
|
case action.TargetFieldName_FIELD_NAME_INTERRUPT_ON_ERROR:
|
|
return query.TargetColumnInterruptOnError
|
|
default:
|
|
return query.TargetColumnID
|
|
}
|
|
}
|
|
|
|
func targetQueriesToQuery(queries []*action.TargetSearchQuery) (_ []query.SearchQuery, err error) {
|
|
q := make([]query.SearchQuery, len(queries))
|
|
for i, query := range queries {
|
|
q[i], err = targetQueryToQuery(query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return q, nil
|
|
}
|
|
|
|
func targetQueryToQuery(query *action.TargetSearchQuery) (query.SearchQuery, error) {
|
|
switch q := query.Query.(type) {
|
|
case *action.TargetSearchQuery_TargetNameQuery:
|
|
return targetNameQueryToQuery(q.TargetNameQuery)
|
|
case *action.TargetSearchQuery_InTargetIdsQuery:
|
|
return targetInTargetIdsQueryToQuery(q.InTargetIdsQuery)
|
|
default:
|
|
return nil, zerrors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
|
}
|
|
}
|
|
|
|
func targetNameQueryToQuery(q *action.TargetNameQuery) (query.SearchQuery, error) {
|
|
return query.NewTargetNameSearchQuery(object.TextMethodToQuery(q.Method), q.GetTargetName())
|
|
}
|
|
|
|
func targetInTargetIdsQueryToQuery(q *action.InTargetIDsQuery) (query.SearchQuery, error) {
|
|
return query.NewTargetInIDsSearchQuery(q.GetTargetIds())
|
|
}
|
|
|
|
func (s *Server) GetTargetByID(ctx context.Context, req *action.GetTargetByIDRequest) (_ *action.GetTargetByIDResponse, err error) {
|
|
if err := checkExecutionEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := s.query.GetTargetByID(ctx, req.GetTargetId())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &action.GetTargetByIDResponse{
|
|
Target: targetToPb(resp),
|
|
}, nil
|
|
}
|
|
|
|
func targetsToPb(targets []*query.Target) []*action.Target {
|
|
t := make([]*action.Target, len(targets))
|
|
for i, target := range targets {
|
|
t[i] = targetToPb(target)
|
|
}
|
|
return t
|
|
}
|
|
|
|
func targetToPb(t *query.Target) *action.Target {
|
|
target := &action.Target{
|
|
Details: object.DomainToDetailsPb(&t.ObjectDetails),
|
|
TargetId: t.ID,
|
|
Name: t.Name,
|
|
Timeout: durationpb.New(t.Timeout),
|
|
Endpoint: t.Endpoint,
|
|
}
|
|
|
|
switch t.TargetType {
|
|
case domain.TargetTypeWebhook:
|
|
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
|
|
}
|
|
return target
|
|
}
|
|
|
|
func (s *Server) ListExecutions(ctx context.Context, req *action.ListExecutionsRequest) (*action.ListExecutionsResponse, error) {
|
|
if err := checkExecutionEnabled(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
queries, err := listExecutionsRequestToModel(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := s.query.SearchExecutions(ctx, queries)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &action.ListExecutionsResponse{
|
|
Result: executionsToPb(resp.Executions),
|
|
Details: object.ToListDetails(resp.SearchResponse),
|
|
}, nil
|
|
}
|
|
|
|
func listExecutionsRequestToModel(req *action.ListExecutionsRequest) (*query.ExecutionSearchQueries, error) {
|
|
offset, limit, asc := object.ListQueryToQuery(req.Query)
|
|
queries, err := executionQueriesToQuery(req.Queries)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &query.ExecutionSearchQueries{
|
|
SearchRequest: query.SearchRequest{
|
|
Offset: offset,
|
|
Limit: limit,
|
|
Asc: asc,
|
|
},
|
|
Queries: queries,
|
|
}, nil
|
|
}
|
|
|
|
func executionQueriesToQuery(queries []*action.SearchQuery) (_ []query.SearchQuery, err error) {
|
|
q := make([]query.SearchQuery, len(queries))
|
|
for i, query := range queries {
|
|
q[i], err = executionQueryToQuery(query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return q, nil
|
|
}
|
|
|
|
func executionQueryToQuery(searchQuery *action.SearchQuery) (query.SearchQuery, error) {
|
|
switch q := searchQuery.Query.(type) {
|
|
case *action.SearchQuery_InConditionsQuery:
|
|
return inConditionsQueryToQuery(q.InConditionsQuery)
|
|
case *action.SearchQuery_ExecutionTypeQuery:
|
|
return executionTypeToQuery(q.ExecutionTypeQuery)
|
|
case *action.SearchQuery_IncludeQuery:
|
|
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")
|
|
}
|
|
}
|
|
|
|
func executionTypeToQuery(q *action.ExecutionTypeQuery) (query.SearchQuery, error) {
|
|
switch q.ExecutionType {
|
|
case action.ExecutionType_EXECUTION_TYPE_UNSPECIFIED:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeUnspecified)
|
|
case action.ExecutionType_EXECUTION_TYPE_REQUEST:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeRequest)
|
|
case action.ExecutionType_EXECUTION_TYPE_RESPONSE:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeResponse)
|
|
case action.ExecutionType_EXECUTION_TYPE_EVENT:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeEvent)
|
|
case action.ExecutionType_EXECUTION_TYPE_FUNCTION:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeFunction)
|
|
default:
|
|
return query.NewExecutionTypeSearchQuery(domain.ExecutionTypeUnspecified)
|
|
}
|
|
}
|
|
|
|
func inConditionsQueryToQuery(q *action.InConditionsQuery) (query.SearchQuery, error) {
|
|
values := make([]string, len(q.GetConditions()))
|
|
for i, condition := range q.GetConditions() {
|
|
id, err := conditionToID(condition)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
values[i] = id
|
|
}
|
|
return query.NewExecutionInIDsSearchQuery(values)
|
|
}
|
|
|
|
func conditionToID(q *action.Condition) (string, error) {
|
|
switch t := q.GetConditionType().(type) {
|
|
case *action.Condition_Request:
|
|
cond := &command.ExecutionAPICondition{
|
|
Method: t.Request.GetMethod(),
|
|
Service: t.Request.GetService(),
|
|
All: t.Request.GetAll(),
|
|
}
|
|
return cond.ID(domain.ExecutionTypeRequest), nil
|
|
case *action.Condition_Response:
|
|
cond := &command.ExecutionAPICondition{
|
|
Method: t.Response.GetMethod(),
|
|
Service: t.Response.GetService(),
|
|
All: t.Response.GetAll(),
|
|
}
|
|
return cond.ID(domain.ExecutionTypeResponse), nil
|
|
case *action.Condition_Event:
|
|
cond := &command.ExecutionEventCondition{
|
|
Event: t.Event.GetEvent(),
|
|
Group: t.Event.GetGroup(),
|
|
All: t.Event.GetAll(),
|
|
}
|
|
return cond.ID(), nil
|
|
case *action.Condition_Function:
|
|
return command.ExecutionFunctionCondition(t.Function.GetName()).ID(), nil
|
|
default:
|
|
return "", zerrors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
|
}
|
|
}
|
|
|
|
func executionsToPb(executions []*query.Execution) []*action.Execution {
|
|
e := make([]*action.Execution, len(executions))
|
|
for i, execution := range executions {
|
|
e[i] = executionToPb(execution)
|
|
}
|
|
return e
|
|
}
|
|
|
|
func executionToPb(e *query.Execution) *action.Execution {
|
|
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),
|
|
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, "/")}}}
|
|
}
|