feat: add http as smtp provider (#8545)

# Which Problems Are Solved

Send Email messages as a HTTP call to a relay, for own logic on handling
different Email providers

# How the Problems Are Solved

Create endpoints under Email provider to manage SMTP and HTTP in the
notification handlers.

# Additional Changes

Clean up old logic in command and query side to handle the general Email
providers with deactivate, activate and remove.

# Additional Context

Partially closes #8270

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz
2024-09-12 06:27:29 +02:00
committed by GitHub
parent d8a71d217c
commit 21c38b061d
28 changed files with 3575 additions and 1152 deletions

View File

@@ -8,26 +8,38 @@ import (
old_handler "github.com/zitadel/zitadel/internal/eventstore/handler"
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
"github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/zerrors"
)
const (
SMTPConfigProjectionTable = "projections.smtp_configs2"
SMTPConfigColumnInstanceID = "instance_id"
SMTPConfigColumnResourceOwner = "resource_owner"
SMTPConfigColumnID = "id"
SMTPConfigColumnCreationDate = "creation_date"
SMTPConfigColumnChangeDate = "change_date"
SMTPConfigColumnSequence = "sequence"
SMTPConfigColumnTLS = "tls"
SMTPConfigColumnSenderAddress = "sender_address"
SMTPConfigColumnSenderName = "sender_name"
SMTPConfigColumnReplyToAddress = "reply_to_address"
SMTPConfigColumnSMTPHost = "host"
SMTPConfigColumnSMTPUser = "username"
SMTPConfigColumnSMTPPassword = "password"
SMTPConfigColumnState = "state"
SMTPConfigColumnDescription = "description"
SMTPConfigProjectionTable = "projections.smtp_configs3"
SMTPConfigTable = SMTPConfigProjectionTable + "_" + smtpConfigSMTPTableSuffix
SMTPConfigHTTPTable = SMTPConfigProjectionTable + "_" + smtpConfigHTTPTableSuffix
SMTPConfigColumnInstanceID = "instance_id"
SMTPConfigColumnResourceOwner = "resource_owner"
SMTPConfigColumnAggregateID = "aggregate_id"
SMTPConfigColumnID = "id"
SMTPConfigColumnCreationDate = "creation_date"
SMTPConfigColumnChangeDate = "change_date"
SMTPConfigColumnSequence = "sequence"
SMTPConfigColumnState = "state"
SMTPConfigColumnDescription = "description"
smtpConfigSMTPTableSuffix = "smtp"
SMTPConfigSMTPColumnInstanceID = "instance_id"
SMTPConfigSMTPColumnID = "id"
SMTPConfigSMTPColumnTLS = "tls"
SMTPConfigSMTPColumnSenderAddress = "sender_address"
SMTPConfigSMTPColumnSenderName = "sender_name"
SMTPConfigSMTPColumnReplyToAddress = "reply_to_address"
SMTPConfigSMTPColumnHost = "host"
SMTPConfigSMTPColumnUser = "username"
SMTPConfigSMTPColumnPassword = "password"
smtpConfigHTTPTableSuffix = "http"
SMTPConfigHTTPColumnInstanceID = "instance_id"
SMTPConfigHTTPColumnID = "id"
SMTPConfigHTTPColumnEndpoint = "endpoint"
)
type smtpConfigProjection struct{}
@@ -41,25 +53,43 @@ func (*smtpConfigProjection) Name() string {
}
func (*smtpConfigProjection) Init() *old_handler.Check {
return handler.NewTableCheck(
return handler.NewMultiTableCheck(
handler.NewTable([]*handler.InitColumn{
handler.NewColumn(SMTPConfigColumnID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnAggregateID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnCreationDate, handler.ColumnTypeTimestamp),
handler.NewColumn(SMTPConfigColumnChangeDate, handler.ColumnTypeTimestamp),
handler.NewColumn(SMTPConfigColumnSequence, handler.ColumnTypeInt64),
handler.NewColumn(SMTPConfigColumnResourceOwner, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnInstanceID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnTLS, handler.ColumnTypeBool),
handler.NewColumn(SMTPConfigColumnSenderAddress, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnSenderName, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnReplyToAddress, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnSMTPHost, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnSMTPUser, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnSMTPPassword, handler.ColumnTypeJSONB, handler.Nullable()),
handler.NewColumn(SMTPConfigColumnState, handler.ColumnTypeEnum),
handler.NewColumn(SMTPConfigColumnDescription, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigColumnState, handler.ColumnTypeEnum),
},
handler.NewPrimaryKey(SMTPConfigColumnInstanceID, SMTPConfigColumnResourceOwner, SMTPConfigColumnID),
handler.NewPrimaryKey(SMTPConfigColumnInstanceID, SMTPConfigColumnID),
),
handler.NewSuffixedTable([]*handler.InitColumn{
handler.NewColumn(SMTPConfigSMTPColumnID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnInstanceID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnTLS, handler.ColumnTypeBool),
handler.NewColumn(SMTPConfigSMTPColumnSenderAddress, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnSenderName, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnReplyToAddress, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnHost, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnUser, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigSMTPColumnPassword, handler.ColumnTypeJSONB, handler.Nullable()),
},
handler.NewPrimaryKey(SMTPConfigSMTPColumnInstanceID, SMTPConfigSMTPColumnID),
smtpConfigSMTPTableSuffix,
handler.WithForeignKey(handler.NewForeignKeyOfPublicKeys()),
),
handler.NewSuffixedTable([]*handler.InitColumn{
handler.NewColumn(SMTPConfigHTTPColumnID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigHTTPColumnInstanceID, handler.ColumnTypeText),
handler.NewColumn(SMTPConfigHTTPColumnEndpoint, handler.ColumnTypeText),
},
handler.NewPrimaryKey(SMTPConfigHTTPColumnInstanceID, SMTPConfigHTTPColumnID),
smtpConfigHTTPTableSuffix,
handler.WithForeignKey(handler.NewForeignKeyOfPublicKeys()),
),
)
}
@@ -81,6 +111,14 @@ func (p *smtpConfigProjection) Reducers() []handler.AggregateReducer {
Event: instance.SMTPConfigPasswordChangedEventType,
Reduce: p.reduceSMTPConfigPasswordChanged,
},
{
Event: instance.SMTPConfigHTTPAddedEventType,
Reduce: p.reduceSMTPConfigHTTPAdded,
},
{
Event: instance.SMTPConfigHTTPChangedEventType,
Reduce: p.reduceSMTPConfigHTTPChanged,
},
{
Event: instance.SMTPConfigActivatedEventType,
Reduce: p.reduceSMTPConfigActivated,
@@ -103,9 +141,9 @@ func (p *smtpConfigProjection) Reducers() []handler.AggregateReducer {
}
func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SMTPConfigAddedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-sk99F", "reduce.wrong.event.type %s", instance.SMTPConfigAddedEventType)
e, err := assertEvent[*instance.SMTPConfigAddedEvent](event)
if err != nil {
return nil, err
}
// Deal with old and unique SMTP settings (empty ID)
@@ -118,83 +156,116 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
state = domain.SMTPConfigStateActive
}
return handler.NewCreateStatement(
return handler.NewMultiStatement(
e,
[]handler.Column{
handler.NewCol(SMTPConfigColumnCreationDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnID, id),
handler.NewCol(SMTPConfigColumnTLS, e.TLS),
handler.NewCol(SMTPConfigColumnSenderAddress, e.SenderAddress),
handler.NewCol(SMTPConfigColumnSenderName, e.SenderName),
handler.NewCol(SMTPConfigColumnReplyToAddress, e.ReplyToAddress),
handler.NewCol(SMTPConfigColumnSMTPHost, e.Host),
handler.NewCol(SMTPConfigColumnSMTPUser, e.User),
handler.NewCol(SMTPConfigColumnSMTPPassword, e.Password),
handler.NewCol(SMTPConfigColumnState, state),
handler.NewCol(SMTPConfigColumnDescription, description),
},
handler.AddCreateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigColumnCreationDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID),
handler.NewCol(SMTPConfigColumnID, id),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, state),
handler.NewCol(SMTPConfigColumnDescription, description),
},
),
handler.AddCreateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigSMTPColumnID, e.ID),
handler.NewCol(SMTPConfigSMTPColumnTLS, e.TLS),
handler.NewCol(SMTPConfigSMTPColumnSenderAddress, e.SenderAddress),
handler.NewCol(SMTPConfigSMTPColumnSenderName, e.SenderName),
handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, e.ReplyToAddress),
handler.NewCol(SMTPConfigSMTPColumnHost, e.Host),
handler.NewCol(SMTPConfigSMTPColumnUser, e.User),
handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password),
},
handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
),
), nil
}
func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SMTPConfigChangedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-wl0wd", "reduce.wrong.event.type %s", instance.SMTPConfigChangedEventType)
func (p *smtpConfigProjection) reduceSMTPConfigHTTPAdded(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*instance.SMTPConfigHTTPAddedEvent](event)
if err != nil {
return nil, err
}
columns := make([]handler.Column, 0, 8)
columns = append(columns, handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()))
return handler.NewMultiStatement(
e,
handler.AddCreateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigColumnCreationDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCol(SMTPConfigColumnAggregateID, e.Aggregate().ID),
handler.NewCol(SMTPConfigColumnID, e.ID),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
handler.NewCol(SMTPConfigColumnDescription, e.Description),
},
),
handler.AddCreateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
handler.NewCol(SMTPConfigSMTPColumnID, e.ID),
handler.NewCol(SMTPConfigHTTPColumnEndpoint, e.Endpoint),
},
handler.WithTableSuffix(smtpConfigHTTPTableSuffix),
),
), nil
}
// Deal with old and unique SMTP settings (empty ID)
id := e.ID
if e.ID == "" {
id = e.Aggregate().ResourceOwner
func (p *smtpConfigProjection) reduceSMTPConfigHTTPChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*instance.SMTPConfigHTTPChangedEvent](event)
if err != nil {
return nil, err
}
if e.TLS != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnTLS, *e.TLS))
}
if e.FromAddress != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnSenderAddress, *e.FromAddress))
}
if e.FromName != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnSenderName, *e.FromName))
}
if e.ReplyToAddress != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnReplyToAddress, *e.ReplyToAddress))
}
if e.Host != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnSMTPHost, *e.Host))
}
if e.User != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnSMTPUser, *e.User))
}
if e.Password != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnSMTPPassword, *e.Password))
stmts := make([]func(eventstore.Event) handler.Exec, 0, 3)
columns := []handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
}
if e.Description != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnDescription, *e.Description))
}
return handler.NewUpdateStatement(
e,
columns,
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
), nil
if len(columns) > 0 {
stmts = append(stmts, handler.AddUpdateStatement(
columns,
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, e.ID),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
))
}
smtpColumns := make([]handler.Column, 0, 1)
if e.Endpoint != nil {
smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigHTTPColumnEndpoint, *e.Endpoint))
}
if len(smtpColumns) > 0 {
stmts = append(stmts, handler.AddUpdateStatement(
smtpColumns,
[]handler.Condition{
handler.NewCond(SMTPConfigHTTPColumnID, e.ID),
handler.NewCond(SMTPConfigHTTPColumnInstanceID, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(smtpConfigHTTPTableSuffix),
))
}
return handler.NewMultiStatement(e, stmts...), nil
}
func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SMTPConfigPasswordChangedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-fk02f", "reduce.wrong.event.type %s", instance.SMTPConfigChangedEventType)
func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*instance.SMTPConfigChangedEvent](event)
if err != nil {
return nil, err
}
// Deal with old and unique SMTP settings (empty ID)
@@ -203,25 +274,101 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
id = e.Aggregate().ResourceOwner
}
return handler.NewUpdateStatement(
stmts := make([]func(eventstore.Event) handler.Exec, 0, 3)
columns := []handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
}
if e.Description != nil {
columns = append(columns, handler.NewCol(SMTPConfigColumnDescription, *e.Description))
}
if len(columns) > 0 {
stmts = append(stmts, handler.AddUpdateStatement(
columns,
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
))
}
httpColumns := make([]handler.Column, 0, 7)
if e.TLS != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnTLS, *e.TLS))
}
if e.FromAddress != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderAddress, *e.FromAddress))
}
if e.FromName != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnSenderName, *e.FromName))
}
if e.ReplyToAddress != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, *e.ReplyToAddress))
}
if e.Host != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnHost, *e.Host))
}
if e.User != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnUser, *e.User))
}
if e.Password != nil {
httpColumns = append(httpColumns, handler.NewCol(SMTPConfigSMTPColumnPassword, *e.Password))
}
if len(httpColumns) > 0 {
stmts = append(stmts, handler.AddUpdateStatement(
httpColumns,
[]handler.Condition{
handler.NewCond(SMTPConfigSMTPColumnID, e.ID),
handler.NewCond(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
))
}
return handler.NewMultiStatement(e, stmts...), nil
}
func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.Event) (*handler.Statement, error) {
e, err := assertEvent[*instance.SMTPConfigPasswordChangedEvent](event)
if err != nil {
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(
e,
[]handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnSMTPPassword, e.Password),
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password),
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
),
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
),
), nil
}
func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SMTPConfigActivatedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-fq92r", "reduce.wrong.event.type %s", instance.SMTPConfigActivatedEventType)
e, err := assertEvent[*instance.SMTPConfigActivatedEvent](event)
if err != nil {
return nil, err
}
// Deal with old and unique SMTP settings (empty ID)
@@ -230,25 +377,38 @@ func (p *smtpConfigProjection) reduceSMTPConfigActivated(event eventstore.Event)
id = e.Aggregate().ResourceOwner
}
return handler.NewUpdateStatement(
return handler.NewMultiStatement(
e,
[]handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateActive),
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateInactive),
},
[]handler.Condition{
handler.Not(handler.NewCond(SMTPConfigColumnID, e.ID)),
handler.NewCond(SMTPConfigColumnState, domain.SMTPConfigStateActive),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
),
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(SMTPConfigColumnChangeDate, e.CreationDate()),
handler.NewCol(SMTPConfigColumnSequence, e.Sequence()),
handler.NewCol(SMTPConfigColumnState, domain.SMTPConfigStateActive),
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
),
), nil
}
func (p *smtpConfigProjection) reduceSMTPConfigDeactivated(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SMTPConfigDeactivatedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-hv89j", "reduce.wrong.event.type %s", instance.SMTPConfigDeactivatedEventType)
e, err := assertEvent[*instance.SMTPConfigDeactivatedEvent](event)
if err != nil {
return nil, err
}
// Deal with old and unique SMTP settings (empty ID)
@@ -266,7 +426,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigDeactivated(event eventstore.Even
},
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
), nil
@@ -288,7 +447,6 @@ func (p *smtpConfigProjection) reduceSMTPConfigRemoved(event eventstore.Event) (
e,
[]handler.Condition{
handler.NewCond(SMTPConfigColumnID, id),
handler.NewCond(SMTPConfigColumnResourceOwner, e.Aggregate().ResourceOwner),
handler.NewCond(SMTPConfigColumnInstanceID, e.Aggregate().InstanceID),
},
), nil

