mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 19:44:21 +00:00
f653589609
# Which Problems Are Solved The recently added possibility to generate and verify codes through Twilio verification service did failed on checking OTP SMS code through the session API. Additionally, password codes generated by the V2 API and sent through phone would always use the internal generator and verification mechanism rather than the configured. # How the Problems Are Solved - Correctly set the verifier for OTP SMS for the session API - Always use the internal verifier for OTP Email (for now) - Select the generator / verifier based on the configuration for password codes with notification type SMS for V2 APIs # Additional Changes None # Additional Context - relates to #8678 - reported by customer --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
729 lines
21 KiB
Go
729 lines
21 KiB
Go
package command
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"golang.org/x/text/language"
|
|
|
|
"github.com/muhlemmer/gu"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
"github.com/zitadel/zitadel/internal/repository/instance"
|
|
"github.com/zitadel/zitadel/internal/repository/user"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
)
|
|
|
|
func TestCommands_RequestPasswordReset(t *testing.T) {
|
|
type fields struct {
|
|
checkPermission domain.PermissionCheck
|
|
eventstore func(t *testing.T) *eventstore.Eventstore
|
|
userEncryption crypto.EncryptionAlgorithm
|
|
}
|
|
type args struct {
|
|
ctx context.Context
|
|
userID string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "missing userID",
|
|
fields: fields{
|
|
eventstore: expectEventstore(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "",
|
|
},
|
|
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-SAFdda", "Errors.User.IDMissing"),
|
|
},
|
|
{
|
|
name: "user not existing",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowNotFound(nil, "COMMAND-SAF4f", "Errors.User.NotFound"),
|
|
},
|
|
{
|
|
name: "user not initialized",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
eventFromEventPusher(
|
|
user.NewHumanInitialCodeAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("code")}, 10*time.Second, ""),
|
|
),
|
|
),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised"),
|
|
},
|
|
{
|
|
name: "missing permission",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &Commands{
|
|
checkPermission: tt.fields.checkPermission,
|
|
eventstore: tt.fields.eventstore(t),
|
|
userEncryption: tt.fields.userEncryption,
|
|
}
|
|
_, _, err := c.RequestPasswordReset(tt.args.ctx, tt.args.userID)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
// successful cases are tested in TestCommands_requestPasswordReset
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommands_RequestPasswordResetReturnCode(t *testing.T) {
|
|
type fields struct {
|
|
checkPermission domain.PermissionCheck
|
|
eventstore func(t *testing.T) *eventstore.Eventstore
|
|
userEncryption crypto.EncryptionAlgorithm
|
|
}
|
|
type args struct {
|
|
ctx context.Context
|
|
userID string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "missing userID",
|
|
fields: fields{
|
|
eventstore: expectEventstore(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "",
|
|
},
|
|
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-SAFdda", "Errors.User.IDMissing"),
|
|
},
|
|
{
|
|
name: "user not existing",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowNotFound(nil, "COMMAND-SAF4f", "Errors.User.NotFound"),
|
|
},
|
|
{
|
|
name: "user not initialized",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
eventFromEventPusher(
|
|
user.NewHumanInitialCodeAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("code")}, 10*time.Second, ""),
|
|
),
|
|
),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised"),
|
|
},
|
|
{
|
|
name: "missing permission",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &Commands{
|
|
checkPermission: tt.fields.checkPermission,
|
|
eventstore: tt.fields.eventstore(t),
|
|
userEncryption: tt.fields.userEncryption,
|
|
}
|
|
_, _, err := c.RequestPasswordResetReturnCode(tt.args.ctx, tt.args.userID)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
// successful cases are tested in TestCommands_requestPasswordReset
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommands_RequestPasswordResetURLTemplate(t *testing.T) {
|
|
type fields struct {
|
|
checkPermission domain.PermissionCheck
|
|
eventstore func(t *testing.T) *eventstore.Eventstore
|
|
userEncryption crypto.EncryptionAlgorithm
|
|
}
|
|
type args struct {
|
|
ctx context.Context
|
|
userID string
|
|
urlTmpl string
|
|
notificationType domain.NotificationType
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "invalid template",
|
|
fields: fields{
|
|
eventstore: expectEventstore(),
|
|
},
|
|
args: args{
|
|
userID: "user1",
|
|
urlTmpl: "{{",
|
|
},
|
|
wantErr: zerrors.ThrowInvalidArgument(nil, "DOMAIN-oGh5e", "Errors.User.InvalidURLTemplate"),
|
|
},
|
|
|
|
{
|
|
name: "missing userID",
|
|
fields: fields{
|
|
eventstore: expectEventstore(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "",
|
|
},
|
|
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-SAFdda", "Errors.User.IDMissing"),
|
|
},
|
|
{
|
|
name: "user not existing",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowNotFound(nil, "COMMAND-SAF4f", "Errors.User.NotFound"),
|
|
},
|
|
{
|
|
name: "user not initialized",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
eventFromEventPusher(
|
|
user.NewHumanInitialCodeAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("code")}, 10*time.Second, ""),
|
|
),
|
|
),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised"),
|
|
},
|
|
{
|
|
name: "missing permission",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &Commands{
|
|
checkPermission: tt.fields.checkPermission,
|
|
eventstore: tt.fields.eventstore(t),
|
|
userEncryption: tt.fields.userEncryption,
|
|
}
|
|
_, _, err := c.RequestPasswordResetURLTemplate(tt.args.ctx, tt.args.userID, tt.args.urlTmpl, tt.args.notificationType)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
// successful cases are tested in TestCommands_requestPasswordReset
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommands_requestPasswordReset(t *testing.T) {
|
|
defaultGenerators := &SecretGenerators{
|
|
OTPSMS: &crypto.GeneratorConfig{
|
|
Length: 8,
|
|
Expiry: time.Hour,
|
|
IncludeLowerLetters: true,
|
|
IncludeUpperLetters: true,
|
|
IncludeDigits: true,
|
|
IncludeSymbols: true,
|
|
},
|
|
}
|
|
type fields struct {
|
|
checkPermission domain.PermissionCheck
|
|
eventstore func(t *testing.T) *eventstore.Eventstore
|
|
userEncryption crypto.EncryptionAlgorithm
|
|
newCode encrypedCodeFunc
|
|
newEncryptedCodeWithDefault encryptedCodeWithDefaultFunc
|
|
defaultSecretGenerators *SecretGenerators
|
|
}
|
|
type args struct {
|
|
ctx context.Context
|
|
userID string
|
|
returnCode bool
|
|
urlTmpl string
|
|
notificationType domain.NotificationType
|
|
}
|
|
type res struct {
|
|
details *domain.ObjectDetails
|
|
code *string
|
|
err error
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
res res
|
|
}{
|
|
{
|
|
name: "missing userID",
|
|
fields: fields{
|
|
eventstore: expectEventstore(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "",
|
|
},
|
|
res: res{
|
|
err: zerrors.ThrowInvalidArgument(nil, "COMMAND-SAFdda", "Errors.User.IDMissing"),
|
|
},
|
|
},
|
|
{
|
|
name: "user not existing",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
res: res{
|
|
err: zerrors.ThrowNotFound(nil, "COMMAND-SAF4f", "Errors.User.NotFound"),
|
|
},
|
|
},
|
|
{
|
|
name: "user not initialized",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
eventFromEventPusher(
|
|
user.NewHumanInitialCodeAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "keyID", Crypted: []byte("code")}, 10*time.Second, ""),
|
|
),
|
|
),
|
|
),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
res: res{
|
|
err: zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised"),
|
|
},
|
|
},
|
|
{
|
|
name: "missing permission",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
res: res{
|
|
err: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
|
},
|
|
},
|
|
{
|
|
name: "code generated",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
expectPush(
|
|
user.NewHumanPasswordCodeAddedEventV2(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{
|
|
CryptoType: crypto.TypeEncryption,
|
|
Algorithm: "enc",
|
|
KeyID: "id",
|
|
Crypted: []byte("code"),
|
|
},
|
|
10*time.Minute,
|
|
domain.NotificationTypeEmail,
|
|
"",
|
|
false,
|
|
"",
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckAllowed(),
|
|
newCode: mockEncryptedCode("code", 10*time.Minute),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
},
|
|
res: res{
|
|
details: &domain.ObjectDetails{
|
|
ResourceOwner: "org1",
|
|
},
|
|
code: nil,
|
|
},
|
|
},
|
|
{
|
|
name: "code generated template",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
expectPush(
|
|
user.NewHumanPasswordCodeAddedEventV2(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{
|
|
CryptoType: crypto.TypeEncryption,
|
|
Algorithm: "enc",
|
|
KeyID: "id",
|
|
Crypted: []byte("code"),
|
|
},
|
|
10*time.Minute,
|
|
domain.NotificationTypeEmail,
|
|
"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
false,
|
|
"",
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckAllowed(),
|
|
newCode: mockEncryptedCode("code", 10*time.Minute),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
urlTmpl: "https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
},
|
|
res: res{
|
|
details: &domain.ObjectDetails{
|
|
ResourceOwner: "org1",
|
|
},
|
|
code: nil,
|
|
},
|
|
},
|
|
{
|
|
name: "code generated template sms",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigActivatedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
),
|
|
),
|
|
),
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigTwilioAddedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
"",
|
|
"sid",
|
|
"senderNumber",
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "id", Crypted: []byte("crypted")},
|
|
"",
|
|
),
|
|
),
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigActivatedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
),
|
|
),
|
|
),
|
|
expectPush(
|
|
user.NewHumanPasswordCodeAddedEventV2(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{
|
|
CryptoType: crypto.TypeEncryption,
|
|
Algorithm: "enc",
|
|
KeyID: "id",
|
|
Crypted: []byte("code"),
|
|
},
|
|
10*time.Minute,
|
|
domain.NotificationTypeSms,
|
|
"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
false,
|
|
"",
|
|
),
|
|
),
|
|
),
|
|
defaultSecretGenerators: defaultGenerators,
|
|
checkPermission: newMockPermissionCheckAllowed(),
|
|
newEncryptedCodeWithDefault: mockEncryptedCodeWithDefault("code", 10*time.Minute),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
urlTmpl: "https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
notificationType: domain.NotificationTypeSms,
|
|
},
|
|
res: res{
|
|
details: &domain.ObjectDetails{
|
|
ResourceOwner: "org1",
|
|
},
|
|
code: nil,
|
|
},
|
|
},
|
|
{
|
|
name: "code generated template sms external",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigActivatedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
),
|
|
),
|
|
),
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigTwilioAddedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
"",
|
|
"sid",
|
|
"senderNumber",
|
|
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "id", Crypted: []byte("crypted")},
|
|
"verifyServiceSid",
|
|
),
|
|
),
|
|
eventFromEventPusher(
|
|
instance.NewSMSConfigActivatedEvent(
|
|
context.Background(),
|
|
&instance.NewAggregate("instanceID").Aggregate,
|
|
"id",
|
|
),
|
|
),
|
|
),
|
|
expectPush(
|
|
user.NewHumanPasswordCodeAddedEventV2(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
nil,
|
|
0,
|
|
domain.NotificationTypeSms,
|
|
"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
false,
|
|
"id",
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckAllowed(),
|
|
newCode: mockEncryptedCode("code", 10*time.Minute),
|
|
defaultSecretGenerators: defaultGenerators,
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
urlTmpl: "https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
|
|
notificationType: domain.NotificationTypeSms,
|
|
},
|
|
res: res{
|
|
details: &domain.ObjectDetails{
|
|
ResourceOwner: "org1",
|
|
},
|
|
code: nil,
|
|
},
|
|
},
|
|
{
|
|
name: "code generated returned",
|
|
fields: fields{
|
|
eventstore: expectEventstore(
|
|
expectFilter(
|
|
eventFromEventPusher(
|
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
"username", "firstname", "lastname", "nickname", "displayname",
|
|
language.English, domain.GenderUnspecified, "email", false),
|
|
),
|
|
),
|
|
expectPush(
|
|
user.NewHumanPasswordCodeAddedEventV2(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
|
&crypto.CryptoValue{
|
|
CryptoType: crypto.TypeEncryption,
|
|
Algorithm: "enc",
|
|
KeyID: "id",
|
|
Crypted: []byte("code"),
|
|
},
|
|
10*time.Minute,
|
|
domain.NotificationTypeEmail,
|
|
"",
|
|
true,
|
|
"",
|
|
),
|
|
),
|
|
),
|
|
checkPermission: newMockPermissionCheckAllowed(),
|
|
newCode: mockEncryptedCode("code", 10*time.Minute),
|
|
},
|
|
args: args{
|
|
ctx: context.Background(),
|
|
userID: "userID",
|
|
returnCode: true,
|
|
},
|
|
res: res{
|
|
details: &domain.ObjectDetails{
|
|
ResourceOwner: "org1",
|
|
},
|
|
code: gu.Ptr("code"),
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &Commands{
|
|
checkPermission: tt.fields.checkPermission,
|
|
eventstore: tt.fields.eventstore(t),
|
|
userEncryption: tt.fields.userEncryption,
|
|
newEncryptedCode: tt.fields.newCode,
|
|
newEncryptedCodeWithDefault: tt.fields.newEncryptedCodeWithDefault,
|
|
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
|
|
}
|
|
|
|
got, gotPlainCode, err := c.requestPasswordReset(tt.args.ctx, tt.args.userID, tt.args.returnCode, tt.args.urlTmpl, tt.args.notificationType)
|
|
require.ErrorIs(t, err, tt.res.err)
|
|
assertObjectDetails(t, tt.res.details, got)
|
|
assert.Equal(t, tt.res.code, gotPlainCode)
|
|
})
|
|
}
|
|
}
|