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

@@ -14,38 +14,50 @@ import (
)
var (
expectedSMSConfigQuery = regexp.QuoteMeta(`SELECT projections.sms_configs2.id,` +
` projections.sms_configs2.aggregate_id,` +
` projections.sms_configs2.creation_date,` +
` projections.sms_configs2.change_date,` +
` projections.sms_configs2.resource_owner,` +
` projections.sms_configs2.state,` +
` projections.sms_configs2.sequence,` +
expectedSMSConfigQuery = regexp.QuoteMeta(`SELECT projections.sms_configs3.id,` +
` projections.sms_configs3.aggregate_id,` +
` projections.sms_configs3.creation_date,` +
` projections.sms_configs3.change_date,` +
` projections.sms_configs3.resource_owner,` +
` projections.sms_configs3.state,` +
` projections.sms_configs3.sequence,` +
` projections.sms_configs3.description,` +
// twilio config
` projections.sms_configs2_twilio.sms_id,` +
` projections.sms_configs2_twilio.sid,` +
` projections.sms_configs2_twilio.token,` +
` projections.sms_configs2_twilio.sender_number` +
` FROM projections.sms_configs2` +
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` +
` projections.sms_configs3_twilio.sms_id,` +
` projections.sms_configs3_twilio.sid,` +
` projections.sms_configs3_twilio.token,` +
` projections.sms_configs3_twilio.sender_number,` +
// http config
` projections.sms_configs3_http.sms_id,` +
` projections.sms_configs3_http.endpoint` +
` FROM projections.sms_configs3` +
` LEFT JOIN projections.sms_configs3_twilio ON projections.sms_configs3.id = projections.sms_configs3_twilio.sms_id AND projections.sms_configs3.instance_id = projections.sms_configs3_twilio.instance_id` +
` LEFT JOIN projections.sms_configs3_http ON projections.sms_configs3.id = projections.sms_configs3_http.sms_id AND projections.sms_configs3.instance_id = projections.sms_configs3_http.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedSMSConfigsQuery = regexp.QuoteMeta(`SELECT projections.sms_configs2.id,` +
` projections.sms_configs2.aggregate_id,` +
` projections.sms_configs2.creation_date,` +
` projections.sms_configs2.change_date,` +
` projections.sms_configs2.resource_owner,` +
` projections.sms_configs2.state,` +
` projections.sms_configs2.sequence,` +
expectedSMSConfigsQuery = regexp.QuoteMeta(`SELECT projections.sms_configs3.id,` +
` projections.sms_configs3.aggregate_id,` +
` projections.sms_configs3.creation_date,` +
` projections.sms_configs3.change_date,` +
` projections.sms_configs3.resource_owner,` +
` projections.sms_configs3.state,` +
` projections.sms_configs3.sequence,` +
` projections.sms_configs3.description,` +
// twilio config
` projections.sms_configs2_twilio.sms_id,` +
` projections.sms_configs2_twilio.sid,` +
` projections.sms_configs2_twilio.token,` +
` projections.sms_configs2_twilio.sender_number,` +
` projections.sms_configs3_twilio.sms_id,` +
` projections.sms_configs3_twilio.sid,` +
` projections.sms_configs3_twilio.token,` +
` projections.sms_configs3_twilio.sender_number,` +
// http config
` projections.sms_configs3_http.sms_id,` +
` projections.sms_configs3_http.endpoint,` +
` COUNT(*) OVER ()` +
` FROM projections.sms_configs2` +
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` +
` FROM projections.sms_configs3` +
` LEFT JOIN projections.sms_configs3_twilio ON projections.sms_configs3.id = projections.sms_configs3_twilio.sms_id AND projections.sms_configs3.instance_id = projections.sms_configs3_twilio.instance_id` +
` LEFT JOIN projections.sms_configs3_http ON projections.sms_configs3.id = projections.sms_configs3_http.sms_id AND projections.sms_configs3.instance_id = projections.sms_configs3_http.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
smsConfigCols = []string{
@@ -56,16 +68,20 @@ var (
"resource_owner",
"state",
"sequence",
"description",
// twilio config
"sms_id",
"sid",
"token",
"sender-number",
// http config
"sms_id",
"endpoint",
}
smsConfigsCols = append(smsConfigCols, "count")
)
func Test_SMSConfigssPrepare(t *testing.T) {
func Test_SMSConfigsPrepare(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
err checkErr
@@ -104,11 +120,15 @@ func Test_SMSConfigssPrepare(t *testing.T) {
"ro",
domain.SMSConfigStateInactive,
uint64(20211109),
"description",
// twilio config
"sms-id",
"sid",
&crypto.CryptoValue{},
"sender-number",
// http config
nil,
nil,
},
},
),
@@ -126,6 +146,7 @@ func Test_SMSConfigssPrepare(t *testing.T) {
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
Sequence: 20211109,
Description: "description",
TwilioConfig: &Twilio{
SID: "sid",
Token: &crypto.CryptoValue{},
@@ -135,6 +156,56 @@ func Test_SMSConfigssPrepare(t *testing.T) {
},
},
},
{
name: "prepareSMSQuery http config",
prepare: prepareSMSConfigsQuery,
want: want{
sqlExpectations: mockQueries(
expectedSMSConfigsQuery,
smsConfigsCols,
[][]driver.Value{
{
"sms-id",
"agg-id",
testNow,
testNow,
"ro",
domain.SMSConfigStateInactive,
uint64(20211109),
"description",
// twilio config
nil,
nil,
nil,
nil,
// http config
"sms-id",
"endpoint",
},
},
),
},
object: &SMSConfigs{
SearchResponse: SearchResponse{
Count: 1,
},
Configs: []*SMSConfig{
{
ID: "sms-id",
AggregateID: "agg-id",
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
Sequence: 20211109,
Description: "description",
HTTPConfig: &HTTP{
Endpoint: "endpoint",
},
},
},
},
},
{
name: "prepareSMSConfigsQuery multiple result",
prepare: prepareSMSConfigsQuery,
@@ -149,13 +220,17 @@ func Test_SMSConfigssPrepare(t *testing.T) {
testNow,
testNow,
"ro",
domain.SMSConfigStateInactive,
domain.SMSConfigStateActive,
uint64(20211109),
"description",
// twilio config
"sms-id",
"sid",
&crypto.CryptoValue{},
"sender-number",
// http config
nil,
nil,
},
{
"sms-id2",
@@ -165,18 +240,40 @@ func Test_SMSConfigssPrepare(t *testing.T) {
"ro",
domain.SMSConfigStateInactive,
uint64(20211109),
"description",
// twilio config
"sms-id2",
"sid2",
&crypto.CryptoValue{},
"sender-number2",
// http config
nil,
nil,
},
{
"sms-id3",
"agg-id",
testNow,
testNow,
"ro",
domain.SMSConfigStateInactive,
uint64(20211109),
"description",
// twilio config
nil,
nil,
nil,
nil,
// http config
"sms-id3",
"endpoint3",
},
},
),
},
object: &SMSConfigs{
SearchResponse: SearchResponse{
Count: 2,
Count: 3,
},
Configs: []*SMSConfig{
{
@@ -185,8 +282,9 @@ func Test_SMSConfigssPrepare(t *testing.T) {
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
State: domain.SMSConfigStateActive,
Sequence: 20211109,
Description: "description",
TwilioConfig: &Twilio{
SID: "sid",
Token: &crypto.CryptoValue{},
@@ -201,12 +299,26 @@ func Test_SMSConfigssPrepare(t *testing.T) {
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
Sequence: 20211109,
Description: "description",
TwilioConfig: &Twilio{
SID: "sid2",
Token: &crypto.CryptoValue{},
SenderNumber: "sender-number2",
},
},
{
ID: "sms-id3",
AggregateID: "agg-id",
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
Sequence: 20211109,
Description: "description",
HTTPConfig: &HTTP{
Endpoint: "endpoint3",
},
},
},
},
},
@@ -265,7 +377,50 @@ func Test_SMSConfigPrepare(t *testing.T) {
object: (*SMSConfig)(nil),
},
{
name: "prepareSMSConfigQuery found",
name: "prepareSMSConfigQuery, twilio, found",
prepare: prepareSMSConfigQuery,
want: want{
sqlExpectations: mockQuery(
expectedSMSConfigQuery,
smsConfigCols,
[]driver.Value{
"sms-id",
"agg-id",
testNow,
testNow,
"ro",
domain.SMSConfigStateActive,
uint64(20211109),
"description",
// twilio config
"sms-id",
"sid",
&crypto.CryptoValue{},
"sender-number",
// http config
nil,
nil,
},
),
},
object: &SMSConfig{
ID: "sms-id",
AggregateID: "agg-id",
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "ro",
State: domain.SMSConfigStateActive,
Sequence: 20211109,
Description: "description",
TwilioConfig: &Twilio{
SID: "sid",
SenderNumber: "sender-number",
Token: &crypto.CryptoValue{},
},
},
},
{
name: "prepareSMSConfigQuery, http, found",
prepare: prepareSMSConfigQuery,
want: want{
sqlExpectations: mockQuery(
@@ -279,11 +434,15 @@ func Test_SMSConfigPrepare(t *testing.T) {
"ro",
domain.SMSConfigStateInactive,
uint64(20211109),
"description",
// twilio config
nil,
nil,
nil,
nil,
// http config
"sms-id",
"sid",
&crypto.CryptoValue{},
"sender-number",
"endpoint",
},
),
},
@@ -295,10 +454,9 @@ func Test_SMSConfigPrepare(t *testing.T) {
ResourceOwner: "ro",
State: domain.SMSConfigStateInactive,
Sequence: 20211109,
TwilioConfig: &Twilio{
SID: "sid",
SenderNumber: "sender-number",
Token: &crypto.CryptoValue{},
Description: "description",
HTTPConfig: &HTTP{
Endpoint: "endpoint",
},
},
},