feat: limit amount of active actions (#3143)

* max actions

* fix: max allowed actions

* fix: max allowed actions

* fix tests
This commit is contained in:
Livio Amstutz
2022-02-02 09:04:05 +01:00
committed by GitHub
parent 585ebf9a81
commit 1367a2e139
32 changed files with 583 additions and 123 deletions

View File

@@ -67,13 +67,14 @@ func (q *Queries) GetFlow(ctx context.Context, flowType domain.FlowType, orgID s
return scan(rows)
}
func (q *Queries) GetActionsByFlowAndTriggerType(ctx context.Context, flowType domain.FlowType, triggerType domain.TriggerType, orgID string) ([]*Action, error) {
func (q *Queries) GetActiveActionsByFlowAndTriggerType(ctx context.Context, flowType domain.FlowType, triggerType domain.TriggerType, orgID string) ([]*Action, error) {
stmt, scan := prepareTriggerActionsQuery()
query, args, err := stmt.Where(
sq.Eq{
FlowsTriggersColumnFlowType.identifier(): flowType,
FlowsTriggersColumnTriggerType.identifier(): triggerType,
FlowsTriggersColumnResourceOwner.identifier(): orgID,
ActionColumnState.identifier(): domain.ActionStateActive,
},
).ToSql()
if err != nil {
@@ -135,7 +136,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
ActionColumnCreationDate.identifier(),
ActionColumnChangeDate.identifier(),
ActionColumnResourceOwner.identifier(),
//ActionColumnState.identifier(),
ActionColumnState.identifier(),
ActionColumnSequence.identifier(),
ActionColumnName.identifier(),
ActionColumnScript.identifier(),
@@ -152,7 +153,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
&action.CreationDate,
&action.ChangeDate,
&action.ResourceOwner,
//&action.State, //TODO: state in next release
&action.State,
&action.Sequence,
&action.Name,
&action.Script,
@@ -177,7 +178,7 @@ func prepareFlowQuery() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
ActionColumnCreationDate.identifier(),
ActionColumnChangeDate.identifier(),
ActionColumnResourceOwner.identifier(),
//ActionColumnState.identifier(),
ActionColumnState.identifier(),
ActionColumnSequence.identifier(),
ActionColumnName.identifier(),
ActionColumnScript.identifier(),
@@ -199,6 +200,7 @@ func prepareFlowQuery() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
actionCreationDate pq.NullTime
actionChangeDate pq.NullTime
actionResourceOwner sql.NullString
actionState sql.NullInt32
actionSequence sql.NullInt64
actionName sql.NullString
actionScript sql.NullString
@@ -212,7 +214,7 @@ func prepareFlowQuery() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
&actionCreationDate,
&actionChangeDate,
&actionResourceOwner,
//&action.State, //TODO: state in next release
&actionState,
&actionSequence,
&actionName,
&actionScript,
@@ -232,6 +234,7 @@ func prepareFlowQuery() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
CreationDate: actionCreationDate.Time,
ChangeDate: actionChangeDate.Time,
ResourceOwner: actionResourceOwner.String,
State: domain.ActionState(actionState.Int32),
Sequence: uint64(actionSequence.Int64),
Name: actionName.String,
Script: actionScript.String,

View File

@@ -31,6 +31,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script,`+
@@ -54,6 +55,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script,`+
@@ -67,6 +69,7 @@ func Test_FlowPrepares(t *testing.T) {
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
@@ -80,6 +83,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.ActionStateActive,
uint64(20211115),
"action-name",
"script",
@@ -99,6 +103,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name",
Script: "script",
@@ -116,6 +121,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script,`+
@@ -129,6 +135,7 @@ func Test_FlowPrepares(t *testing.T) {
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
@@ -142,6 +149,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.ActionStateActive,
uint64(20211115),
"action-name-pre",
"script",
@@ -154,6 +162,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.ActionStateActive,
uint64(20211115),
"action-name-post",
"script",
@@ -173,6 +182,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name-pre",
Script: "script",
@@ -184,6 +194,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name-post",
Script: "script",
@@ -201,6 +212,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script,`+
@@ -214,6 +226,7 @@ func Test_FlowPrepares(t *testing.T) {
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
@@ -230,6 +243,7 @@ func Test_FlowPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
domain.TriggerTypePostCreation,
uint64(20211109),
domain.FlowTypeExternalAuthentication,
@@ -251,6 +265,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script,`+
@@ -279,6 +294,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script`+
@@ -299,6 +315,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script`+
@@ -309,6 +326,7 @@ func Test_FlowPrepares(t *testing.T) {
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
@@ -319,6 +337,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.AddressStateActive,
uint64(20211115),
"action-name",
"script",
@@ -332,6 +351,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name",
Script: "script",
@@ -347,6 +367,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script`+
@@ -357,6 +378,7 @@ func Test_FlowPrepares(t *testing.T) {
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
@@ -367,6 +389,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.AddressStateActive,
uint64(20211115),
"action-name-1",
"script",
@@ -376,6 +399,7 @@ func Test_FlowPrepares(t *testing.T) {
testNow,
testNow,
"ro",
domain.ActionStateActive,
uint64(20211115),
"action-name-2",
"script",
@@ -389,6 +413,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name-1",
Script: "script",
@@ -398,6 +423,7 @@ func Test_FlowPrepares(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.ActionStateActive,
Sequence: 20211115,
Name: "action-name-2",
Script: "script",
@@ -413,6 +439,7 @@ func Test_FlowPrepares(t *testing.T) {
` zitadel.projections.actions.creation_date,`+
` zitadel.projections.actions.change_date,`+
` zitadel.projections.actions.resource_owner,`+
` zitadel.projections.actions.action_state,`+
` zitadel.projections.actions.sequence,`+
` zitadel.projections.actions.name,`+
` zitadel.projections.actions.script`+

View File

@@ -38,7 +38,8 @@ type Features struct {
CustomTextMessage bool
CustomTextLogin bool
LockoutPolicy bool
Actions bool
ActionsAllowed domain.ActionsAllowed
MaxActions int32
}
var (
@@ -141,8 +142,12 @@ var (
name: projection.FeatureLockoutPolicyCol,
table: featureTable,
}
FeatureActions = Column{
name: projection.FeatureActionsCol,
FeatureActionsAllowed = Column{
name: projection.FeatureActionsAllowedCol,
table: featureTable,
}
FeatureMaxActions = Column{
name: projection.FeatureMaxActionsCol,
table: featureTable,
}
)
@@ -207,7 +212,8 @@ func prepareFeaturesQuery() (sq.SelectBuilder, func(*sql.Row) (*Features, error)
FeatureCustomTextMessage.identifier(),
FeatureCustomTextLogin.identifier(),
FeatureLockoutPolicy.identifier(),
FeatureActions.identifier(),
FeatureActionsAllowed.identifier(),
FeatureMaxActions.identifier(),
).From(featureTable.identifier()).PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Features, error) {
p := new(Features)
@@ -239,7 +245,8 @@ func prepareFeaturesQuery() (sq.SelectBuilder, func(*sql.Row) (*Features, error)
&p.CustomTextMessage,
&p.CustomTextLogin,
&p.LockoutPolicy,
&p.Actions,
&p.ActionsAllowed,
&p.MaxActions,
)
if err != nil {
if errs.Is(err, sql.ErrNoRows) {
@@ -301,7 +308,7 @@ func (f *Features) EnabledFeatureTypes() []string {
if f.LockoutPolicy {
list = append(list, domain.FeatureLockoutPolicy)
}
if f.Actions {
if f.ActionsAllowed != domain.ActionsNotAllowed {
list = append(list, domain.FeatureActions)
}
return list

View File

@@ -53,7 +53,8 @@ func Test_FeaturesPrepares(t *testing.T) {
` zitadel.projections.features.custom_text_message,`+
` zitadel.projections.features.custom_text_login,`+
` zitadel.projections.features.lockout_policy,`+
` zitadel.projections.features.actions`+
` zitadel.projections.features.actions_allowed,`+
` zitadel.projections.features.max_actions`+
` FROM zitadel.projections.features`),
nil,
nil,
@@ -96,7 +97,8 @@ func Test_FeaturesPrepares(t *testing.T) {
` zitadel.projections.features.custom_text_message,`+
` zitadel.projections.features.custom_text_login,`+
` zitadel.projections.features.lockout_policy,`+
` zitadel.projections.features.actions`+
` zitadel.projections.features.actions_allowed,`+
` zitadel.projections.features.max_actions`+
` FROM zitadel.projections.features`),
[]string{
"aggregate_id",
@@ -123,7 +125,8 @@ func Test_FeaturesPrepares(t *testing.T) {
"custom_text_message",
"custom_text_login",
"lockout_policy",
"actions",
"actions_allowed",
"max_actions",
},
[]driver.Value{
"aggregate-id",
@@ -150,7 +153,8 @@ func Test_FeaturesPrepares(t *testing.T) {
true,
true,
true,
true,
domain.ActionsMaxAllowed,
10,
},
),
},
@@ -179,7 +183,8 @@ func Test_FeaturesPrepares(t *testing.T) {
CustomTextMessage: true,
CustomTextLogin: true,
LockoutPolicy: true,
Actions: true,
ActionsAllowed: domain.ActionsMaxAllowed,
MaxActions: 10,
},
},
{
@@ -211,7 +216,8 @@ func Test_FeaturesPrepares(t *testing.T) {
` zitadel.projections.features.custom_text_message,`+
` zitadel.projections.features.custom_text_login,`+
` zitadel.projections.features.lockout_policy,`+
` zitadel.projections.features.actions`+
` zitadel.projections.features.actions_allowed,`+
` zitadel.projections.features.max_actions`+
` FROM zitadel.projections.features`),
[]string{
"aggregate_id",
@@ -238,7 +244,8 @@ func Test_FeaturesPrepares(t *testing.T) {
"custom_text_message",
"custom_text_login",
"lockout_policy",
"actions",
"actions_allowed",
"max_actions",
},
[]driver.Value{
"aggregate-id",
@@ -265,7 +272,8 @@ func Test_FeaturesPrepares(t *testing.T) {
true,
true,
true,
true,
domain.ActionsMaxAllowed,
10,
},
),
},
@@ -294,7 +302,8 @@ func Test_FeaturesPrepares(t *testing.T) {
CustomTextMessage: true,
CustomTextLogin: true,
LockoutPolicy: true,
Actions: true,
ActionsAllowed: domain.ActionsMaxAllowed,
MaxActions: 10,
},
},
{
@@ -326,7 +335,8 @@ func Test_FeaturesPrepares(t *testing.T) {
` zitadel.projections.features.custom_text_message,`+
` zitadel.projections.features.custom_text_login,`+
` zitadel.projections.features.lockout_policy,`+
` zitadel.projections.features.actions`+
` zitadel.projections.features.actions_allowed,`+
` zitadel.projections.features.max_actions`+
` FROM zitadel.projections.features`),
sql.ErrConnDone,
),

View File

@@ -5,6 +5,8 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/handler"
@@ -82,7 +84,8 @@ const (
FeatureCustomTextMessageCol = "custom_text_message"
FeatureCustomTextLoginCol = "custom_text_login"
FeatureLockoutPolicyCol = "lockout_policy"
FeatureActionsCol = "actions"
FeatureActionsAllowedCol = "actions_allowed"
FeatureMaxActionsCol = "max_actions"
)
func (p *FeatureProjection) reduceFeatureSet(event eventstore.Event) (*handler.Statement, error) {
@@ -173,7 +176,17 @@ func (p *FeatureProjection) reduceFeatureSet(event eventstore.Event) (*handler.S
cols = append(cols, handler.NewCol(FeatureLockoutPolicyCol, *featureEvent.LockoutPolicy))
}
if featureEvent.Actions != nil {
cols = append(cols, handler.NewCol(FeatureActionsCol, *featureEvent.Actions))
actionsAllowed := domain.ActionsNotAllowed
if *featureEvent.Actions {
actionsAllowed = domain.ActionsAllowedUnlimited
}
cols = append(cols, handler.NewCol(FeatureActionsAllowedCol, actionsAllowed))
}
if featureEvent.ActionsAllowed != nil {
cols = append(cols, handler.NewCol(FeatureActionsAllowedCol, *featureEvent.ActionsAllowed))
}
if featureEvent.MaxActions != nil {
cols = append(cols, handler.NewCol(FeatureMaxActionsCol, *featureEvent.MaxActions))
}
return crdb.NewUpsertStatement(
&featureEvent,

View File

@@ -50,7 +50,8 @@ func TestFeatureProjection_reduces(t *testing.T) {
"customTextMessage": true,
"customTextLogin": true,
"lockoutPolicy": true,
"actions": true
"actionsAllowed": 1,
"maxActions": 10
}`),
), org.FeaturesSetEventMapper),
},
@@ -63,7 +64,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions_allowed, max_actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -89,7 +90,8 @@ func TestFeatureProjection_reduces(t *testing.T) {
true,
true,
true,
true,
domain.ActionsMaxAllowed,
10,
},
},
},
@@ -136,7 +138,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions_allowed) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -162,7 +164,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
true,
true,
true,
true,
domain.ActionsAllowedUnlimited,
},
},
},
@@ -266,7 +268,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions_allowed) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -292,7 +294,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
true,
true,
true,
true,
domain.ActionsAllowedUnlimited,
},
},
},
@@ -327,7 +329,8 @@ func TestFeatureProjection_reduces(t *testing.T) {
"customTextMessage": true,
"customTextLogin": true,
"lockoutPolicy": true,
"actions": true
"actionsAllowed": 1,
"maxActions": 10
}`),
), iam.FeaturesSetEventMapper),
},
@@ -339,7 +342,7 @@ func TestFeatureProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)",
expectedStmt: "UPSERT INTO zitadel.projections.features (aggregate_id, change_date, sequence, is_default, tier_name, tier_description, state, state_description, audit_log_retention, login_policy_factors, login_policy_idp, login_policy_passwordless, login_policy_registration, login_policy_username_login, login_policy_password_reset, password_complexity_policy, label_policy_private_label, label_policy_watermark, custom_domain, privacy_policy, metadata_user, custom_text_message, custom_text_login, lockout_policy, actions_allowed, max_actions) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -365,7 +368,8 @@ func TestFeatureProjection_reduces(t *testing.T) {
true,
true,
true,
true,
domain.ActionsMaxAllowed,
10,
},
},
},