fix: correctly create SMTP provider list (#8724)

# Which Problems Are Solved

https://github.com/zitadel/zitadel/pull/8545 incorrectly created the
list of current smtp providers, if an SMTP provider was changed, that
was created before https://github.com/zitadel/zitadel/pull/6932 /
[v2.50.0](https://github.com/zitadel/zitadel/releases/tag/v2.50.0)).
This led to problems when trying to send emails to users (email
verification and OTP email).

# How the Problems Are Solved

Correctly handle events of old SMTP configurations, which do not have an
id set.

# Additional Changes

None

# Additional Context

- relates to #8545
- support requests from cloud customers

(cherry picked from commit 0bcf136f6f130fb57f7ccd9bd210d2a6e84c8204)
This commit is contained in:
Stefan Benz 2024-10-04 11:34:44 +02:00 committed by Livio Spring
parent 5215d98a30
commit 1f07d4128f
No known key found for this signature in database
GPG Key ID: 26BB1C2FA5952CF0
3 changed files with 240 additions and 103 deletions

View File

@ -11,7 +11,7 @@ import (
) )
const ( const (
SMTPConfigProjectionTable = "projections.smtp_configs4" SMTPConfigProjectionTable = "projections.smtp_configs5"
SMTPConfigTable = SMTPConfigProjectionTable + "_" + smtpConfigSMTPTableSuffix SMTPConfigTable = SMTPConfigProjectionTable + "_" + smtpConfigSMTPTableSuffix
SMTPConfigHTTPTable = SMTPConfigProjectionTable + "_" + smtpConfigHTTPTableSuffix SMTPConfigHTTPTable = SMTPConfigProjectionTable + "_" + smtpConfigHTTPTableSuffix
@ -146,12 +146,9 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
description := e.Description description := e.Description
state := domain.SMTPConfigStateInactive state := domain.SMTPConfigStateInactive
if e.ID == "" { if e.ID == "" {
id = e.Aggregate().ResourceOwner
description = "generic" description = "generic"
state = domain.SMTPConfigStateActive state = domain.SMTPConfigStateActive
} }
@ -165,7 +162,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner), handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID), handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID),
handler.NewCol(SMTPConfigColumnID, id), handler.NewCol(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()), handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, state), handler.NewCol(SMTPConfigColumnState, state),
handler.NewCol(SMTPConfigColumnDescription, description), handler.NewCol(SMTPConfigColumnDescription, description),
@ -174,7 +171,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
handler.AddCreateStatement( handler.AddCreateStatement(
[]handler.Column{ []handler.Column{
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID), handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigSMTPColumnID, id), handler.NewCol(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCol(SMTPConfigSMTPColumnTLS, e.TLS), handler.NewCol(SMTPConfigSMTPColumnTLS, e.TLS),
handler.NewCol(SMTPConfigSMTPColumnSenderAddress, e.SenderAddress), handler.NewCol(SMTPConfigSMTPColumnSenderAddress, e.SenderAddress),
handler.NewCol(SMTPConfigSMTPColumnSenderName, e.SenderName), handler.NewCol(SMTPConfigSMTPColumnSenderName, e.SenderName),
@ -203,7 +200,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigHTTPAdded(event eventstore.Event)
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner), handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID), handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID),
handler.NewCol(SMTPConfigColumnID, e.ID), handler.NewCol(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()), handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive), handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
handler.NewCol(SMTPConfigColumnDescription, e.Description), handler.NewCol(SMTPConfigColumnDescription, e.Description),
@ -211,8 +208,8 @@ func (p *smtpConfigProjection) reduceSMTPConfigHTTPAdded(event eventstore.Event)
), ),
handler.AddCreateStatement( handler.AddCreateStatement(
[]handler.Column{ []handler.Column{
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID), handler.NewCol(SMTPConfigHTTPColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigSMTPColumnID, e.ID), handler.NewCol(SMTPConfigHTTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCol(SMTPConfigHTTPColumnEndpoint, e.Endpoint), handler.NewCol(SMTPConfigHTTPColumnEndpoint, e.Endpoint),
}, },
handler.WithTableSuffix(smtpConfigHTTPTableSuffix), handler.WithTableSuffix(smtpConfigHTTPTableSuffix),
@ -238,7 +235,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigHTTPChanged(event eventstore.Even
stmts = append(stmts, handler.AddUpdateStatement( stmts = append(stmts, handler.AddUpdateStatement(
columns, columns,
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, e.ID), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
)) ))
@ -252,7 +249,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigHTTPChanged(event eventstore.Even
stmts = append(stmts, handler.AddUpdateStatement( stmts = append(stmts, handler.AddUpdateStatement(
smtpColumns, smtpColumns,
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigHTTPColumnID, e.ID), handler.NewCond(SMTPConfigHTTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigHTTPColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigHTTPColumnInstanceID, e.Aggregate().InstanceID),
}, },
handler.WithTableSuffix(smtpConfigHTTPTableSuffix), handler.WithTableSuffix(smtpConfigHTTPTableSuffix),
@ -268,12 +265,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
}
stmts := make([]func(eventstore.Event) handler.Exec, 0, 3) stmts := make([]func(eventstore.Event) handler.Exec, 0, 3)
columns := []handler.Column{ columns := []handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()), handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
@ -286,39 +277,39 @@ func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (
stmts = append(stmts, handler.AddUpdateStatement( stmts = append(stmts, handler.AddUpdateStatement(
columns, columns,
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
)) ))
} }
httpColumns := make([]handler.Column, 0, 7) smtpColumns := make([]handler.Column, 0, 7)
if e.TLS != nil { if e.TLS != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnTLS, *e.TLS)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnTLS, *e.TLS))
} }
if e.FromAddress != nil { if e.FromAddress != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderAddress, *e.FromAddress)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderAddress, *e.FromAddress))
} }
if e.FromName != nil { if e.FromName != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderName, *e.FromName)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderName, *e.FromName))
} }
if e.ReplyToAddress != nil { if e.ReplyToAddress != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, *e.ReplyToAddress)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, *e.ReplyToAddress))
} }
if e.Host != nil { if e.Host != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnHost, *e.Host)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnHost, *e.Host))
} }
if e.User != nil { if e.User != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnUser, *e.User)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnUser, *e.User))
} }
if e.Password != nil { if e.Password != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnPassword, *e.Password)) smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnPassword, *e.Password))
} }
if len(httpColumns) > 0 { if len(smtpColumns) > 0 {
stmts = append(stmts, handler.AddUpdateStatement( stmts = append(stmts, handler.AddUpdateStatement(
httpColumns, smtpColumns,
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigSMTPColumnID, e.ID), handler.NewCond(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
}, },
handler.WithTableSuffix(smtpConfigSMTPTableSuffix), handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
@ -334,12 +325,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
}
return handler.NewMultiStatement( return handler.NewMultiStatement(
e, e,
handler.AddUpdateStatement( handler.AddUpdateStatement(
@ -347,8 +332,8 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password), handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password),
}, },
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
}, },
handler.WithTableSuffix(smtpConfigSMTPTableSuffix), handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
), ),
@ -358,7 +343,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()), handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
}, },
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
), ),
@ -371,12 +356,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event)
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
}
return handler.NewMultiStatement( return handler.NewMultiStatement(
e, e,
handler.AddUpdateStatement( handler.AddUpdateStatement(
@ -386,7 +365,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event)
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive), handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
}, },
[]handler.Condition{ []handler.Condition{
handler.Not(handler.NewCond(SMTPConfigColumnID, e.ID)), handler.Not(handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate()))),
handler.NewCond(SMTPConfigColumnState, domain.SMTPConfigStateActive), handler.NewCond(SMTPConfigColumnState, domain.SMTPConfigStateActive),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
@ -398,7 +377,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event)
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateActive), handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateActive),
}, },
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
), ),
@ -411,12 +390,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigDeactivated(event eventstore.Even
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
}
return handler.NewUpdateStatement( return handler.NewUpdateStatement(
e, e,
[]handler.Column{ []handler.Column{
@ -425,7 +398,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigDeactivated(event eventstore.Even
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive), handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
}, },
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
), nil ), nil
@ -437,17 +410,19 @@ func (p *smtpConfigProjection) reduceSMTPConfigRemoved(event eventstore.Event) (
return nil, err return nil, err
} }
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
}
return handler.NewDeleteStatement( return handler.NewDeleteStatement(
e, e,
[]handler.Condition{ []handler.Condition{
handler.NewCond(SMTPConfigColumnID, id), handler.NewCond(SMTPConfigColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID), handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
}, },
), nil ), nil
} }
func getSMTPConfigID(id string, aggregate *eventstore.Aggregate) string {
if id != "" {
return id
}
// Deal with old and unique SMTP settings (empty ID)
return aggregate.ResourceOwner
}

