mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:17:32 +00:00
feat: Notification providers config (#3212)
* feat: add login check lifetimes to login policy * feat: org features test * feat: debug notificatiaon events * feat: debug notification file/log commands * feat: add requests to proto * feat: add api for debug notification providers file/log * feat: add projection for debug notifiication providers * feat: requests * feat: merge v2 * feat: add settings proto to generate * feat: notifiaction providers * fix: remove unused code * Update iam_converter.go Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/k3a/html2text"
|
||||
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
)
|
||||
|
||||
func InitChatChannel(config ChatConfig) (channels.NotificationChannel, error) {
|
||||
|
||||
url, err := url.Parse(config.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logging.Log("NOTIF-kSvPp").Debug("successfully initialized chat email and sms channel")
|
||||
|
||||
return channels.HandleMessageFunc(func(message channels.Message) error {
|
||||
contentText := message.GetContent()
|
||||
if config.Compact {
|
||||
contentText = html2text.HTML2Text(contentText)
|
||||
}
|
||||
for _, splittedMsg := range splitMessage(contentText, config.SplitCount) {
|
||||
if err := sendMessage(splittedMsg, url); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func sendMessage(message string, chatUrl *url.URL) error {
|
||||
chatMsg := &struct {
|
||||
Text string `json:"text"`
|
||||
}{Text: message}
|
||||
req, err := json.Marshal(chatMsg)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowInternal(err, "PROVI-s8uie", "Could not unmarshal content")
|
||||
}
|
||||
|
||||
response, err := http.Post(chatUrl.String(), "application/json; charset=UTF-8", bytes.NewReader(req))
|
||||
if err != nil {
|
||||
return caos_errs.ThrowInternal(err, "PROVI-si93s", "unable to send message")
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
defer response.Body.Close()
|
||||
bodyBytes, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowInternal(err, "PROVI-PSLd3", "unable to read response message")
|
||||
}
|
||||
logging.LogWithFields("PROVI-PS0kx", "Body", string(bodyBytes)).Warn("Chat Message post didnt get 200 OK")
|
||||
return caos_errs.ThrowInternal(nil, "PROVI-LSopw", string(bodyBytes))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func splitMessage(message string, count int) []string {
|
||||
if count == 0 {
|
||||
return []string{message}
|
||||
}
|
||||
var splits []string
|
||||
var l, r int
|
||||
for l, r = 0, count; r < len(message); l, r = r, r+count {
|
||||
for !utf8.RuneStart(message[r]) {
|
||||
r--
|
||||
}
|
||||
splits = append(splits, message[l:r])
|
||||
}
|
||||
splits = append(splits, message[l:])
|
||||
return splits
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package chat
|
||||
|
||||
type ChatConfig struct {
|
||||
// Defaults to true if DebugMode is set to true
|
||||
Enabled *bool
|
||||
Url string
|
||||
SplitCount int
|
||||
Compact bool
|
||||
}
|
@@ -19,9 +19,11 @@ import (
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
)
|
||||
|
||||
func InitFSChannel(config FSConfig) (channels.NotificationChannel, error) {
|
||||
|
||||
if err := os.MkdirAll(config.Path, os.ModePerm); err != nil {
|
||||
func InitFSChannel(path string, config FSConfig) (channels.NotificationChannel, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if err := os.MkdirAll(path, os.ModePerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -46,6 +48,6 @@ func InitFSChannel(config FSConfig) (channels.NotificationChannel, error) {
|
||||
return caos_errors.ThrowUnimplementedf(nil, "NOTIF-6f9a1", "filesystem provider doesn't support message type %T", message)
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(filepath.Join(config.Path, fileName), []byte(content), 0666)
|
||||
return ioutil.WriteFile(filepath.Join(path, fileName), []byte(content), 0666)
|
||||
}), nil
|
||||
}
|
||||
|
@@ -2,6 +2,5 @@ package fs
|
||||
|
||||
type FSConfig struct {
|
||||
Enabled bool
|
||||
Path string
|
||||
Compact bool
|
||||
}
|
||||
|
@@ -24,12 +24,15 @@ type Email struct {
|
||||
|
||||
func InitSMTPChannel(ctx context.Context, getSMTPConfig func(ctx context.Context) (*EmailConfig, error)) (*Email, error) {
|
||||
smtpConfig, err := getSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logging.Log("NOTIF-4n4Ih").Debug("successfully initialized smtp email channel")
|
||||
logging.New().Debug("successfully initialized smtp email channel")
|
||||
|
||||
return &Email{
|
||||
smtpClient: client,
|
||||
|
@@ -18,10 +18,10 @@ type Config struct {
|
||||
Repository eventsourcing.Config
|
||||
}
|
||||
|
||||
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) {
|
||||
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) {
|
||||
statikFS, err := fs.NewWithNamespace("notification")
|
||||
logging.OnError(err).Panic("unable to start listener")
|
||||
|
||||
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix, smtpPasswordEncAlg)
|
||||
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix, smtpPasswordEncAlg, smsCrypto)
|
||||
logging.OnError(err).Panic("unable to start app")
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ func (h *handler) Eventstore() v1.Eventstore {
|
||||
return h.es
|
||||
}
|
||||
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) []queryv1.Handler {
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) []queryv1.Handler {
|
||||
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey)
|
||||
logging.OnError(err).Fatal("error create new aes crypto")
|
||||
|
||||
@@ -52,6 +52,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
||||
dir,
|
||||
assetsPrefix,
|
||||
smtpPasswordEncAlg,
|
||||
smsCrypto,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/command"
|
||||
@@ -43,18 +46,10 @@ type Notification struct {
|
||||
assetsPrefix string
|
||||
queries *query.Queries
|
||||
smtpPasswordCrypto crypto.EncryptionAlgorithm
|
||||
smsTokenCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
|
||||
func newNotification(
|
||||
handler handler,
|
||||
command *command.Commands,
|
||||
query *query.Queries,
|
||||
defaults sd.SystemDefaults,
|
||||
aesCrypto crypto.EncryptionAlgorithm,
|
||||
statikDir http.FileSystem,
|
||||
assetsPrefix string,
|
||||
smtpPasswordEncAlg crypto.EncryptionAlgorithm,
|
||||
) *Notification {
|
||||
func newNotification(handler handler, command *command.Commands, query *query.Queries, defaults sd.SystemDefaults, aesCrypto crypto.EncryptionAlgorithm, statikDir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) *Notification {
|
||||
h := &Notification{
|
||||
handler: handler,
|
||||
command: command,
|
||||
@@ -64,6 +59,7 @@ func newNotification(
|
||||
assetsPrefix: assetsPrefix,
|
||||
queries: query,
|
||||
smtpPasswordCrypto: smtpPasswordEncAlg,
|
||||
smsTokenCrypto: smsCrypto,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
@@ -165,7 +161,7 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendUserInitCode(ctx, string(template.Template), translator, user, initCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendUserInitCode(ctx, string(template.Template), translator, user, initCode, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -203,7 +199,7 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPasswordCode(ctx, string(template.Template), translator, user, pwCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendPasswordCode(ctx, string(template.Template), translator, user, pwCode, n.systemDefaults, n.getSMTPConfig, n.getTwilioConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -242,7 +238,7 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendEmailVerificationCode(ctx, string(template.Template), translator, user, emailCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendEmailVerificationCode(ctx, string(template.Template), translator, user, emailCode, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -268,7 +264,7 @@ func (n *Notification) handlePhoneVerificationCode(event *models.Event) (err err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPhoneVerificationCode(translator, user, phoneCode, n.systemDefaults, n.AesCrypto)
|
||||
err = types.SendPhoneVerificationCode(context.Background(), translator, user, phoneCode, n.systemDefaults, n.getTwilioConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -308,7 +304,7 @@ func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendDomainClaimed(ctx, string(template.Template), translator, user, data["userName"], n.systemDefaults, n.getSMTPConfig, colors, n.assetsPrefix)
|
||||
err = types.SendDomainClaimed(ctx, string(template.Template), translator, user, data["userName"], n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -355,7 +351,7 @@ func (n *Notification) handlePasswordlessRegistrationLink(event *models.Event) (
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendPasswordlessRegistrationLink(ctx, string(template.Template), translator, user, addedEvent, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendPasswordlessRegistrationLink(ctx, string(template.Template), translator, user, addedEvent, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -394,7 +390,7 @@ func (n *Notification) getUserEvents(userID string, sequence uint64) ([]*models.
|
||||
}
|
||||
|
||||
func (n *Notification) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-s9opc", "id", event.AggregateID, "sequence", event.Sequence).WithError(err).Warn("something went wrong in notification handler")
|
||||
logging.WithFields("id", event.AggregateID, "sequence", event.Sequence).WithError(err).Warn("something went wrong in notification handler")
|
||||
return spooler.HandleError(event, err, n.view.GetLatestNotificationFailedEvent, n.view.ProcessedNotificationFailedEvent, n.view.ProcessedNotificationSequence, n.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
@@ -437,6 +433,48 @@ func (n *Notification) getSMTPConfig(ctx context.Context) (*smtp.EmailConfig, er
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Read iam twilio config
|
||||
func (n *Notification) getTwilioConfig(ctx context.Context) (*twilio.TwilioConfig, error) {
|
||||
config, err := n.queries.SMSProviderConfigByID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config.TwilioConfig == nil {
|
||||
return nil, errors.ThrowNotFound(nil, "HANDLER-8nfow", "Errors.SMS.Twilio.NotFound")
|
||||
}
|
||||
token, err := crypto.Decrypt(config.TwilioConfig.Token, n.smtpPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &twilio.TwilioConfig{
|
||||
SID: config.TwilioConfig.SID,
|
||||
Token: string(token),
|
||||
SenderNumber: config.TwilioConfig.SenderNumber,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Read iam filesystem provider config
|
||||
func (n *Notification) getFileSystemProvider(ctx context.Context) (*fs.FSConfig, error) {
|
||||
config, err := n.queries.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fs.FSConfig{
|
||||
Compact: config.Compact,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Read iam log provider config
|
||||
func (n *Notification) getLogProvider(ctx context.Context) (*log.LogConfig, error) {
|
||||
config, err := n.queries.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeLog)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &log.LogConfig{
|
||||
Compact: config.Compact,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *Notification) getTranslatorWithOrgTexts(orgID, textType string) (*i18n.Translator, error) {
|
||||
ctx := context.Background()
|
||||
translator, err := i18n.NewTranslator(n.statikDir, i18n.TranslatorConfig{DefaultLanguage: n.queries.GetDefaultLanguage(ctx)})
|
||||
|
@@ -22,7 +22,7 @@ type EsRepository struct {
|
||||
spooler *es_spol.Spooler
|
||||
}
|
||||
|
||||
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) (*EsRepository, error) {
|
||||
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) (*EsRepository, error) {
|
||||
es, err := v1.Start(dbClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -33,7 +33,7 @@ func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg)
|
||||
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg, smsCrypto)
|
||||
|
||||
return &EsRepository{
|
||||
spool,
|
||||
|
@@ -21,12 +21,12 @@ type SpoolerConfig struct {
|
||||
Handlers handler.Configs
|
||||
}
|
||||
|
||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) *spooler.Spooler {
|
||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) *spooler.Spooler {
|
||||
spoolerConfig := spooler.Config{
|
||||
Eventstore: es,
|
||||
Locker: &locker{dbClient: sql},
|
||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg),
|
||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg, smsCrypto),
|
||||
}
|
||||
spool := spoolerConfig.New()
|
||||
spool.Start()
|
||||
|
@@ -22,3 +22,7 @@ func (c *Chain) HandleMessage(message channels.Message) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Chain) Len() int {
|
||||
return len(c.channels)
|
||||
}
|
||||
|
@@ -1,45 +1,28 @@
|
||||
package senders
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
"github.com/caos/zitadel/internal/notification/channels/chat"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
)
|
||||
|
||||
func debugChannels(config systemdefaults.Notifications) (channels.NotificationChannel, error) {
|
||||
|
||||
func debugChannels(ctx context.Context, config systemdefaults.Notifications, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (*Chain, error) {
|
||||
var (
|
||||
providers []channels.NotificationChannel
|
||||
enableChat bool
|
||||
providers []channels.NotificationChannel
|
||||
)
|
||||
|
||||
if config.Providers.Chat.Enabled != nil {
|
||||
enableChat = *config.Providers.Chat.Enabled
|
||||
} else {
|
||||
// ensures backward compatible configuration
|
||||
enableChat = config.DebugMode
|
||||
}
|
||||
|
||||
if enableChat {
|
||||
p, err := chat.InitChatChannel(config.Providers.Chat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if fsProvider, err := getFileSystemProvider(ctx); err == nil {
|
||||
p, err := fs.InitFSChannel(config.FileSystemPath, *fsProvider)
|
||||
if err == nil {
|
||||
providers = append(providers, p)
|
||||
}
|
||||
providers = append(providers, p)
|
||||
}
|
||||
|
||||
if config.Providers.FileSystem.Enabled {
|
||||
p, err := fs.InitFSChannel(config.Providers.FileSystem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
providers = append(providers, p)
|
||||
}
|
||||
|
||||
if config.Providers.Log.Enabled {
|
||||
providers = append(providers, log.InitStdoutChannel(config.Providers.Log))
|
||||
if logProvider, err := getLogProvider(ctx); err == nil {
|
||||
providers = append(providers, log.InitStdoutChannel(*logProvider))
|
||||
}
|
||||
|
||||
return chainChannels(providers...), nil
|
||||
|
@@ -3,25 +3,21 @@ package senders
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
)
|
||||
|
||||
func EmailChannels(ctx context.Context, config systemdefaults.Notifications, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error)) (channels.NotificationChannel, error) {
|
||||
|
||||
debug, err := debugChannels(config)
|
||||
func EmailChannels(ctx context.Context, config systemdefaults.Notifications, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) {
|
||||
p, err := smtp.InitSMTPChannel(ctx, emailConfig)
|
||||
if err == nil {
|
||||
chain.channels = append(chain.channels, p)
|
||||
}
|
||||
chain, err = debugChannels(ctx, config, getFileSystemProvider, getLogProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
logging.New().Info("Error in creating debug channels")
|
||||
}
|
||||
|
||||
if !config.DebugMode {
|
||||
p, err := smtp.InitSMTPChannel(ctx, emailConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chainChannels(debug, p), nil
|
||||
}
|
||||
|
||||
return debug, nil
|
||||
return chain, nil
|
||||
}
|
||||
|
@@ -1,21 +1,21 @@
|
||||
package senders
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
)
|
||||
|
||||
func SMSChannels(config systemdefaults.Notifications) (channels.NotificationChannel, error) {
|
||||
|
||||
debug, err := debugChannels(config)
|
||||
func SMSChannels(ctx context.Context, config systemdefaults.Notifications, twilioConfig *twilio.TwilioConfig, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) {
|
||||
if twilioConfig != nil {
|
||||
chain.channels = append(chain.channels, twilio.InitTwilioChannel(*twilioConfig))
|
||||
}
|
||||
chain, err = debugChannels(ctx, config, getFileSystemProvider, getLogProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !config.DebugMode {
|
||||
return chainChannels(debug, twilio.InitTwilioChannel(config.Providers.Twilio)), nil
|
||||
}
|
||||
|
||||
return debug, nil
|
||||
return chain, nil
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
@@ -18,7 +20,7 @@ type DomainClaimedData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -35,5 +37,5 @@ func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Tr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(ctx, user, domainClaimedData.Subject, template, systemDefaults.Notifications, emailConfig, true)
|
||||
return generateEmail(ctx, user, domainClaimedData.Subject, template, systemDefaults.Notifications, emailConfig, getFileSystemProvider, getLogProvider, true)
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
@@ -19,7 +21,7 @@ type EmailVerificationCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -41,5 +43,5 @@ func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
@@ -25,7 +27,7 @@ type UrlData struct {
|
||||
PasswordSet bool
|
||||
}
|
||||
|
||||
func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -45,5 +47,5 @@ func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Tra
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(ctx, user, initCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
return generateEmail(ctx, user, initCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||
}
|
||||
|
@@ -7,7 +7,10 @@ import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@@ -21,7 +24,7 @@ type PasswordCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getTwilioConfig func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -44,8 +47,8 @@ func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Tra
|
||||
return err
|
||||
}
|
||||
if code.NotificationType == int32(domain.NotificationTypeSms) {
|
||||
return generateSms(user, passwordResetData.Text, systemDefaults.Notifications, false)
|
||||
return generateSms(ctx, user, passwordResetData.Text, systemDefaults.Notifications, getTwilioConfig, getFileSystemProvider, getLogProvider, false)
|
||||
}
|
||||
return generateEmail(ctx, user, passwordResetData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
return generateEmail(ctx, user, passwordResetData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
@@ -19,7 +21,7 @@ type PasswordlessRegistrationLinkData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -36,5 +38,5 @@ func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, tran
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||
}
|
||||
|
@@ -1,12 +1,16 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
@@ -16,7 +20,7 @@ type PhoneVerificationCodeData struct {
|
||||
UserID string
|
||||
}
|
||||
|
||||
func SendPhoneVerificationCode(translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
|
||||
func SendPhoneVerificationCode(ctx context.Context, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, getTwilioConfig func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -31,5 +35,5 @@ func SendPhoneVerificationCode(translator *i18n.Translator, user *view_model.Not
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateSms(user, template, systemDefaults.Notifications, true)
|
||||
return generateSms(ctx, user, template, systemDefaults.Notifications, getTwilioConfig, getFileSystemProvider, getLogProvider, true)
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ import (
|
||||
"context"
|
||||
"html"
|
||||
|
||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
"github.com/caos/zitadel/internal/notification/senders"
|
||||
@@ -12,7 +15,7 @@ import (
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), lastEmail bool) error {
|
||||
func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), lastEmail bool) error {
|
||||
content = html.UnescapeString(content)
|
||||
message := &messages.Email{
|
||||
Recipients: []string{user.VerifiedEmail},
|
||||
@@ -23,12 +26,15 @@ func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, co
|
||||
message.Recipients = []string{user.LastEmail}
|
||||
}
|
||||
|
||||
channels, err := senders.EmailChannels(ctx, config, smtpConfig)
|
||||
channelChain, err := senders.EmailChannels(ctx, config, smtpConfig, getFileSystemProvider, getLogProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return channels.HandleMessage(message)
|
||||
if channelChain.Len() == 0 {
|
||||
return caos_errors.ThrowPreconditionFailed(nil, "MAIL-83nof", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
return channelChain.HandleMessage(message)
|
||||
}
|
||||
|
||||
func mapNotifyUserToArgs(user *view_model.NotifyUser) map[string]interface{} {
|
||||
|
@@ -1,15 +1,26 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
"github.com/caos/zitadel/internal/notification/senders"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
func generateSms(user *view_model.NotifyUser, content string, config systemdefaults.Notifications, lastPhone bool) error {
|
||||
func generateSms(ctx context.Context, user *view_model.NotifyUser, content string, config systemdefaults.Notifications, getTwilioProvider func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), lastPhone bool) error {
|
||||
number := ""
|
||||
twilio, err := getTwilioProvider(ctx)
|
||||
if err == nil {
|
||||
number = twilio.SenderNumber
|
||||
}
|
||||
message := &messages.SMS{
|
||||
SenderPhoneNumber: config.Providers.Twilio.SenderNumber,
|
||||
SenderPhoneNumber: number,
|
||||
RecipientPhoneNumber: user.VerifiedPhone,
|
||||
Content: content,
|
||||
}
|
||||
@@ -17,9 +28,10 @@ func generateSms(user *view_model.NotifyUser, content string, config systemdefau
|
||||
message.RecipientPhoneNumber = user.LastPhone
|
||||
}
|
||||
|
||||
channels, err := senders.SMSChannels(config)
|
||||
if err != nil {
|
||||
return err
|
||||
channelChain, err := senders.SMSChannels(ctx, config, twilio, getFileSystemProvider, getLogProvider)
|
||||
|
||||
if channelChain.Len() == 0 {
|
||||
return caos_errors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
return channels.HandleMessage(message)
|
||||
return channelChain.HandleMessage(message)
|
||||
}
|
||||
|
Reference in New Issue
Block a user