From 024eedc1b586815a3433c7e605175c482143eb5e Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 13 May 2022 14:13:07 +0200 Subject: [PATCH] feat: enable default smtp config on setup (#3622) * feat: enable default smtp config on setup * fix tests * fix channel order Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> --- cmd/admin/setup/03.go | 12 +- cmd/admin/setup/config.go | 1 + cmd/admin/setup/setup.go | 1 + internal/api/grpc/admin/iam_settings.go | 4 +- internal/command/instance.go | 20 +- .../instance_secret_generator_model.go | 2 +- internal/command/smtp.go | 213 +++++++++++------- internal/command/smtp_test.go | 132 ++++++----- .../notification/channels/smtp/channel.go | 1 + .../eventsourcing/handler/notification.go | 1 + internal/notification/senders/debug.go | 4 +- internal/notification/senders/email.go | 13 +- internal/notification/senders/sms.go | 11 +- internal/query/projection/smtp.go | 3 +- internal/repository/instance/smtp_config.go | 2 +- 15 files changed, 261 insertions(+), 159 deletions(-) diff --git a/cmd/admin/setup/03.go b/cmd/admin/setup/03.go index 36a0fcbc27..deefc7a445 100644 --- a/cmd/admin/setup/03.go +++ b/cmd/admin/setup/03.go @@ -24,6 +24,7 @@ type DefaultInstance struct { instanceSetup command.InstanceSetup userEncryptionKey *crypto.KeyConfig + smtpEncryptionKey *crypto.KeyConfig masterKey string db *sql.DB es *eventstore.Eventstore @@ -42,12 +43,19 @@ func (mig *DefaultInstance) Execute(ctx context.Context) error { if err = verifyKey(mig.userEncryptionKey, keyStorage); err != nil { return err } - userAlg, err := crypto.NewAESCrypto(mig.userEncryptionKey, keyStorage) if err != nil { return err } + if err = verifyKey(mig.smtpEncryptionKey, keyStorage); err != nil { + return err + } + smtpEncryption, err := crypto.NewAESCrypto(mig.smtpEncryptionKey, keyStorage) + if err != nil { + return err + } + cmd, err := command.StartCommands(mig.es, mig.defaults, mig.zitadelRoles, @@ -58,7 +66,7 @@ func (mig *DefaultInstance) Execute(ctx context.Context) error { mig.externalPort, nil, nil, - nil, + smtpEncryption, nil, userAlg, nil, diff --git a/cmd/admin/setup/config.go b/cmd/admin/setup/config.go index cffcc842bf..f5bc602d57 100644 --- a/cmd/admin/setup/config.go +++ b/cmd/admin/setup/config.go @@ -53,6 +53,7 @@ type Steps struct { type encryptionKeyConfig struct { User *crypto.KeyConfig + SMTP *crypto.KeyConfig } func MustNewSteps(v *viper.Viper) *Steps { diff --git a/cmd/admin/setup/setup.go b/cmd/admin/setup/setup.go index 28e6224b8b..80721c39ef 100644 --- a/cmd/admin/setup/setup.go +++ b/cmd/admin/setup/setup.go @@ -61,6 +61,7 @@ func Setup(config *Config, steps *Steps, masterKey string) { steps.S3DefaultInstance.instanceSetup = config.DefaultInstance steps.S3DefaultInstance.userEncryptionKey = config.EncryptionKeys.User + steps.S3DefaultInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP steps.S3DefaultInstance.masterKey = masterKey steps.S3DefaultInstance.db = dbClient steps.S3DefaultInstance.es = eventstoreClient diff --git a/internal/api/grpc/admin/iam_settings.go b/internal/api/grpc/admin/iam_settings.go index c583a7e26e..c5ea8602bd 100644 --- a/internal/api/grpc/admin/iam_settings.go +++ b/internal/api/grpc/admin/iam_settings.go @@ -56,7 +56,7 @@ func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigR } func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) { - details, err := s.command.ChangeSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), UpdateSMTPToConfig(req)) + details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req)) if err != nil { return nil, err } @@ -69,7 +69,7 @@ func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPC } func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) { - details, err := s.command.ChangeSMTPConfigPassword(ctx, authz.GetInstance(ctx).InstanceID(), req.Password) + details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password) if err != nil { return nil, err } diff --git a/internal/command/instance.go b/internal/command/instance.go index 6adcfd8860..2f172450bb 100644 --- a/internal/command/instance.go +++ b/internal/command/instance.go @@ -14,6 +14,7 @@ import ( "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/id" + "github.com/zitadel/zitadel/internal/notification/channels/smtp" "github.com/zitadel/zitadel/internal/repository/instance" "github.com/zitadel/zitadel/internal/repository/org" "github.com/zitadel/zitadel/internal/repository/project" @@ -96,8 +97,9 @@ type InstanceSetup struct { MaxAttempts uint64 ShouldShowLockoutFailure bool } - EmailTemplate []byte - MessageTexts []*domain.CustomMessageText + EmailTemplate []byte + MessageTexts []*domain.CustomMessageText + SMTPConfiguration *smtp.EmailConfig } type ZitadelConfig struct { @@ -261,6 +263,20 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str ClockSkew: 0, } + if setup.SMTPConfiguration != nil { + validations = append(validations, + c.prepareAddSMTPConfig( + instanceAgg, + setup.SMTPConfiguration.From, + setup.SMTPConfiguration.FromName, + setup.SMTPConfiguration.SMTP.Host, + setup.SMTPConfiguration.SMTP.User, + []byte(setup.SMTPConfiguration.SMTP.Password), + setup.SMTPConfiguration.Tls, + ), + ) + } + validations = append(validations, AddOrgCommand(ctx, orgAgg, setup.Org.Name), AddHumanCommand(userAgg, &setup.Org.Human, c.userPasswordAlg, c.userEncryption), diff --git a/internal/command/instance_secret_generator_model.go b/internal/command/instance_secret_generator_model.go index 474841da0e..b4122edb50 100644 --- a/internal/command/instance_secret_generator_model.go +++ b/internal/command/instance_secret_generator_model.go @@ -45,7 +45,7 @@ func (wm *InstanceSecretGeneratorConfigWriteModel) Reduce() error { wm.IncludeLowerLetters = e.IncludeLowerLetters wm.IncludeUpperLetters = e.IncludeUpperLetters wm.IncludeDigits = e.IncludeDigits - wm.IncludeSymbols = e.IncludeDigits + wm.IncludeSymbols = e.IncludeSymbols wm.State = domain.SecretGeneratorStateActive case *instance.SecretGeneratorChangedEvent: if wm.GeneratorType != e.GeneratorType { diff --git a/internal/command/smtp.go b/internal/command/smtp.go index d80a989f3d..07720d630a 100644 --- a/internal/command/smtp.go +++ b/internal/command/smtp.go @@ -2,118 +2,169 @@ package command import ( "context" + "strings" + "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/command/preparation" "github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/domain" + "github.com/zitadel/zitadel/internal/errors" caos_errs "github.com/zitadel/zitadel/internal/errors" + "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/notification/channels/smtp" "github.com/zitadel/zitadel/internal/repository/instance" ) -func (c *Commands) AddSMTPConfig(ctx context.Context, instanceID string, config *smtp.EmailConfig) (*domain.ObjectDetails, error) { - smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID) +func (c *Commands) AddSMTPConfig(ctx context.Context, config *smtp.EmailConfig) (*domain.ObjectDetails, error) { + instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID()) + validation := c.prepareAddSMTPConfig(instanceAgg, config.From, config.FromName, config.SMTP.Host, config.SMTP.User, []byte(config.SMTP.Password), config.Tls) + cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation) if err != nil { return nil, err } - if smtpConfigWriteModel.State == domain.SMTPConfigStateActive { - return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-en9lw", "Errors.SMTPConfig.AlreadyExists") + events, err := c.eventstore.Push(ctx, cmds...) + if err != nil { + return nil, err + } + return &domain.ObjectDetails{ + Sequence: events[len(events)-1].Sequence(), + EventDate: events[len(events)-1].CreationDate(), + ResourceOwner: events[len(events)-1].Aggregate().InstanceID, + }, nil +} + +func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *smtp.EmailConfig) (*domain.ObjectDetails, error) { + instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID()) + validation := c.prepareChangeSMTPConfig(instanceAgg, config.From, config.FromName, config.SMTP.Host, config.SMTP.User, config.Tls) + cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation) + if err != nil { + return nil, err + } + events, err := c.eventstore.Push(ctx, cmds...) + if err != nil { + return nil, err + } + return &domain.ObjectDetails{ + Sequence: events[len(events)-1].Sequence(), + EventDate: events[len(events)-1].CreationDate(), + ResourceOwner: events[len(events)-1].Aggregate().InstanceID, + }, nil +} + +func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string) (*domain.ObjectDetails, error) { + instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID()) + smtpConfigWriteModel, err := getSMTPConfigWriteModel(ctx, c.eventstore.Filter) + if err != nil { + return nil, err + } + if smtpConfigWriteModel.State != domain.SMTPConfigStateActive { + return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound") } var smtpPassword *crypto.CryptoValue - if config.SMTP.Password != "" { - smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpEncryption) + if password != "" { + smtpPassword, err = crypto.Encrypt([]byte(password), c.smtpEncryption) if err != nil { return nil, err } } - - iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel) - pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigAddedEvent( + events, err := c.eventstore.Push(ctx, instance.NewSMTPConfigPasswordChangedEvent( ctx, - iamAgg, - config.Tls, - config.From, - config.FromName, - config.SMTP.Host, - config.SMTP.User, + &instanceAgg.Aggregate, smtpPassword)) if err != nil { return nil, err } - err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...) - if err != nil { - return nil, err - } - return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil + return &domain.ObjectDetails{ + Sequence: events[len(events)-1].Sequence(), + EventDate: events[len(events)-1].CreationDate(), + ResourceOwner: events[len(events)-1].Aggregate().InstanceID, + }, nil } -func (c *Commands) ChangeSMTPConfig(ctx context.Context, instanceID string, config *smtp.EmailConfig) (*domain.ObjectDetails, error) { - smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID) - if err != nil { - return nil, err +func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, host, user string, password []byte, tls bool) preparation.Validation { + return func() (preparation.CreateCommands, error) { + if from = strings.TrimSpace(from); from == "" { + return nil, errors.ThrowInvalidArgument(nil, "INST-mruNY", "Errors.Invalid.Argument") + } + if host = strings.TrimSpace(host); host == "" { + return nil, errors.ThrowInvalidArgument(nil, "INST-SF3g1", "Errors.Invalid.Argument") + } + return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) { + writeModel, err := getSMTPConfigWriteModel(ctx, filter) + if err != nil { + return nil, err + } + if writeModel.State == domain.SMTPConfigStateActive { + return nil, errors.ThrowAlreadyExists(nil, "INST-W3VS2", "Errors.SMTPConfig.AlreadyExists") + } + var smtpPassword *crypto.CryptoValue + if password != nil { + smtpPassword, err = crypto.Encrypt(password, c.smtpEncryption) + if err != nil { + return nil, err + } + } + return []eventstore.Command{ + instance.NewSMTPConfigAddedEvent( + ctx, + &a.Aggregate, + tls, + from, + name, + host, + user, + smtpPassword, + ), + }, nil + }, nil } - if smtpConfigWriteModel.State == domain.SMTPConfigStateUnspecified { - return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound") - } - iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel) - - changedEvent, hasChanged, err := smtpConfigWriteModel.NewChangedEvent( - ctx, - iamAgg, - config.Tls, - config.From, - config.FromName, - config.SMTP.Host, - config.SMTP.User) - if err != nil { - return nil, err - } - if !hasChanged { - return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-m0o3f", "Errors.NoChangesFound") - } - pushedEvents, err := c.eventstore.Push(ctx, changedEvent) - if err != nil { - return nil, err - } - err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...) - if err != nil { - return nil, err - } - return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil } -func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, instanceID, password string) (*domain.ObjectDetails, error) { - smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID) - if err != nil { - return nil, err +func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, host, user string, tls bool) preparation.Validation { + return func() (preparation.CreateCommands, error) { + if from = strings.TrimSpace(from); from == "" { + return nil, errors.ThrowInvalidArgument(nil, "INST-ASv2d", "Errors.Invalid.Argument") + } + if host = strings.TrimSpace(host); host == "" { + return nil, errors.ThrowInvalidArgument(nil, "INST-VDwvq", "Errors.Invalid.Argument") + } + return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) { + writeModel, err := getSMTPConfigWriteModel(ctx, filter) + if err != nil { + return nil, err + } + if writeModel.State != domain.SMTPConfigStateActive { + return nil, errors.ThrowNotFound(nil, "INST-Svq1a", "Errors.SMTPConfig.NotFound") + } + changedEvent, hasChanged, err := writeModel.NewChangedEvent( + ctx, + &a.Aggregate, + tls, + from, + name, + host, + user, + ) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-m0o3f", "Errors.NoChangesFound") + } + return []eventstore.Command{ + changedEvent, + }, nil + }, nil } - if smtpConfigWriteModel.State == domain.SMTPConfigStateUnspecified { - return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound") - } - iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel) - newPW, err := crypto.Encrypt([]byte(password), c.smtpEncryption) - if err != nil { - return nil, err - } - pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigPasswordChangedEvent( - ctx, - iamAgg, - newPW)) - if err != nil { - return nil, err - } - err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...) - if err != nil { - return nil, err - } - return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil } -func (c *Commands) getSMTPConfig(ctx context.Context, instanceID string) (_ *InstanceSMTPConfigWriteModel, err error) { - writeModel := NewInstanceSMTPConfigWriteModel(instanceID) - err = c.eventstore.FilterToQueryReducer(ctx, writeModel) +func getSMTPConfigWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer) (_ *InstanceSMTPConfigWriteModel, err error) { + writeModel := NewInstanceSMTPConfigWriteModel(authz.GetInstance(ctx).InstanceID()) + events, err := filter(ctx, writeModel.Query()) if err != nil { return nil, err } - - return writeModel, nil + if len(events) == 0 { + return writeModel, nil + } + writeModel.AppendEvents(events...) + err = writeModel.Reduce() + return writeModel, err } diff --git a/internal/command/smtp_test.go b/internal/command/smtp_test.go index cce72ee58e..f0766e8cad 100644 --- a/internal/command/smtp_test.go +++ b/internal/command/smtp_test.go @@ -7,6 +7,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + "github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/domain" caos_errs "github.com/zitadel/zitadel/internal/errors" @@ -22,9 +23,8 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { alg crypto.EncryptionAlgorithm } type args struct { - ctx context.Context - instanceID string - smtp *smtp.EmailConfig + ctx context.Context + smtp *smtp.EmailConfig } type res struct { want *domain.ObjectDetails @@ -57,10 +57,16 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { ), }, args: args{ - ctx: context.Background(), - instanceID: "INSTANCE", + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ - Tls: true, + Tls: true, + From: "from", + FromName: "name", + SMTP: smtp.SMTP{ + Host: "host", + User: "user", + Password: "password", + }, }, }, res: res{ @@ -75,21 +81,23 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { expectFilter(), expectPush( []*repository.Event{ - eventFromEventPusher(instance.NewSMTPConfigAddedEvent( - context.Background(), - &instance.NewAggregate("INSTANCE").Aggregate, - true, - "from", - "name", - "host", - "user", - &crypto.CryptoValue{ - CryptoType: crypto.TypeEncryption, - Algorithm: "enc", - KeyID: "id", - Crypted: []byte("password"), - }, - ), + eventFromEventPusherWithInstanceID( + "INSTANCE", + instance.NewSMTPConfigAddedEvent( + context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, + "from", + "name", + "host", + "user", + &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("password"), + }, + ), ), }, ), @@ -97,8 +105,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), }, args: args{ - ctx: context.Background(), - instanceID: "INSTANCE", + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, From: "from", @@ -123,7 +130,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { eventstore: tt.fields.eventstore, smtpEncryption: tt.fields.alg, } - got, err := r.AddSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.smtp) + got, err := r.AddSMTPConfig(tt.args.ctx, tt.args.smtp) if tt.res.err == nil { assert.NoError(t, err) } @@ -142,9 +149,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { eventstore *eventstore.Eventstore } type args struct { - ctx context.Context - instanceID string - smtp *smtp.EmailConfig + ctx context.Context + smtp *smtp.EmailConfig } type res struct { want *domain.ObjectDetails @@ -156,6 +162,21 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { args args res res }{ + { + name: "empty config, invalid argument error", + fields: fields{ + eventstore: eventstoreExpect( + t, + ), + }, + args: args{ + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), + smtp: &smtp.EmailConfig{}, + }, + res: res{ + err: caos_errs.IsErrorInvalidArgument, + }, + }, { name: "smtp not existing, not found error", fields: fields{ @@ -165,14 +186,21 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ), }, args: args{ - ctx: context.Background(), - smtp: &smtp.EmailConfig{}, + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), + smtp: &smtp.EmailConfig{ + Tls: true, + From: "from", + FromName: "name", + SMTP: smtp.SMTP{ + Host: "host", + User: "user", + }, + }, }, res: res{ err: caos_errs.IsNotFound, }, }, - { name: "no changes, precondition error", fields: fields{ @@ -195,8 +223,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ), }, args: args{ - ctx: context.Background(), - instanceID: "INSTANCE", + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, From: "from", @@ -232,7 +259,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ), expectPush( []*repository.Event{ - eventFromEventPusher( + eventFromEventPusherWithInstanceID( + "INSTANCE", newSMTPConfigChangedEvent( context.Background(), false, @@ -247,7 +275,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ), }, args: args{ - ctx: context.Background(), + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: false, From: "from2", @@ -270,7 +298,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { r := &Commands{ eventstore: tt.fields.eventstore, } - got, err := r.ChangeSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.smtp) + got, err := r.ChangeSMTPConfig(tt.args.ctx, tt.args.smtp) if tt.res.err == nil { assert.NoError(t, err) } @@ -290,9 +318,8 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) { alg crypto.EncryptionAlgorithm } type args struct { - ctx context.Context - instanceID string - password string + ctx context.Context + password string } type res struct { want *domain.ObjectDetails @@ -341,16 +368,18 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) { ), expectPush( []*repository.Event{ - eventFromEventPusher(instance.NewSMTPConfigPasswordChangedEvent( - context.Background(), - &instance.NewAggregate("INSTANCE").Aggregate, - &crypto.CryptoValue{ - CryptoType: crypto.TypeEncryption, - Algorithm: "enc", - KeyID: "id", - Crypted: []byte("password"), - }, - ), + eventFromEventPusherWithInstanceID( + "INSTANCE", + instance.NewSMTPConfigPasswordChangedEvent( + context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + &crypto.CryptoValue{ + CryptoType: crypto.TypeEncryption, + Algorithm: "enc", + KeyID: "id", + Crypted: []byte("password"), + }, + ), ), }, ), @@ -358,9 +387,8 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) { alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), }, args: args{ - ctx: context.Background(), - instanceID: "INSTANCE", - password: "password", + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), + password: "password", }, res: res{ want: &domain.ObjectDetails{ @@ -375,7 +403,7 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) { eventstore: tt.fields.eventstore, smtpEncryption: tt.fields.alg, } - got, err := r.ChangeSMTPConfigPassword(tt.args.ctx, tt.args.instanceID, tt.args.password) + got, err := r.ChangeSMTPConfigPassword(tt.args.ctx, tt.args.password) if tt.res.err == nil { assert.NoError(t, err) } diff --git a/internal/notification/channels/smtp/channel.go b/internal/notification/channels/smtp/channel.go index 3f54d2f7de..0b5ac61b9d 100644 --- a/internal/notification/channels/smtp/channel.go +++ b/internal/notification/channels/smtp/channel.go @@ -29,6 +29,7 @@ func InitSMTPChannel(ctx context.Context, getSMTPConfig func(ctx context.Context } client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls) if err != nil { + logging.New().WithError(err).Error("could not connect to smtp") return nil, err } diff --git a/internal/notification/repository/eventsourcing/handler/notification.go b/internal/notification/repository/eventsourcing/handler/notification.go index 184ce36b36..a759672a0e 100644 --- a/internal/notification/repository/eventsourcing/handler/notification.go +++ b/internal/notification/repository/eventsourcing/handler/notification.go @@ -483,6 +483,7 @@ func (n *Notification) getSMTPConfig(ctx context.Context) (*smtp.EmailConfig, er return &smtp.EmailConfig{ From: config.SenderAddress, FromName: config.SenderName, + Tls: config.TLS, SMTP: smtp.SMTP{ Host: config.Host, User: config.User, diff --git a/internal/notification/senders/debug.go b/internal/notification/senders/debug.go index 73f4f4d80c..cc512858c6 100644 --- a/internal/notification/senders/debug.go +++ b/internal/notification/senders/debug.go @@ -8,7 +8,7 @@ import ( "github.com/zitadel/zitadel/internal/notification/channels/log" ) -func debugChannels(ctx context.Context, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (*Chain, error) { +func debugChannels(ctx context.Context, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) []channels.NotificationChannel { var ( providers []channels.NotificationChannel ) @@ -24,5 +24,5 @@ func debugChannels(ctx context.Context, getFileSystemProvider func(ctx context.C providers = append(providers, log.InitStdoutChannel(*logProvider)) } - return chainChannels(providers...), nil + return providers } diff --git a/internal/notification/senders/email.go b/internal/notification/senders/email.go index 26e07d5755..3b3aa4a2cd 100644 --- a/internal/notification/senders/email.go +++ b/internal/notification/senders/email.go @@ -3,21 +3,18 @@ package senders import ( "context" - "github.com/zitadel/logging" - + "github.com/zitadel/zitadel/internal/notification/channels" "github.com/zitadel/zitadel/internal/notification/channels/fs" "github.com/zitadel/zitadel/internal/notification/channels/log" "github.com/zitadel/zitadel/internal/notification/channels/smtp" ) func EmailChannels(ctx context.Context, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) { + channels := make([]channels.NotificationChannel, 0, 3) p, err := smtp.InitSMTPChannel(ctx, emailConfig) if err == nil { - chain.channels = append(chain.channels, p) + channels = append(channels, p) } - chain, err = debugChannels(ctx, getFileSystemProvider, getLogProvider) - if err != nil { - logging.New().Info("Error in creating debug channels") - } - return chain, nil + channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...) + return chainChannels(channels...), nil } diff --git a/internal/notification/senders/sms.go b/internal/notification/senders/sms.go index 2e15d054cd..d7b5f5ff64 100644 --- a/internal/notification/senders/sms.go +++ b/internal/notification/senders/sms.go @@ -3,18 +3,17 @@ package senders import ( "context" + "github.com/zitadel/zitadel/internal/notification/channels" "github.com/zitadel/zitadel/internal/notification/channels/fs" "github.com/zitadel/zitadel/internal/notification/channels/log" "github.com/zitadel/zitadel/internal/notification/channels/twilio" ) func SMSChannels(ctx context.Context, twilioConfig *twilio.TwilioConfig, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) { + channels := make([]channels.NotificationChannel, 0, 3) if twilioConfig != nil { - chain.channels = append(chain.channels, twilio.InitTwilioChannel(*twilioConfig)) + channels = append(channels, twilio.InitTwilioChannel(*twilioConfig)) } - chain, err = debugChannels(ctx, getFileSystemProvider, getLogProvider) - if err != nil { - return nil, err - } - return chain, nil + channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...) + return chainChannels(channels...), nil } diff --git a/internal/query/projection/smtp.go b/internal/query/projection/smtp.go index 4496b830dd..c64a373a09 100644 --- a/internal/query/projection/smtp.go +++ b/internal/query/projection/smtp.go @@ -8,7 +8,6 @@ import ( "github.com/zitadel/zitadel/internal/eventstore/handler" "github.com/zitadel/zitadel/internal/eventstore/handler/crdb" "github.com/zitadel/zitadel/internal/repository/instance" - "github.com/zitadel/zitadel/internal/repository/project" ) const ( @@ -61,7 +60,7 @@ func NewSMTPConfigProjection(ctx context.Context, config crdb.StatementHandlerCo func (p *SMTPConfigProjection) reducers() []handler.AggregateReducer { return []handler.AggregateReducer{ { - Aggregate: project.AggregateType, + Aggregate: instance.AggregateType, EventRedusers: []handler.EventReducer{ { Event: instance.SMTPConfigAddedEventType, diff --git a/internal/repository/instance/smtp_config.go b/internal/repository/instance/smtp_config.go index 9b722adbac..7feeb441b7 100644 --- a/internal/repository/instance/smtp_config.go +++ b/internal/repository/instance/smtp_config.go @@ -11,7 +11,7 @@ import ( ) const ( - smtpConfigPrefix = "smtp.config" + smtpConfigPrefix = "smtp.config." SMTPConfigAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + "added" SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed" SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"