feat: add http as sms provider (#8540)

# Which Problems Are Solved

Send SMS messages as a HTTP call to a relay, for own logic on handling
different SMS providers.

# How the Problems Are Solved

Add HTTP as SMS provider type and handling of webhook messages in the
notification handlers.

# Additional Changes

Clean up old Twilio events, which were supposed to handle the general
SMS 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:
Stefan Benz
2024-09-06 15:11:36 +02:00
committed by GitHub
parent d2e0ac07f1
commit 5bdf1a4547
26 changed files with 2536 additions and 593 deletions

View File

@@ -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/sms"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
"github.com/zitadel/zitadel/internal/notification/senders"
"github.com/zitadel/zitadel/internal/notification/templates"
@@ -24,7 +24,7 @@ type Notify func(
type ChannelChains interface {
Email(context.Context) (*senders.Chain, *smtp.Config, error)
SMS(context.Context) (*senders.Chain, *twilio.Config, error)
SMS(context.Context) (*senders.Chain, *sms.Config, error)
Webhook(context.Context, webhook.Config) (*senders.Chain, error)
}
@@ -79,7 +79,7 @@ func sanitizeArgsForHTML(args map[string]any) {
}
}
func SendSMSTwilio(
func SendSMS(
ctx context.Context,
channels ChannelChains,
translator *i18n.Translator,
@@ -99,7 +99,8 @@ func SendSMSTwilio(
ctx,
channels,
user,
data.Text,
data,
args,
allowUnverifiedNotificationChannel,
triggeringEvent,
)

View File

@@ -2,40 +2,78 @@ package types
import (
"context"
"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"
)
type serializableData struct {
ContextInfo map[string]interface{} `json:"contextInfo,omitempty"`
TemplateData templates.TemplateData `json:"templateData,omitempty"`
Args map[string]interface{} `json:"args,omitempty"`
}
func generateSms(
ctx context.Context,
channels ChannelChains,
user *query.NotifyUser,
content string,
data templates.TemplateData,
args map[string]interface{},
lastPhone bool,
triggeringEvent eventstore.Event,
) error {
number := ""
smsChannels, twilioConfig, err := channels.SMS(ctx)
smsChannels, config, err := channels.SMS(ctx)
logging.OnError(err).Error("could not create sms channel")
if smsChannels == nil || smsChannels.Len() == 0 {
return zerrors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
}
if err == nil {
number = twilioConfig.SenderNumber
}
message := &messages.SMS{
SenderPhoneNumber: number,
RecipientPhoneNumber: user.VerifiedPhone,
Content: content,
TriggeringEvent: triggeringEvent,
}
recipient := user.VerifiedPhone
if lastPhone {
message.RecipientPhoneNumber = user.LastPhone
recipient = user.LastPhone
}
return smsChannels.HandleMessage(message)
if config.TwilioConfig != nil {
number := ""
if err == nil {
number = config.TwilioConfig.SenderNumber
}
message := &messages.SMS{
SenderPhoneNumber: number,
RecipientPhoneNumber: recipient,
Content: data.Text,
TriggeringEvent: triggeringEvent,
}
return smsChannels.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{}{
"recipientPhoneNumber": recipient,
"eventType": triggeringEvent.Type(),
"provider": config.ProviderConfig,
}
message := &messages.JSON{
Serializable: &serializableData{
TemplateData: data,
Args: caseArgs,
ContextInfo: contextInfo,
},
TriggeringEvent: triggeringEvent,
}
webhookChannels, err := channels.Webhook(ctx, *config.WebhookConfig)
if err != nil {
return err
}
return webhookChannels.HandleMessage(message)
}
return zerrors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
}