mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:47:32 +00:00
feat: add domain verification notification (#649)
* fix: dont (re)generate client secret with auth type none * fix(cors): allow Origin from request * feat: add origin allow list and fix some core issues * rename migration * fix UserIDsByDomain * feat: send email to users after domain claim * username * check origin on userinfo * update oidc pkg * fix: add migration 1.6 * change username * change username * remove unique email aggregate * change username in mgmt * search global user by login name * fix test * change user search in angular * fix tests * merge * userview in angular * fix merge * Update pkg/grpc/management/proto/management.proto Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * Update internal/notification/static/i18n/de.yaml Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * fix Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"golang.org/x/text/language"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
req_model "github.com/caos/zitadel/internal/auth_request/model"
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
@@ -17,6 +19,7 @@ type UserView struct {
|
||||
ResourceOwner string
|
||||
PasswordSet bool
|
||||
PasswordChangeRequired bool
|
||||
UsernameChangeRequired bool
|
||||
PasswordChanged time.Time
|
||||
LastLogin time.Time
|
||||
UserName string
|
||||
|
@@ -670,11 +670,11 @@ func (es *UserEventstore) ChangeEmail(ctx context.Context, email *usr_model.Emai
|
||||
repoNew := model.EmailFromModel(email)
|
||||
repoEmailCode := model.EmailCodeFromModel(emailCode)
|
||||
|
||||
updateAggregates, err := EmailChangeAggregate(ctx, es.AggregateCreator(), repoExisting, repoNew, repoEmailCode)
|
||||
updateAggregate, err := EmailChangeAggregate(ctx, es.AggregateCreator(), repoExisting, repoNew, repoEmailCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoExisting.AppendEvents, updateAggregates...)
|
||||
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoExisting.AppendEvents, updateAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1112,6 +1112,48 @@ func (es *UserEventstore) PrepareDomainClaimed(ctx context.Context, userIDs []st
|
||||
return aggregates, nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) DomainClaimedSent(ctx context.Context, userID string) error {
|
||||
if userID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-0posw", "Errors.User.UserIDMissing")
|
||||
}
|
||||
user, err := es.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoUser := model.UserFromModel(user)
|
||||
agg := DomainClaimedSentAggregate(es.AggregateCreator(), repoUser)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoUser.AppendEvents, agg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es.userCache.cacheUser(repoUser)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) ChangeUsername(ctx context.Context, userID, username string, orgIamPolicy *org_model.OrgIAMPolicy) error {
|
||||
user, err := es.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldUsername := user.UserName
|
||||
user.UserName = username
|
||||
if err := user.CheckOrgIAMPolicy(orgIamPolicy); err != nil {
|
||||
return err
|
||||
}
|
||||
repoUser := model.UserFromModel(user)
|
||||
aggregates, err := UsernameChangedAggregates(ctx, es.AggregateCreator(), repoUser, oldUsername, orgIamPolicy.UserLoginMustBeDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoUser.AppendEvents, aggregates...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
es.userCache.cacheUser(repoUser)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) generateTemporaryLoginName() (string, error) {
|
||||
id, err := es.idGenerator.Next()
|
||||
if err != nil {
|
||||
|
@@ -5,7 +5,6 @@ import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
const (
|
||||
UserAggregate models.AggregateType = "user"
|
||||
UserUserNameAggregate models.AggregateType = "user.username"
|
||||
UserEmailAggregate models.AggregateType = "user.email"
|
||||
|
||||
UserAdded models.EventType = "user.added"
|
||||
UserRegistered models.EventType = "user.selfregistered"
|
||||
@@ -16,8 +15,6 @@ const (
|
||||
|
||||
UserUserNameReserved models.EventType = "user.username.reserved"
|
||||
UserUserNameReleased models.EventType = "user.username.released"
|
||||
UserEmailReserved models.EventType = "user.email.reserved"
|
||||
UserEmailReleased models.EventType = "user.email.released"
|
||||
|
||||
UserLocked models.EventType = "user.locked"
|
||||
UserUnlocked models.EventType = "user.unlocked"
|
||||
@@ -44,8 +41,9 @@ const (
|
||||
UserPhoneCodeAdded models.EventType = "user.phone.code.added"
|
||||
UserPhoneCodeSent models.EventType = "user.phone.code.sent"
|
||||
|
||||
UserProfileChanged models.EventType = "user.profile.changed"
|
||||
UserAddressChanged models.EventType = "user.address.changed"
|
||||
UserProfileChanged models.EventType = "user.profile.changed"
|
||||
UserAddressChanged models.EventType = "user.address.changed"
|
||||
UserUserNameChanged models.EventType = "user.username.changed"
|
||||
|
||||
MfaOtpAdded models.EventType = "user.mfa.otp.added"
|
||||
MfaOtpVerified models.EventType = "user.mfa.otp.verified"
|
||||
@@ -56,5 +54,6 @@ const (
|
||||
|
||||
SignedOut models.EventType = "user.signed.out"
|
||||
|
||||
DomainClaimed models.EventType = "user.domain.claimed"
|
||||
DomainClaimed models.EventType = "user.domain.claimed"
|
||||
DomainClaimedSent models.EventType = "user.domain.claimed.sent"
|
||||
)
|
||||
|
@@ -134,7 +134,8 @@ func (u *User) AppendEvent(event *es_models.Event) (err error) {
|
||||
case UserAdded,
|
||||
UserRegistered,
|
||||
UserProfileChanged,
|
||||
DomainClaimed:
|
||||
DomainClaimed,
|
||||
UserUserNameChanged:
|
||||
u.setData(event)
|
||||
case UserDeactivated:
|
||||
u.appendDeactivatedEvent()
|
||||
|
@@ -33,14 +33,6 @@ func UserUserNameUniqueQuery(userName string) *es_models.SearchQuery {
|
||||
SetLimit(1)
|
||||
}
|
||||
|
||||
func UserEmailUniqueQuery(email string) *es_models.SearchQuery {
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.UserEmailAggregate).
|
||||
AggregateIDFilter(email).
|
||||
OrderDesc().
|
||||
SetLimit(1)
|
||||
}
|
||||
|
||||
func UserAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, user *model.User) (*es_models.Aggregate, error) {
|
||||
if user == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dis83", "Errors.Internal")
|
||||
@@ -111,11 +103,7 @@ func UserCreateAggregate(ctx context.Context, aggCreator *es_models.AggregateCre
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*es_models.Aggregate{
|
||||
agg,
|
||||
uniqueAggregates[0],
|
||||
uniqueAggregates[1],
|
||||
}, nil
|
||||
return append(uniqueAggregates, agg), nil
|
||||
}
|
||||
|
||||
func UserRegisterAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, user *model.User, resourceOwner string, initCode *model.InitUserCode, userLoginMustBeDomain bool) ([]*es_models.Aggregate, error) {
|
||||
@@ -148,11 +136,7 @@ func UserRegisterAggregate(ctx context.Context, aggCreator *es_models.AggregateC
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*es_models.Aggregate{
|
||||
agg,
|
||||
uniqueAggregates[0],
|
||||
uniqueAggregates[1],
|
||||
}, nil
|
||||
return append(uniqueAggregates, agg), nil
|
||||
}
|
||||
|
||||
func getUniqueUserAggregates(ctx context.Context, aggCreator *es_models.AggregateCreator, user *model.User, resourceOwner string, userLoginMustBeDomain bool) ([]*es_models.Aggregate, error) {
|
||||
@@ -161,13 +145,8 @@ func getUniqueUserAggregates(ctx context.Context, aggCreator *es_models.Aggregat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
emailAggregate, err := reservedUniqueEmailAggregate(ctx, aggCreator, resourceOwner, user.EmailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*es_models.Aggregate{
|
||||
userNameAggregate,
|
||||
emailAggregate,
|
||||
}, nil
|
||||
}
|
||||
func reservedUniqueUserNameAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, resourceOwner, userName string, userLoginMustBeDomain bool) (*es_models.Aggregate, error) {
|
||||
@@ -206,36 +185,18 @@ func releasedUniqueUserNameAggregate(ctx context.Context, aggCreator *es_models.
|
||||
return aggregate.SetPrecondition(UserUserNameUniqueQuery(username), isEventValidation(aggregate, model.UserUserNameReleased)), nil
|
||||
}
|
||||
|
||||
func reservedUniqueEmailAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, resourceOwner, email string) (aggregate *es_models.Aggregate, err error) {
|
||||
aggregate, err = aggCreator.NewAggregate(ctx, email, model.UserEmailAggregate, model.UserVersion, 0)
|
||||
if resourceOwner != "" {
|
||||
aggregate, err = aggCreator.NewAggregate(ctx, email, model.UserEmailAggregate, model.UserVersion, 0, es_models.OverwriteResourceOwner(resourceOwner))
|
||||
}
|
||||
func changeUniqueUserNameAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, resourceOwner, oldUsername, username string, userLoginMustBeDomain bool) ([]*es_models.Aggregate, error) {
|
||||
aggregates := make([]*es_models.Aggregate, 2)
|
||||
var err error
|
||||
aggregates[0], err = releasedUniqueUserNameAggregate(ctx, aggCreator, resourceOwner, oldUsername)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregate, err = aggregate.AppendEvent(model.UserEmailReserved, nil)
|
||||
aggregates[1], err = reservedUniqueUserNameAggregate(ctx, aggCreator, resourceOwner, username, userLoginMustBeDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return aggregate.SetPrecondition(UserEmailUniqueQuery(email), isEventValidation(aggregate, model.UserEmailReserved)), nil
|
||||
}
|
||||
|
||||
func releasedUniqueEmailAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, resourceOwner, email string) (aggregate *es_models.Aggregate, err error) {
|
||||
aggregate, err = aggCreator.NewAggregate(ctx, email, model.UserEmailAggregate, model.UserVersion, 0)
|
||||
if resourceOwner != "" {
|
||||
aggregate, err = aggCreator.NewAggregate(ctx, email, model.UserEmailAggregate, model.UserVersion, 0, es_models.OverwriteResourceOwner(resourceOwner))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregate, err = aggregate.AppendEvent(model.UserEmailReleased, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return aggregate.SetPrecondition(UserEmailUniqueQuery(email), isEventValidation(aggregate, model.UserEmailReleased)), nil
|
||||
return aggregates, nil
|
||||
}
|
||||
|
||||
func UserDeactivateAggregate(aggCreator *es_models.AggregateCreator, user *model.User) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
@@ -401,7 +362,7 @@ func ProfileChangeAggregate(aggCreator *es_models.AggregateCreator, existing *mo
|
||||
}
|
||||
}
|
||||
|
||||
func EmailChangeAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *model.User, email *model.Email, code *model.EmailCode) ([]*es_models.Aggregate, error) {
|
||||
func EmailChangeAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existing *model.User, email *model.Email, code *model.EmailCode) (*es_models.Aggregate, error) {
|
||||
if email == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dki8s", "Errors.Internal")
|
||||
}
|
||||
@@ -412,17 +373,6 @@ func EmailChangeAggregate(ctx context.Context, aggCreator *es_models.AggregateCr
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-s90pw", "Errors.NoChangesFound")
|
||||
}
|
||||
aggregates := make([]*es_models.Aggregate, 0, 4)
|
||||
reserveEmailAggregate, err := reservedUniqueEmailAggregate(ctx, aggCreator, "", email.EmailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregates = append(aggregates, reserveEmailAggregate)
|
||||
releaseEmailAggregate, err := releasedUniqueEmailAggregate(ctx, aggCreator, "", existing.EmailAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregates = append(aggregates, releaseEmailAggregate)
|
||||
agg, err := UserAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -446,7 +396,7 @@ func EmailChangeAggregate(ctx context.Context, aggCreator *es_models.AggregateCr
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return append(aggregates, agg), nil
|
||||
return agg, nil
|
||||
}
|
||||
|
||||
func EmailVerifiedAggregate(aggCreator *es_models.AggregateCreator, existing *model.User) es_sdk.AggregateFunc {
|
||||
@@ -673,7 +623,10 @@ func SignOutAggregates(aggCreator *es_models.AggregateCreator, existingUsers []*
|
||||
}
|
||||
|
||||
func DomainClaimedAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, existingUser *model.User, tempName string) ([]*es_models.Aggregate, error) {
|
||||
aggregates := make([]*es_models.Aggregate, 3)
|
||||
aggregates, err := changeUniqueUserNameAggregate(ctx, aggCreator, existingUser.ResourceOwner, existingUser.UserName, tempName, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userAggregate, err := UserAggregateOverwriteContext(ctx, aggCreator, existingUser, existingUser.ResourceOwner, existingUser.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -682,18 +635,41 @@ func DomainClaimedAggregate(ctx context.Context, aggCreator *es_models.Aggregate
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregates[0] = userAggregate
|
||||
releasedUniqueAggregate, err := releasedUniqueUserNameAggregate(ctx, aggCreator, existingUser.ResourceOwner, existingUser.UserName)
|
||||
return append(aggregates, userAggregate), nil
|
||||
}
|
||||
|
||||
func DomainClaimedSentAggregate(aggCreator *es_models.AggregateCreator, user *model.User) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
agg, err := UserAggregate(ctx, aggCreator, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.DomainClaimedSent, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func UsernameChangedAggregates(ctx context.Context, aggCreator *es_models.AggregateCreator, user *model.User, oldUsername string, userLoginMustBeDomain bool) ([]*es_models.Aggregate, error) {
|
||||
aggregates, err := changeUniqueUserNameAggregate(ctx, aggCreator, user.ResourceOwner, oldUsername, user.UserName, userLoginMustBeDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregates[1] = releasedUniqueAggregate
|
||||
reservedUniqueAggregate, err := reservedUniqueUserNameAggregate(ctx, aggCreator, existingUser.ResourceOwner, tempName, false)
|
||||
userAggregate, err := UserAggregate(ctx, aggCreator, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aggregates[2] = reservedUniqueAggregate
|
||||
return aggregates, nil
|
||||
userAggregate, err = userAggregate.AppendEvent(model.UserUserNameChanged, map[string]interface{}{"userName": user.UserName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !userLoginMustBeDomain {
|
||||
validationQuery := es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(org_es_model.OrgAggregate).
|
||||
AggregateIDsFilter()
|
||||
|
||||
validation := addUserNameValidation(user.UserName)
|
||||
userAggregate.SetPrecondition(validationQuery, validation)
|
||||
}
|
||||
return append(aggregates, userAggregate), nil
|
||||
}
|
||||
|
||||
func isEventValidation(aggregate *es_models.Aggregate, eventType es_models.EventType) func(...*es_models.Event) error {
|
||||
|
@@ -136,7 +136,7 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
eventLen: 1,
|
||||
eventTypes: []models.EventType{model.UserAdded},
|
||||
checkData: []bool{true},
|
||||
aggregatesLen: 3,
|
||||
aggregatesLen: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -166,7 +166,7 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
eventLen: 2,
|
||||
eventTypes: []models.EventType{model.UserAdded, model.InitializedUserCodeAdded},
|
||||
checkData: []bool{true, true},
|
||||
aggregatesLen: 3,
|
||||
aggregatesLen: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -184,7 +184,7 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
eventLen: 2,
|
||||
eventTypes: []models.EventType{model.UserAdded, model.UserPhoneCodeAdded},
|
||||
checkData: []bool{true, true},
|
||||
aggregatesLen: 3,
|
||||
aggregatesLen: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -201,7 +201,7 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
eventLen: 2,
|
||||
eventTypes: []models.EventType{model.UserAdded, model.UserEmailVerified},
|
||||
checkData: []bool{true, false},
|
||||
aggregatesLen: 3,
|
||||
aggregatesLen: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -219,7 +219,7 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
eventLen: 2,
|
||||
eventTypes: []models.EventType{model.UserAdded, model.UserPhoneVerified},
|
||||
checkData: []bool{true, false},
|
||||
aggregatesLen: 3,
|
||||
aggregatesLen: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -231,17 +231,17 @@ func TestUserCreateAggregate(t *testing.T) {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.aggregatesLen, len(aggregates))
|
||||
}
|
||||
|
||||
if !tt.res.wantErr && len(aggregates[0].Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregates[0].Events))
|
||||
if !tt.res.wantErr && len(aggregates[1].Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregates[1].Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if !tt.res.wantErr && aggregates[0].Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregates[0].Events[i].Type.String())
|
||||
if !tt.res.wantErr && aggregates[1].Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregates[1].Events[i].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && tt.res.checkData[i] && aggregates[0].Events[i].Data == nil {
|
||||
if !tt.res.wantErr && tt.res.checkData[i] && aggregates[1].Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if !tt.res.wantErr && !tt.res.checkData[i] && aggregates[0].Events[i].Data != nil {
|
||||
if !tt.res.wantErr && !tt.res.checkData[i] && aggregates[1].Events[i].Data != nil {
|
||||
t.Errorf("should not have data in event")
|
||||
}
|
||||
}
|
||||
@@ -352,14 +352,14 @@ func TestUserRegisterAggregate(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
aggregates, err := UserRegisterAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.new, tt.args.resourceOwner, tt.args.initCode, false)
|
||||
|
||||
if tt.res.errFunc == nil && len(aggregates[0].Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregates[0].Events))
|
||||
if tt.res.errFunc == nil && len(aggregates[1].Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregates[1].Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if tt.res.errFunc == nil && aggregates[0].Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregates[0].Events[i].Type.String())
|
||||
if tt.res.errFunc == nil && aggregates[1].Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregates[1].Events[i].Type.String())
|
||||
}
|
||||
if tt.res.errFunc == nil && aggregates[0].Events[i].Data == nil {
|
||||
if tt.res.errFunc == nil && aggregates[1].Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
@@ -1226,16 +1226,16 @@ func TestChangeEmailAggregate(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
aggregates, err := EmailChangeAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.existing, tt.args.email, tt.args.code)
|
||||
aggregate, err := EmailChangeAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.existing, tt.args.email, tt.args.code)
|
||||
|
||||
if tt.res.errFunc == nil && len(aggregates[2].Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregates[1].Events))
|
||||
if tt.res.errFunc == nil && len(aggregate.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(aggregate.Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if tt.res.errFunc == nil && aggregates[2].Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregates[1].Events[i].Type.String())
|
||||
if tt.res.errFunc == nil && aggregate.Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], aggregate.Events[i].Type.String())
|
||||
}
|
||||
if tt.res.errFunc == nil && aggregates[2].Events[i].Data == nil {
|
||||
if tt.res.errFunc == nil && aggregate.Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ type UserView struct {
|
||||
State int32 `json:"-" gorm:"column:user_state"`
|
||||
PasswordSet bool `json:"-" gorm:"column:password_set"`
|
||||
PasswordChangeRequired bool `json:"-" gorm:"column:password_change_required"`
|
||||
UsernameChangeRequired bool `json:"-" gorm:"column:username_change_required"`
|
||||
PasswordChanged time.Time `json:"-" gorm:"column:password_change"`
|
||||
LastLogin time.Time `json:"-" gorm:"column:last_login"`
|
||||
UserName string `json:"userName" gorm:"column:user_name"`
|
||||
@@ -72,6 +73,7 @@ func UserFromModel(user *model.UserView) *UserView {
|
||||
State: int32(user.State),
|
||||
PasswordSet: user.PasswordSet,
|
||||
PasswordChangeRequired: user.PasswordChangeRequired,
|
||||
UsernameChangeRequired: user.UsernameChangeRequired,
|
||||
PasswordChanged: user.PasswordChanged,
|
||||
LastLogin: user.LastLogin,
|
||||
UserName: user.UserName,
|
||||
@@ -109,6 +111,7 @@ func UserToModel(user *UserView) *model.UserView {
|
||||
State: model.UserState(user.State),
|
||||
PasswordSet: user.PasswordSet,
|
||||
PasswordChangeRequired: user.PasswordChangeRequired,
|
||||
UsernameChangeRequired: user.UsernameChangeRequired,
|
||||
PasswordChanged: user.PasswordChanged,
|
||||
LastLogin: user.LastLogin,
|
||||
PreferredLoginName: user.PreferredLoginName,
|
||||
@@ -181,8 +184,13 @@ func (u *UserView) AppendEvent(event *models.Event) (err error) {
|
||||
case es_model.UserPasswordChanged:
|
||||
err = u.setPasswordData(event)
|
||||
case es_model.UserProfileChanged,
|
||||
es_model.UserAddressChanged,
|
||||
es_model.DomainClaimed:
|
||||
es_model.UserAddressChanged:
|
||||
err = u.setData(event)
|
||||
case es_model.DomainClaimed:
|
||||
u.UsernameChangeRequired = true
|
||||
err = u.setData(event)
|
||||
case es_model.UserUserNameChanged:
|
||||
u.UsernameChangeRequired = false
|
||||
err = u.setData(event)
|
||||
case es_model.UserEmailChanged:
|
||||
u.IsEmailVerified = false
|
||||
|
@@ -94,9 +94,9 @@ func SearchUsers(db *gorm.DB, table string, req *usr_model.UserSearchRequest) ([
|
||||
return users, count, nil
|
||||
}
|
||||
|
||||
func GetGlobalUserByEmail(db *gorm.DB, table, email string) (*model.UserView, error) {
|
||||
func GetGlobalUserByLoginName(db *gorm.DB, table, loginName string) (*model.UserView, error) {
|
||||
user := new(model.UserView)
|
||||
query := repository.PrepareGetByKey(table, model.UserSearchKey(usr_model.UserSearchKeyEmail), email)
|
||||
query := repository.PrepareGetByQuery(table, &model.UserSearchQuery{Key: usr_model.UserSearchKeyLoginNames, Value: loginName, Method: global_model.SearchMethodListContains})
|
||||
err := query(db, user)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-8uWer", "Errors.User.NotFound")
|
||||
|
Reference in New Issue
Block a user