View File

@@ -28,19 +28,20 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
instance.SMTPConfigChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test",
"tls": true,
"senderAddress": "sender",
"senderName": "name",
"replyToAddress": "reply-to",
"host": "host",
"user": "user",
"id": "44444",
"resource_owner": "ro-id",
"instance_id": "instance-id"
"user": "user"
}`,
),
), instance.SMTPConfigChangedEventMapper),
), eventstore.GenericEventMapper[instance.SMTPConfigChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigChanged,
want: wantReduce{
@@ -49,19 +50,233 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, tls, sender_address, sender_name, reply_to_address, host, username, description) = ($1, $2, $3, $4, $5, $6, $7, $8, $9) WHERE (id = $10) AND (resource_owner = $11) AND (instance_id = $12)",
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"test",
"config-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3_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",
"config-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceSMTPConfigChanged, description",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"test",
"44444",
"ro-id",
"config-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceSMTPConfigChanged, senderAddress",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"senderAddress": "sender"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"config-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3_smtp SET sender_address = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"sender",
"config-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceSMTPConfigHTTPChanged",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigHTTPChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test",
"endpoint": "endpoint"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigHTTPChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigHTTPChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"test",
"config-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"endpoint",
"config-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceSMTPConfigHTTPChanged, description",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigHTTPChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigHTTPChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigHTTPChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"test",
"config-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceSMTPConfigHTTPChanged, endpoint",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigHTTPChangedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"endpoint": "endpoint"
}`,
),
), eventstore.GenericEventMapper[instance.SMTPConfigHTTPChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigHTTPChanged,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"config-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"endpoint",
"config-id",
"instance-id",
},
},
@@ -77,9 +292,12 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
instance.SMTPConfigAddedEventType,
instance.AggregateType,
[]byte(`{
"tls": true,
"id": "id",
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test",
"tls": true,
"senderAddress": "sender",
"senderName": "name",
"replyToAddress": "reply-to",
@@ -91,7 +309,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
"keyId": "key-id"
}
}`),
), instance.SMTPConfigAddedEventMapper),
), eventstore.GenericEventMapper[instance.SMTPConfigAddedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigAdded,
want: wantReduce{
@@ -100,14 +318,24 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.smtp_configs2 (creation_date, change_date, resource_owner, instance_id, sequence, id, tls, sender_address, sender_name, reply_to_address, host, username, password, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)",
expectedStmt: "INSERT INTO projections.smtp_configs3 (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{}{
anyArg{},
anyArg{},
"ro-id",
"instance-id",
"ro-id",
"agg-id",
"config-id",
uint64(15),
"id",
domain.SMTPConfigStateInactive,
"test",
},
},
{
expectedStmt: "INSERT INTO projections.smtp_configs3_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{}{
"instance-id",
"config-id",
true,
"sender",
"name",
@@ -115,10 +343,58 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
"host",
"user",
anyArg{},
domain.SMTPConfigState(3),
},
},
},
},
},
},
{
name: "reduceSMTPConfigHTTPAdded",
args: args{
event: getEvent(
testEvent(
instance.SMTPConfigHTTPAddedEventType,
instance.AggregateType,
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"description": "test",
"senderAddress": "sender",
"endpoint": "endpoint"
}`),
), eventstore.GenericEventMapper[instance.SMTPConfigHTTPAddedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigHTTPAdded,
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.smtp_configs3 (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{}{
anyArg{},
anyArg{},
"instance-id",
"ro-id",
"agg-id",
"config-id",
uint64(15),
domain.SMTPConfigStateInactive,
"test",
},
},
{
expectedStmt: "INSERT INTO projections.smtp_configs3_http (instance_id, id, endpoint) VALUES ($1, $2, $3)",
expectedArgs: []interface{}{
"instance-id",
"config-id",
"endpoint",
},
},
},
},
},
@@ -130,9 +406,12 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
instance.SMTPConfigActivatedEventType,
instance.AggregateType,
[]byte(`{
"id": "config-id"
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id"
}`),
), instance.SMTPConfigActivatedEventMapper),
), eventstore.GenericEventMapper[instance.SMTPConfigActivatedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigActivated,
want: wantReduce{
@@ -141,13 +420,23 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.smtp_configs3 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,
"config-id",
domain.SMTPConfigStateActive,
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SMTPConfigStateActive,
"config-id",
"ro-id",
"instance-id",
},
},
@@ -162,9 +451,12 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
instance.SMTPConfigDeactivatedEventType,
instance.AggregateType,
[]byte(`{
"id": "config-id"
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id"
}`),
), instance.SMTPConfigDeactivatedEventMapper),
), eventstore.GenericEventMapper[instance.SMTPConfigDeactivatedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigDeactivated,
want: wantReduce{
@@ -173,13 +465,12 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SMTPConfigStateInactive,
"config-id",
"ro-id",
"instance-id",
},
},
@@ -195,14 +486,17 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
instance.SMTPConfigPasswordChangedEventType,
instance.AggregateType,
[]byte(`{
"id": "config-id",
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id",
"password": {
"cryptoType": 0,
"algorithm": "RSA-265",
"keyId": "key-id"
}
}`),
), instance.SMTPConfigPasswordChangedEventMapper),
), eventstore.GenericEventMapper[instance.SMTPConfigPasswordChangedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigPasswordChanged,
want: wantReduce{
@@ -211,13 +505,19 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.smtp_configs2 SET (change_date, sequence, password) = ($1, $2, $3) WHERE (id = $4) AND (resource_owner = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.smtp_configs3_smtp SET password = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
anyArg{},
"config-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.smtp_configs3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
anyArg{},
"config-id",
"ro-id",
"instance-id",
},
},
@@ -231,8 +531,13 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
event: getEvent(testEvent(
instance.SMTPConfigRemovedEventType,
instance.AggregateType,
[]byte(`{ "id": "config-id"}`),
), instance.SMTPConfigRemovedEventMapper),
[]byte(`{
"instance_id": "instance-id",
"resource_owner": "ro-id",
"aggregate_id": "agg-id",
"id": "config-id"
}`),
), eventstore.GenericEventMapper[instance.SMTPConfigRemovedEvent]),
},
reduce: (&smtpConfigProjection{}).reduceSMTPConfigRemoved,
want: wantReduce{
@@ -241,10 +546,9 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.smtp_configs2 WHERE (id = $1) AND (resource_owner = $2) AND (instance_id = $3)",
expectedStmt: "DELETE FROM projections.smtp_configs3 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"config-id",
"ro-id",
"instance-id",
},
},
@@ -269,7 +573,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.smtp_configs2 WHERE (instance_id = $1)",
expectedStmt: "DELETE FROM projections.smtp_configs3 WHERE (instance_id = $1)",
expectedArgs: []interface{}{
"agg-id",
},