mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-13 11:40:16 +00:00
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:
@@ -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 {
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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")
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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),
|
||||
|
@@ -5,4 +5,5 @@ type SMTPConfigState int32
|
||||
const (
|
||||
SMTPConfigStateUnspecified SMTPConfigState = iota
|
||||
SMTPConfigStateActive
|
||||
SMTPConfigStateRemoved
|
||||
)
|
||||
|
@@ -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).
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user