fix: user init mail (for wrong email) (#891)

* add resendInitialMail

* disable email notifications (when not initialised)

* fix resend init mail

* add tests

* cleanup

* cleanup

* fix tests

* add resend trigger, dialog

* refactor contact component, add sendinitmail fnc

* skip email if empty

* reload user on phone email changes, i18n warndialog on dl

* lint

* rebuild mgmt proto

* remove initial focus

* Update console/src/assets/i18n/de.json

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
This commit is contained in:
Livio Amstutz
2020-11-16 11:43:22 +01:00
committed by GitHub
parent 69c39b5eb2
commit 376fba72d8
42 changed files with 11465 additions and 18601 deletions

View File

@@ -3,7 +3,6 @@ package eventsourcing
import (
"context"
"encoding/json"
iam_model "github.com/caos/zitadel/internal/iam/model"
"net"
"testing"
"time"
@@ -15,6 +14,7 @@ import (
"github.com/caos/zitadel/internal/crypto"
caos_errs "github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/user/model"
repo_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
@@ -1287,7 +1287,7 @@ func TestPasswordID(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
@@ -1366,7 +1366,7 @@ func TestSetOneTimePassword(t *testing.T) {
{
name: "create one time pw",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{Email: &repo_model.Email{EmailAddress: "email"}}}, true),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, SecretString: "Password"},
@@ -1516,8 +1516,10 @@ func TestCheckPassword(t *testing.T) {
Algorithm: "hash",
Crypted: []byte("password"),
}},
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
@@ -1582,8 +1584,10 @@ func TestSetPassword(t *testing.T) {
KeyID: "id",
Crypted: []byte("code"),
}},
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
@@ -1627,8 +1631,11 @@ func TestSetPassword(t *testing.T) {
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{},
Human: &repo_model.Human{
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
@@ -1653,8 +1660,10 @@ func TestSetPassword(t *testing.T) {
KeyID: "id",
Crypted: []byte("code2"),
}},
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
@@ -1759,8 +1768,11 @@ func TestChangePassword(t *testing.T) {
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{},
Human: &repo_model.Human{
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
@@ -1784,8 +1796,10 @@ func TestChangePassword(t *testing.T) {
Algorithm: "hash",
Crypted: []byte("older"),
}},
Email: &repo_model.Email{EmailAddress: "email"},
},
},
true,
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &iam_model.PasswordComplexityPolicyView{},
@@ -1859,7 +1873,12 @@ func TestRequestSetPassword(t *testing.T) {
{
name: "create pw",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Email: &repo_model.Email{EmailAddress: "email"},
}},
true),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
notifyType: model.NotificationTypeEmail,
@@ -1868,6 +1887,18 @@ func TestRequestSetPassword(t *testing.T) {
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: false},
},
},
{
name: "initial state",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}, false),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
notifyType: model.NotificationTypeEmail,
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty userid",
args: args{
@@ -1905,6 +1936,84 @@ func TestRequestSetPassword(t *testing.T) {
}
}
func TestResendInitialMail(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
mail string
}
type res struct {
password *model.Password
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "resend ok",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
mail: "",
},
res: res{
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: false},
},
},
{
name: "resend with email ok",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
mail: "email",
},
res: res{
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: false},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
mail: "",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
mail: "",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.ResendInitialMail(tt.args.ctx, tt.args.userID, tt.args.mail)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestPasswordCodeSent(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
@@ -2170,7 +2279,7 @@ func TestProfileByID(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
},
@@ -2237,7 +2346,7 @@ func TestChangeProfile(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, FirstName: "FirstName Changed", LastName: "LastName Changed"},
},
@@ -2304,7 +2413,7 @@ func TestEmailByID(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
@@ -2371,7 +2480,7 @@ func TestChangeEmail(t *testing.T) {
{
name: "change email address, verified",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, true),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: true},
},
@@ -2389,7 +2498,7 @@ func TestChangeEmail(t *testing.T) {
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
},
}),
}, true),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: false},
},
@@ -2397,6 +2506,24 @@ func TestChangeEmail(t *testing.T) {
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: false},
},
},
{
name: "user state initial",
args: args{
es: GetMockManipulateUserWithEmailCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
},
}, false),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: false},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty userid",
args: args{
@@ -2423,7 +2550,9 @@ func TestChangeEmail(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeEmail(tt.args.ctx, tt.args.email)
if (tt.res.errFunc != nil && !tt.res.errFunc(err)) || (tt.res.errFunc == nil && err != nil) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
@@ -2433,9 +2562,6 @@ func TestChangeEmail(t *testing.T) {
if tt.res.errFunc == nil && result.IsEmailVerified != tt.res.email.IsEmailVerified {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.email.IsEmailVerified, result.IsEmailVerified)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
@@ -2551,12 +2677,30 @@ func TestCreateEmailVerificationCode(t *testing.T) {
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
}}),
}}, true),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{},
},
{
name: "initial state",
args: args{
es: GetMockManipulateUserWithEmailCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
},
}, false),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty userid",
args: args{
@@ -2606,7 +2750,7 @@ func TestCreateEmailVerificationCode(t *testing.T) {
err := tt.args.es.CreateEmailVerificationCode(tt.args.ctx, tt.args.userID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not ger err")
t.Errorf("should not get err, got: %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
@@ -2695,7 +2839,7 @@ func TestPhoneByID(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
@@ -2762,7 +2906,7 @@ func TestChangePhone(t *testing.T) {
{
name: "change phone, verified",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "0711234567", IsPhoneVerified: true},
},
@@ -3149,7 +3293,7 @@ func TestAddressByID(t *testing.T) {
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
@@ -3216,7 +3360,7 @@ func TestChangeAddress(t *testing.T) {
{
name: "change address ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
es: GetMockManipulateUserFull(ctrl, false),
ctx: authz.NewMockContext("orgID", "userID"),
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Country: "CountryChanged"},
},