mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-15 04:18:01 +00:00
1602 lines
59 KiB
Go
1602 lines
59 KiB
Go
|
package handlers
|
||
|
|
||
|
import (
|
||
|
"database/sql"
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/muhlemmer/gu"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
"go.uber.org/mock/gomock"
|
||
|
|
||
|
"github.com/zitadel/zitadel/internal/domain"
|
||
|
"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"
|
||
|
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
|
||
|
"github.com/zitadel/zitadel/internal/notification/handlers/mock"
|
||
|
"github.com/zitadel/zitadel/internal/notification/messages"
|
||
|
"github.com/zitadel/zitadel/internal/notification/senders"
|
||
|
"github.com/zitadel/zitadel/internal/query"
|
||
|
"github.com/zitadel/zitadel/internal/repository/session"
|
||
|
"github.com/zitadel/zitadel/internal/repository/user"
|
||
|
)
|
||
|
|
||
|
func Test_userNotifierLegacy_reduceInitCodeAdded(t *testing.T) {
|
||
|
expectMailSubject := "Initialize User"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanInitCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanInitialCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanInitCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanInitialCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s/ui/login/user/init?authRequestID=%s&code=%s&loginname=%s&orgID=%s&passwordset=%t&userID=%s", eventOrigin, "", testCode, preferredLoginName, orgID, false, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanInitCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanInitialCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/user/init?authRequestID=%s&code=%s&loginname=%s&orgID=%s&passwordset=%t&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, "", testCode, preferredLoginName, orgID, false, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanInitCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanInitialCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url with authRequestID",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/user/init?authRequestID=%s&code=%s&loginname=%s&orgID=%s&passwordset=%t&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, authRequestID, testCode, preferredLoginName, orgID, false, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanInitCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanInitialCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
AuthRequestID: authRequestID,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
// TODO: Why don't we have an url template on user.HumanInitialCodeAddedEvent?
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reduceInitCodeAdded(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reduceEmailCodeAdded(t *testing.T) {
|
||
|
expectMailSubject := "Verify email"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s/ui/login/mail/verification?authRequestID=%s&code=%s&orgID=%s&userID=%s", eventOrigin, "", testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/mail/verification?authRequestID=%s&code=%s&orgID=%s&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, "", testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url with authRequestID",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/mail/verification?authRequestID=%s&code=%s&orgID=%s&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, authRequestID, testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
AuthRequestID: authRequestID,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with url template and event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
urlTemplate := "https://my.custom.url/org/{{.OrgID}}/user/{{.UserID}}/verify/{{.Code}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("https://my.custom.url/org/%s/user/%s/verify/%s", orgID, userID, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanEmailVerificationCodeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanEmailCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: urlTemplate,
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reduceEmailCodeAdded(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reducePasswordCodeAdded(t *testing.T) {
|
||
|
expectMailSubject := "Reset password"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s/ui/login/password/init?authRequestID=%s&code=%s&orgID=%s&userID=%s", eventOrigin, "", testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/password/init?authRequestID=%s&code=%s&orgID=%s&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, "", testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url with authRequestID",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/password/init?authRequestID=%s&code=%s&orgID=%s&userID=%s", externalProtocol, instancePrimaryDomain, externalPort, authRequestID, testCode, orgID, userID)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
AuthRequestID: authRequestID,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with url template and event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
urlTemplate := "https://my.custom.url/org/{{.OrgID}}/user/{{.UserID}}/verify/{{.Code}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("https://my.custom.url/org/%s/user/%s/verify/%s", orgID, userID, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: urlTemplate,
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "external code",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
expectContent := "We received a password reset request. Please use the button below to reset your password. (Code ) If you didn't ask for this mail, please ignore it."
|
||
|
w.messageSMS = &messages.SMS{
|
||
|
SenderPhoneNumber: "senderNumber",
|
||
|
RecipientPhoneNumber: lastPhone,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordCodeSent(gomock.Any(), orgID, userID, &senders.CodeGeneratorInfo{ID: smsProviderID, VerificationID: verificationID}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordCodeAddedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: nil,
|
||
|
Expiry: 0,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
NotificationType: domain.NotificationTypeSms,
|
||
|
GeneratorID: smsProviderID,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reducePasswordCodeAdded(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reduceDomainClaimed(t *testing.T) {
|
||
|
expectMailSubject := "Domain has been claimed"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().UserDomainClaimedSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &user.DomainClaimedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().UserDomainClaimedSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &user.DomainClaimedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reduceDomainClaimed(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reducePasswordlessCodeRequested(t *testing.T) {
|
||
|
expectMailSubject := "Add Passwordless Login"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanPasswordlessInitCodeSent(gomock.Any(), userID, orgID, codeID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordlessInitCodeRequestedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
ID: codeID,
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanPasswordlessInitCodeSent(gomock.Any(), userID, orgID, codeID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordlessInitCodeRequestedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
ID: codeID,
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectContent := fmt.Sprintf("%s/ui/login/login/passwordless/init?userID=%s&orgID=%s&codeID=%s&code=%s", eventOrigin, userID, orgID, codeID, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanPasswordlessInitCodeSent(gomock.Any(), userID, orgID, codeID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordlessInitCodeRequestedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
ID: codeID,
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/ui/login/login/passwordless/init?userID=%s&orgID=%s&codeID=%s&code=%s", externalProtocol, instancePrimaryDomain, externalPort, userID, orgID, codeID, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanPasswordlessInitCodeSent(gomock.Any(), userID, orgID, codeID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordlessInitCodeRequestedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
ID: codeID,
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: "",
|
||
|
CodeReturned: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with url template and event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
urlTemplate := "https://my.custom.url/org/{{.OrgID}}/user/{{.UserID}}/verify/{{.Code}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("https://my.custom.url/org/%s/user/%s/verify/%s", orgID, userID, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().HumanPasswordlessInitCodeSent(gomock.Any(), userID, orgID, codeID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordlessInitCodeRequestedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
ID: codeID,
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTemplate: urlTemplate,
|
||
|
CodeReturned: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reducePasswordlessCodeRequested(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reducePasswordChanged(t *testing.T) {
|
||
|
expectMailSubject := "Password of user has changed"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
queries.EXPECT().NotificationPolicyByOrg(gomock.Any(), gomock.Any(), orgID, gomock.Any()).Return(&query.NotificationPolicy{
|
||
|
PasswordChange: true,
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordChangeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordChangedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{lastEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
queries.EXPECT().NotificationPolicyByOrg(gomock.Any(), gomock.Any(), orgID, gomock.Any()).Return(&query.NotificationPolicy{
|
||
|
PasswordChange: true,
|
||
|
}, nil)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
commands.EXPECT().PasswordChangeSent(gomock.Any(), orgID, userID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &user.HumanPasswordChangedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
stmt, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reducePasswordChanged(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
err = stmt.Execute(nil, "")
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reduceOTPEmailChallenged(t *testing.T) {
|
||
|
expectMailSubject := "Verify One-Time Password"
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s%s/%s/%s", eventOrigin, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{verifiedEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
commands.EXPECT().OTPEmailSent(gomock.Any(), userID, orgID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &session.OTPEmailChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTmpl: "",
|
||
|
ReturnCode: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.LogoURL}}"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d%s/%s/%s", externalProtocol, instancePrimaryDomain, externalPort, assetsPath, policyID, logoURL)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{verifiedEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, "testcode")
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
commands.EXPECT().OTPEmailSent(gomock.Any(), userID, orgID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &session.OTPEmailChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTmpl: "",
|
||
|
ReturnCode: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s/otp/verify?loginName=%s&code=%s", eventOrigin, preferredLoginName, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{verifiedEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
commands.EXPECT().OTPEmailSent(gomock.Any(), userID, orgID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &session.OTPEmailChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
URLTmpl: "",
|
||
|
ReturnCode: false,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("%s://%s:%d/otp/verify?loginName=%s&code=%s", externalProtocol, instancePrimaryDomain, externalPort, preferredLoginName, testCode)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{verifiedEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
commands.EXPECT().OTPEmailSent(gomock.Any(), userID, orgID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
}, args{
|
||
|
event: &session.OTPEmailChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
ReturnCode: false,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "button url with url template and event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
givenTemplate := "{{.URL}}"
|
||
|
urlTemplate := "https://my.custom.url/user/{{.LoginName}}/verify"
|
||
|
testCode := "testcode"
|
||
|
expectContent := fmt.Sprintf("https://my.custom.url/user/%s/verify", preferredLoginName)
|
||
|
w.message = &messages.Email{
|
||
|
Recipients: []string{verifiedEmail},
|
||
|
Subject: expectMailSubject,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
codeAlg, code := cryptoValue(t, ctrl, testCode)
|
||
|
expectTemplateWithNotifyUserQueries(queries, givenTemplate)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
commands.EXPECT().OTPEmailSent(gomock.Any(), userID, orgID).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
userDataCrypto: codeAlg,
|
||
|
SMSTokenCrypto: nil,
|
||
|
}, args{
|
||
|
event: &session.OTPEmailChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: code,
|
||
|
Expiry: time.Hour,
|
||
|
ReturnCode: false,
|
||
|
URLTmpl: urlTemplate,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
_, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reduceSessionOTPEmailChallenged(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_userNotifierLegacy_reduceOTPSMSChallenged(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
test func(*gomock.Controller, *mock.MockQueries, *mock.MockCommands) (fields, args, wantLegacy)
|
||
|
}{{
|
||
|
name: "asset url with event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
testCode := ""
|
||
|
expiry := 0 * time.Hour
|
||
|
expectContent := fmt.Sprintf(`%[1]s is your one-time password for %[2]s. Use it within the next %[3]s.
|
||
|
@%[2]s #%[1]s`, testCode, eventOriginDomain, expiry)
|
||
|
w.messageSMS = &messages.SMS{
|
||
|
SenderPhoneNumber: "senderNumber",
|
||
|
RecipientPhoneNumber: verifiedPhone,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
expectTemplateWithNotifyUserQueriesSMS(queries)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
commands.EXPECT().OTPSMSSent(gomock.Any(), userID, orgID, &senders.CodeGeneratorInfo{ID: smsProviderID, VerificationID: verificationID}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &session.OTPSMSChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: nil,
|
||
|
Expiry: expiry,
|
||
|
CodeReturned: false,
|
||
|
GeneratorID: smsProviderID,
|
||
|
TriggeredAtOrigin: eventOrigin,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
}, {
|
||
|
name: "asset url without event trigger url",
|
||
|
test: func(ctrl *gomock.Controller, queries *mock.MockQueries, commands *mock.MockCommands) (f fields, a args, w wantLegacy) {
|
||
|
testCode := ""
|
||
|
expiry := 0 * time.Hour
|
||
|
expectContent := fmt.Sprintf(`%[1]s is your one-time password for %[2]s. Use it within the next %[3]s.
|
||
|
@%[2]s #%[1]s`, testCode, instancePrimaryDomain, expiry)
|
||
|
w.messageSMS = &messages.SMS{
|
||
|
SenderPhoneNumber: "senderNumber",
|
||
|
RecipientPhoneNumber: verifiedPhone,
|
||
|
Content: expectContent,
|
||
|
}
|
||
|
expectTemplateWithNotifyUserQueriesSMS(queries)
|
||
|
queries.EXPECT().SessionByID(gomock.Any(), gomock.Any(), userID, gomock.Any()).Return(&query.Session{}, nil)
|
||
|
queries.EXPECT().SearchInstanceDomains(gomock.Any(), gomock.Any()).Return(&query.InstanceDomains{
|
||
|
Domains: []*query.InstanceDomain{{
|
||
|
Domain: instancePrimaryDomain,
|
||
|
IsPrimary: true,
|
||
|
}},
|
||
|
}, nil)
|
||
|
commands.EXPECT().OTPSMSSent(gomock.Any(), userID, orgID, &senders.CodeGeneratorInfo{ID: smsProviderID, VerificationID: verificationID}).Return(nil)
|
||
|
return fields{
|
||
|
queries: queries,
|
||
|
commands: commands,
|
||
|
es: eventstore.NewEventstore(&eventstore.Config{
|
||
|
Querier: es_repo_mock.NewRepo(t).ExpectFilterEvents().MockQuerier,
|
||
|
}),
|
||
|
}, args{
|
||
|
event: &session.OTPSMSChallengedEvent{
|
||
|
BaseEvent: *eventstore.BaseEventFromRepo(&repository.Event{
|
||
|
AggregateID: userID,
|
||
|
ResourceOwner: sql.NullString{String: orgID},
|
||
|
CreationDate: time.Now().UTC(),
|
||
|
}),
|
||
|
Code: nil,
|
||
|
Expiry: expiry,
|
||
|
CodeReturned: false,
|
||
|
GeneratorID: smsProviderID,
|
||
|
},
|
||
|
}, w
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
ctrl := gomock.NewController(t)
|
||
|
queries := mock.NewMockQueries(ctrl)
|
||
|
commands := mock.NewMockCommands(ctrl)
|
||
|
f, a, w := tt.test(ctrl, queries, commands)
|
||
|
_, err := newUserNotifierLegacy(t, ctrl, queries, f, a, w).reduceSessionOTPSMSChallenged(a.event)
|
||
|
if w.err != nil {
|
||
|
w.err(t, err)
|
||
|
} else {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type wantLegacy struct {
|
||
|
message *messages.Email
|
||
|
messageSMS *messages.SMS
|
||
|
err assert.ErrorAssertionFunc
|
||
|
}
|
||
|
|
||
|
func newUserNotifierLegacy(t *testing.T, ctrl *gomock.Controller, queries *mock.MockQueries, f fields, a args, w wantLegacy) *userNotifierLegacy {
|
||
|
queries.EXPECT().NotificationProviderByIDAndType(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&query.DebugNotificationProvider{}, nil)
|
||
|
smtpAlg, _ := cryptoValue(t, ctrl, "smtppw")
|
||
|
channel := channel_mock.NewMockNotificationChannel(ctrl)
|
||
|
if w.err == nil {
|
||
|
if w.message != nil {
|
||
|
w.message.TriggeringEvent = a.event
|
||
|
channel.EXPECT().HandleMessage(w.message).Return(nil)
|
||
|
}
|
||
|
if w.messageSMS != nil {
|
||
|
w.messageSMS.TriggeringEvent = a.event
|
||
|
channel.EXPECT().HandleMessage(w.messageSMS).DoAndReturn(func(message *messages.SMS) error {
|
||
|
message.VerificationID = gu.Ptr(verificationID)
|
||
|
return nil
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
return &userNotifierLegacy{
|
||
|
commands: f.commands,
|
||
|
queries: NewNotificationQueries(
|
||
|
f.queries,
|
||
|
f.es,
|
||
|
externalDomain,
|
||
|
externalPort,
|
||
|
externalSecure,
|
||
|
"",
|
||
|
f.userDataCrypto,
|
||
|
smtpAlg,
|
||
|
f.SMSTokenCrypto,
|
||
|
),
|
||
|
otpEmailTmpl: defaultOTPEmailTemplate,
|
||
|
channels: ¬ificationChannels{
|
||
|
Chain: *senders.ChainChannels(channel),
|
||
|
EmailConfig: &email.Config{
|
||
|
ProviderConfig: &email.Provider{
|
||
|
ID: "emailProviderID",
|
||
|
Description: "description",
|
||
|
},
|
||
|
SMTPConfig: &smtp.Config{
|
||
|
SMTP: smtp.SMTP{
|
||
|
Host: "host",
|
||
|
User: "user",
|
||
|
Password: "password",
|
||
|
},
|
||
|
Tls: true,
|
||
|
From: "from",
|
||
|
FromName: "fromName",
|
||
|
ReplyToAddress: "replyToAddress",
|
||
|
},
|
||
|
WebhookConfig: nil,
|
||
|
},
|
||
|
SMSConfig: &sms.Config{
|
||
|
ProviderConfig: &sms.Provider{
|
||
|
ID: "smsProviderID",
|
||
|
Description: "description",
|
||
|
},
|
||
|
TwilioConfig: &twilio.Config{
|
||
|
SID: "sid",
|
||
|
Token: "token",
|
||
|
SenderNumber: "senderNumber",
|
||
|
VerifyServiceSID: "verifyServiceSID",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
}
|