mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:47:32 +00:00
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:
140
internal/api/grpc/admin/email.go
Normal file
140
internal/api/grpc/admin/email.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func (s *Server) GetEmailProvider(ctx context.Context, req *admin_pb.GetEmailProviderRequest) (*admin_pb.GetEmailProviderResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetEmailProviderResponse{
|
||||
Config: emailProviderToProviderPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetEmailProviderById(ctx context.Context, req *admin_pb.GetEmailProviderByIdRequest) (*admin_pb.GetEmailProviderByIdResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigByID(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetEmailProviderByIdResponse{
|
||||
Config: emailProviderToProviderPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddEmailProviderSMTP(ctx context.Context, req *admin_pb.AddEmailProviderSMTPRequest) (*admin_pb.AddEmailProviderSMTPResponse, error) {
|
||||
config := addEmailProviderSMTPToConfig(ctx, req)
|
||||
if err := s.command.AddSMTPConfig(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddEmailProviderSMTPResponse{
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
Id: config.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateEmailProviderSMTP(ctx context.Context, req *admin_pb.UpdateEmailProviderSMTPRequest) (*admin_pb.UpdateEmailProviderSMTPResponse, error) {
|
||||
config := updateEmailProviderSMTPToConfig(ctx, req)
|
||||
if err := s.command.ChangeSMTPConfig(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateEmailProviderSMTPResponse{
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AddEmailProviderHTTP(ctx context.Context, req *admin_pb.AddEmailProviderHTTPRequest) (*admin_pb.AddEmailProviderHTTPResponse, error) {
|
||||
config := addEmailProviderHTTPToConfig(ctx, req)
|
||||
if err := s.command.AddSMTPConfigHTTP(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddEmailProviderHTTPResponse{
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
Id: config.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateEmailProviderHTTP(ctx context.Context, req *admin_pb.UpdateEmailProviderHTTPRequest) (*admin_pb.UpdateEmailProviderHTTPResponse, error) {
|
||||
config := updateEmailProviderHTTPToConfig(ctx, req)
|
||||
if err := s.command.ChangeSMTPConfigHTTP(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateEmailProviderHTTPResponse{
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveEmailProvider(ctx context.Context, req *admin_pb.RemoveEmailProviderRequest) (*admin_pb.RemoveEmailProviderResponse, error) {
|
||||
details, err := s.command.RemoveSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.RemoveEmailProviderResponse{
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateEmailProviderSMTPPassword(ctx context.Context, req *admin_pb.UpdateEmailProviderSMTPPasswordRequest) (*admin_pb.UpdateEmailProviderSMTPPasswordResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateEmailProviderSMTPPasswordResponse{
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ListEmailProviders(ctx context.Context, req *admin_pb.ListEmailProvidersRequest) (*admin_pb.ListEmailProvidersResponse, error) {
|
||||
queries, err := listEmailProvidersToModel(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := s.query.SearchSMTPConfigs(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.ListEmailProvidersResponse{
|
||||
Details: object.ToListDetails(result.Count, result.Sequence, result.LastRun),
|
||||
Result: emailProvidersToPb(result.Configs),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ActivateEmailProvider(ctx context.Context, req *admin_pb.ActivateEmailProviderRequest) (*admin_pb.ActivateEmailProviderResponse, error) {
|
||||
result, err := s.command.ActivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.ActivateEmailProviderResponse{
|
||||
Details: object.DomainToAddDetailsPb(result),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) DeactivateEmailProvider(ctx context.Context, req *admin_pb.DeactivateEmailProviderRequest) (*admin_pb.DeactivateEmailProviderResponse, error) {
|
||||
result, err := s.command.DeactivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.DeactivateEmailProviderResponse{
|
||||
Details: object.DomainToAddDetailsPb(result),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) TestEmailProviderById(ctx context.Context, req *admin_pb.TestEmailProviderSMTPByIdRequest) (*admin_pb.TestEmailProviderSMTPByIdResponse, error) {
|
||||
if err := s.command.TestSMTPConfigById(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.TestEmailProviderSMTPByIdResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *Server) TestEmailProviderSMTP(ctx context.Context, req *admin_pb.TestEmailProviderSMTPRequest) (*admin_pb.TestEmailProviderSMTPResponse, error) {
|
||||
if err := s.command.TestSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress, testEmailProviderSMTPToConfig(req)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.TestEmailProviderSMTPResponse{}, nil
|
||||
}
|
145
internal/api/grpc/admin/email_converters.go
Normal file
145
internal/api/grpc/admin/email_converters.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
settings_pb "github.com/zitadel/zitadel/pkg/grpc/settings"
|
||||
)
|
||||
|
||||
func listEmailProvidersToModel(req *admin_pb.ListEmailProvidersRequest) (*query.SMTPConfigsSearchQueries, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
return &query.SMTPConfigsSearchQueries{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func emailProvidersToPb(configs []*query.SMTPConfig) []*settings_pb.EmailProvider {
|
||||
c := make([]*settings_pb.EmailProvider, len(configs))
|
||||
for i, config := range configs {
|
||||
c[i] = emailProviderToProviderPb(config)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func emailProviderToProviderPb(config *query.SMTPConfig) *settings_pb.EmailProvider {
|
||||
return &settings_pb.EmailProvider{
|
||||
Details: object.ToViewDetailsPb(config.Sequence, config.CreationDate, config.ChangeDate, config.ResourceOwner),
|
||||
Id: config.ID,
|
||||
Description: config.Description,
|
||||
State: emailProviderStateToPb(config.State),
|
||||
Config: emailProviderToPb(config),
|
||||
}
|
||||
}
|
||||
|
||||
func emailProviderStateToPb(state domain.SMTPConfigState) settings_pb.EmailProviderState {
|
||||
switch state {
|
||||
case domain.SMTPConfigStateUnspecified, domain.SMTPConfigStateRemoved:
|
||||
return settings_pb.EmailProviderState_EMAIL_PROVIDER_STATE_UNSPECIFIED
|
||||
case domain.SMTPConfigStateActive:
|
||||
return settings_pb.EmailProviderState_EMAIL_PROVIDER_ACTIVE
|
||||
case domain.SMTPConfigStateInactive:
|
||||
return settings_pb.EmailProviderState_EMAIL_PROVIDER_INACTIVE
|
||||
default:
|
||||
return settings_pb.EmailProviderState_EMAIL_PROVIDER_STATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func emailProviderToPb(config *query.SMTPConfig) settings_pb.EmailConfig {
|
||||
if config.SMTPConfig != nil {
|
||||
return smtpToPb(config.SMTPConfig)
|
||||
}
|
||||
if config.HTTPConfig != nil {
|
||||
return httpToPb(config.HTTPConfig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func httpToPb(http *query.HTTP) *settings_pb.EmailProvider_Http {
|
||||
return &settings_pb.EmailProvider_Http{
|
||||
Http: &settings_pb.EmailProviderHTTP{
|
||||
Endpoint: http.Endpoint,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func smtpToPb(config *query.SMTP) *settings_pb.EmailProvider_Smtp {
|
||||
return &settings_pb.EmailProvider_Smtp{
|
||||
Smtp: &settings_pb.EmailProviderSMTP{
|
||||
Tls: config.TLS,
|
||||
Host: config.Host,
|
||||
User: config.User,
|
||||
SenderAddress: config.SenderAddress,
|
||||
SenderName: config.SenderName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func addEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.AddEmailProviderSMTPRequest) *command.AddSMTPConfig {
|
||||
return &command.AddSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func updateEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.UpdateEmailProviderSMTPRequest) *command.ChangeSMTPConfig {
|
||||
return &command.ChangeSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
ID: req.Id,
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func addEmailProviderHTTPToConfig(ctx context.Context, req *admin_pb.AddEmailProviderHTTPRequest) *command.AddSMTPConfigHTTP {
|
||||
return &command.AddSMTPConfigHTTP{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
Description: req.Description,
|
||||
Endpoint: req.Endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func updateEmailProviderHTTPToConfig(ctx context.Context, req *admin_pb.UpdateEmailProviderHTTPRequest) *command.ChangeSMTPConfigHTTP {
|
||||
return &command.ChangeSMTPConfigHTTP{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
ID: req.Id,
|
||||
Description: req.Description,
|
||||
Endpoint: req.Endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func testEmailProviderSMTPToConfig(req *admin_pb.TestEmailProviderSMTPRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,14 +1,16 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
@@ -131,50 +133,51 @@ func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType)
|
||||
}
|
||||
}
|
||||
|
||||
func AddSMTPToConfig(req *admin_pb.AddSMTPConfigRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
func addSMTPToConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) *command.AddSMTPConfig {
|
||||
return &command.AddSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
},
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
func updateSMTPToConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) *command.ChangeSMTPConfig {
|
||||
return &command.ChangeSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
ID: req.Id,
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
},
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigToPb(smtp *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
mapped := &settings_pb.SMTPConfig{
|
||||
Description: smtp.Description,
|
||||
Tls: smtp.TLS,
|
||||
SenderAddress: smtp.SenderAddress,
|
||||
SenderName: smtp.SenderName,
|
||||
ReplyToAddress: smtp.ReplyToAddress,
|
||||
Host: smtp.Host,
|
||||
User: smtp.User,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.ResourceOwner),
|
||||
Id: smtp.ID,
|
||||
State: settings_pb.SMTPConfigState(smtp.State),
|
||||
if smtp.SMTPConfig != nil {
|
||||
return &settings_pb.SMTPConfig{
|
||||
Description: smtp.Description,
|
||||
Tls: smtp.SMTPConfig.TLS,
|
||||
SenderAddress: smtp.SMTPConfig.SenderAddress,
|
||||
SenderName: smtp.SMTPConfig.SenderName,
|
||||
ReplyToAddress: smtp.SMTPConfig.ReplyToAddress,
|
||||
Host: smtp.SMTPConfig.Host,
|
||||
User: smtp.SMTPConfig.User,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.ResourceOwner),
|
||||
Id: smtp.ID,
|
||||
State: settings_pb.SMTPConfigState(smtp.State),
|
||||
}
|
||||
}
|
||||
return mapped
|
||||
return nil
|
||||
}
|
||||
|
||||
func SecurityPolicyToPb(policy *query.SecurityPolicy) *settings_pb.SecurityPolicy {
|
||||
|
@@ -20,10 +20,7 @@ func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigR
|
||||
}
|
||||
|
||||
func (s *Server) GetSMTPConfigById(ctx context.Context, req *admin_pb.GetSMTPConfigByIdRequest) (*admin_pb.GetSMTPConfigByIdResponse, error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
resourceOwner := instanceID // Will be replaced when orgs have smtp configs
|
||||
|
||||
smtp, err := s.query.SMTPConfigByID(ctx, instanceID, resourceOwner, req.Id)
|
||||
smtp, err := s.query.SMTPConfigByID(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -33,29 +30,23 @@ func (s *Server) GetSMTPConfigById(ctx context.Context, req *admin_pb.GetSMTPCon
|
||||
}
|
||||
|
||||
func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) (*admin_pb.AddSMTPConfigResponse, error) {
|
||||
id, details, err := s.command.AddSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), AddSMTPToConfig(req))
|
||||
if err != nil {
|
||||
config := addSMTPToConfig(ctx, req)
|
||||
if err := s.command.AddSMTPConfig(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.AddSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
Id: id,
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
Id: config.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
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(), req.Id, UpdateSMTPToConfig(req))
|
||||
if err != nil {
|
||||
config := updateSMTPToConfig(ctx, req)
|
||||
if err := s.command.ChangeSMTPConfig(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
Details: object.DomainToChangeDetailsPb(config.Details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -65,10 +56,7 @@ func (s *Server) RemoveSMTPConfig(ctx context.Context, req *admin_pb.RemoveSMTPC
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.RemoveSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -78,10 +66,7 @@ func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.Upd
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigPasswordResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -101,19 +86,11 @@ func (s *Server) ListSMTPConfigs(ctx context.Context, req *admin_pb.ListSMTPConf
|
||||
}
|
||||
|
||||
func (s *Server) ActivateSMTPConfig(ctx context.Context, req *admin_pb.ActivateSMTPConfigRequest) (*admin_pb.ActivateSMTPConfigResponse, error) {
|
||||
// Get the ID of current SMTP active provider if any
|
||||
currentActiveProviderID := ""
|
||||
smtp, err := s.query.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err == nil {
|
||||
currentActiveProviderID = smtp.ID
|
||||
}
|
||||
|
||||
result, err := s.command.ActivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, currentActiveProviderID)
|
||||
result, err := s.command.ActivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
return &admin_pb.ActivateSMTPConfigResponse{
|
||||
Details: object.DomainToAddDetailsPb(result),
|
||||
}, nil
|
||||
|
@@ -2,6 +2,7 @@ package admin
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
settings_pb "github.com/zitadel/zitadel/pkg/grpc/settings"
|
||||
@@ -23,12 +24,12 @@ func SMTPConfigToProviderPb(config *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
Details: object.ToViewDetailsPb(config.Sequence, config.CreationDate, config.ChangeDate, config.ResourceOwner),
|
||||
Id: config.ID,
|
||||
Description: config.Description,
|
||||
Tls: config.TLS,
|
||||
Host: config.Host,
|
||||
User: config.User,
|
||||
State: settings_pb.SMTPConfigState(config.State),
|
||||
SenderAddress: config.SenderAddress,
|
||||
SenderName: config.SenderName,
|
||||
Tls: config.SMTPConfig.TLS,
|
||||
Host: config.SMTPConfig.Host,
|
||||
User: config.SMTPConfig.User,
|
||||
State: SMTPConfigStateToPb(config.State),
|
||||
SenderAddress: config.SMTPConfig.SenderAddress,
|
||||
SenderName: config.SMTPConfig.SenderName,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,3 +40,16 @@ func SMTPConfigsToPb(configs []*query.SMTPConfig) []*settings_pb.SMTPConfig {
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func SMTPConfigStateToPb(state domain.SMTPConfigState) settings_pb.SMTPConfigState {
|
||||
switch state {
|
||||
case domain.SMTPConfigStateUnspecified, domain.SMTPConfigStateRemoved:
|
||||
return settings_pb.SMTPConfigState_SMTP_CONFIG_STATE_UNSPECIFIED
|
||||
case domain.SMTPConfigStateActive:
|
||||
return settings_pb.SMTPConfigState_SMTP_CONFIG_ACTIVE
|
||||
case domain.SMTPConfigStateInactive:
|
||||
return settings_pb.SMTPConfigState_SMTP_CONFIG_INACTIVE
|
||||
default:
|
||||
return settings_pb.SMTPConfigState_SMTP_CONFIG_STATE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ type InstanceSetup struct {
|
||||
}
|
||||
EmailTemplate []byte
|
||||
MessageTexts []*domain.CustomMessageText
|
||||
SMTPConfiguration *smtp.Config
|
||||
SMTPConfiguration *SMTPConfiguration
|
||||
OIDCSettings *OIDCSettings
|
||||
Quotas *SetQuotas
|
||||
Features *InstanceFeatures
|
||||
@@ -124,6 +124,15 @@ type InstanceSetup struct {
|
||||
Restrictions *SetRestrictions
|
||||
}
|
||||
|
||||
type SMTPConfiguration struct {
|
||||
Description string
|
||||
SMTP smtp.SMTP
|
||||
Tls bool
|
||||
From string
|
||||
FromName string
|
||||
ReplyToAddress string
|
||||
}
|
||||
|
||||
type OIDCSettings struct {
|
||||
AccessTokenLifetime time.Duration
|
||||
IdTokenLifetime time.Duration
|
||||
@@ -440,7 +449,7 @@ func setupOIDCSettings(commands *Commands, validations *[]preparation.Validation
|
||||
)
|
||||
}
|
||||
|
||||
func setupSMTPSettings(commands *Commands, validations *[]preparation.Validation, smtpConfig *smtp.Config, instanceAgg *instance.Aggregate) {
|
||||
func setupSMTPSettings(commands *Commands, validations *[]preparation.Validation, smtpConfig *SMTPConfiguration, instanceAgg *instance.Aggregate) {
|
||||
if smtpConfig == nil {
|
||||
return
|
||||
}
|
||||
|
@@ -12,8 +12,20 @@ import (
|
||||
type IAMSMTPConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
ID string
|
||||
Description string
|
||||
ID string
|
||||
Description string
|
||||
|
||||
SMTPConfig *SMTPConfig
|
||||
HTTPConfig *HTTPConfig
|
||||
|
||||
State domain.SMTPConfigState
|
||||
|
||||
domain string
|
||||
domainState domain.InstanceDomainState
|
||||
smtpSenderAddressMatchesInstanceDomain bool
|
||||
}
|
||||
|
||||
type SMTPConfig struct {
|
||||
TLS bool
|
||||
Host string
|
||||
User string
|
||||
@@ -21,11 +33,6 @@ type IAMSMTPConfigWriteModel struct {
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
ReplyToAddress string
|
||||
State domain.SMTPConfigState
|
||||
|
||||
domain string
|
||||
domainState domain.InstanceDomainState
|
||||
smtpSenderAddressMatchesInstanceDomain bool
|
||||
}
|
||||
|
||||
func NewIAMSMTPConfigWriteModel(instanceID, id, domain string) *IAMSMTPConfigWriteModel {
|
||||
@@ -73,6 +80,23 @@ func (wm *IAMSMTPConfigWriteModel) Reduce() error {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigChangedEvent(e)
|
||||
case *instance.SMTPConfigPasswordChangedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
if e.Password != nil {
|
||||
wm.SMTPConfig.Password = e.Password
|
||||
}
|
||||
case *instance.SMTPConfigHTTPAddedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigHTTPAddedEvent(e)
|
||||
case *instance.SMTPConfigHTTPChangedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
}
|
||||
wm.reduceSMTPConfigHTTPChangedEvent(e)
|
||||
case *instance.SMTPConfigRemovedEvent:
|
||||
if wm.ID != e.ID {
|
||||
continue
|
||||
@@ -120,6 +144,8 @@ func (wm *IAMSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
instance.SMTPConfigRemovedEventType,
|
||||
instance.SMTPConfigChangedEventType,
|
||||
instance.SMTPConfigPasswordChangedEventType,
|
||||
instance.SMTPConfigHTTPAddedEventType,
|
||||
instance.SMTPConfigHTTPChangedEventType,
|
||||
instance.SMTPConfigActivatedEventType,
|
||||
instance.SMTPConfigDeactivatedEventType,
|
||||
instance.SMTPConfigRemovedEventType,
|
||||
@@ -133,6 +159,9 @@ func (wm *IAMSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, id, description string, tls bool, fromAddress, fromName, replyToAddress, smtpHost, smtpUser string, smtpPassword *crypto.CryptoValue) (*instance.SMTPConfigChangedEvent, bool, error) {
|
||||
changes := make([]instance.SMTPConfigChanges, 0)
|
||||
var err error
|
||||
if wm.SMTPConfig == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
if wm.ID != id {
|
||||
changes = append(changes, instance.ChangeSMTPConfigID(id))
|
||||
@@ -140,22 +169,22 @@ func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregat
|
||||
if wm.Description != description {
|
||||
changes = append(changes, instance.ChangeSMTPConfigDescription(description))
|
||||
}
|
||||
if wm.TLS != tls {
|
||||
if wm.SMTPConfig.TLS != tls {
|
||||
changes = append(changes, instance.ChangeSMTPConfigTLS(tls))
|
||||
}
|
||||
if wm.SenderAddress != fromAddress {
|
||||
if wm.SMTPConfig.SenderAddress != fromAddress {
|
||||
changes = append(changes, instance.ChangeSMTPConfigFromAddress(fromAddress))
|
||||
}
|
||||
if wm.SenderName != fromName {
|
||||
if wm.SMTPConfig.SenderName != fromName {
|
||||
changes = append(changes, instance.ChangeSMTPConfigFromName(fromName))
|
||||
}
|
||||
if wm.ReplyToAddress != replyToAddress {
|
||||
if wm.SMTPConfig.ReplyToAddress != replyToAddress {
|
||||
changes = append(changes, instance.ChangeSMTPConfigReplyToAddress(replyToAddress))
|
||||
}
|
||||
if wm.Host != smtpHost {
|
||||
if wm.SMTPConfig.Host != smtpHost {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPHost(smtpHost))
|
||||
}
|
||||
if wm.User != smtpUser {
|
||||
if wm.SMTPConfig.User != smtpUser {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPUser(smtpUser))
|
||||
}
|
||||
if smtpPassword != nil {
|
||||
@@ -171,15 +200,58 @@ func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregat
|
||||
return changeEvent, true, nil
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) NewHTTPChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, id, description, endpoint string) (*instance.SMTPConfigHTTPChangedEvent, bool, error) {
|
||||
changes := make([]instance.SMTPConfigHTTPChanges, 0)
|
||||
var err error
|
||||
if wm.HTTPConfig == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
if wm.ID != id {
|
||||
changes = append(changes, instance.ChangeSMTPConfigHTTPID(id))
|
||||
}
|
||||
if wm.Description != description {
|
||||
changes = append(changes, instance.ChangeSMTPConfigHTTPDescription(description))
|
||||
}
|
||||
if wm.HTTPConfig.Endpoint != endpoint {
|
||||
changes = append(changes, instance.ChangeSMTPConfigHTTPEndpoint(endpoint))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := instance.NewSMTPConfigHTTPChangeEvent(ctx, aggregate, id, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigAddedEvent(e *instance.SMTPConfigAddedEvent) {
|
||||
wm.Description = e.Description
|
||||
wm.TLS = e.TLS
|
||||
wm.Host = e.Host
|
||||
wm.User = e.User
|
||||
wm.Password = e.Password
|
||||
wm.SenderAddress = e.SenderAddress
|
||||
wm.SenderName = e.SenderName
|
||||
wm.ReplyToAddress = e.ReplyToAddress
|
||||
wm.SMTPConfig = &SMTPConfig{
|
||||
TLS: e.TLS,
|
||||
Host: e.Host,
|
||||
User: e.User,
|
||||
Password: e.Password,
|
||||
SenderName: e.SenderName,
|
||||
SenderAddress: e.SenderAddress,
|
||||
ReplyToAddress: e.ReplyToAddress,
|
||||
}
|
||||
wm.State = domain.SMTPConfigStateInactive
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
wm.Description = "generic"
|
||||
wm.ID = e.Aggregate().ResourceOwner
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigHTTPAddedEvent(e *instance.SMTPConfigHTTPAddedEvent) {
|
||||
wm.Description = e.Description
|
||||
wm.HTTPConfig = &HTTPConfig{
|
||||
Endpoint: e.Endpoint,
|
||||
}
|
||||
wm.State = domain.SMTPConfigStateInactive
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
@@ -191,29 +263,54 @@ func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigAddedEvent(e *instance.SMTPCo
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigChangedEvent(e *instance.SMTPConfigChangedEvent) {
|
||||
if wm.SMTPConfig == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if e.Description != nil {
|
||||
wm.Description = *e.Description
|
||||
}
|
||||
if e.TLS != nil {
|
||||
wm.TLS = *e.TLS
|
||||
wm.SMTPConfig.TLS = *e.TLS
|
||||
}
|
||||
if e.Host != nil {
|
||||
wm.Host = *e.Host
|
||||
wm.SMTPConfig.Host = *e.Host
|
||||
}
|
||||
if e.User != nil {
|
||||
wm.User = *e.User
|
||||
wm.SMTPConfig.User = *e.User
|
||||
}
|
||||
if e.Password != nil {
|
||||
wm.Password = e.Password
|
||||
wm.SMTPConfig.Password = e.Password
|
||||
}
|
||||
if e.FromAddress != nil {
|
||||
wm.SenderAddress = *e.FromAddress
|
||||
wm.SMTPConfig.SenderAddress = *e.FromAddress
|
||||
}
|
||||
if e.FromName != nil {
|
||||
wm.SenderName = *e.FromName
|
||||
wm.SMTPConfig.SenderName = *e.FromName
|
||||
}
|
||||
if e.ReplyToAddress != nil {
|
||||
wm.ReplyToAddress = *e.ReplyToAddress
|
||||
wm.SMTPConfig.ReplyToAddress = *e.ReplyToAddress
|
||||
}
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
wm.Description = "generic"
|
||||
wm.ID = e.Aggregate().ResourceOwner
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigHTTPChangedEvent(e *instance.SMTPConfigHTTPChangedEvent) {
|
||||
if wm.HTTPConfig == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if e.Description != nil {
|
||||
wm.Description = *e.Description
|
||||
}
|
||||
if e.Endpoint != nil {
|
||||
wm.HTTPConfig.Endpoint = *e.Endpoint
|
||||
}
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
@@ -227,13 +324,8 @@ func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigChangedEvent(e *instance.SMTP
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigRemovedEvent(e *instance.SMTPConfigRemovedEvent) {
|
||||
wm.Description = ""
|
||||
wm.TLS = false
|
||||
wm.SenderName = ""
|
||||
wm.SenderAddress = ""
|
||||
wm.ReplyToAddress = ""
|
||||
wm.Host = ""
|
||||
wm.User = ""
|
||||
wm.Password = nil
|
||||
wm.HTTPConfig = nil
|
||||
wm.SMTPConfig = nil
|
||||
wm.State = domain.SMTPConfigStateRemoved
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
|
@@ -15,151 +15,189 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, instanceID string, config *smtp.Config) (string, *domain.ObjectDetails, error) {
|
||||
id, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
type AddSMTPConfig struct {
|
||||
Details *domain.ObjectDetails
|
||||
ResourceOwner string
|
||||
ID string
|
||||
|
||||
Description string
|
||||
Host string
|
||||
User string
|
||||
Password string
|
||||
Tls bool
|
||||
From string
|
||||
FromName string
|
||||
ReplyToAddress string
|
||||
}
|
||||
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, config *AddSMTPConfig) (err error) {
|
||||
if config.ResourceOwner == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-PQN0wsqSyi", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.ID == "" {
|
||||
config.ID, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
from := strings.TrimSpace(config.From)
|
||||
if from == "" {
|
||||
return "", nil, zerrors.ThrowInvalidArgument(nil, "INST-ASv2d", "Errors.Invalid.Argument")
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-SAAFpV8VKV", "Errors.Invalid.Argument")
|
||||
}
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
description := strings.TrimSpace(config.Description)
|
||||
replyTo := strings.TrimSpace(config.ReplyToAddress)
|
||||
hostAndPort := strings.TrimSpace(config.SMTP.Host)
|
||||
hostAndPort := strings.TrimSpace(config.Host)
|
||||
|
||||
if _, _, err := net.SplitHostPort(hostAndPort); err != nil {
|
||||
return "", nil, zerrors.ThrowInvalidArgument(nil, "INST-9JdRe", "Errors.Invalid.Argument")
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-EvAtufIinh", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
if config.SMTP.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpEncryption)
|
||||
if config.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, senderDomain)
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, senderDomain)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
err = checkSenderAddress(smtpConfigWriteModel)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id,
|
||||
description,
|
||||
config.Tls,
|
||||
config.From,
|
||||
config.FromName,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.SMTP.User,
|
||||
smtpPassword,
|
||||
))
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
config.ID,
|
||||
description,
|
||||
config.Tls,
|
||||
config.From,
|
||||
config.FromName,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.User,
|
||||
smtpPassword,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
return id, writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, instanceID string, id string, config *smtp.Config) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-x8vo9", "Errors.IDMissing")
|
||||
type ChangeSMTPConfig struct {
|
||||
Details *domain.ObjectDetails
|
||||
ResourceOwner string
|
||||
ID string
|
||||
|
||||
Description string
|
||||
Host string
|
||||
User string
|
||||
Password string
|
||||
Tls bool
|
||||
From string
|
||||
FromName string
|
||||
ReplyToAddress string
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *ChangeSMTPConfig) error {
|
||||
if config.ResourceOwner == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-jwA8gxldy3", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-2JPlSRzuHy", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
from := strings.TrimSpace(config.From)
|
||||
if from == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-HSv2d", "Errors.Invalid.Argument")
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-gyPUXOTA4N", "Errors.Invalid.Argument")
|
||||
}
|
||||
fromSplitted := strings.Split(from, "@")
|
||||
senderDomain := fromSplitted[len(fromSplitted)-1]
|
||||
description := strings.TrimSpace(config.Description)
|
||||
replyTo := strings.TrimSpace(config.ReplyToAddress)
|
||||
hostAndPort := strings.TrimSpace(config.SMTP.Host)
|
||||
hostAndPort := strings.TrimSpace(config.Host)
|
||||
if _, _, err := net.SplitHostPort(hostAndPort); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-Kv875", "Errors.Invalid.Argument")
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-kZNVkuL32L", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
var err error
|
||||
if config.SMTP.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpEncryption)
|
||||
if config.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, senderDomain)
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, senderDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-7j8gv", "Errors.SMTPConfig.NotFound")
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-j5IDFtt3T1", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
err = checkSenderAddress(smtpConfigWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
|
||||
changedEvent, hasChanged, err := smtpConfigWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
config.ID,
|
||||
description,
|
||||
config.Tls,
|
||||
from,
|
||||
config.FromName,
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.SMTP.User,
|
||||
config.User,
|
||||
smtpPassword,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-lh3op", "Errors.NoChangesFound")
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
err = c.pushAppendAndReduce(ctx, smtpConfigWriteModel, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, instanceID, id string, password string) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, resourceOwner, id string, password string) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-gHAyvUXCAF", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-BCkAf7LcJA", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, resourceOwner, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if smtpConfigWriteModel.State != domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound")
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-rDHzqjGuKQ", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
@@ -170,68 +208,152 @@ func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, instanceID, id
|
||||
}
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigPasswordChangedEvent(
|
||||
ctx,
|
||||
&instanceAgg.Aggregate,
|
||||
id,
|
||||
smtpPassword))
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigPasswordChangedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
id,
|
||||
smtpPassword,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ActivateSMTPConfig(ctx context.Context, instanceID, id, activatedId string) (*domain.ObjectDetails, error) {
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-nm56k", "Errors.IDMissing")
|
||||
}
|
||||
type AddSMTPConfigHTTP struct {
|
||||
Details *domain.ObjectDetails
|
||||
ResourceOwner string
|
||||
ID string
|
||||
|
||||
if len(activatedId) > 0 {
|
||||
_, err := c.DeactivateSMTPConfig(ctx, instanceID, activatedId)
|
||||
Description string
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func (c *Commands) AddSMTPConfigHTTP(ctx context.Context, config *AddSMTPConfigHTTP) (err error) {
|
||||
if config.ResourceOwner == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-FTNDXc8ACS", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.ID == "" {
|
||||
config.ID, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.pushAppendAndReduce(ctx, smtpConfigWriteModel, instance.NewSMTPConfigHTTPAddedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
config.ID,
|
||||
config.Description,
|
||||
config.Endpoint,
|
||||
))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
type ChangeSMTPConfigHTTP struct {
|
||||
Details *domain.ObjectDetails
|
||||
ResourceOwner string
|
||||
ID string
|
||||
|
||||
Description string
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfigHTTP(ctx context.Context, config *ChangeSMTPConfigHTTP) (err error) {
|
||||
if config.ResourceOwner == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-k7QCGOWyJA", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-2MHkV8ObWo", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.HTTPConfig == nil {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-xIrdledqv4", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
changedEvent, hasChanged, err := smtpConfigWriteModel.NewHTTPChangedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
config.ID,
|
||||
config.Description,
|
||||
config.Endpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasChanged {
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
err = c.pushAppendAndReduce(ctx, smtpConfigWriteModel, changedEvent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) ActivateSMTPConfig(ctx context.Context, resourceOwner, id string) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-h5htMCebv3", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-1hPl6oVMJa", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, resourceOwner, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-kg8yr", "Errors.SMTPConfig.NotFound")
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-E9K20hxOS9", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateActive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-ed3lr", "Errors.SMTPConfig.AlreadyActive")
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-vUHBSmBzaw", "Errors.SMTPConfig.AlreadyActive")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigActivatedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigActivatedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
id,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) DeactivateSMTPConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) DeactivateSMTPConfig(ctx context.Context, resourceOwner, id string) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-pvNHou89Tw", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-98ikl", "Errors.IDMissing")
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-jLTIMrtApO", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, resourceOwner, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -239,46 +361,47 @@ func (c *Commands) DeactivateSMTPConfig(ctx context.Context, instanceID, id stri
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-k39PJ", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateInactive {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-km8g3", "Errors.SMTPConfig.AlreadyDeactivated")
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-km8g3", "Errors.SMTPConfig.AlreadyDeactivated")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigDeactivatedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigDeactivatedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
id,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveSMTPConfig(ctx context.Context, instanceID, id string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) RemoveSMTPConfig(ctx context.Context, resourceOwner, id string) (*domain.ObjectDetails, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-t2WsPRgGaK", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if id == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SMTP-7f5cv", "Errors.IDMissing")
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-0ZV5whuUfu", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, resourceOwner, id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-kg8rt", "Errors.SMTPConfig.NotFound")
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-09CXlTDL6w", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
iamAgg := InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, instance.NewSMTPConfigRemovedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigRemovedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
id,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -303,11 +426,11 @@ func (c *Commands) TestSMTPConfig(ctx context.Context, instanceID, id, email str
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.SMTPConfig == nil {
|
||||
return zerrors.ThrowNotFound(nil, "SMTP-p9cc", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
password, err = crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
|
||||
password, err = crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.Password, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -338,23 +461,22 @@ func (c *Commands) TestSMTPConfigById(ctx context.Context, instanceID, id, email
|
||||
return err
|
||||
}
|
||||
|
||||
if !smtpConfigWriteModel.State.Exists() {
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.SMTPConfig == nil {
|
||||
return zerrors.ThrowNotFound(nil, "SMTP-99klw", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
password, err := crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
|
||||
password, err := crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.Password, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smtpConfig := &smtp.Config{
|
||||
Description: smtpConfigWriteModel.Description,
|
||||
Tls: smtpConfigWriteModel.TLS,
|
||||
From: smtpConfigWriteModel.SenderAddress,
|
||||
FromName: smtpConfigWriteModel.SenderName,
|
||||
Tls: smtpConfigWriteModel.SMTPConfig.TLS,
|
||||
From: smtpConfigWriteModel.SMTPConfig.SenderAddress,
|
||||
FromName: smtpConfigWriteModel.SMTPConfig.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: smtpConfigWriteModel.Host,
|
||||
User: smtpConfigWriteModel.User,
|
||||
Host: smtpConfigWriteModel.SMTPConfig.Host,
|
||||
User: smtpConfigWriteModel.SMTPConfig.User,
|
||||
Password: password,
|
||||
},
|
||||
}
|
||||
@@ -373,7 +495,7 @@ func checkSenderAddress(writeModel *IAMSMTPConfigWriteModel) error {
|
||||
return nil
|
||||
}
|
||||
if !writeModel.domainState.Exists() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "INST-83nl8", "Errors.SMTPConfig.SenderAdressNotCustomDomain")
|
||||
return zerrors.ThrowInvalidArgument(nil, "INST-xtWIiR2ZbR", "Errors.SMTPConfig.SenderAdressNotCustomDomain")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/sms"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/handlers"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
@@ -62,20 +62,20 @@ func registerCounter(counter, desc string) {
|
||||
logging.WithFields("metric", counter).OnError(err).Panic("unable to register counter")
|
||||
}
|
||||
|
||||
func (c *channels) Email(ctx context.Context) (*senders.Chain, *smtp.Config, error) {
|
||||
smtpCfg, err := c.q.GetSMTPConfig(ctx)
|
||||
func (c *channels) Email(ctx context.Context) (*senders.Chain, *email.Config, error) {
|
||||
emailCfg, err := c.q.GetActiveEmailConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
chain, err := senders.EmailChannels(
|
||||
ctx,
|
||||
smtpCfg,
|
||||
emailCfg,
|
||||
c.q.GetFileSystemProvider,
|
||||
c.q.GetLogProvider,
|
||||
c.counters.success.email,
|
||||
c.counters.failed.email,
|
||||
)
|
||||
return chain, smtpCfg, err
|
||||
return chain, emailCfg, err
|
||||
}
|
||||
|
||||
func (c *channels) SMS(ctx context.Context) (*senders.Chain, *sms.Config, error) {
|
||||
|
17
internal/notification/channels/email/config.go
Normal file
17
internal/notification/channels/email/config.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package email
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ProviderConfig *Provider
|
||||
SMTPConfig *smtp.Config
|
||||
WebhookConfig *webhook.Config
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
package smtp
|
||||
|
||||
type Config struct {
|
||||
Description string
|
||||
SMTP SMTP
|
||||
Tls bool
|
||||
From string
|
||||
@@ -18,3 +17,7 @@ type SMTP struct {
|
||||
func (smtp *SMTP) HasAuth() bool {
|
||||
return smtp.User != "" && smtp.Password != ""
|
||||
}
|
||||
|
||||
type ConfigHTTP struct {
|
||||
Endpoint string
|
||||
}
|
||||
|
56
internal/notification/handlers/config_email.go
Normal file
56
internal/notification/handlers/config_email.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
// GetSMTPConfig reads the iam SMTP provider config
|
||||
func (n *NotificationQueries) GetActiveEmailConfig(ctx context.Context) (*email.Config, error) {
|
||||
config, err := n.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
provider := &email.Provider{
|
||||
ID: config.ID,
|
||||
Description: config.Description,
|
||||
}
|
||||
if config.SMTPConfig != nil {
|
||||
password, err := crypto.DecryptString(config.SMTPConfig.Password, n.SMTPPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &email.Config{
|
||||
ProviderConfig: provider,
|
||||
SMTPConfig: &smtp.Config{
|
||||
From: config.SMTPConfig.SenderAddress,
|
||||
FromName: config.SMTPConfig.SenderName,
|
||||
ReplyToAddress: config.SMTPConfig.ReplyToAddress,
|
||||
Tls: config.SMTPConfig.TLS,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: config.SMTPConfig.Host,
|
||||
User: config.SMTPConfig.User,
|
||||
Password: password,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if config.HTTPConfig != nil {
|
||||
return &email.Config{
|
||||
ProviderConfig: provider,
|
||||
WebhookConfig: &webhook.Config{
|
||||
CallURL: config.HTTPConfig.Endpoint,
|
||||
Method: http.MethodPost,
|
||||
Headers: nil,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, zerrors.ThrowNotFound(err, "QUERY-KPQleOckOV", "Errors.SMTPConfig.NotFound")
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
)
|
||||
|
||||
// GetSMTPConfig reads the iam SMTP provider config
|
||||
func (n *NotificationQueries) GetSMTPConfig(ctx context.Context) (*smtp.Config, error) {
|
||||
config, err := n.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
password, err := crypto.DecryptString(config.Password, n.SMTPPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &smtp.Config{
|
||||
Description: config.Description,
|
||||
From: config.SenderAddress,
|
||||
FromName: config.SenderName,
|
||||
ReplyToAddress: config.ReplyToAddress,
|
||||
Tls: config.TLS,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: config.Host,
|
||||
User: config.User,
|
||||
Password: password,
|
||||
},
|
||||
}, nil
|
||||
}
|
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
es_repo_mock "github.com/zitadel/zitadel/internal/eventstore/repository/mock"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
channel_mock "github.com/zitadel/zitadel/internal/notification/channels/mock"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/sms"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
@@ -1449,7 +1450,27 @@ func newUserNotifier(t *testing.T, ctrl *gomock.Controller, queries *mock.MockQu
|
||||
f.SMSTokenCrypto,
|
||||
),
|
||||
otpEmailTmpl: defaultOTPEmailTemplate,
|
||||
channels: &channels{Chain: *senders.ChainChannels(channel)},
|
||||
channels: &channels{
|
||||
Chain: *senders.ChainChannels(channel),
|
||||
EmailConfig: &email.Config{
|
||||
ProviderConfig: &email.Provider{
|
||||
ID: "ID",
|
||||
Description: "Description",
|
||||
},
|
||||
SMTPConfig: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
Tls: true,
|
||||
From: "from",
|
||||
FromName: "fromName",
|
||||
ReplyToAddress: "replyToAddress",
|
||||
},
|
||||
WebhookConfig: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1457,10 +1478,11 @@ var _ types.ChannelChains = (*channels)(nil)
|
||||
|
||||
type channels struct {
|
||||
senders.Chain
|
||||
EmailConfig *email.Config
|
||||
}
|
||||
|
||||
func (c *channels) Email(context.Context) (*senders.Chain, *smtp.Config, error) {
|
||||
return &c.Chain, nil, nil
|
||||
func (c *channels) Email(context.Context) (*senders.Chain, *email.Config, error) {
|
||||
return &c.Chain, c.EmailConfig, nil
|
||||
}
|
||||
|
||||
func (c *channels) SMS(context.Context) (*senders.Chain, *sms.Config, error) {
|
||||
|
@@ -7,38 +7,61 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/fs"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/instrumenting"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/log"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
)
|
||||
|
||||
const smtpSpanName = "smtp.NotificationChannel"
|
||||
|
||||
func EmailChannels(
|
||||
ctx context.Context,
|
||||
emailConfig *smtp.Config,
|
||||
emailConfig *email.Config,
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) (chain *Chain, err error) {
|
||||
channels := make([]channels.NotificationChannel, 0, 3)
|
||||
p, err := smtp.InitChannel(emailConfig)
|
||||
logging.WithFields(
|
||||
"instance", authz.GetInstance(ctx).InstanceID(),
|
||||
).OnError(err).Debug("initializing SMTP channel failed")
|
||||
if err == nil {
|
||||
channels = append(
|
||||
channels,
|
||||
instrumenting.Wrap(
|
||||
ctx,
|
||||
p,
|
||||
smtpSpanName,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
),
|
||||
)
|
||||
if emailConfig.SMTPConfig != nil {
|
||||
p, err := smtp.InitChannel(emailConfig.SMTPConfig)
|
||||
logging.WithFields(
|
||||
"instance", authz.GetInstance(ctx).InstanceID(),
|
||||
).OnError(err).Debug("initializing SMTP channel failed")
|
||||
if err == nil {
|
||||
channels = append(
|
||||
channels,
|
||||
instrumenting.Wrap(
|
||||
ctx,
|
||||
p,
|
||||
smtpSpanName,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
if emailConfig.WebhookConfig != nil {
|
||||
webhookChannel, err := webhook.InitChannel(ctx, *emailConfig.WebhookConfig)
|
||||
logging.WithFields(
|
||||
"instance", authz.GetInstance(ctx).InstanceID(),
|
||||
"callurl", emailConfig.WebhookConfig.CallURL,
|
||||
).OnError(err).Debug("initializing JSON channel failed")
|
||||
if err == nil {
|
||||
channels = append(
|
||||
channels,
|
||||
instrumenting.Wrap(
|
||||
ctx,
|
||||
webhookChannel,
|
||||
webhookSpanName,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...)
|
||||
return ChainChannels(channels...), nil
|
||||
|
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/i18n"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/sms"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
"github.com/zitadel/zitadel/internal/notification/templates"
|
||||
@@ -23,7 +23,7 @@ type Notify func(
|
||||
) error
|
||||
|
||||
type ChannelChains interface {
|
||||
Email(context.Context) (*senders.Chain, *smtp.Config, error)
|
||||
Email(context.Context) (*senders.Chain, *email.Config, error)
|
||||
SMS(context.Context) (*senders.Chain, *sms.Config, error)
|
||||
Webhook(context.Context, webhook.Config) (*senders.Chain, error)
|
||||
}
|
||||
@@ -54,8 +54,9 @@ func SendEmail(
|
||||
ctx,
|
||||
channels,
|
||||
user,
|
||||
data.Subject,
|
||||
template,
|
||||
data,
|
||||
args,
|
||||
allowUnverifiedNotificationChannel,
|
||||
triggeringEvent,
|
||||
)
|
||||
|
@@ -3,9 +3,13 @@ package types
|
||||
import (
|
||||
"context"
|
||||
"html"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/messages"
|
||||
"github.com/zitadel/zitadel/internal/notification/templates"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -14,29 +18,56 @@ func generateEmail(
|
||||
ctx context.Context,
|
||||
channels ChannelChains,
|
||||
user *query.NotifyUser,
|
||||
subject,
|
||||
content string,
|
||||
template string,
|
||||
data templates.TemplateData,
|
||||
args map[string]interface{},
|
||||
lastEmail bool,
|
||||
triggeringEvent eventstore.Event,
|
||||
) error {
|
||||
content = html.UnescapeString(content)
|
||||
message := &messages.Email{
|
||||
Recipients: []string{user.VerifiedEmail},
|
||||
Subject: subject,
|
||||
Content: content,
|
||||
TriggeringEvent: triggeringEvent,
|
||||
}
|
||||
if lastEmail {
|
||||
message.Recipients = []string{user.LastEmail}
|
||||
}
|
||||
emailChannels, _, err := channels.Email(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emailChannels, config, err := channels.Email(ctx)
|
||||
logging.OnError(err).Error("could not create email channel")
|
||||
if emailChannels == nil || emailChannels.Len() == 0 {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "MAIL-83nof", "Errors.Notification.Channels.NotPresent")
|
||||
return zerrors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
return emailChannels.HandleMessage(message)
|
||||
recipient := user.VerifiedEmail
|
||||
if lastEmail {
|
||||
recipient = user.LastEmail
|
||||
}
|
||||
if config.SMTPConfig != nil {
|
||||
message := &messages.Email{
|
||||
Recipients: []string{recipient},
|
||||
Subject: data.Subject,
|
||||
Content: html.UnescapeString(template),
|
||||
TriggeringEvent: triggeringEvent,
|
||||
}
|
||||
return emailChannels.HandleMessage(message)
|
||||
}
|
||||
if config.WebhookConfig != nil {
|
||||
caseArgs := make(map[string]interface{}, len(args))
|
||||
for k, v := range args {
|
||||
caseArgs[strings.ToLower(string(k[0]))+k[1:]] = v
|
||||
}
|
||||
contextInfo := map[string]interface{}{
|
||||
"recipientEmailAddress": recipient,
|
||||
"eventType": triggeringEvent.Type(),
|
||||
"provider": config.ProviderConfig,
|
||||
}
|
||||
|
||||
message := &messages.JSON{
|
||||
Serializable: &serializableData{
|
||||
ContextInfo: contextInfo,
|
||||
TemplateData: data,
|
||||
Args: caseArgs,
|
||||
},
|
||||
TriggeringEvent: triggeringEvent,
|
||||
}
|
||||
webhookChannels, err := channels.Webhook(ctx, *config.WebhookConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return webhookChannels.HandleMessage(message)
|
||||
}
|
||||
return zerrors.ThrowPreconditionFailed(nil, "MAIL-83nof", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
|
||||
func mapNotifyUserToArgs(user *query.NotifyUser, args map[string]interface{}) map[string]interface{} {
|
||||
|
@@ -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
|
||||
|
@@ -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",
|
||||
},
|
||||
|
@@ -256,7 +256,7 @@ func prepareSMSConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
|
||||
&twilioConfig.token,
|
||||
&twilioConfig.senderNumber,
|
||||
|
||||
&httpConfig.smsID,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
)
|
||||
|
||||
@@ -268,7 +268,7 @@ func prepareSMSConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBu
|
||||
}
|
||||
|
||||
twilioConfig.set(config)
|
||||
httpConfig.set(config)
|
||||
httpConfig.setSMS(config)
|
||||
|
||||
return config, nil
|
||||
}
|
||||
@@ -322,7 +322,7 @@ func prepareSMSConfigsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
&twilioConfig.token,
|
||||
&twilioConfig.senderNumber,
|
||||
|
||||
&httpConfig.smsID,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
|
||||
&configs.Count,
|
||||
@@ -333,7 +333,7 @@ func prepareSMSConfigsQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
}
|
||||
|
||||
twilioConfig.set(config)
|
||||
httpConfig.set(config)
|
||||
httpConfig.setSMS(config)
|
||||
|
||||
configs.Configs = append(configs.Configs, config)
|
||||
}
|
||||
@@ -361,12 +361,12 @@ func (c sqlTwilioConfig) set(smsConfig *SMSConfig) {
|
||||
}
|
||||
|
||||
type sqlHTTPConfig struct {
|
||||
smsID sql.NullString
|
||||
id sql.NullString
|
||||
endpoint sql.NullString
|
||||
}
|
||||
|
||||
func (c sqlHTTPConfig) set(smsConfig *SMSConfig) {
|
||||
if !c.smsID.Valid {
|
||||
func (c sqlHTTPConfig) setSMS(smsConfig *SMSConfig) {
|
||||
if !c.id.Valid {
|
||||
return
|
||||
}
|
||||
smsConfig.HTTPConfig = &HTTP{
|
||||
|
@@ -52,34 +52,6 @@ var (
|
||||
name: projection.SMTPConfigColumnSequence,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnTLS = Column{
|
||||
name: projection.SMTPConfigColumnTLS,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnSenderAddress = Column{
|
||||
name: projection.SMTPConfigColumnSenderAddress,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnSenderName = Column{
|
||||
name: projection.SMTPConfigColumnSenderName,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnReplyToAddress = Column{
|
||||
name: projection.SMTPConfigColumnReplyToAddress,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnSMTPHost = Column{
|
||||
name: projection.SMTPConfigColumnSMTPHost,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnSMTPUser = Column{
|
||||
name: projection.SMTPConfigColumnSMTPUser,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnSMTPPassword = Column{
|
||||
name: projection.SMTPConfigColumnSMTPPassword,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
SMTPConfigColumnID = Column{
|
||||
name: projection.SMTPConfigColumnID,
|
||||
table: smtpConfigsTable,
|
||||
@@ -92,13 +64,82 @@ var (
|
||||
name: projection.SMTPConfigColumnDescription,
|
||||
table: smtpConfigsTable,
|
||||
}
|
||||
|
||||
smtpConfigsSMTPTable = table{
|
||||
name: projection.SMTPConfigTable,
|
||||
instanceIDCol: projection.SMTPConfigColumnInstanceID,
|
||||
}
|
||||
SMTPConfigSMTPColumnInstanceID = Column{
|
||||
name: projection.SMTPConfigColumnInstanceID,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnID = Column{
|
||||
name: projection.SMTPConfigColumnID,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnTLS = Column{
|
||||
name: projection.SMTPConfigSMTPColumnTLS,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnSenderAddress = Column{
|
||||
name: projection.SMTPConfigSMTPColumnSenderAddress,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnSenderName = Column{
|
||||
name: projection.SMTPConfigSMTPColumnSenderName,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnReplyToAddress = Column{
|
||||
name: projection.SMTPConfigSMTPColumnReplyToAddress,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnHost = Column{
|
||||
name: projection.SMTPConfigSMTPColumnHost,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnUser = Column{
|
||||
name: projection.SMTPConfigSMTPColumnUser,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnPassword = Column{
|
||||
name: projection.SMTPConfigSMTPColumnPassword,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
|
||||
smtpConfigsHTTPTable = table{
|
||||
name: projection.SMTPConfigHTTPTable,
|
||||
instanceIDCol: projection.SMTPConfigHTTPColumnInstanceID,
|
||||
}
|
||||
SMTPConfigHTTPColumnInstanceID = Column{
|
||||
name: projection.SMTPConfigHTTPColumnInstanceID,
|
||||
table: smtpConfigsHTTPTable,
|
||||
}
|
||||
SMTPConfigHTTPColumnID = Column{
|
||||
name: projection.SMTPConfigHTTPColumnID,
|
||||
table: smtpConfigsHTTPTable,
|
||||
}
|
||||
SMTPConfigHTTPColumnEndpoint = Column{
|
||||
name: projection.SMTPConfigHTTPColumnEndpoint,
|
||||
table: smtpConfigsHTTPTable,
|
||||
}
|
||||
)
|
||||
|
||||
type SMTPConfig struct {
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
AggregateID string
|
||||
ID string
|
||||
Sequence uint64
|
||||
Description string
|
||||
|
||||
SMTPConfig *SMTP
|
||||
HTTPConfig *HTTP
|
||||
|
||||
State domain.SMTPConfigState
|
||||
}
|
||||
|
||||
type SMTP struct {
|
||||
TLS bool
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
@@ -106,9 +147,6 @@ type SMTPConfig struct {
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
ID string
|
||||
State domain.SMTPConfigState
|
||||
Description string
|
||||
}
|
||||
|
||||
func (q *Queries) SMTPConfigActive(ctx context.Context, resourceOwner string) (config *SMTPConfig, err error) {
|
||||
@@ -132,15 +170,14 @@ func (q *Queries) SMTPConfigActive(ctx context.Context, resourceOwner string) (c
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (q *Queries) SMTPConfigByID(ctx context.Context, instanceID, resourceOwner, id string) (config *SMTPConfig, err error) {
|
||||
func (q *Queries) SMTPConfigByID(ctx context.Context, instanceID, id string) (config *SMTPConfig, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareSMTPConfigQuery(ctx, q.client)
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
SMTPConfigColumnResourceOwner.identifier(): resourceOwner,
|
||||
SMTPConfigColumnInstanceID.identifier(): instanceID,
|
||||
SMTPConfigColumnID.identifier(): id,
|
||||
SMTPConfigColumnInstanceID.identifier(): instanceID,
|
||||
SMTPConfigColumnID.identifier(): id,
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-8f8gw", "Errors.Query.SQLStatement")
|
||||
@@ -161,35 +198,49 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
SMTPConfigColumnChangeDate.identifier(),
|
||||
SMTPConfigColumnResourceOwner.identifier(),
|
||||
SMTPConfigColumnSequence.identifier(),
|
||||
SMTPConfigColumnTLS.identifier(),
|
||||
SMTPConfigColumnSenderAddress.identifier(),
|
||||
SMTPConfigColumnSenderName.identifier(),
|
||||
SMTPConfigColumnReplyToAddress.identifier(),
|
||||
SMTPConfigColumnSMTPHost.identifier(),
|
||||
SMTPConfigColumnSMTPUser.identifier(),
|
||||
SMTPConfigColumnSMTPPassword.identifier(),
|
||||
SMTPConfigColumnID.identifier(),
|
||||
SMTPConfigColumnState.identifier(),
|
||||
SMTPConfigColumnDescription.identifier()).
|
||||
From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||
SMTPConfigColumnDescription.identifier(),
|
||||
|
||||
SMTPConfigSMTPColumnID.identifier(),
|
||||
SMTPConfigSMTPColumnTLS.identifier(),
|
||||
SMTPConfigSMTPColumnSenderAddress.identifier(),
|
||||
SMTPConfigSMTPColumnSenderName.identifier(),
|
||||
SMTPConfigSMTPColumnReplyToAddress.identifier(),
|
||||
SMTPConfigSMTPColumnHost.identifier(),
|
||||
SMTPConfigSMTPColumnUser.identifier(),
|
||||
SMTPConfigSMTPColumnPassword.identifier(),
|
||||
|
||||
SMTPConfigHTTPColumnID.identifier(),
|
||||
SMTPConfigHTTPColumnEndpoint.identifier()).
|
||||
From(smtpConfigsTable.identifier()).
|
||||
LeftJoin(join(SMTPConfigSMTPColumnID, SMTPConfigColumnID)).
|
||||
LeftJoin(join(SMTPConfigHTTPColumnID, SMTPConfigColumnID) + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*SMTPConfig, error) {
|
||||
config := new(SMTPConfig)
|
||||
var (
|
||||
smtpConfig = sqlSmtpConfig{}
|
||||
httpConfig = sqlHTTPConfig{}
|
||||
)
|
||||
err := row.Scan(
|
||||
&config.CreationDate,
|
||||
&config.ChangeDate,
|
||||
&config.ResourceOwner,
|
||||
&config.Sequence,
|
||||
&config.TLS,
|
||||
&config.SenderAddress,
|
||||
&config.SenderName,
|
||||
&config.ReplyToAddress,
|
||||
&config.Host,
|
||||
&config.User,
|
||||
&password,
|
||||
&config.ID,
|
||||
&config.State,
|
||||
&config.Description,
|
||||
&smtpConfig.id,
|
||||
&smtpConfig.tls,
|
||||
&smtpConfig.senderAddress,
|
||||
&smtpConfig.senderName,
|
||||
&smtpConfig.replyToAddress,
|
||||
&smtpConfig.host,
|
||||
&smtpConfig.user,
|
||||
&password,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
@@ -197,7 +248,9 @@ func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectB
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-9k87F", "Errors.Internal")
|
||||
}
|
||||
config.Password = password
|
||||
smtpConfig.password = password
|
||||
smtpConfig.set(config)
|
||||
httpConfig.setSMTP(config)
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
@@ -208,38 +261,53 @@ func prepareSMTPConfigsQuery(ctx context.Context, db prepareDatabase) (sq.Select
|
||||
SMTPConfigColumnChangeDate.identifier(),
|
||||
SMTPConfigColumnResourceOwner.identifier(),
|
||||
SMTPConfigColumnSequence.identifier(),
|
||||
SMTPConfigColumnTLS.identifier(),
|
||||
SMTPConfigColumnSenderAddress.identifier(),
|
||||
SMTPConfigColumnSenderName.identifier(),
|
||||
SMTPConfigColumnReplyToAddress.identifier(),
|
||||
SMTPConfigColumnSMTPHost.identifier(),
|
||||
SMTPConfigColumnSMTPUser.identifier(),
|
||||
SMTPConfigColumnSMTPPassword.identifier(),
|
||||
SMTPConfigColumnID.identifier(),
|
||||
SMTPConfigColumnState.identifier(),
|
||||
SMTPConfigColumnDescription.identifier(),
|
||||
countColumn.identifier()).
|
||||
From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||
|
||||
SMTPConfigSMTPColumnID.identifier(),
|
||||
SMTPConfigSMTPColumnTLS.identifier(),
|
||||
SMTPConfigSMTPColumnSenderAddress.identifier(),
|
||||
SMTPConfigSMTPColumnSenderName.identifier(),
|
||||
SMTPConfigSMTPColumnReplyToAddress.identifier(),
|
||||
SMTPConfigSMTPColumnHost.identifier(),
|
||||
SMTPConfigSMTPColumnUser.identifier(),
|
||||
SMTPConfigSMTPColumnPassword.identifier(),
|
||||
|
||||
SMTPConfigHTTPColumnID.identifier(),
|
||||
SMTPConfigHTTPColumnEndpoint.identifier(),
|
||||
countColumn.identifier(),
|
||||
).From(smtpConfigsTable.identifier()).
|
||||
LeftJoin(join(SMTPConfigSMTPColumnID, SMTPConfigColumnID)).
|
||||
LeftJoin(join(SMTPConfigHTTPColumnID, SMTPConfigColumnID) + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*SMTPConfigs, error) {
|
||||
configs := &SMTPConfigs{Configs: []*SMTPConfig{}}
|
||||
for rows.Next() {
|
||||
config := new(SMTPConfig)
|
||||
password := new(crypto.CryptoValue)
|
||||
var (
|
||||
smtpConfig = sqlSmtpConfig{}
|
||||
httpConfig = sqlHTTPConfig{}
|
||||
)
|
||||
err := rows.Scan(
|
||||
&config.CreationDate,
|
||||
&config.ChangeDate,
|
||||
&config.ResourceOwner,
|
||||
&config.Sequence,
|
||||
&config.TLS,
|
||||
&config.SenderAddress,
|
||||
&config.SenderName,
|
||||
&config.ReplyToAddress,
|
||||
&config.Host,
|
||||
&config.User,
|
||||
&config.Password,
|
||||
&config.ID,
|
||||
&config.State,
|
||||
&config.Description,
|
||||
&smtpConfig.id,
|
||||
&smtpConfig.tls,
|
||||
&smtpConfig.senderAddress,
|
||||
&smtpConfig.senderName,
|
||||
&smtpConfig.replyToAddress,
|
||||
&smtpConfig.host,
|
||||
&smtpConfig.user,
|
||||
&password,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
&configs.Count,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -248,6 +316,9 @@ func prepareSMTPConfigsQuery(ctx context.Context, db prepareDatabase) (sq.Select
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-9k87F", "Errors.Internal")
|
||||
}
|
||||
smtpConfig.password = password
|
||||
smtpConfig.set(config)
|
||||
httpConfig.setSMTP(config)
|
||||
configs.Configs = append(configs.Configs, config)
|
||||
}
|
||||
return configs, nil
|
||||
@@ -277,3 +348,38 @@ func (q *Queries) SearchSMTPConfigs(ctx context.Context, queries *SMTPConfigsSea
|
||||
configs.State, err = q.latestState(ctx, smsConfigsTable)
|
||||
return configs, err
|
||||
}
|
||||
|
||||
type sqlSmtpConfig struct {
|
||||
id sql.NullString
|
||||
tls sql.NullBool
|
||||
senderAddress sql.NullString
|
||||
senderName sql.NullString
|
||||
replyToAddress sql.NullString
|
||||
host sql.NullString
|
||||
user sql.NullString
|
||||
password *crypto.CryptoValue
|
||||
}
|
||||
|
||||
func (c sqlSmtpConfig) set(smtpConfig *SMTPConfig) {
|
||||
if !c.id.Valid {
|
||||
return
|
||||
}
|
||||
smtpConfig.SMTPConfig = &SMTP{
|
||||
TLS: c.tls.Bool,
|
||||
SenderAddress: c.senderAddress.String,
|
||||
SenderName: c.senderName.String,
|
||||
ReplyToAddress: c.replyToAddress.String,
|
||||
Host: c.host.String,
|
||||
User: c.user.String,
|
||||
Password: c.password,
|
||||
}
|
||||
}
|
||||
|
||||
func (c sqlHTTPConfig) setSMTP(smtpConfig *SMTPConfig) {
|
||||
if !c.id.Valid {
|
||||
return
|
||||
}
|
||||
smtpConfig.HTTPConfig = &HTTP{
|
||||
Endpoint: c.endpoint.String,
|
||||
}
|
||||
}
|
||||
|
@@ -14,27 +14,36 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs2.creation_date,` +
|
||||
` projections.smtp_configs2.change_date,` +
|
||||
` projections.smtp_configs2.resource_owner,` +
|
||||
` projections.smtp_configs2.sequence,` +
|
||||
` projections.smtp_configs2.tls,` +
|
||||
` projections.smtp_configs2.sender_address,` +
|
||||
` projections.smtp_configs2.sender_name,` +
|
||||
` projections.smtp_configs2.reply_to_address,` +
|
||||
` projections.smtp_configs2.host,` +
|
||||
` projections.smtp_configs2.username,` +
|
||||
` projections.smtp_configs2.password,` +
|
||||
` projections.smtp_configs2.id,` +
|
||||
` projections.smtp_configs2.state,` +
|
||||
` projections.smtp_configs2.description` +
|
||||
` FROM projections.smtp_configs2` +
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs3.creation_date,` +
|
||||
` projections.smtp_configs3.change_date,` +
|
||||
` projections.smtp_configs3.resource_owner,` +
|
||||
` projections.smtp_configs3.sequence,` +
|
||||
` projections.smtp_configs3.id,` +
|
||||
` projections.smtp_configs3.state,` +
|
||||
` projections.smtp_configs3.description,` +
|
||||
` projections.smtp_configs3_smtp.id,` +
|
||||
` projections.smtp_configs3_smtp.tls,` +
|
||||
` projections.smtp_configs3_smtp.sender_address,` +
|
||||
` projections.smtp_configs3_smtp.sender_name,` +
|
||||
` projections.smtp_configs3_smtp.reply_to_address,` +
|
||||
` projections.smtp_configs3_smtp.host,` +
|
||||
` projections.smtp_configs3_smtp.username,` +
|
||||
` projections.smtp_configs3_smtp.password,` +
|
||||
` projections.smtp_configs3_http.id,` +
|
||||
` projections.smtp_configs3_http.endpoint` +
|
||||
` FROM projections.smtp_configs3` +
|
||||
` LEFT JOIN projections.smtp_configs3_smtp ON projections.smtp_configs3.id = projections.smtp_configs3_smtp.id AND projections.smtp_configs3.instance_id = projections.smtp_configs3_smtp.instance_id` +
|
||||
` LEFT JOIN projections.smtp_configs3_http ON projections.smtp_configs3.id = projections.smtp_configs3_http.id AND projections.smtp_configs3.instance_id = projections.smtp_configs3_http.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`
|
||||
prepareSMTPConfigCols = []string{
|
||||
"creation_date",
|
||||
"change_date",
|
||||
"resource_owner",
|
||||
"sequence",
|
||||
"id",
|
||||
"state",
|
||||
"description",
|
||||
"id",
|
||||
"tls",
|
||||
"sender_address",
|
||||
"sender_name",
|
||||
@@ -43,8 +52,7 @@ var (
|
||||
"smtp_user",
|
||||
"smtp_password",
|
||||
"id",
|
||||
"state",
|
||||
"description",
|
||||
"endpoint",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -89,6 +97,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
"2232323",
|
||||
domain.SMTPConfigStateActive,
|
||||
"test",
|
||||
"2232323",
|
||||
true,
|
||||
"sender",
|
||||
"name",
|
||||
@@ -96,27 +108,69 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
"2232323",
|
||||
domain.SMTPConfigStateActive,
|
||||
"test",
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
TLS: true,
|
||||
SenderAddress: "sender",
|
||||
SenderName: "name",
|
||||
ReplyToAddress: "reply-to",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
Description: "test",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
SMTPConfig: &SMTP{
|
||||
TLS: true,
|
||||
SenderAddress: "sender",
|
||||
SenderName: "name",
|
||||
ReplyToAddress: "reply-to",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
Description: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareSMTPConfigQuery found, http",
|
||||
prepare: prepareSMTPConfigQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(prepareSMTPConfigStmt),
|
||||
prepareSMTPConfigCols,
|
||||
[]driver.Value{
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
"2232323",
|
||||
domain.SMTPConfigStateActive,
|
||||
"test",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"2232323",
|
||||
"endpoint",
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
HTTPConfig: &HTTP{
|
||||
Endpoint: "endpoint",
|
||||
},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
Description: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -131,6 +185,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211109),
|
||||
"44442323",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test2",
|
||||
"44442323",
|
||||
true,
|
||||
"sender2",
|
||||
"name2",
|
||||
@@ -138,27 +196,28 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
"host2",
|
||||
"user2",
|
||||
&crypto.CryptoValue{},
|
||||
"44442323",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test2",
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
TLS: true,
|
||||
SenderAddress: "sender2",
|
||||
SenderName: "name2",
|
||||
ReplyToAddress: "reply-to2",
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "44442323",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test2",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
SMTPConfig: &SMTP{
|
||||
TLS: true,
|
||||
SenderAddress: "sender2",
|
||||
SenderName: "name2",
|
||||
ReplyToAddress: "reply-to2",
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
ID: "44442323",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test2",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -173,6 +232,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211109),
|
||||
"23234444",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test3",
|
||||
"23234444",
|
||||
true,
|
||||
"sender3",
|
||||
"name3",
|
||||
@@ -180,27 +243,28 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
"host3",
|
||||
"user3",
|
||||
&crypto.CryptoValue{},
|
||||
"23234444",
|
||||
domain.SMTPConfigStateInactive,
|
||||
"test3",
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &SMTPConfig{
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
TLS: true,
|
||||
SenderAddress: "sender3",
|
||||
SenderName: "name3",
|
||||
ReplyToAddress: "reply-to3",
|
||||
Host: "host3",
|
||||
User: "user3",
|
||||
Password: &crypto.CryptoValue{},
|
||||
ID: "23234444",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test3",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211109,
|
||||
SMTPConfig: &SMTP{
|
||||
TLS: true,
|
||||
SenderAddress: "sender3",
|
||||
SenderName: "name3",
|
||||
ReplyToAddress: "reply-to3",
|
||||
Host: "host3",
|
||||
User: "user3",
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
ID: "23234444",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
Description: "test3",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@@ -12,12 +12,14 @@ func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SecretGeneratorAddedEventType, SecretGeneratorAddedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SecretGeneratorChangedEventType, SecretGeneratorChangedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SecretGeneratorRemovedEventType, SecretGeneratorRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigAddedEventType, SMTPConfigAddedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigChangedEventType, SMTPConfigChangedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigActivatedEventType, SMTPConfigActivatedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigDeactivatedEventType, SMTPConfigDeactivatedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigPasswordChangedEventType, SMTPConfigPasswordChangedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigRemovedEventType, SMTPConfigRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigAddedEventType, eventstore.GenericEventMapper[SMTPConfigAddedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigChangedEventType, eventstore.GenericEventMapper[SMTPConfigChangedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigActivatedEventType, eventstore.GenericEventMapper[SMTPConfigActivatedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigDeactivatedEventType, eventstore.GenericEventMapper[SMTPConfigDeactivatedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigPasswordChangedEventType, eventstore.GenericEventMapper[SMTPConfigPasswordChangedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigHTTPAddedEventType, eventstore.GenericEventMapper[SMTPConfigHTTPAddedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigHTTPChangedEventType, eventstore.GenericEventMapper[SMTPConfigHTTPChangedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMTPConfigRemovedEventType, eventstore.GenericEventMapper[SMTPConfigRemovedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMSConfigTwilioAddedEventType, eventstore.GenericEventMapper[SMSConfigTwilioAddedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMSConfigTwilioChangedEventType, eventstore.GenericEventMapper[SMSConfigTwilioChangedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SMSConfigTwilioTokenChangedEventType, eventstore.GenericEventMapper[SMSConfigTwilioTokenChangedEvent])
|
||||
|
@@ -10,16 +10,19 @@ import (
|
||||
|
||||
const (
|
||||
smtpConfigPrefix = "smtp.config."
|
||||
httpConfigPrefix = "http."
|
||||
SMTPConfigAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + "added"
|
||||
SMTPConfigChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "changed"
|
||||
SMTPConfigPasswordChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + "password.changed"
|
||||
SMTPConfigHTTPAddedEventType = instanceEventTypePrefix + smtpConfigPrefix + httpConfigPrefix + "added"
|
||||
SMTPConfigHTTPChangedEventType = instanceEventTypePrefix + smtpConfigPrefix + httpConfigPrefix + "changed"
|
||||
SMTPConfigRemovedEventType = instanceEventTypePrefix + smtpConfigPrefix + "removed"
|
||||
SMTPConfigActivatedEventType = instanceEventTypePrefix + smtpConfigPrefix + "activated"
|
||||
SMTPConfigDeactivatedEventType = instanceEventTypePrefix + smtpConfigPrefix + "deactivated"
|
||||
)
|
||||
|
||||
type SMTPConfigAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
|
||||
ID string `json:"id,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
@@ -45,7 +48,7 @@ func NewSMTPConfigAddedEvent(
|
||||
password *crypto.CryptoValue,
|
||||
) *SMTPConfigAddedEvent {
|
||||
return &SMTPConfigAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigAddedEventType,
|
||||
@@ -61,6 +64,9 @@ func NewSMTPConfigAddedEvent(
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
func (e *SMTPConfigAddedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigAddedEvent) Payload() interface{} {
|
||||
return e
|
||||
@@ -70,29 +76,21 @@ func (e *SMTPConfigAddedEvent) UniqueConstraints() []*eventstore.UniqueConstrain
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigAddedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigAdded := &SMTPConfigAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigAdded)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-39fks", "unable to unmarshal smtp config added")
|
||||
}
|
||||
|
||||
return smtpConfigAdded, nil
|
||||
type SMTPConfigChangedEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
FromAddress *string `json:"senderAddress,omitempty"`
|
||||
FromName *string `json:"senderName,omitempty"`
|
||||
ReplyToAddress *string `json:"replyToAddress,omitempty"`
|
||||
TLS *bool `json:"tls,omitempty"`
|
||||
Host *string `json:"host,omitempty"`
|
||||
User *string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
type SMTPConfigChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
FromAddress *string `json:"senderAddress,omitempty"`
|
||||
FromName *string `json:"senderName,omitempty"`
|
||||
ReplyToAddress *string `json:"replyToAddress,omitempty"`
|
||||
TLS *bool `json:"tls,omitempty"`
|
||||
Host *string `json:"host,omitempty"`
|
||||
User *string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
func (e *SMTPConfigChangedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigChangedEvent) Payload() interface{} {
|
||||
@@ -113,7 +111,7 @@ func NewSMTPConfigChangeEvent(
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "IAM-o0pWf", "Errors.NoChangesFound")
|
||||
}
|
||||
changeEvent := &SMTPConfigChangedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigChangedEventType,
|
||||
@@ -182,23 +180,10 @@ func ChangeSMTPConfigSMTPPassword(password *crypto.CryptoValue) func(event *SMTP
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigChangedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
e := &SMTPConfigChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
|
||||
err := event.Unmarshal(e)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-m09oo", "unable to unmarshal smtp changed")
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
type SMTPConfigPasswordChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigPasswordChangedEvent(
|
||||
@@ -208,7 +193,7 @@ func NewSMTPConfigPasswordChangedEvent(
|
||||
password *crypto.CryptoValue,
|
||||
) *SMTPConfigPasswordChangedEvent {
|
||||
return &SMTPConfigPasswordChangedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigPasswordChangedEventType,
|
||||
@@ -217,6 +202,10 @@ func NewSMTPConfigPasswordChangedEvent(
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigPasswordChangedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigPasswordChangedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
@@ -225,21 +214,109 @@ func (e *SMTPConfigPasswordChangedEvent) UniqueConstraints() []*eventstore.Uniqu
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigPasswordChangedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigPasswordChanged := &SMTPConfigPasswordChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigPasswordChanged)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-99iNF", "unable to unmarshal smtp config password changed")
|
||||
}
|
||||
type SMTPConfigHTTPAddedEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
|
||||
return smtpConfigPasswordChanged, nil
|
||||
ID string `json:"id,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigHTTPAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id, description string,
|
||||
endpoint string,
|
||||
) *SMTPConfigHTTPAddedEvent {
|
||||
return &SMTPConfigHTTPAddedEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigHTTPAddedEventType,
|
||||
),
|
||||
ID: id,
|
||||
Description: description,
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPAddedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPAddedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPAddedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
type SMTPConfigHTTPChangedEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Endpoint *string `json:"endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPChangedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPChangedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *SMTPConfigHTTPChangedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSMTPConfigHTTPChangeEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
id string,
|
||||
changes []SMTPConfigHTTPChanges,
|
||||
) (*SMTPConfigHTTPChangedEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "IAM-o0pWf", "Errors.NoChangesFound")
|
||||
}
|
||||
changeEvent := &SMTPConfigHTTPChangedEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigHTTPChangedEventType,
|
||||
),
|
||||
ID: id,
|
||||
}
|
||||
for _, change := range changes {
|
||||
change(changeEvent)
|
||||
}
|
||||
return changeEvent, nil
|
||||
}
|
||||
|
||||
type SMTPConfigHTTPChanges func(event *SMTPConfigHTTPChangedEvent)
|
||||
|
||||
func ChangeSMTPConfigHTTPID(id string) func(event *SMTPConfigHTTPChangedEvent) {
|
||||
return func(e *SMTPConfigHTTPChangedEvent) {
|
||||
e.ID = id
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigHTTPDescription(description string) func(event *SMTPConfigHTTPChangedEvent) {
|
||||
return func(e *SMTPConfigHTTPChangedEvent) {
|
||||
e.Description = &description
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigHTTPEndpoint(endpoint string) func(event *SMTPConfigHTTPChangedEvent) {
|
||||
return func(e *SMTPConfigHTTPChangedEvent) {
|
||||
e.Endpoint = &endpoint
|
||||
}
|
||||
}
|
||||
|
||||
type SMTPConfigActivatedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigActivatedEvent(
|
||||
@@ -248,7 +325,7 @@ func NewSMTPConfigActivatedEvent(
|
||||
id string,
|
||||
) *SMTPConfigActivatedEvent {
|
||||
return &SMTPConfigActivatedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigActivatedEventType,
|
||||
@@ -257,6 +334,10 @@ func NewSMTPConfigActivatedEvent(
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigActivatedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigActivatedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
@@ -265,21 +346,9 @@ func (e *SMTPConfigActivatedEvent) UniqueConstraints() []*eventstore.UniqueConst
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigActivatedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigActivated := &SMTPConfigActivatedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigActivated)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-KPr5t", "unable to unmarshal smtp config removed")
|
||||
}
|
||||
|
||||
return smtpConfigActivated, nil
|
||||
}
|
||||
|
||||
type SMTPConfigDeactivatedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigDeactivatedEvent(
|
||||
@@ -288,7 +357,7 @@ func NewSMTPConfigDeactivatedEvent(
|
||||
id string,
|
||||
) *SMTPConfigDeactivatedEvent {
|
||||
return &SMTPConfigDeactivatedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigDeactivatedEventType,
|
||||
@@ -297,6 +366,10 @@ func NewSMTPConfigDeactivatedEvent(
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigDeactivatedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
|
||||
func (e *SMTPConfigDeactivatedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
@@ -305,21 +378,9 @@ func (e *SMTPConfigDeactivatedEvent) UniqueConstraints() []*eventstore.UniqueCon
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigDeactivatedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigDeactivated := &SMTPConfigDeactivatedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigDeactivated)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-KPr5t", "unable to unmarshal smtp config removed")
|
||||
}
|
||||
|
||||
return smtpConfigDeactivated, nil
|
||||
}
|
||||
|
||||
type SMTPConfigRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigRemovedEvent(
|
||||
@@ -328,7 +389,7 @@ func NewSMTPConfigRemovedEvent(
|
||||
id string,
|
||||
) *SMTPConfigRemovedEvent {
|
||||
return &SMTPConfigRemovedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
SMTPConfigRemovedEventType,
|
||||
@@ -337,6 +398,9 @@ func NewSMTPConfigRemovedEvent(
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigRemovedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
func (e *SMTPConfigRemovedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
@@ -344,15 +408,3 @@ func (e *SMTPConfigRemovedEvent) Payload() interface{} {
|
||||
func (e *SMTPConfigRemovedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SMTPConfigRemovedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
smtpConfigRemoved := &SMTPConfigRemovedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := event.Unmarshal(smtpConfigRemoved)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "IAM-DVw1s", "unable to unmarshal smtp config removed")
|
||||
}
|
||||
|
||||
return smtpConfigRemoved, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user