mirror of
https://github.com/zitadel/zitadel.git
synced 2025-11-14 14:53:21 +00:00
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:
@@ -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"},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user