View File

@ -20,6 +20,61 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
reduce func(event eventstore.Event) (*handler.Statement, error) reduce func(event eventstore.Event) (*handler.Statement, error)
want wantReduce want wantReduce
}{ }{
{
name: "reduceSMTPConfigChanged (no id)",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"description": "test",
"tls": true,
"senderAddress": "sender",
"senderName": "name",
"replyToAddress": "reply-to",
"host": "host",
"user": "user"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"test",
"ro-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs5_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
expectedArgs: []interface{}{
true,
"sender",
"name",
"reply-to",
"host",
"user",
"ro-id",
"instance-id",
},
},
},
},
},
},
{ {
name: "reduceSMTPConfigChanged", name: "reduceSMTPConfigChanged",
args: args{ args: args{
@ -50,7 +105,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -60,7 +115,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)", expectedStmt: "UPDATE projections.smtp_configs5_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
true, true,
"sender", "sender",
@ -100,7 +155,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -137,7 +192,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -146,7 +201,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4_smtp SET sender_address = $1 WHERE (id = $2) AND (instance_id = $3)", expectedStmt: "UPDATE projections.smtp_configs5_smtp SET sender_address = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"sender", "sender",
"config-id", "config-id",
@ -182,7 +237,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -192,7 +247,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)", expectedStmt: "UPDATE projections.smtp_configs5_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"endpoint", "endpoint",
"config-id", "config-id",
@ -227,7 +282,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -264,7 +319,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -273,7 +328,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)", expectedStmt: "UPDATE projections.smtp_configs5_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"endpoint", "endpoint",
"config-id", "config-id",
@ -316,7 +371,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
anyArg{}, anyArg{},
@ -330,7 +385,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedStmt: "INSERT INTO projections.smtp_configs5_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
"ro-id", "ro-id",
@ -381,7 +436,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
anyArg{}, anyArg{},
@ -395,7 +450,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedStmt: "INSERT INTO projections.smtp_configs5_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
"config-id", "config-id",
@ -437,7 +492,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
anyArg{}, anyArg{},
@ -451,7 +506,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "INSERT INTO projections.smtp_configs4_http (instance_id, id, endpoint) VALUES ($1, $2, $3)", expectedStmt: "INSERT INTO projections.smtp_configs5_http (instance_id, id, endpoint) VALUES ($1, $2, $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
"config-id", "config-id",
@ -483,7 +538,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -494,7 +549,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -507,6 +562,50 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
}, },
{
name: "reduceSMTPConfigActivated (no id)",
args: args{
event: getEvent(testEvent(
instance.SMTPConfigActivatedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id"
}`),
), eventstore.GenericEventMapper[instance.SMTPConfigActivatedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigActivated,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SMTPConfigStateInactive,
"ro-id",
domain.SMTPConfigStateActive,
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SMTPConfigStateActive,
"ro-id",
"instance-id",
},
},
},
},
},
},
{ {
name: "reduceSMTPConfigDeactivated", name: "reduceSMTPConfigDeactivated",
args: args{ args: args{
@ -528,7 +627,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -541,6 +640,39 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
}, },
{
name: "reduceSMTPConfigDeactivated (no id)",
args: args{
event: getEvent(testEvent(
instance.SMTPConfigDeactivatedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id"
}`),
), eventstore.GenericEventMapper[instance.SMTPConfigDeactivatedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigDeactivated,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SMTPConfigStateInactive,
"ro-id",
"instance-id",
},
},
},
},
},
},
{ {
name: "reduceSMTPConfigPasswordChanged", name: "reduceSMTPConfigPasswordChanged",
args: args{ args: args{
@ -568,7 +700,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.smtp_configs4_smtp SET password = $1 WHERE (id = $2) AND (instance_id = $3)", expectedStmt: "UPDATE projections.smtp_configs5_smtp SET password = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
"config-id", "config-id",
@ -576,7 +708,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
{ {
expectedStmt: "UPDATE projections.smtp_configs4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
anyArg{}, anyArg{},
uint64(15), uint64(15),
@ -609,7 +741,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "DELETE FROM projections.smtp_configs4 WHERE (id = $1) AND (instance_id = $2)", expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"config-id", "config-id",
"instance-id", "instance-id",
@ -619,6 +751,36 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
}, },
}, },
}, },
{
name: "reduceSMTPConfigRemoved (no id)",
args: args{
event: getEvent(testEvent(
instance.SMTPConfigRemovedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id"
}`),
), eventstore.GenericEventMapper[instance.SMTPConfigRemovedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigRemoved,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"ro-id",
"instance-id",
},
},
},
},
},
},
{ {
name: "instance reduceInstanceRemoved", name: "instance reduceInstanceRemoved",
args: args{ args: args{
@ -636,7 +798,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "DELETE FROM projections.smtp_configs4 WHERE (instance_id = $1)", expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (instance_id = $1)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"agg-id", "agg-id",
}, },

View File

@ -14,26 +14,26 @@ import (
) )
var ( var (
prepareSMTPConfigStmt = `SELECT projections.smtp_configs4.creation_date,` + prepareSMTPConfigStmt = `SELECT projections.smtp_configs5.creation_date,` +
` projections.smtp_configs4.change_date,` + ` projections.smtp_configs5.change_date,` +
` projections.smtp_configs4.resource_owner,` + ` projections.smtp_configs5.resource_owner,` +
` projections.smtp_configs4.sequence,` + ` projections.smtp_configs5.sequence,` +
` projections.smtp_configs4.id,` + ` projections.smtp_configs5.id,` +
` projections.smtp_configs4.state,` + ` projections.smtp_configs5.state,` +
` projections.smtp_configs4.description,` + ` projections.smtp_configs5.description,` +
` projections.smtp_configs4_smtp.id,` + ` projections.smtp_configs5_smtp.id,` +
` projections.smtp_configs4_smtp.tls,` + ` projections.smtp_configs5_smtp.tls,` +
` projections.smtp_configs4_smtp.sender_address,` + ` projections.smtp_configs5_smtp.sender_address,` +
` projections.smtp_configs4_smtp.sender_name,` + ` projections.smtp_configs5_smtp.sender_name,` +
` projections.smtp_configs4_smtp.reply_to_address,` + ` projections.smtp_configs5_smtp.reply_to_address,` +
` projections.smtp_configs4_smtp.host,` + ` projections.smtp_configs5_smtp.host,` +
` projections.smtp_configs4_smtp.username,` + ` projections.smtp_configs5_smtp.username,` +
` projections.smtp_configs4_smtp.password,` + ` projections.smtp_configs5_smtp.password,` +
` projections.smtp_configs4_http.id,` + ` projections.smtp_configs5_http.id,` +
` projections.smtp_configs4_http.endpoint` + ` projections.smtp_configs5_http.endpoint` +
` FROM projections.smtp_configs4` + ` FROM projections.smtp_configs5` +
` LEFT JOIN projections.smtp_configs4_smtp ON projections.smtp_configs4.id = projections.smtp_configs4_smtp.id AND projections.smtp_configs4.instance_id = projections.smtp_configs4_smtp.instance_id` + ` LEFT JOIN projections.smtp_configs5_smtp ON projections.smtp_configs5.id = projections.smtp_configs5_smtp.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_smtp.instance_id` +
` LEFT JOIN projections.smtp_configs4_http ON projections.smtp_configs4.id = projections.smtp_configs4_http.id AND projections.smtp_configs4.instance_id = projections.smtp_configs4_http.instance_id` + ` LEFT JOIN projections.smtp_configs5_http ON projections.smtp_configs5.id = projections.smtp_configs5_http.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_http.instance_id` +
` AS OF SYSTEM TIME '-1 ms'` ` AS OF SYSTEM TIME '-1 ms'`
prepareSMTPConfigCols = []string{ prepareSMTPConfigCols = []string{
"creation_date", "creation_date",