fix: add smtp config, remove smtp and sms provider, console adaptations (#3792)

* fix: add AddSMTPConfig to admin api

* addsmtpconfig

* fix: add RemoveSMTPConfig and RemoveSMSProvider to admin api

* update twilio, token fcn

* fix account switcher, twilio token set, cleanup dialog

* cleanup

* buttons

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Max Peintner
2022-06-10 12:39:38 +02:00
committed by GitHub
parent ab7651fe26
commit 3500961fbb
29 changed files with 793 additions and 275 deletions

View File

@@ -55,6 +55,19 @@ func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigR
}, nil
}
func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) (*admin_pb.AddSMTPConfigResponse, error) {
details, err := s.command.AddSMTPConfig(ctx, AddSMTPToConfig(req))
if err != nil {
return nil, err
}
return &admin_pb.AddSMTPConfigResponse{
Details: object.ChangeToDetailsPb(
details.Sequence,
details.EventDate,
details.ResourceOwner),
}, nil
}
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req))
if err != nil {
@@ -68,6 +81,19 @@ func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPC
}, nil
}
func (s *Server) RemoveSMTPConfig(ctx context.Context, _ *admin_pb.RemoveSMTPConfigRequest) (*admin_pb.RemoveSMTPConfigResponse, error) {
details, err := s.command.RemoveSMTPConfig(ctx)
if err != nil {
return nil, err
}
return &admin_pb.RemoveSMTPConfigResponse{
Details: object.ChangeToDetailsPb(
details.Sequence,
details.EventDate,
details.ResourceOwner),
}, nil
}
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password)
if err != nil {

View File

@@ -1,12 +1,12 @@
package admin
import (
"github.com/zitadel/zitadel/internal/domain"
"google.golang.org/protobuf/types/known/durationpb"
"github.com/zitadel/zitadel/internal/api/grpc/object"
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
"github.com/zitadel/zitadel/internal/query"
@@ -113,6 +113,19 @@ func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType)
}
}
func AddSMTPToConfig(req *admin_pb.AddSMTPConfigRequest) *smtp.EmailConfig {
return &smtp.EmailConfig{
Tls: req.Tls,
From: req.SenderAddress,
FromName: req.SenderName,
SMTP: smtp.SMTP{
Host: req.Host,
User: req.User,
Password: req.Password,
},
}
}
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.EmailConfig {
return &smtp.EmailConfig{
Tls: req.Tls,

View File

@@ -73,3 +73,14 @@ func (s *Server) UpdateSMSProviderTwilioToken(ctx context.Context, req *admin_pb
Details: object.DomainToChangeDetailsPb(result),
}, nil
}
func (s *Server) RemoveSMSProvider(ctx context.Context, req *admin_pb.RemoveSMSProviderRequest) (*admin_pb.RemoveSMSProviderResponse, error) {
result, err := s.command.RemoveSMSConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
if err != nil {
return nil, err
}
return &admin_pb.RemoveSMSProviderResponse{
Details: object.DomainToAddDetailsPb(result),
}, nil
}

View File

@@ -82,6 +82,14 @@ func (wm *InstanceSMTPConfigWriteModel) Reduce() error {
if e.User != nil {
wm.User = *e.User
}
case *instance.SMTPConfigRemovedEvent:
wm.State = domain.SMTPConfigStateRemoved
wm.TLS = false
wm.SenderName = ""
wm.SenderAddress = ""
wm.Host = ""
wm.User = ""
wm.Password = nil
case *instance.DomainAddedEvent:
wm.domainState = domain.InstanceDomainStateActive
case *instance.DomainRemovedEvent:

View File

@@ -170,7 +170,7 @@ func (c *Commands) DeactivateSMSConfigTwilio(ctx context.Context, instanceID, id
return writeModelToObjectDetails(&smsConfigWriteModel.WriteModel), nil
}
func (c *Commands) RemoveSMSConfigTwilio(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
func (c *Commands) RemoveSMSConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
if id == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "SMS-3j9fs", "Errors.IDMissing")
}
@@ -178,7 +178,7 @@ func (c *Commands) RemoveSMSConfigTwilio(ctx context.Context, instanceID, id str
if err != nil {
return nil, err
}
if !smsConfigWriteModel.State.Exists() || smsConfigWriteModel.Twilio == nil {
if !smsConfigWriteModel.State.Exists() {
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-sn9we", "Errors.SMSConfig.NotFound")
}

View File

@@ -496,7 +496,7 @@ func TestCommandSide_DeactivateSMSConfigTwilio(t *testing.T) {
}
}
func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
func TestCommandSide_RemoveSMSConfig(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
}
@@ -547,7 +547,7 @@ func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
},
},
{
name: "sms config twilio remove, ok",
name: "sms config remove, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
@@ -593,7 +593,7 @@ func TestCommandSide_RemoveSMSConfigTwilio(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
got, err := r.RemoveSMSConfigTwilio(tt.args.ctx, tt.args.instanceID, tt.args.id)
got, err := r.RemoveSMSConfig(tt.args.ctx, tt.args.instanceID, tt.args.id)
if tt.res.err == nil {
assert.NoError(t, err)
}

View File

@@ -81,6 +81,24 @@ func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string
}, nil
}
func (c *Commands) RemoveSMTPConfig(ctx context.Context) (*domain.ObjectDetails, error) {
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
validation := c.prepareRemoveSMTPConfig(instanceAgg)
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) 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 == "" {
@@ -171,6 +189,23 @@ func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, ho
}
}
func (c *Commands) prepareRemoveSMTPConfig(a *instance.Aggregate) preparation.Validation {
return func() (preparation.CreateCommands, error) {
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-Sfefg", "Errors.SMTPConfig.NotFound")
}
return []eventstore.Command{
instance.NewSMTPConfigRemovedEvent(ctx, &a.Aggregate),
}, nil
}, nil
}
}
func checkSenderAddress(writeModel *InstanceSMTPConfigWriteModel) error {
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
return nil

View File

@@ -554,6 +554,101 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
}
}
func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
}
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "smtp config, error not found",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
},
res: res{
err: caos_errs.IsNotFound,
},
},
{
name: "remove smtp config, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewSMTPConfigAddedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
true,
"from",
"name",
"host",
"user",
&crypto.CryptoValue{},
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewSMTPConfigRemovedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
),
),
},
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
smtpEncryption: tt.fields.alg,
}
got, err := r.RemoveSMTPConfig(tt.args.ctx)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assert.Equal(t, tt.res.want, got)
}
})
}
}
func newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromName, host, user string) *instance.SMTPConfigChangedEvent {
changes := []instance.SMTPConfigChanges{
instance.ChangeSMTPConfigTLS(tls),

View File

@@ -5,4 +5,5 @@ type SMTPConfigState int32
const (
SMTPConfigStateUnspecified SMTPConfigState = iota
SMTPConfigStateActive
SMTPConfigStateRemoved
)

View File

@@ -15,6 +15,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(SMTPConfigAddedEventType, SMTPConfigAddedEventMapper).
RegisterFilterEventMapper(SMTPConfigChangedEventType, SMTPConfigChangedEventMapper).
RegisterFilterEventMapper(SMTPConfigPasswordChangedEventType, SMTPConfigPasswordChangedEventMapper).
RegisterFilterEventMapper(SMTPConfigRemovedEventType, SMTPConfigRemovedEventMapper).
RegisterFilterEventMapper(SMSConfigTwilioAddedEventType, SMSConfigTwilioAddedEventMapper).
RegisterFilterEventMapper(SMSConfigTwilioChangedEventType, SMSConfigTwilioChangedEventMapper).
RegisterFilterEventMapper(SMSConfigTwilioTokenChangedEventType, SMSConfigTwilioTokenChangedEventMapper).

View File

@@ -15,6 +15,7 @@ const (
SMTPConfigAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + "added"
SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed"
SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"
SMTPConfigRemovedEventType = instanceEventTypePrefix + smtpConfigPrefix + "removed"
)
type SMTPConfigAddedEvent struct {
@@ -197,3 +198,40 @@ func SMTPConfigPasswordChangedEventMapper(event *repository.Event) (eventstore.E
return smtpConfigPasswordChagned, nil
}
type SMTPConfigRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func NewSMTPConfigRemovedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
) *SMTPConfigRemovedEvent {
return &SMTPConfigRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
aggregate,
SMTPConfigRemovedEventType,
),
}
}
func (e *SMTPConfigRemovedEvent) Data() interface{} {
return e
}
func (e *SMTPConfigRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func SMTPConfigRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
smtpConfigRemoved := &SMTPConfigRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, smtpConfigRemoved)
if err != nil {
return nil, errors.ThrowInternal(err, "IAM-DVw1s", "unable to unmarshal smtp config removed")
}
return smtpConfigRemoved, nil
}