mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-03 04:42:15 +00:00
feat: add executions for actions v2 (#7433)
* feat: add events for execution * feat: add events for execution and command side * feat: add events for execution and command side * feat: add api endpoints for set and delete executions with integration tests * feat: add integration and unit tests and more existence checks * feat: add integration and unit tests and more existence checks * feat: unit tests for includes in executions * feat: integration tests for includes in executions * fix: linting * fix: update internal/api/api.go Co-authored-by: Tim Möhlmann <[email protected]> * fix: update internal/command/command.go Co-authored-by: Tim Möhlmann <[email protected]> * fix: apply suggestions from code review Co-authored-by: Tim Möhlmann <[email protected]> * fix: change api return * fix: change aggregateID with prefix of execution type and add to documentation * fix: change body in proto for documentation and correct linting * fix: changed existing check to single query in separate writemodel * fix: linter changes and list endpoints for conditions in executions * fix: remove writemodel query on exeuction set as state before is irrelevant * fix: testing for exists write models and correction * fix: translations for errors and event types --------- Co-authored-by: Tim Möhlmann <[email protected]>
This commit is contained in:
co-authored by
Tim Möhlmann
parent
ce7ebffa84
commit
2731099db3
@@ -0,0 +1,285 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/repository/execution"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type ExecutionAPICondition struct {
|
||||
Method string
|
||||
Service string
|
||||
All bool
|
||||
}
|
||||
|
||||
func (e *ExecutionAPICondition) IsValid() error {
|
||||
if e.Method == "" && e.Service == "" && !e.All {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-3tkej630e6", "Errors.Execution.Invalid")
|
||||
}
|
||||
// never set two conditions
|
||||
if e.Method != "" && (e.Service != "" || e.All) ||
|
||||
e.Service != "" && (e.Method != "" || e.All) ||
|
||||
e.All && (e.Method != "" || e.Service != "") {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-nee5q8aszq", "Errors.Execution.Invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ExecutionAPICondition) ID(executionType domain.ExecutionType) string {
|
||||
if e.Method != "" {
|
||||
return execution.ID(executionType, e.Method)
|
||||
}
|
||||
if e.Service != "" {
|
||||
return execution.ID(executionType, e.Service)
|
||||
}
|
||||
if e.All {
|
||||
return execution.IDAll(executionType)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *ExecutionAPICondition) Existing(c *Commands) error {
|
||||
if e.Method != "" && !c.GrpcMethodExisting(e.Method) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-vysplsevt8", "Errors.Execution.ConditionInvalid")
|
||||
}
|
||||
if e.Service != "" && !c.GrpcServiceExisting(e.Service) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-qu6dfhiioq", "Errors.Execution.ConditionInvalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetExecutionRequest(ctx context.Context, cond *ExecutionAPICondition, set *SetExecution, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cond.Existing(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if set.AggregateID == "" {
|
||||
set.AggregateID = cond.ID(domain.ExecutionTypeRequest)
|
||||
}
|
||||
return c.setExecution(ctx, set, resourceOwner)
|
||||
}
|
||||
|
||||
func (c *Commands) SetExecutionResponse(ctx context.Context, cond *ExecutionAPICondition, set *SetExecution, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cond.Existing(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if set.AggregateID == "" {
|
||||
set.AggregateID = cond.ID(domain.ExecutionTypeResponse)
|
||||
}
|
||||
return c.setExecution(ctx, set, resourceOwner)
|
||||
}
|
||||
|
||||
type ExecutionFunctionCondition string
|
||||
|
||||
func (e ExecutionFunctionCondition) IsValid() error {
|
||||
if e == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-5folwn5jws", "Errors.Execution.Invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e ExecutionFunctionCondition) ID() string {
|
||||
return execution.ID(domain.ExecutionTypeFunction, string(e))
|
||||
}
|
||||
|
||||
func (e ExecutionFunctionCondition) Existing(c *Commands) error {
|
||||
if !c.ActionFunctionExisting(string(e)) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-cdy39t0ksr", "Errors.Execution.ConditionInvalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetExecutionFunction(ctx context.Context, cond ExecutionFunctionCondition, set *SetExecution, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cond.Existing(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if set.AggregateID == "" {
|
||||
set.AggregateID = cond.ID()
|
||||
}
|
||||
return c.setExecution(ctx, set, resourceOwner)
|
||||
}
|
||||
|
||||
type ExecutionEventCondition struct {
|
||||
Event string
|
||||
Group string
|
||||
All bool
|
||||
}
|
||||
|
||||
func (e *ExecutionEventCondition) IsValid() error {
|
||||
if e.Event == "" && e.Group == "" && !e.All {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-w5smb6v7qu", "Errors.Execution.Invalid")
|
||||
}
|
||||
// never set two conditions
|
||||
if e.Event != "" && (e.Group != "" || e.All) ||
|
||||
e.Group != "" && (e.Event != "" || e.All) ||
|
||||
e.All && (e.Event != "" || e.Group != "") {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-hdm4zl1hmd", "Errors.Execution.Invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ExecutionEventCondition) ID() string {
|
||||
if e.Event != "" {
|
||||
return execution.ID(domain.ExecutionTypeEvent, e.Event)
|
||||
}
|
||||
if e.Group != "" {
|
||||
return execution.ID(domain.ExecutionTypeEvent, e.Group)
|
||||
}
|
||||
if e.All {
|
||||
return execution.IDAll(domain.ExecutionTypeEvent)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *ExecutionEventCondition) Existing(c *Commands) error {
|
||||
if e.Event != "" && !c.EventExisting(e.Event) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-74aaqj8fv9", "Errors.Execution.ConditionInvalid")
|
||||
}
|
||||
if e.Group != "" && !c.EventGroupExisting(e.Group) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-er5oneb5lz", "Errors.Execution.ConditionInvalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetExecutionEvent(ctx context.Context, cond *ExecutionEventCondition, set *SetExecution, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cond.Existing(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if set.AggregateID == "" {
|
||||
set.AggregateID = cond.ID()
|
||||
}
|
||||
return c.setExecution(ctx, set, resourceOwner)
|
||||
}
|
||||
|
||||
type SetExecution struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Targets []string
|
||||
Includes []string
|
||||
}
|
||||
|
||||
func (e *SetExecution) IsValid() error {
|
||||
if len(e.Targets) == 0 && len(e.Includes) == 0 {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-56bteot2uj", "Errors.Execution.NoTargets")
|
||||
}
|
||||
if len(e.Targets) > 0 && len(e.Includes) > 0 {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-5zleae34r1", "Errors.Execution.Invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *SetExecution) Existing(c *Commands, ctx context.Context, resourceOwner string) error {
|
||||
if len(e.Targets) > 0 && !c.existsTargetsByIDs(ctx, e.Targets, resourceOwner) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-17e8fq1ggk", "Errors.Target.NotFound")
|
||||
}
|
||||
if len(e.Includes) > 0 && !c.existsExecutionsByIDs(ctx, e.Includes, resourceOwner) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-slgj0l4cdz", "Errors.Execution.IncludeNotFound")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) setExecution(ctx context.Context, set *SetExecution, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if resourceOwner == "" || set.AggregateID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-gg3a6ol4om", "Errors.IDMissing")
|
||||
}
|
||||
if err := set.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wm := NewExecutionWriteModel(set.AggregateID, resourceOwner)
|
||||
// Check if targets and includes for execution are existing
|
||||
if err := set.Existing(c, ctx, resourceOwner); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.pushAppendAndReduce(ctx, wm, execution.NewSetEvent(
|
||||
ctx,
|
||||
ExecutionAggregateFromWriteModel(&wm.WriteModel),
|
||||
set.Targets,
|
||||
set.Includes,
|
||||
)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&wm.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) DeleteExecutionRequest(ctx context.Context, cond *ExecutionAPICondition, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.deleteExecution(ctx, cond.ID(domain.ExecutionTypeRequest), resourceOwner)
|
||||
}
|
||||
|
||||
func (c *Commands) DeleteExecutionResponse(ctx context.Context, cond *ExecutionAPICondition, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.deleteExecution(ctx, cond.ID(domain.ExecutionTypeResponse), resourceOwner)
|
||||
}
|
||||
|
||||
func (c *Commands) DeleteExecutionFunction(ctx context.Context, cond ExecutionFunctionCondition, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.deleteExecution(ctx, cond.ID(), resourceOwner)
|
||||
}
|
||||
|
||||
func (c *Commands) DeleteExecutionEvent(ctx context.Context, cond *ExecutionEventCondition, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if err := cond.IsValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.deleteExecution(ctx, cond.ID(), resourceOwner)
|
||||
}
|
||||
|
||||
func (c *Commands) deleteExecution(ctx context.Context, aggID string, resourceOwner string) (_ *domain.ObjectDetails, err error) {
|
||||
if resourceOwner == "" || aggID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-cnic97c0g3", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
wm, err := c.getExecutionWriteModelByID(ctx, aggID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !wm.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-suq2upd3rt", "Errors.Execution.NotFound")
|
||||
}
|
||||
if err := c.pushAppendAndReduce(ctx, wm, execution.NewRemovedEvent(
|
||||
ctx,
|
||||
ExecutionAggregateFromWriteModel(&wm.WriteModel),
|
||||
)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&wm.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) existsExecutionsByIDs(ctx context.Context, ids []string, resourceOwner string) bool {
|
||||
wm := NewExecutionsExistWriteModel(ids, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, wm)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return wm.AllExists()
|
||||
}
|
||||
|
||||
func (c *Commands) getExecutionWriteModelByID(ctx context.Context, id string, resourceOwner string) (*ExecutionWriteModel, error) {
|
||||
wm := NewExecutionWriteModel(id, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, wm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wm, nil
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/execution"
|
||||
)
|
||||
|
||||
type ExecutionWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Targets []string
|
||||
Includes []string
|
||||
}
|
||||
|
||||
func (e *ExecutionWriteModel) Exists() bool {
|
||||
return len(e.Targets) > 0 || len(e.Includes) > 0
|
||||
}
|
||||
|
||||
func NewExecutionWriteModel(id string, resourceOwner string) *ExecutionWriteModel {
|
||||
return &ExecutionWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: id,
|
||||
ResourceOwner: resourceOwner,
|
||||
InstanceID: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ExecutionWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *execution.SetEvent:
|
||||
wm.Targets = e.Targets
|
||||
wm.Includes = e.Includes
|
||||
case *execution.RemovedEvent:
|
||||
wm.Targets = nil
|
||||
wm.Includes = nil
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ExecutionWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(execution.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(execution.SetEventType,
|
||||
execution.RemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func ExecutionAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return &eventstore.Aggregate{
|
||||
ID: wm.AggregateID,
|
||||
Type: execution.AggregateType,
|
||||
ResourceOwner: wm.ResourceOwner,
|
||||
InstanceID: wm.InstanceID,
|
||||
Version: execution.AggregateVersion,
|
||||
}
|
||||
}
|
||||
|
||||
type ExecutionsExistWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
ids []string
|
||||
existingIDs []string
|
||||
}
|
||||
|
||||
func (e *ExecutionsExistWriteModel) AllExists() bool {
|
||||
return len(e.ids) == len(e.existingIDs)
|
||||
}
|
||||
|
||||
func NewExecutionsExistWriteModel(ids []string, resourceOwner string) *ExecutionsExistWriteModel {
|
||||
return &ExecutionsExistWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
ResourceOwner: resourceOwner,
|
||||
InstanceID: resourceOwner,
|
||||
},
|
||||
ids: ids,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *ExecutionsExistWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *execution.SetEvent:
|
||||
if !slices.Contains(wm.existingIDs, e.Aggregate().ID) {
|
||||
wm.existingIDs = append(wm.existingIDs, e.Aggregate().ID)
|
||||
}
|
||||
case *execution.RemovedEvent:
|
||||
i := slices.Index(wm.existingIDs, e.Aggregate().ID)
|
||||
if i >= 0 {
|
||||
wm.existingIDs = slices.Delete(wm.existingIDs, i, i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *ExecutionsExistWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(execution.AggregateType).
|
||||
AggregateIDs(wm.ids...).
|
||||
EventTypes(execution.SetEventType,
|
||||
execution.RemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/execution"
|
||||
)
|
||||
|
||||
func TestCommandSide_executionsExistsWriteModel(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
ids []string
|
||||
resourceOwner string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res bool
|
||||
}{
|
||||
{
|
||||
name: "execution, single",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "execution, single reset",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "execution, single before removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "execution, single removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "execution, multiple",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "execution, multiple, first removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "execution, multiple, second removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "execution, multiple, third removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "execution, multiple, before removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "execution, multiple, all removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "execution, multiple, two removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution1", "org1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewSetEvent(context.Background(),
|
||||
execution.NewAggregate("execution3", "org1"),
|
||||
[]string{"target"},
|
||||
[]string{"include"},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
execution.NewRemovedEvent(context.Background(),
|
||||
execution.NewAggregate("execution2", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"execution1", "execution2", "execution3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
assert.Equal(t, tt.res, c.existsExecutionsByIDs(tt.args.ctx, tt.args.ids, tt.args.resourceOwner))
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,8 +52,14 @@ func (c *Commands) AddTarget(ctx context.Context, add *AddTarget, resourceOwner
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
wm, err := c.getTargetWriteModelByID(ctx, add.AggregateID, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if wm.State.Exists() {
|
||||
return nil, zerrors.ThrowAlreadyExists(nil, "INSTANCE-9axkz0jvzm", "Errors.Target.AlreadyExists")
|
||||
}
|
||||
|
||||
wm := NewTargetWriteModel(add.AggregateID, resourceOwner)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, target.NewAddedEvent(
|
||||
ctx,
|
||||
TargetAggregateFromWriteModel(&wm.WriteModel),
|
||||
@@ -167,6 +173,15 @@ func (c *Commands) DeleteTarget(ctx context.Context, id, resourceOwner string) (
|
||||
return writeModelToObjectDetails(&existing.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) existsTargetsByIDs(ctx context.Context, ids []string, resourceOwner string) bool {
|
||||
wm := NewTargetsExistsWriteModel(ids, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, wm)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return wm.AllExists()
|
||||
}
|
||||
|
||||
func (c *Commands) getTargetWriteModelByID(ctx context.Context, id string, resourceOwner string) (*TargetWriteModel, error) {
|
||||
wm := NewTargetWriteModel(id, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, wm)
|
||||
|
||||
@@ -2,11 +2,11 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/action"
|
||||
"github.com/zitadel/zitadel/internal/repository/target"
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ func (wm *TargetWriteModel) Reduce() error {
|
||||
if e.InterruptOnError != nil {
|
||||
wm.InterruptOnError = *e.InterruptOnError
|
||||
}
|
||||
case *action.RemovedEvent:
|
||||
case *target.RemovedEvent:
|
||||
wm.State = domain.TargetRemoved
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,54 @@ func (wm *TargetWriteModel) NewChangedEvent(
|
||||
return target.NewChangedEvent(ctx, agg, changes)
|
||||
}
|
||||
|
||||
type TargetsExistsWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
ids []string
|
||||
existingIDs []string
|
||||
}
|
||||
|
||||
func (e *TargetsExistsWriteModel) AllExists() bool {
|
||||
return len(e.ids) == len(e.existingIDs)
|
||||
}
|
||||
|
||||
func NewTargetsExistsWriteModel(ids []string, resourceOwner string) *TargetsExistsWriteModel {
|
||||
return &TargetsExistsWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
ResourceOwner: resourceOwner,
|
||||
InstanceID: resourceOwner,
|
||||
},
|
||||
ids: ids,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *TargetsExistsWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *target.AddedEvent:
|
||||
if !slices.Contains(wm.existingIDs, e.Aggregate().ID) {
|
||||
wm.existingIDs = append(wm.existingIDs, e.Aggregate().ID)
|
||||
}
|
||||
case *target.RemovedEvent:
|
||||
i := slices.Index(wm.existingIDs, e.Aggregate().ID)
|
||||
if i >= 0 {
|
||||
wm.existingIDs = slices.Delete(wm.existingIDs, i, i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *TargetsExistsWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(target.AggregateType).
|
||||
AggregateIDs(wm.ids...).
|
||||
EventTypes(target.AddedEventType,
|
||||
target.RemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func TargetAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
|
||||
return &eventstore.Aggregate{
|
||||
ID: wm.AggregateID,
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/target"
|
||||
)
|
||||
|
||||
func targetAddEvent(aggID, resourceOwner string) *target.AddedEvent {
|
||||
return target.NewAddedEvent(context.Background(),
|
||||
target.NewAggregate(aggID, resourceOwner),
|
||||
"name",
|
||||
domain.TargetTypeWebhook,
|
||||
"https://example.com",
|
||||
time.Second,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
func targetRemoveEvent(aggID, resourceOwner string) *target.RemovedEvent {
|
||||
return target.NewRemovedEvent(context.Background(),
|
||||
target.NewAggregate(aggID, resourceOwner),
|
||||
"name",
|
||||
)
|
||||
}
|
||||
|
||||
func TestCommandSide_targetsExistsWriteModel(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
ids []string
|
||||
resourceOwner string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res bool
|
||||
}{
|
||||
{
|
||||
name: "target, single",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "target, single reset",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
|
||||
targetAddEvent("target", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "target, single before removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "target, single removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "target, multiple",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "target, multiple, first removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "target, multiple, second removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "target, multiple, third removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
name: "target, multiple, before removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "target, multiple, all removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target3", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "target, multiple, two removed",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target1", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target2", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetAddEvent("target3", "org1"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
targetRemoveEvent("target2", "org1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
ids: []string{"target1", "target2", "target3"},
|
||||
},
|
||||
res: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
assert.Equal(t, tt.res, c.existsTargetsByIDs(tt.args.ctx, tt.args.ids, tt.args.resourceOwner))
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,7 @@ func TestCommands_AddTarget(t *testing.T) {
|
||||
"unique constraint failed, error",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPushFailed(
|
||||
zerrors.ThrowPreconditionFailed(nil, "id", "name already exists"),
|
||||
target.NewAddedEvent(context.Background(),
|
||||
@@ -151,10 +152,43 @@ func TestCommands_AddTarget(t *testing.T) {
|
||||
err: zerrors.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
"already existing",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
target.NewAddedEvent(context.Background(),
|
||||
target.NewAggregate("id1", "org1"),
|
||||
"name",
|
||||
domain.TargetTypeWebhook,
|
||||
"https://example.com",
|
||||
time.Second,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: mock.ExpectID(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
add: &AddTarget{
|
||||
Name: "name",
|
||||
TargetType: domain.TargetTypeWebhook,
|
||||
Timeout: time.Second,
|
||||
URL: "https://example.com",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res{
|
||||
err: zerrors.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
"push ok",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
target.NewAddedEvent(context.Background(),
|
||||
target.NewAggregate("id1", "org1"),
|
||||
@@ -190,6 +224,7 @@ func TestCommands_AddTarget(t *testing.T) {
|
||||
"push full ok",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
target.NewAddedEvent(context.Background(),
|
||||
target.NewAggregate("id1", "org1"),
|
||||
|
||||
@@ -74,6 +74,12 @@ type Commands struct {
|
||||
defaultSecretGenerators *SecretGenerators
|
||||
|
||||
samlCertificateAndKeyGenerator func(id string) ([]byte, []byte, error)
|
||||
|
||||
GrpcMethodExisting func(method string) bool
|
||||
GrpcServiceExisting func(method string) bool
|
||||
ActionFunctionExisting func(function string) bool
|
||||
EventExisting func(event string) bool
|
||||
EventGroupExisting func(group string) bool
|
||||
}
|
||||
|
||||
func StartCommands(
|
||||
@@ -132,6 +138,13 @@ func StartCommands(
|
||||
defaultRefreshTokenIdleLifetime: defaultRefreshTokenIdleLifetime,
|
||||
defaultSecretGenerators: defaultSecretGenerators,
|
||||
samlCertificateAndKeyGenerator: samlCertificateAndKeyGenerator(defaults.KeyConfig.Size),
|
||||
// always true for now until we can check with an eventlist
|
||||
EventExisting: func(event string) bool { return true },
|
||||
// always true for now until we can check with an eventlist
|
||||
EventGroupExisting: func(group string) bool { return true },
|
||||
GrpcServiceExisting: func(service string) bool { return false },
|
||||
GrpcMethodExisting: func(method string) bool { return false },
|
||||
ActionFunctionExisting: domain.FunctionExists(),
|
||||
}
|
||||
|
||||
repo.codeAlg = crypto.NewBCrypt(defaults.SecretGenerators.PasswordSaltCost)
|
||||
|
||||
Reference in New Issue
Block a user