diff --git a/internal/api/grpc/management/user.go b/internal/api/grpc/management/user.go index 14af284176..af65d566bb 100644 --- a/internal/api/grpc/management/user.go +++ b/internal/api/grpc/management/user.go @@ -60,48 +60,48 @@ func (s *Server) CreateUser(ctx context.Context, in *management.CreateUserReques } func (s *Server) DeactivateUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) { - user, err := s.user.DeactivateUser(ctx, in.Id) + user, err := s.command.DeactivateUser(ctx, in.Id) if err != nil { return nil, err } - return userFromModel(user), nil + return userFromDomain(user), nil } func (s *Server) ReactivateUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) { - user, err := s.user.ReactivateUser(ctx, in.Id) + user, err := s.command.ReactivateUser(ctx, in.Id) if err != nil { return nil, err } - return userFromModel(user), nil + return userFromDomain(user), nil } func (s *Server) LockUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) { - user, err := s.user.LockUser(ctx, in.Id) + user, err := s.command.LockUser(ctx, in.Id) if err != nil { return nil, err } - return userFromModel(user), nil + return userFromDomain(user), nil } func (s *Server) UnlockUser(ctx context.Context, in *management.UserID) (*management.UserResponse, error) { - user, err := s.user.UnlockUser(ctx, in.Id) + user, err := s.command.UnlockUser(ctx, in.Id) if err != nil { return nil, err } - return userFromModel(user), nil + return userFromDomain(user), nil } func (s *Server) DeleteUser(ctx context.Context, in *management.UserID) (*empty.Empty, error) { - err := s.user.RemoveUser(ctx, in.Id) + err := s.command.RemoveUser(ctx, in.Id) return &empty.Empty{}, err } func (s *Server) UpdateUserMachine(ctx context.Context, in *management.UpdateMachineRequest) (*management.MachineResponse, error) { - machine, err := s.user.ChangeMachine(ctx, updateMachineToModel(in)) + machine, err := s.command.ChangeMachine(ctx, updateMachineToDomain(in)) if err != nil { return nil, err } - return machineFromModel(machine), nil + return machineFromDomain(machine), nil } func (s *Server) GetUserProfile(ctx context.Context, in *management.UserID) (*management.UserProfileView, error) { @@ -117,11 +117,11 @@ func (s *Server) ChangeUserUserName(ctx context.Context, request *management.Upd } func (s *Server) UpdateUserProfile(ctx context.Context, request *management.UpdateUserProfileRequest) (*management.UserProfile, error) { - profile, err := s.user.ChangeProfile(ctx, updateProfileToModel(request)) + profile, err := s.command.ChangeHumanProfile(ctx, updateProfileToDomain(request)) if err != nil { return nil, err } - return profileFromModel(profile), nil + return profileFromDomain(profile), nil } func (s *Server) GetUserEmail(ctx context.Context, in *management.UserID) (*management.UserEmailView, error) { @@ -133,11 +133,11 @@ func (s *Server) GetUserEmail(ctx context.Context, in *management.UserID) (*mana } func (s *Server) ChangeUserEmail(ctx context.Context, request *management.UpdateUserEmailRequest) (*management.UserEmail, error) { - email, err := s.user.ChangeEmail(ctx, updateEmailToModel(request)) + email, err := s.command.ChangeHumanEmail(ctx, updateEmailToDomain(request)) if err != nil { return nil, err } - return emailFromModel(email), nil + return emailFromDomain(email), nil } func (s *Server) ResendEmailVerificationMail(ctx context.Context, in *management.UserID) (*empty.Empty, error) { @@ -180,11 +180,11 @@ func (s *Server) GetUserAddress(ctx context.Context, in *management.UserID) (*ma } func (s *Server) UpdateUserAddress(ctx context.Context, request *management.UpdateUserAddressRequest) (*management.UserAddress, error) { - address, err := s.user.ChangeAddress(ctx, updateAddressToModel(request)) + address, err := s.command.ChangeHumanAddress(ctx, updateAddressToDomain(request)) if err != nil { return nil, err } - return addressFromModel(address), nil + return addressFromDomain(address), nil } func (s *Server) SendSetPasswordNotification(ctx context.Context, request *management.SetPasswordNotificationRequest) (*empty.Empty, error) { diff --git a/internal/api/grpc/management/user_converter.go b/internal/api/grpc/management/user_converter.go index b62bd2b8c4..38bd686de8 100644 --- a/internal/api/grpc/management/user_converter.go +++ b/internal/api/grpc/management/user_converter.go @@ -43,32 +43,6 @@ func userFromDomain(user *domain.User) *management.UserResponse { return userResp } -func userFromModel(user *usr_model.User) *management.UserResponse { - creationDate, err := ptypes.TimestampProto(user.CreationDate) - logging.Log("GRPC-8duwe").OnError(err).Debug("unable to parse timestamp") - - changeDate, err := ptypes.TimestampProto(user.ChangeDate) - logging.Log("GRPC-ckoe3d").OnError(err).Debug("unable to parse timestamp") - - userResp := &management.UserResponse{ - Id: user.AggregateID, - State: management.UserState(user.State), - CreationDate: creationDate, - ChangeDate: changeDate, - Sequence: user.Sequence, - UserName: user.UserName, - } - - if user.Machine != nil { - userResp.User = &management.UserResponse_Machine{Machine: machineFromModel(user.Machine)} - } - if user.Human != nil { - userResp.User = &management.UserResponse_Human{Human: humanFromModel(user.Human)} - } - - return userResp -} - func userCreateToDomain(user *management.CreateUserRequest) *domain.User { var human *domain.Human var machine *domain.Machine @@ -232,7 +206,7 @@ func userMembershipSearchKeyToModel(key management.UserMembershipSearchKey) usr_ } } -func profileFromModel(profile *usr_model.Profile) *management.UserProfile { +func profileFromDomain(profile *domain.Profile) *management.UserProfile { creationDate, err := ptypes.TimestampProto(profile.CreationDate) logging.Log("GRPC-dkso3").OnError(err).Debug("unable to parse timestamp") @@ -276,21 +250,21 @@ func profileViewFromModel(profile *usr_model.Profile) *management.UserProfileVie } } -func updateProfileToModel(u *management.UpdateUserProfileRequest) *usr_model.Profile { +func updateProfileToDomain(u *management.UpdateUserProfileRequest) *domain.Profile { preferredLanguage, err := language.Parse(u.PreferredLanguage) logging.Log("GRPC-d8k2s").OnError(err).Debug("language malformed") - return &usr_model.Profile{ + return &domain.Profile{ ObjectRoot: models.ObjectRoot{AggregateID: u.Id}, FirstName: u.FirstName, LastName: u.LastName, NickName: u.NickName, PreferredLanguage: preferredLanguage, - Gender: usr_model.Gender(u.Gender), + Gender: genderToDomain(u.Gender), } } -func emailFromModel(email *usr_model.Email) *management.UserEmail { +func emailFromDomain(email *domain.Email) *management.UserEmail { creationDate, err := ptypes.TimestampProto(email.CreationDate) logging.Log("GRPC-d9ow2").OnError(err).Debug("unable to parse timestamp") @@ -324,8 +298,8 @@ func emailViewFromModel(email *usr_model.Email) *management.UserEmailView { } } -func updateEmailToModel(e *management.UpdateUserEmailRequest) *usr_model.Email { - return &usr_model.Email{ +func updateEmailToDomain(e *management.UpdateUserEmailRequest) *domain.Email { + return &domain.Email{ ObjectRoot: models.ObjectRoot{AggregateID: e.Id}, EmailAddress: e.Email, IsEmailVerified: e.IsEmailVerified, @@ -373,7 +347,7 @@ func updatePhoneToModel(e *management.UpdateUserPhoneRequest) *usr_model.Phone { } } -func addressFromModel(address *usr_model.Address) *management.UserAddress { +func addressFromDomain(address *domain.Address) *management.UserAddress { creationDate, err := ptypes.TimestampProto(address.CreationDate) logging.Log("GRPC-ud8w7").OnError(err).Debug("unable to parse timestamp") @@ -413,8 +387,8 @@ func addressViewFromModel(address *usr_model.Address) *management.UserAddressVie } } -func updateAddressToModel(address *management.UpdateUserAddressRequest) *usr_model.Address { - return &usr_model.Address{ +func updateAddressToDomain(address *management.UpdateUserAddressRequest) *domain.Address { + return &domain.Address{ ObjectRoot: models.ObjectRoot{AggregateID: address.Id}, Country: address.Country, StreetAddress: address.StreetAddress, diff --git a/internal/api/grpc/management/user_machine_converter.go b/internal/api/grpc/management/user_machine_converter.go index 9d46a2f107..6b64756a58 100644 --- a/internal/api/grpc/management/user_machine_converter.go +++ b/internal/api/grpc/management/user_machine_converter.go @@ -20,9 +20,10 @@ func machineCreateToDomain(machine *management.CreateMachineRequest) *domain.Mac } } -func updateMachineToModel(machine *management.UpdateMachineRequest) *usr_model.Machine { - return &usr_model.Machine{ +func updateMachineToDomain(machine *management.UpdateMachineRequest) *domain.Machine { + return &domain.Machine{ ObjectRoot: models.ObjectRoot{AggregateID: machine.Id}, + Name: machine.Name, Description: machine.Description, } } @@ -34,13 +35,6 @@ func machineFromDomain(account *domain.Machine) *management.MachineResponse { } } -func machineFromModel(account *usr_model.Machine) *management.MachineResponse { - return &management.MachineResponse{ - Name: account.Name, - Description: account.Description, - } -} - func machineViewFromModel(machine *usr_model.MachineView) *management.MachineView { lastKeyAdded, err := ptypes.TimestampProto(machine.LastKeyAdded) logging.Log("MANAG-wGcAQ").OnError(err).Debug("unable to parse date") diff --git a/internal/eventstore/v2/eventstore.go b/internal/eventstore/v2/eventstore.go index 2f80b564e6..bb4f3e862f 100644 --- a/internal/eventstore/v2/eventstore.go +++ b/internal/eventstore/v2/eventstore.go @@ -207,7 +207,7 @@ func eventData(event EventPusher) ([]byte, error) { if dataType.Kind() == reflect.Struct { dataBytes, err := json.Marshal(event.Data()) if err != nil { - return nil, errors.ThrowInvalidArgument(err, "V2-xG87M", "could not marhsal data") + return nil, errors.ThrowInvalidArgument(err, "V2-xG87M", "could not marshal data") } return dataBytes, nil } diff --git a/internal/v2/command/iam_policy_label_model.go b/internal/v2/command/iam_policy_label_model.go index 8d745d4044..096eab1ccc 100644 --- a/internal/v2/command/iam_policy_label_model.go +++ b/internal/v2/command/iam_policy_label_model.go @@ -45,16 +45,15 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent( primaryColor, secondaryColor string, ) (*iam.LabelPolicyChangedEvent, bool) { - hasChanged := false changedEvent := iam.NewLabelPolicyChangedEvent(ctx) if wm.PrimaryColor != primaryColor { hasChanged = true - changedEvent.PrimaryColor = primaryColor + changedEvent.PrimaryColor = &primaryColor } if wm.SecondaryColor != secondaryColor { hasChanged = true - changedEvent.SecondaryColor = secondaryColor + changedEvent.SecondaryColor = &secondaryColor } return changedEvent, hasChanged } diff --git a/internal/v2/command/iam_policy_login_model.go b/internal/v2/command/iam_policy_login_model.go index ff669e70ac..e29185df0a 100644 --- a/internal/v2/command/iam_policy_login_model.go +++ b/internal/v2/command/iam_policy_login_model.go @@ -58,23 +58,23 @@ func (wm *IAMLoginPolicyWriteModel) NewChangedEvent( changedEvent := iam.NewLoginPolicyChangedEvent(ctx) if wm.AllowUserNamePassword == allowUsernamePassword { hasChanged = true - changedEvent.AllowUserNamePassword = allowUsernamePassword + changedEvent.AllowUserNamePassword = &allowUsernamePassword } if wm.AllowRegister == allowRegister { hasChanged = true - changedEvent.AllowRegister = allowRegister + changedEvent.AllowRegister = &allowRegister } if wm.AllowExternalIDP == allowExternalIDP { hasChanged = true - changedEvent.AllowExternalIDP = allowExternalIDP + changedEvent.AllowExternalIDP = &allowExternalIDP } if wm.ForceMFA != forceMFA { hasChanged = true - changedEvent.ForceMFA = forceMFA + changedEvent.ForceMFA = &forceMFA } if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType { hasChanged = true - changedEvent.PasswordlessType = passwordlessType + changedEvent.PasswordlessType = &passwordlessType } return changedEvent, hasChanged } diff --git a/internal/v2/command/iam_policy_org_iam_model.go b/internal/v2/command/iam_policy_org_iam_model.go index 8ecbda2f72..1113890fd8 100644 --- a/internal/v2/command/iam_policy_org_iam_model.go +++ b/internal/v2/command/iam_policy_org_iam_model.go @@ -45,7 +45,7 @@ func (wm *IAMOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLo changedEvent := iam.NewOrgIAMPolicyChangedEvent(ctx) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { hasChanged = true - changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain + changedEvent.UserLoginMustBeDomain = &userLoginMustBeDomain } return changedEvent, hasChanged } diff --git a/internal/v2/command/iam_policy_password_age_model.go b/internal/v2/command/iam_policy_password_age_model.go index f7dcfaafd6..12418acaa2 100644 --- a/internal/v2/command/iam_policy_password_age_model.go +++ b/internal/v2/command/iam_policy_password_age_model.go @@ -45,11 +45,11 @@ func (wm *IAMPasswordAgePolicyWriteModel) NewChangedEvent(ctx context.Context, e changedEvent := iam.NewPasswordAgePolicyChangedEvent(ctx) if wm.ExpireWarnDays != expireWarnDays { hasChanged = true - changedEvent.ExpireWarnDays = expireWarnDays + changedEvent.ExpireWarnDays = &expireWarnDays } if wm.MaxAgeDays != maxAgeDays { hasChanged = true - changedEvent.MaxAgeDays = maxAgeDays + changedEvent.MaxAgeDays = &maxAgeDays } return changedEvent, hasChanged } diff --git a/internal/v2/command/iam_policy_password_complexity_model.go b/internal/v2/command/iam_policy_password_complexity_model.go index b9b03e5457..6f67e89d43 100644 --- a/internal/v2/command/iam_policy_password_complexity_model.go +++ b/internal/v2/command/iam_policy_password_complexity_model.go @@ -53,23 +53,23 @@ func (wm *IAMPasswordComplexityPolicyWriteModel) NewChangedEvent( changedEvent := iam.NewPasswordComplexityPolicyChangedEvent(ctx) if wm.MinLength != minLength { hasChanged = true - changedEvent.MinLength = minLength + changedEvent.MinLength = &minLength } if wm.HasLowercase != hasLowercase { hasChanged = true - changedEvent.HasLowercase = hasLowercase + changedEvent.HasLowercase = &hasLowercase } if wm.HasUpperCase != hasUppercase { hasChanged = true - changedEvent.HasUpperCase = hasUppercase + changedEvent.HasUpperCase = &hasUppercase } if wm.HasNumber != hasNumber { hasChanged = true - changedEvent.HasNumber = hasNumber + changedEvent.HasNumber = &hasNumber } if wm.HasSymbol != hasSymbol { hasChanged = true - changedEvent.HasSymbol = hasSymbol + changedEvent.HasSymbol = &hasSymbol } return changedEvent, hasChanged } diff --git a/internal/v2/command/iam_policy_password_lockout_model.go b/internal/v2/command/iam_policy_password_lockout_model.go index be81f63e88..f13a163988 100644 --- a/internal/v2/command/iam_policy_password_lockout_model.go +++ b/internal/v2/command/iam_policy_password_lockout_model.go @@ -45,11 +45,11 @@ func (wm *IAMPasswordLockoutPolicyWriteModel) NewChangedEvent(ctx context.Contex changedEvent := iam.NewPasswordLockoutPolicyChangedEvent(ctx) if wm.MaxAttempts != maxAttempts { hasChanged = true - changedEvent.MaxAttempts = maxAttempts + changedEvent.MaxAttempts = &maxAttempts } if wm.ShowLockOutFailures != showLockoutFailure { hasChanged = true - changedEvent.ShowLockOutFailures = showLockoutFailure + changedEvent.ShowLockOutFailures = &showLockoutFailure } return changedEvent, hasChanged } diff --git a/internal/v2/command/org_policy_org_iam_model.go b/internal/v2/command/org_policy_org_iam_model.go index b2ad24880f..9a8a69da4c 100644 --- a/internal/v2/command/org_policy_org_iam_model.go +++ b/internal/v2/command/org_policy_org_iam_model.go @@ -45,7 +45,7 @@ func (wm *ORGOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLo changedEvent := org.NewOrgIAMPolicyChangedEvent(ctx) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { hasChanged = true - changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain + changedEvent.UserLoginMustBeDomain = &userLoginMustBeDomain } return changedEvent, hasChanged } diff --git a/internal/v2/command/org_policy_password_complexity_model.go b/internal/v2/command/org_policy_password_complexity_model.go index 123f685a16..cb5e141673 100644 --- a/internal/v2/command/org_policy_password_complexity_model.go +++ b/internal/v2/command/org_policy_password_complexity_model.go @@ -53,23 +53,23 @@ func (wm *OrgPasswordComplexityPolicyWriteModel) NewChangedEvent( changedEvent := org.NewPasswordComplexityPolicyChangedEvent(ctx) if wm.MinLength != minLength { hasChanged = true - changedEvent.MinLength = minLength + changedEvent.MinLength = &minLength } if wm.HasLowercase != hasLowercase { hasChanged = true - changedEvent.HasLowercase = hasLowercase + changedEvent.HasLowercase = &hasLowercase } if wm.HasUpperCase != hasUppercase { hasChanged = true - changedEvent.HasUpperCase = hasUppercase + changedEvent.HasUpperCase = &hasUppercase } if wm.HasNumber != hasNumber { hasChanged = true - changedEvent.HasNumber = hasNumber + changedEvent.HasNumber = &hasNumber } if wm.HasSymbol != hasSymbol { hasChanged = true - changedEvent.HasSymbol = hasSymbol + changedEvent.HasSymbol = &hasSymbol } return changedEvent, hasChanged } diff --git a/internal/v2/command/policy_label_model.go b/internal/v2/command/policy_label_model.go index 0c13c77012..aa82f4625a 100644 --- a/internal/v2/command/policy_label_model.go +++ b/internal/v2/command/policy_label_model.go @@ -21,8 +21,12 @@ func (wm *LabelPolicyWriteModel) Reduce() error { wm.SecondaryColor = e.SecondaryColor wm.IsActive = true case *policy.LabelPolicyChangedEvent: - wm.PrimaryColor = e.PrimaryColor - wm.SecondaryColor = e.SecondaryColor + if e.PrimaryColor != nil { + wm.PrimaryColor = *e.PrimaryColor + } + if e.SecondaryColor != nil { + wm.SecondaryColor = *e.SecondaryColor + } case *policy.LabelPolicyRemovedEvent: wm.IsActive = false } diff --git a/internal/v2/command/policy_login_model.go b/internal/v2/command/policy_login_model.go index 31d1ae2297..c37a1d12b5 100644 --- a/internal/v2/command/policy_login_model.go +++ b/internal/v2/command/policy_login_model.go @@ -28,11 +28,21 @@ func (wm *LoginPolicyWriteModel) Reduce() error { wm.PasswordlessType = e.PasswordlessType wm.IsActive = true case *policy.LoginPolicyChangedEvent: - wm.AllowRegister = e.AllowRegister - wm.AllowUserNamePassword = e.AllowUserNamePassword - wm.AllowExternalIDP = e.AllowExternalIDP - wm.ForceMFA = e.ForceMFA - wm.PasswordlessType = e.PasswordlessType + if e.AllowRegister != nil { + wm.AllowRegister = *e.AllowRegister + } + if e.AllowUserNamePassword != nil { + wm.AllowUserNamePassword = *e.AllowUserNamePassword + } + if e.AllowExternalIDP != nil { + wm.AllowExternalIDP = *e.AllowExternalIDP + } + if e.ForceMFA != nil { + wm.ForceMFA = *e.ForceMFA + } + if e.PasswordlessType != nil { + wm.PasswordlessType = *e.PasswordlessType + } case *policy.LoginPolicyRemovedEvent: wm.IsActive = false } diff --git a/internal/v2/command/policy_org_iam_model.go b/internal/v2/command/policy_org_iam_model.go index 497ef2f094..06c19057ec 100644 --- a/internal/v2/command/policy_org_iam_model.go +++ b/internal/v2/command/policy_org_iam_model.go @@ -19,7 +19,9 @@ func (wm *PolicyOrgIAMWriteModel) Reduce() error { wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain wm.IsActive = true case *policy.OrgIAMPolicyChangedEvent: - wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain + if e.UserLoginMustBeDomain != nil { + wm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain + } } } return wm.WriteModel.Reduce() diff --git a/internal/v2/command/policy_password_age_model.go b/internal/v2/command/policy_password_age_model.go index d77b4a70a4..d3c6ba31c1 100644 --- a/internal/v2/command/policy_password_age_model.go +++ b/internal/v2/command/policy_password_age_model.go @@ -21,8 +21,12 @@ func (wm *PasswordAgePolicyWriteModel) Reduce() error { wm.MaxAgeDays = e.MaxAgeDays wm.IsActive = true case *policy.PasswordAgePolicyChangedEvent: - wm.ExpireWarnDays = e.ExpireWarnDays - wm.MaxAgeDays = e.MaxAgeDays + if e.ExpireWarnDays != nil { + wm.ExpireWarnDays = *e.ExpireWarnDays + } + if e.ExpireWarnDays != nil { + wm.ExpireWarnDays = *e.ExpireWarnDays + } case *policy.PasswordAgePolicyRemovedEvent: wm.IsActive = false } diff --git a/internal/v2/command/policy_password_complexity_model.go b/internal/v2/command/policy_password_complexity_model.go index 4ac9dc640c..5fcdb80d48 100644 --- a/internal/v2/command/policy_password_complexity_model.go +++ b/internal/v2/command/policy_password_complexity_model.go @@ -27,11 +27,21 @@ func (wm *PasswordComplexityPolicyWriteModel) Reduce() error { wm.HasSymbol = e.HasSymbol wm.IsActive = true case *policy.PasswordComplexityPolicyChangedEvent: - wm.MinLength = e.MinLength - wm.HasLowercase = e.HasLowercase - wm.HasUpperCase = e.HasUpperCase - wm.HasNumber = e.HasNumber - wm.HasSymbol = e.HasSymbol + if e.MinLength != nil { + wm.MinLength = *e.MinLength + } + if e.HasLowercase != nil { + wm.HasLowercase = *e.HasLowercase + } + if e.HasUpperCase != nil { + wm.HasUpperCase = *e.HasUpperCase + } + if e.HasNumber != nil { + wm.HasNumber = *e.HasNumber + } + if e.HasSymbol != nil { + wm.HasSymbol = *e.HasSymbol + } case *policy.PasswordComplexityPolicyRemovedEvent: wm.IsActive = false } diff --git a/internal/v2/command/policy_password_lockout_model.go b/internal/v2/command/policy_password_lockout_model.go index 9c866f1a63..d653942023 100644 --- a/internal/v2/command/policy_password_lockout_model.go +++ b/internal/v2/command/policy_password_lockout_model.go @@ -21,8 +21,12 @@ func (wm *PasswordLockoutPolicyWriteModel) Reduce() error { wm.ShowLockOutFailures = e.ShowLockOutFailures wm.IsActive = true case *policy.PasswordLockoutPolicyChangedEvent: - wm.MaxAttempts = e.MaxAttempts - wm.ShowLockOutFailures = e.ShowLockOutFailures + if e.MaxAttempts != nil { + wm.MaxAttempts = *e.MaxAttempts + } + if e.ShowLockOutFailures != nil { + wm.ShowLockOutFailures = *e.ShowLockOutFailures + } case *policy.PasswordLockoutPolicyRemovedEvent: wm.IsActive = false } diff --git a/internal/v2/command/user.go b/internal/v2/command/user.go index 5ef65bd812..c6e9ed37b1 100644 --- a/internal/v2/command/user.go +++ b/internal/v2/command/user.go @@ -20,7 +20,11 @@ func (r *CommandSide) AddUser(ctx context.Context, user *domain.User) (*domain.U } return &domain.User{UserName: user.UserName, Human: human}, nil } else if user.Machine != nil { - + machine, err := r.AddMachine(ctx, user.ResourceOwner, user.UserName, user.Machine) + if err != nil { + return nil, err + } + return &domain.User{UserName: user.UserName, Machine: machine}, nil } return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined") } @@ -31,9 +35,11 @@ func (r *CommandSide) RegisterUser(ctx context.Context, user *domain.User) (*dom } if user.Human != nil { - - } else if user.Machine != nil { - + human, err := r.RegisterHuman(ctx, user.ResourceOwner, user.UserName, user.Human, nil) + if err != nil { + return nil, err + } + return &domain.User{UserName: user.UserName, Human: human}, nil } return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined") } @@ -122,6 +128,21 @@ func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*domain.Us return writeModelToUser(existingUser), nil } +func (r *CommandSide) RemoveUser(ctx context.Context, userID string) error { + existingUser, err := r.userWriteModelByID(ctx, userID) + if err != nil { + return err + } + if existingUser.UserState != domain.UserStateDeleted { + return caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M0od", "Errors.User.NotFound") + } + userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel) + userAgg.PushEvents(user.NewUserRemovedEvent(ctx)) + //TODO: release unqie username + + return r.eventstore.PushAggregate(ctx, existingUser, userAgg) +} + func (r *CommandSide) userWriteModelByID(ctx context.Context, userID string) (writeModel *UserWriteModel, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() diff --git a/internal/v2/command/user_converter.go b/internal/v2/command/user_converter.go index 241fc7eea2..0e3038360e 100644 --- a/internal/v2/command/user_converter.go +++ b/internal/v2/command/user_converter.go @@ -1,7 +1,6 @@ package command import ( - "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/v2/domain" ) @@ -38,28 +37,28 @@ func writeModelToHuman(wm *HumanWriteModel) *domain.Human { } } -func writeModelToProfile(wm *HumanProfileWriteModel) *model.Profile { - return &model.Profile{ +func writeModelToProfile(wm *HumanProfileWriteModel) *domain.Profile { + return &domain.Profile{ ObjectRoot: writeModelToObjectRoot(wm.WriteModel), FirstName: wm.FirstName, LastName: wm.LastName, NickName: wm.NickName, DisplayName: wm.DisplayName, PreferredLanguage: wm.PreferredLanguage, - Gender: model.Gender(wm.Gender), + Gender: wm.Gender, } } -func writeModelToEmail(wm *HumanEmailWriteModel) *model.Email { - return &model.Email{ +func writeModelToEmail(wm *HumanEmailWriteModel) *domain.Email { + return &domain.Email{ ObjectRoot: writeModelToObjectRoot(wm.WriteModel), EmailAddress: wm.Email, IsEmailVerified: wm.IsEmailVerified, } } -func writeModelToAddress(wm *HumanAddressWriteModel) *model.Address { - return &model.Address{ +func writeModelToAddress(wm *HumanAddressWriteModel) *domain.Address { + return &domain.Address{ ObjectRoot: writeModelToObjectRoot(wm.WriteModel), Country: wm.Country, Locality: wm.Locality, @@ -68,3 +67,11 @@ func writeModelToAddress(wm *HumanAddressWriteModel) *model.Address { StreetAddress: wm.StreetAddress, } } + +func writeModelToMachine(wm *MachineWriteModel) *domain.Machine { + return &domain.Machine{ + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), + Name: wm.Name, + Description: wm.Description, + } +} diff --git a/internal/v2/command/user_human.go b/internal/v2/command/user_human.go index 5587c32f32..f8c1a75a3e 100644 --- a/internal/v2/command/user_human.go +++ b/internal/v2/command/user_human.go @@ -32,32 +32,50 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true) userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel) - userAgg.PushEvents( - user.NewHumanAddedEvent( - ctx, - username, - human.FirstName, - human.LastName, - human.NickName, - human.DisplayName, - human.PreferredLanguage, - human.Gender, - human.EmailAddress, - human.PhoneNumber, + addEvent := user.NewHumanAddedEvent( + ctx, + username, + human.FirstName, + human.LastName, + human.NickName, + human.DisplayName, + human.PreferredLanguage, + human.Gender, + human.EmailAddress, + ) + if human.Phone != nil { + addEvent.AddPhoneData(human.PhoneNumber) + } + if human.Address != nil { + addEvent.AddAddressData( human.Country, human.Locality, human.PostalCode, human.Region, - human.StreetAddress, - ), - ) - //TODO: HashPassword If existing - //TODO: Generate Init Code if needed - //TODO: Generate Phone Code if needed + human.StreetAddress) + } + if human.Password != nil { + addEvent.AddPasswordData(human.SecretCrypto, human.ChangeRequired) + } + userAgg.PushEvents(addEvent) + + if human.IsInitialState() { + initCode, err := domain.NewInitUserCode(r.initializeUserCode) + if err != nil { + return nil, err + } + user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry) + } if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified { userAgg.PushEvents(user.NewHumanEmailVerifiedEvent(ctx)) } - if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified { + if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified { + phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode) + if err != nil { + return nil, err + } + user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry) + } else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified { userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx)) } @@ -68,3 +86,82 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma return writeModelToHuman(addedHuman), nil } + +func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string, human *domain.Human, externalIDP *domain.ExternalIDP) (*domain.Human, error) { + if !human.IsValid() || externalIDP == nil && (human.Password == nil || human.SecretString == "") { + return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-9dk45", "Errors.User.Invalid") + } + userID, err := r.idGenerator.Next() + if err != nil { + return nil, err + } + human.AggregateID = userID + orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID) + if err != nil { + return nil, err + } + pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID) + if err != nil { + return nil, err + } + + addedHuman := NewHumanWriteModel(human.AggregateID) + //TODO: Check Unique Username or unique external idp + human.CheckOrgIAMPolicy(username, orgIAMPolicy) + human.SetNamesAsDisplayname() + human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true) + + userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel) + addEvent := user.NewHumanRegisteredEvent( + ctx, + username, + human.FirstName, + human.LastName, + human.NickName, + human.DisplayName, + human.PreferredLanguage, + human.Gender, + human.EmailAddress, + ) + if human.Phone != nil { + addEvent.AddPhoneData(human.PhoneNumber) + } + if human.Address != nil { + addEvent.AddAddressData( + human.Country, + human.Locality, + human.PostalCode, + human.Region, + human.StreetAddress) + } + if human.Password != nil { + addEvent.AddPasswordData(human.SecretCrypto, human.ChangeRequired) + } + userAgg.PushEvents(addEvent) + //TODO: Add External IDP Event + if human.IsInitialState() { + initCode, err := domain.NewInitUserCode(r.initializeUserCode) + if err != nil { + return nil, err + } + user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry) + } + + if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified { + userAgg.PushEvents(user.NewHumanEmailVerifiedEvent(ctx)) + } + if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified { + phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode) + if err != nil { + return nil, err + } + user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry) + } + + err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg) + if err != nil { + return nil, err + } + + return writeModelToHuman(addedHuman), nil +} diff --git a/internal/v2/command/user_human_address.go b/internal/v2/command/user_human_address.go index f5d80465ab..0bc42db923 100644 --- a/internal/v2/command/user_human_address.go +++ b/internal/v2/command/user_human_address.go @@ -4,11 +4,10 @@ import ( "context" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/telemetry/tracing" - usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/v2/domain" ) -func (r *CommandSide) ChangeHumanAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) { +func (r *CommandSide) ChangeHumanAddress(ctx context.Context, address *domain.Address) (*domain.Address, error) { existingAddress, err := r.addressWriteModel(ctx, address.AggregateID) if err != nil { return nil, err diff --git a/internal/v2/command/user_human_address_model.go b/internal/v2/command/user_human_address_model.go index c9ce9b58aa..66d3a71585 100644 --- a/internal/v2/command/user_human_address_model.go +++ b/internal/v2/command/user_human_address_model.go @@ -58,11 +58,21 @@ func (wm *HumanAddressWriteModel) Reduce() error { wm.StreetAddress = e.StreetAddress wm.UserState = domain.UserStateActive case *user.HumanAddressChangedEvent: - wm.Country = e.Country - wm.Locality = e.Locality - wm.PostalCode = e.PostalCode - wm.Region = e.Region - wm.StreetAddress = e.StreetAddress + if e.Country != nil { + wm.Country = *e.Country + } + if e.Locality != nil { + wm.Locality = *e.Locality + } + if e.PostalCode != nil { + wm.PostalCode = *e.PostalCode + } + if e.Region != nil { + wm.Region = *e.Region + } + if e.StreetAddress != nil { + wm.StreetAddress = *e.StreetAddress + } case *user.UserRemovedEvent: wm.UserState = domain.UserStateDeleted } @@ -87,23 +97,23 @@ func (wm *HumanAddressWriteModel) NewChangedEvent( changedEvent := user.NewHumanAddressChangedEvent(ctx) if wm.Country != country { hasChanged = true - changedEvent.Country = country + changedEvent.Country = &country } if wm.Locality != locality { hasChanged = true - changedEvent.Locality = locality + changedEvent.Locality = &locality } if wm.PostalCode != postalCode { hasChanged = true - changedEvent.PostalCode = postalCode + changedEvent.PostalCode = &postalCode } if wm.Region != region { hasChanged = true - changedEvent.Region = region + changedEvent.Region = ®ion } if wm.StreetAddress != streetAddress { hasChanged = true - changedEvent.StreetAddress = streetAddress + changedEvent.StreetAddress = &streetAddress } return changedEvent, hasChanged } diff --git a/internal/v2/command/user_human_email.go b/internal/v2/command/user_human_email.go index e1843bc64f..dea43a5a15 100644 --- a/internal/v2/command/user_human_email.go +++ b/internal/v2/command/user_human_email.go @@ -4,11 +4,10 @@ import ( "context" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/telemetry/tracing" - usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/v2/domain" ) -func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) { +func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*domain.Email, error) { if !email.IsValid() { return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M9sf", "Errors.Email.Invalid") } diff --git a/internal/v2/command/user_human_model.go b/internal/v2/command/user_human_model.go index 7fb5fb10db..a921eefe81 100644 --- a/internal/v2/command/user_human_model.go +++ b/internal/v2/command/user_human_model.go @@ -1,6 +1,7 @@ package command import ( + "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/user" @@ -31,6 +32,9 @@ type HumanWriteModel struct { Region string StreetAddress string + Secret *crypto.CryptoValue + SecretChangeRequired bool + UserState domain.UserState } @@ -45,21 +49,20 @@ func NewHumanWriteModel(userID string) *HumanWriteModel { func (wm *HumanWriteModel) AppendEvents(events ...eventstore.EventReader) { for _, event := range events { switch e := event.(type) { - case *user.HumanEmailChangedEvent: - wm.AppendEvents(e) - case *user.HumanEmailVerifiedEvent: - wm.AppendEvents(e) - case *user.HumanAddedEvent, *user.HumanRegisteredEvent: - wm.AppendEvents(e) - case *user.UserDeactivatedEvent: - wm.AppendEvents(e) - case *user.UserReactivatedEvent: - wm.AppendEvents(e) - case *user.UserLockedEvent: - wm.AppendEvents(e) - case *user.UserUnlockedEvent: - wm.AppendEvents(e) - case *user.UserRemovedEvent: + case *user.HumanAddedEvent, + *user.HumanRegisteredEvent, + *user.HumanProfileChangedEvent, + *user.HumanEmailChangedEvent, + *user.HumanEmailVerifiedEvent, + *user.HumanPhoneChangedEvent, + *user.HumanPhoneVerifiedEvent, + *user.HumanAddressChangedEvent, + *user.HumanPasswordChangedEvent, + *user.UserDeactivatedEvent, + *user.UserReactivatedEvent, + *user.UserLockedEvent, + *user.UserUnlockedEvent, + *user.UserRemovedEvent: wm.AppendEvents(e) } } @@ -70,11 +73,21 @@ func (wm *HumanWriteModel) Reduce() error { for _, event := range wm.Events { switch e := event.(type) { case *user.HumanAddedEvent: - wm.UserName = e.UserName - wm.UserState = domain.UserStateInitial + wm.reduceHumanAddedEvent(e) case *user.HumanRegisteredEvent: - wm.UserName = e.UserName - wm.UserState = domain.UserStateInitial + wm.reduceHumanRegisteredEvent(e) + case *user.HumanProfileChangedEvent: + wm.reduceHumanProfileChangedEvent(e) + case *user.HumanEmailChangedEvent: + wm.reduceHumanEmailChangedEvent(e) + case *user.HumanEmailVerifiedEvent: + wm.reduceHumanEmailVerifiedEvent() + case *user.HumanPhoneChangedEvent: + wm.reduceHumanPhoneChangedEvent(e) + case *user.HumanPhoneVerifiedEvent: + wm.reduceHumanPhoneVerifiedEvent() + case *user.HumanPasswordChangedEvent: + wm.reduceHumanPasswordChangedEvent(e) case *user.UserLockedEvent: if wm.UserState != domain.UserStateDeleted { wm.UserState = domain.UserStateLocked @@ -102,3 +115,105 @@ func (wm *HumanWriteModel) Query() *eventstore.SearchQueryBuilder { return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType). AggregateIDs(wm.AggregateID) } + +func (wm *HumanWriteModel) reduceHumanAddedEvent(e *user.HumanAddedEvent) { + wm.UserName = e.UserName + wm.FirstName = e.FirstName + wm.LastName = e.LastName + wm.NickName = e.NickName + wm.DisplayName = e.DisplayName + wm.PreferredLanguage = e.PreferredLanguage + wm.Gender = e.Gender + wm.Email = e.EmailAddress + wm.Phone = e.PhoneNumber + wm.Country = e.Country + wm.Locality = e.Locality + wm.PostalCode = e.PostalCode + wm.Region = e.Region + wm.StreetAddress = e.StreetAddress + wm.Secret = e.Secret + wm.SecretChangeRequired = e.ChangeRequired + wm.UserState = domain.UserStateInitial +} + +func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEvent) { + wm.UserName = e.UserName + wm.FirstName = e.FirstName + wm.LastName = e.LastName + wm.NickName = e.NickName + wm.DisplayName = e.DisplayName + wm.PreferredLanguage = e.PreferredLanguage + wm.Gender = e.Gender + wm.Email = e.EmailAddress + wm.Phone = e.PhoneNumber + wm.Country = e.Country + wm.Locality = e.Locality + wm.PostalCode = e.PostalCode + wm.Region = e.Region + wm.StreetAddress = e.StreetAddress + wm.Secret = e.Secret + wm.SecretChangeRequired = e.ChangeRequired + wm.UserState = domain.UserStateInitial +} + +func (wm *HumanWriteModel) reduceHumanProfileChangedEvent(e *user.HumanProfileChangedEvent) { + if e.FirstName != "" { + wm.FirstName = e.FirstName + } + if e.LastName != "" { + wm.LastName = e.LastName + } + if e.NickName != nil { + wm.NickName = *e.NickName + } + if e.DisplayName != nil { + wm.DisplayName = *e.DisplayName + } + if e.PreferredLanguage != nil { + wm.PreferredLanguage = *e.PreferredLanguage + } + if e.Gender != nil { + wm.Gender = *e.Gender + } +} + +func (wm *HumanWriteModel) reduceHumanEmailChangedEvent(e *user.HumanEmailChangedEvent) { + wm.Email = e.EmailAddress + wm.IsEmailVerified = false +} + +func (wm *HumanWriteModel) reduceHumanEmailVerifiedEvent() { + wm.IsEmailVerified = true +} + +func (wm *HumanWriteModel) reduceHumanPhoneChangedEvent(e *user.HumanPhoneChangedEvent) { + wm.Phone = e.PhoneNumber + wm.IsPhoneVerified = false +} + +func (wm *HumanWriteModel) reduceHumanPhoneVerifiedEvent() { + wm.IsPhoneVerified = true +} + +func (wm *HumanWriteModel) reduceHumanAddressChangedEvent(e *user.HumanAddressChangedEvent) { + if e.Country != nil { + wm.Country = *e.Country + } + if e.Locality != nil { + wm.Locality = *e.Locality + } + if e.PostalCode != nil { + wm.PostalCode = *e.PostalCode + } + if e.Region != nil { + wm.Region = *e.Region + } + if e.StreetAddress != nil { + wm.StreetAddress = *e.StreetAddress + } +} + +func (wm *HumanWriteModel) reduceHumanPasswordChangedEvent(e *user.HumanPasswordChangedEvent) { + wm.Secret = e.Secret + wm.SecretChangeRequired = e.ChangeRequired +} diff --git a/internal/v2/command/user_human_profile.go b/internal/v2/command/user_human_profile.go index f8394a3c24..16b261b855 100644 --- a/internal/v2/command/user_human_profile.go +++ b/internal/v2/command/user_human_profile.go @@ -4,11 +4,10 @@ import ( "context" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/telemetry/tracing" - usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/v2/domain" ) -func (r *CommandSide) ChangeHumanProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) { +func (r *CommandSide) ChangeHumanProfile(ctx context.Context, profile *domain.Profile) (*domain.Profile, error) { if !profile.IsValid() { return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-8io0d", "Errors.User.Profile.Invalid") } diff --git a/internal/v2/command/user_human_profile_model.go b/internal/v2/command/user_human_profile_model.go index 0cfaa9fa0b..db50e43407 100644 --- a/internal/v2/command/user_human_profile_model.go +++ b/internal/v2/command/user_human_profile_model.go @@ -62,12 +62,24 @@ func (wm *HumanProfileWriteModel) Reduce() error { wm.Gender = e.Gender wm.UserState = domain.UserStateActive case *user.HumanProfileChangedEvent: - wm.FirstName = e.FirstName - wm.LastName = e.LastName - wm.NickName = e.NickName - wm.DisplayName = e.DisplayName - wm.PreferredLanguage = e.PreferredLanguage - wm.Gender = e.Gender + if e.FirstName != "" { + wm.FirstName = e.FirstName + } + if e.LastName != "" { + wm.LastName = e.LastName + } + if e.NickName != nil { + wm.NickName = *e.NickName + } + if e.DisplayName != nil { + wm.DisplayName = *e.DisplayName + } + if e.PreferredLanguage != nil { + wm.PreferredLanguage = *e.PreferredLanguage + } + if e.Gender != nil { + wm.Gender = *e.Gender + } case *user.UserRemovedEvent: wm.UserState = domain.UserStateDeleted } @@ -101,19 +113,19 @@ func (wm *HumanProfileWriteModel) NewChangedEvent( } if wm.NickName != nickName { hasChanged = true - changedEvent.NickName = nickName + changedEvent.NickName = &nickName } if wm.DisplayName != displayName { hasChanged = true - changedEvent.DisplayName = displayName + changedEvent.DisplayName = &displayName } if wm.PreferredLanguage != preferredLanguage { hasChanged = true - changedEvent.PreferredLanguage = preferredLanguage + changedEvent.PreferredLanguage = &preferredLanguage } if gender.Valid() && wm.Gender != gender { hasChanged = true - changedEvent.Gender = gender + changedEvent.Gender = &gender } return changedEvent, hasChanged diff --git a/internal/v2/command/user_machine.go b/internal/v2/command/user_machine.go new file mode 100644 index 0000000000..ba10508e11 --- /dev/null +++ b/internal/v2/command/user_machine.go @@ -0,0 +1,78 @@ +package command + +import ( + "context" + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/telemetry/tracing" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/user" +) + +func (r *CommandSide) AddMachine(ctx context.Context, orgID, username string, machine *domain.Machine) (*domain.Machine, error) { + if !machine.IsValid() { + return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-5M0ds", "Errors.User.Invalid") + } + userID, err := r.idGenerator.Next() + if err != nil { + return nil, err + } + //TODO: Check Unique username + machine.AggregateID = userID + orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID) + if err != nil { + return nil, err + } + if !orgIAMPolicy.UserLoginMustBeDomain { + return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-6M0ds", "Errors.User.Invalid") + } + + addedMachine := NewMachineWriteModel(machine.AggregateID) + userAgg := UserAggregateFromWriteModel(&addedMachine.WriteModel) + userAgg.PushEvents( + user.NewMachineAddedEvent( + ctx, + username, + machine.Name, + machine.Description, + ), + ) + return writeModelToMachine(addedMachine), nil +} + +func (r *CommandSide) ChangeMachine(ctx context.Context, machine *domain.Machine) (*domain.Machine, error) { + existingUser, err := r.machineWriteModelByID(ctx, machine.AggregateID) + if err != nil { + return nil, err + } + if existingUser.UserState == domain.UserStateDeleted || existingUser.UserState == domain.UserStateUnspecified { + return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M0od", "Errors.User.NotFound") + } + + changedEvent, hasChanged := existingUser.NewChangedEvent(ctx, machine.Name, machine.Description) + if !hasChanged { + return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-2M9fs", "Errors.User.Email.NotChanged") + } + userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel) + userAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingUser, userAgg) + if err != nil { + return nil, err + } + return writeModelToMachine(existingUser), nil +} + +func (r *CommandSide) machineWriteModelByID(ctx context.Context, userID string) (writeModel *MachineWriteModel, err error) { + if userID == "" { + return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-5M0ds", "Errors.User.UserIDMissing") + } + ctx, span := tracing.NewSpan(ctx) + defer func() { span.EndWithError(err) }() + + writeModel = NewMachineWriteModel(userID) + err = r.eventstore.FilterToQueryReducer(ctx, writeModel) + if err != nil { + return nil, err + } + return writeModel, nil +} diff --git a/internal/v2/command/user_machine_write_model.go b/internal/v2/command/user_machine_write_model.go new file mode 100644 index 0000000000..ea6783d741 --- /dev/null +++ b/internal/v2/command/user_machine_write_model.go @@ -0,0 +1,109 @@ +package command + +import ( + "context" + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/user" +) + +type MachineWriteModel struct { + eventstore.WriteModel + + UserName string + + Name string + Description string + UserState domain.UserState +} + +func NewMachineWriteModel(userID string) *MachineWriteModel { + return &MachineWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: userID, + }, + } +} + +func (wm *MachineWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *user.MachineAddedEvent: + wm.AppendEvents(e) + case *user.MachineChangedEvent: + wm.AppendEvents(e) + case *user.UserDeactivatedEvent: + wm.AppendEvents(e) + case *user.UserReactivatedEvent: + wm.AppendEvents(e) + case *user.UserLockedEvent: + wm.AppendEvents(e) + case *user.UserUnlockedEvent: + wm.AppendEvents(e) + case *user.UserRemovedEvent: + wm.AppendEvents(e) + } + } +} + +//TODO: Compute State? initial/active +func (wm *MachineWriteModel) Reduce() error { + for _, event := range wm.Events { + switch e := event.(type) { + case *user.MachineAddedEvent: + wm.UserName = e.UserName + wm.Name = e.Name + wm.Description = e.Description + wm.UserState = domain.UserStateActive + case *user.MachineChangedEvent: + if e.Name != nil { + wm.Name = *e.Name + } + if e.Description != nil { + wm.Description = *e.Description + } + case *user.UserLockedEvent: + if wm.UserState != domain.UserStateDeleted { + wm.UserState = domain.UserStateLocked + } + case *user.UserUnlockedEvent: + if wm.UserState != domain.UserStateDeleted { + wm.UserState = domain.UserStateActive + } + case *user.UserDeactivatedEvent: + if wm.UserState != domain.UserStateDeleted { + wm.UserState = domain.UserStateInactive + } + case *user.UserReactivatedEvent: + if wm.UserState != domain.UserStateDeleted { + wm.UserState = domain.UserStateActive + } + case *user.UserRemovedEvent: + wm.UserState = domain.UserStateDeleted + } + } + return wm.WriteModel.Reduce() +} + +func (wm *MachineWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType). + AggregateIDs(wm.AggregateID) +} + +func (wm *MachineWriteModel) NewChangedEvent( + ctx context.Context, + name, + description string, +) (*user.MachineChangedEvent, bool) { + hasChanged := false + changedEvent := user.NewMachineChangedEvent(ctx) + if wm.Name != name { + hasChanged = true + changedEvent.Name = &name + } + if wm.Description != description { + hasChanged = true + changedEvent.Description = &description + } + return changedEvent, hasChanged +} diff --git a/internal/v2/domain/human.go b/internal/v2/domain/human.go index 7f4a1ff340..61b91a61d1 100644 --- a/internal/v2/domain/human.go +++ b/internal/v2/domain/human.go @@ -17,10 +17,6 @@ type Human struct { *Phone *Address ExternalIDPs []*ExternalIDP - InitCode *InitUserCode - EmailCode *EmailCode - PhoneCode *PhoneCode - PasswordCode *PasswordCode OTP *OTP U2FTokens []*WebAuthNToken PasswordlessTokens []*WebAuthNToken @@ -79,3 +75,18 @@ func (u *Human) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwor } return nil } + +func (u *Human) IsInitialState() bool { + return u.Email == nil || !u.IsEmailVerified || (u.ExternalIDPs == nil || len(u.ExternalIDPs) == 0) && (u.Password == nil || u.SecretString == "") +} + +func NewInitUserCode(generator crypto.Generator) (*InitUserCode, error) { + initCodeCrypto, _, err := crypto.NewCode(generator) + if err != nil { + return nil, err + } + return &InitUserCode{ + Code: initCodeCrypto, + Expiry: generator.Expiry(), + }, nil +} diff --git a/internal/v2/domain/human_phone.go b/internal/v2/domain/human_phone.go index 448c8b703f..3ba7b027a0 100644 --- a/internal/v2/domain/human_phone.go +++ b/internal/v2/domain/human_phone.go @@ -39,3 +39,14 @@ func (p *Phone) formatPhone() error { p.PhoneNumber = libphonenumber.Format(phoneNr, libphonenumber.E164) return nil } + +func NewPhoneCode(phoneGenerator crypto.Generator) (*PhoneCode, error) { + phoneCodeCrypto, _, err := crypto.NewCode(phoneGenerator) + if err != nil { + return nil, err + } + return &PhoneCode{ + Code: phoneCodeCrypto, + Expiry: phoneGenerator.Expiry(), + }, nil +} diff --git a/internal/v2/domain/human_profile.go b/internal/v2/domain/human_profile.go index c90a8a6902..71442c3ab1 100644 --- a/internal/v2/domain/human_profile.go +++ b/internal/v2/domain/human_profile.go @@ -17,3 +17,7 @@ type Profile struct { PreferredLoginName string LoginNames []string } + +func (p *Profile) IsValid() bool { + return p.FirstName != "" && p.LastName != "" +} diff --git a/internal/v2/query/policy_label_model.go b/internal/v2/query/policy_label_model.go index 8dd2579fe9..9ff9fcae0a 100644 --- a/internal/v2/query/policy_label_model.go +++ b/internal/v2/query/policy_label_model.go @@ -21,8 +21,12 @@ func (rm *LabelPolicyReadModel) Reduce() error { rm.SecondaryColor = e.SecondaryColor rm.IsActive = true case *policy.LabelPolicyChangedEvent: - rm.PrimaryColor = e.PrimaryColor - rm.SecondaryColor = e.SecondaryColor + if e.PrimaryColor != nil { + rm.PrimaryColor = *e.PrimaryColor + } + if e.SecondaryColor != nil { + rm.SecondaryColor = *e.SecondaryColor + } case *policy.LabelPolicyRemovedEvent: rm.IsActive = false } diff --git a/internal/v2/query/policy_login_model.go b/internal/v2/query/policy_login_model.go index 89953c1a31..a5d321e2ce 100644 --- a/internal/v2/query/policy_login_model.go +++ b/internal/v2/query/policy_login_model.go @@ -28,11 +28,21 @@ func (rm *LoginPolicyReadModel) Reduce() error { rm.PasswordlessType = e.PasswordlessType rm.IsActive = true case *policy.LoginPolicyChangedEvent: - rm.AllowUserNamePassword = e.AllowUserNamePassword - rm.AllowExternalIDP = e.AllowExternalIDP - rm.AllowRegister = e.AllowRegister - rm.ForceMFA = e.ForceMFA - rm.PasswordlessType = e.PasswordlessType + if e.AllowUserNamePassword != nil { + rm.AllowUserNamePassword = *e.AllowUserNamePassword + } + if e.AllowExternalIDP != nil { + rm.AllowExternalIDP = *e.AllowExternalIDP + } + if e.AllowRegister != nil { + rm.AllowRegister = *e.AllowRegister + } + if e.ForceMFA != nil { + rm.ForceMFA = *e.ForceMFA + } + if e.PasswordlessType != nil { + rm.PasswordlessType = *e.PasswordlessType + } case *policy.LoginPolicyRemovedEvent: rm.IsActive = false } diff --git a/internal/v2/query/policy_org_iam_model.go b/internal/v2/query/policy_org_iam_model.go index c588dc809b..10f3432a89 100644 --- a/internal/v2/query/policy_org_iam_model.go +++ b/internal/v2/query/policy_org_iam_model.go @@ -17,7 +17,9 @@ func (rm *OrgIAMPolicyReadModel) Reduce() error { case *policy.OrgIAMPolicyAddedEvent: rm.UserLoginMustBeDomain = e.UserLoginMustBeDomain case *policy.OrgIAMPolicyChangedEvent: - rm.UserLoginMustBeDomain = e.UserLoginMustBeDomain + if e.UserLoginMustBeDomain != nil { + rm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain + } } } return rm.ReadModel.Reduce() diff --git a/internal/v2/query/policy_password_age_model.go b/internal/v2/query/policy_password_age_model.go index f9820a5299..57a928784f 100644 --- a/internal/v2/query/policy_password_age_model.go +++ b/internal/v2/query/policy_password_age_model.go @@ -19,8 +19,12 @@ func (rm *PasswordAgePolicyReadModel) Reduce() error { rm.ExpireWarnDays = e.ExpireWarnDays rm.MaxAgeDays = e.MaxAgeDays case *policy.PasswordAgePolicyChangedEvent: - rm.ExpireWarnDays = e.ExpireWarnDays - rm.MaxAgeDays = e.MaxAgeDays + if e.ExpireWarnDays != nil { + rm.ExpireWarnDays = *e.ExpireWarnDays + } + if e.MaxAgeDays != nil { + rm.MaxAgeDays = *e.MaxAgeDays + } } } return rm.ReadModel.Reduce() diff --git a/internal/v2/query/policy_password_complexity_model.go b/internal/v2/query/policy_password_complexity_model.go index 748d450ab8..19e722e0ec 100644 --- a/internal/v2/query/policy_password_complexity_model.go +++ b/internal/v2/query/policy_password_complexity_model.go @@ -25,11 +25,21 @@ func (rm *PasswordComplexityPolicyReadModel) Reduce() error { rm.HasNumber = e.HasNumber rm.HasSymbol = e.HasSymbol case *policy.PasswordComplexityPolicyChangedEvent: - rm.MinLength = e.MinLength - rm.HasLowercase = e.HasLowercase - rm.HasUpperCase = e.HasUpperCase - rm.HasNumber = e.HasNumber - rm.HasSymbol = e.HasSymbol + if e.MinLength != nil { + rm.MinLength = *e.MinLength + } + if e.HasLowercase != nil { + rm.HasLowercase = *e.HasLowercase + } + if e.HasUpperCase != nil { + rm.HasUpperCase = *e.HasUpperCase + } + if e.HasNumber != nil { + rm.HasNumber = *e.HasNumber + } + if e.HasSymbol != nil { + rm.HasSymbol = *e.HasSymbol + } } } return rm.ReadModel.Reduce() diff --git a/internal/v2/query/policy_password_lockout_model.go b/internal/v2/query/policy_password_lockout_model.go index 30a0dc899f..e7eb175251 100644 --- a/internal/v2/query/policy_password_lockout_model.go +++ b/internal/v2/query/policy_password_lockout_model.go @@ -19,8 +19,12 @@ func (rm *PasswordLockoutPolicyReadModel) Reduce() error { rm.MaxAttempts = e.MaxAttempts rm.ShowLockOutFailures = e.ShowLockOutFailures case *policy.PasswordLockoutPolicyChangedEvent: - rm.MaxAttempts = e.MaxAttempts - rm.ShowLockOutFailures = e.ShowLockOutFailures + if e.MaxAttempts != nil { + rm.MaxAttempts = *e.MaxAttempts + } + if e.ShowLockOutFailures != nil { + rm.ShowLockOutFailures = *e.ShowLockOutFailures + } } } return rm.ReadModel.Reduce() diff --git a/internal/v2/repository/policy/label.go b/internal/v2/repository/policy/label.go index aab6ef71a3..77a625952b 100644 --- a/internal/v2/repository/policy/label.go +++ b/internal/v2/repository/policy/label.go @@ -53,8 +53,8 @@ func LabelPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReade type LabelPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - PrimaryColor string `json:"primaryColor,omitempty"` - SecondaryColor string `json:"secondaryColor,omitempty"` + PrimaryColor *string `json:"primaryColor,omitempty"` + SecondaryColor *string `json:"secondaryColor,omitempty"` } func (e *LabelPolicyChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/policy/login.go b/internal/v2/repository/policy/login.go index c6321de0bc..c7fdc4ff66 100644 --- a/internal/v2/repository/policy/login.go +++ b/internal/v2/repository/policy/login.go @@ -63,11 +63,11 @@ func LoginPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReade type LoginPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - AllowUserNamePassword bool `json:"allowUsernamePassword,omitempty"` - AllowRegister bool `json:"allowRegister,omitempty"` - AllowExternalIDP bool `json:"allowExternalIdp,omitempty"` - ForceMFA bool `json:"forceMFA,omitempty"` - PasswordlessType domain.PasswordlessType `json:"passwordlessType,omitempty"` + AllowUserNamePassword *bool `json:"allowUsernamePassword,omitempty"` + AllowRegister *bool `json:"allowRegister,omitempty"` + AllowExternalIDP *bool `json:"allowExternalIdp,omitempty"` + ForceMFA *bool `json:"forceMFA,omitempty"` + PasswordlessType *domain.PasswordlessType `json:"passwordlessType,omitempty"` } type LoginPolicyEventData struct { diff --git a/internal/v2/repository/policy/policy_org_iam.go b/internal/v2/repository/policy/policy_org_iam.go index 2e5a3e5d22..3e425ffb33 100644 --- a/internal/v2/repository/policy/policy_org_iam.go +++ b/internal/v2/repository/policy/policy_org_iam.go @@ -49,7 +49,7 @@ func OrgIAMPolicyAddedEventMapper(event *repository.Event) (eventstore.EventRead type OrgIAMPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - UserLoginMustBeDomain bool `json:"userLoginMustBeDomain,omitempty"` + UserLoginMustBeDomain *bool `json:"userLoginMustBeDomain,omitempty"` } func (e *OrgIAMPolicyChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/policy/policy_password_age.go b/internal/v2/repository/policy/policy_password_age.go index ef8353dd55..adf1df496d 100644 --- a/internal/v2/repository/policy/policy_password_age.go +++ b/internal/v2/repository/policy/policy_password_age.go @@ -53,8 +53,8 @@ func PasswordAgePolicyAddedEventMapper(event *repository.Event) (eventstore.Even type PasswordAgePolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - ExpireWarnDays uint64 `json:"expireWarnDays,omitempty"` - MaxAgeDays uint64 `json:"maxAgeDays,omitempty"` + ExpireWarnDays *uint64 `json:"expireWarnDays,omitempty"` + MaxAgeDays *uint64 `json:"maxAgeDays,omitempty"` } func (e *PasswordAgePolicyChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/policy/policy_password_complexity.go b/internal/v2/repository/policy/policy_password_complexity.go index 4d5a50d112..0abf8a3d99 100644 --- a/internal/v2/repository/policy/policy_password_complexity.go +++ b/internal/v2/repository/policy/policy_password_complexity.go @@ -61,11 +61,11 @@ func PasswordComplexityPolicyAddedEventMapper(event *repository.Event) (eventsto type PasswordComplexityPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - MinLength uint64 `json:"minLength,omitempty"` - HasLowercase bool `json:"hasLowercase,omitempty"` - HasUpperCase bool `json:"hasUppercase,omitempty"` - HasNumber bool `json:"hasNumber,omitempty"` - HasSymbol bool `json:"hasSymbol,omitempty"` + MinLength *uint64 `json:"minLength,omitempty"` + HasLowercase *bool `json:"hasLowercase,omitempty"` + HasUpperCase *bool `json:"hasUppercase,omitempty"` + HasNumber *bool `json:"hasNumber,omitempty"` + HasSymbol *bool `json:"hasSymbol,omitempty"` } func (e *PasswordComplexityPolicyChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/policy/policy_password_lockout.go b/internal/v2/repository/policy/policy_password_lockout.go index 024c6adff4..086dac4456 100644 --- a/internal/v2/repository/policy/policy_password_lockout.go +++ b/internal/v2/repository/policy/policy_password_lockout.go @@ -53,8 +53,8 @@ func PasswordLockoutPolicyAddedEventMapper(event *repository.Event) (eventstore. type PasswordLockoutPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - MaxAttempts uint64 `json:"maxAttempts,omitempty"` - ShowLockOutFailures bool `json:"showLockOutFailures,omitempty"` + MaxAttempts *uint64 `json:"maxAttempts,omitempty"` + ShowLockOutFailures *bool `json:"showLockOutFailures,omitempty"` } func (e *PasswordLockoutPolicyChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/user/human.go b/internal/v2/repository/user/human.go index 6d1e030ef4..11414148cd 100644 --- a/internal/v2/repository/user/human.go +++ b/internal/v2/repository/user/human.go @@ -53,6 +53,34 @@ func (e *HumanAddedEvent) Data() interface{} { return e } +func (e *HumanAddedEvent) AddAddressData( + country, + locality, + postalCode, + region, + streetAddress string, +) { + e.Country = country + e.Locality = locality + e.PostalCode = postalCode + e.Region = region + e.StreetAddress = streetAddress +} + +func (e *HumanAddedEvent) AddPhoneData( + phoneNumber string, +) { + e.PhoneNumber = phoneNumber +} + +func (e *HumanAddedEvent) AddPasswordData( + secret *crypto.CryptoValue, + changeRequired bool, +) { + e.Secret = secret + e.ChangeRequired = changeRequired +} + func NewHumanAddedEvent( ctx context.Context, userName, @@ -62,13 +90,7 @@ func NewHumanAddedEvent( displayName string, preferredLanguage language.Tag, gender domain.Gender, - emailAddress, - phoneNumber, - country, - locality, - postalCode, - region, - streetAddress string, + emailAddress string, ) *HumanAddedEvent { return &HumanAddedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( @@ -83,12 +105,6 @@ func NewHumanAddedEvent( PreferredLanguage: preferredLanguage, Gender: gender, EmailAddress: emailAddress, - PhoneNumber: phoneNumber, - Country: country, - Locality: locality, - PostalCode: postalCode, - Region: region, - StreetAddress: streetAddress, } } @@ -125,12 +141,43 @@ type HumanRegisteredEvent struct { PostalCode string `json:"postalCode,omitempty"` Region string `json:"region,omitempty"` StreetAddress string `json:"streetAddress,omitempty"` + + Secret *crypto.CryptoValue `json:"secret,omitempty"` + ChangeRequired bool `json:"changeRequired,omitempty"` } func (e *HumanRegisteredEvent) Data() interface{} { return e } +func (e *HumanRegisteredEvent) AddAddressData( + country, + locality, + postalCode, + region, + streetAddress string, +) { + e.Country = country + e.Locality = locality + e.PostalCode = postalCode + e.Region = region + e.StreetAddress = streetAddress +} + +func (e *HumanRegisteredEvent) AddPhoneData( + phoneNumber string, +) { + e.PhoneNumber = phoneNumber +} + +func (e *HumanRegisteredEvent) AddPasswordData( + secret *crypto.CryptoValue, + changeRequired bool, +) { + e.Secret = secret + e.ChangeRequired = changeRequired +} + func NewHumanRegisteredEvent( ctx context.Context, userName, @@ -140,13 +187,7 @@ func NewHumanRegisteredEvent( displayName string, preferredLanguage language.Tag, gender domain.Gender, - emailAddress, - phoneNumber, - country, - locality, - postalCode, - region, - streetAddress string, + emailAddress string, ) *HumanRegisteredEvent { return &HumanRegisteredEvent{ BaseEvent: *eventstore.NewBaseEventForPush( @@ -161,12 +202,6 @@ func NewHumanRegisteredEvent( PreferredLanguage: preferredLanguage, Gender: gender, EmailAddress: emailAddress, - PhoneNumber: phoneNumber, - Country: country, - Locality: locality, - PostalCode: postalCode, - Region: region, - StreetAddress: streetAddress, } } diff --git a/internal/v2/repository/user/human_address.go b/internal/v2/repository/user/human_address.go index 68163af252..a0d6bfad2e 100644 --- a/internal/v2/repository/user/human_address.go +++ b/internal/v2/repository/user/human_address.go @@ -16,11 +16,11 @@ const ( type HumanAddressChangedEvent struct { eventstore.BaseEvent `json:"-"` - Country string `json:"country,omitempty"` - Locality string `json:"locality,omitempty"` - PostalCode string `json:"postalCode,omitempty"` - Region string `json:"region,omitempty"` - StreetAddress string `json:"streetAddress,omitempty"` + Country *string `json:"country,omitempty"` + Locality *string `json:"locality,omitempty"` + PostalCode *string `json:"postalCode,omitempty"` + Region *string `json:"region,omitempty"` + StreetAddress *string `json:"streetAddress,omitempty"` } func (e *HumanAddressChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/user/human_password.go b/internal/v2/repository/user/human_password.go index e6ddf50abd..e10b025526 100644 --- a/internal/v2/repository/user/human_password.go +++ b/internal/v2/repository/user/human_password.go @@ -20,14 +20,14 @@ const ( HumanPasswordCheckFailedType = passwordEventPrefix + "check.failed" ) -type HumanPasswordChangedChangedEvent struct { +type HumanPasswordChangedEvent struct { eventstore.BaseEvent `json:"-"` Secret *crypto.CryptoValue `json:"secret,omitempty"` - ChangeRequired bool `json:"changeRequired,omitempty"` + ChangeRequired bool `json:"changeRequired"` } -func (e *HumanPasswordChangedChangedEvent) Data() interface{} { +func (e *HumanPasswordChangedEvent) Data() interface{} { return e } @@ -35,8 +35,8 @@ func NewHumanPasswordChangedEvent( ctx context.Context, secret *crypto.CryptoValue, changeRequired bool, -) *HumanPasswordChangedChangedEvent { - return &HumanPasswordChangedChangedEvent{ +) *HumanPasswordChangedEvent { + return &HumanPasswordChangedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, HumanPasswordChangedType, @@ -47,7 +47,7 @@ func NewHumanPasswordChangedEvent( } func HumanPasswordChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { - humanAdded := &HumanPasswordChangedChangedEvent{ + humanAdded := &HumanPasswordChangedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), } err := json.Unmarshal(event.Data, humanAdded) diff --git a/internal/v2/repository/user/human_profile.go b/internal/v2/repository/user/human_profile.go index 2d797e31de..4944b10855 100644 --- a/internal/v2/repository/user/human_profile.go +++ b/internal/v2/repository/user/human_profile.go @@ -18,19 +18,20 @@ const ( type HumanProfileChangedEvent struct { eventstore.BaseEvent `json:"-"` - FirstName string `json:"firstName,omitempty"` - LastName string `json:"lastName,omitempty"` - NickName string `json:"nickName,omitempty"` - DisplayName string `json:"displayName,omitempty"` - PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"` - Gender domain.Gender `json:"gender,omitempty"` + FirstName string `json:"firstName,omitempty"` + LastName string `json:"lastName,omitempty"` + NickName *string `json:"nickName,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + PreferredLanguage *language.Tag `json:"preferredLanguage,omitempty"` + Gender *domain.Gender `json:"gender,omitempty"` } func (e *HumanProfileChangedEvent) Data() interface{} { return e } -func NewHumanProfileChangedEvent(ctx context.Context) *HumanProfileChangedEvent { +func NewHumanProfileChangedEvent( + ctx context.Context) *HumanProfileChangedEvent { return &HumanProfileChangedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, diff --git a/internal/v2/repository/user/machine.go b/internal/v2/repository/user/machine.go index bb61409e56..01a9382803 100644 --- a/internal/v2/repository/user/machine.go +++ b/internal/v2/repository/user/machine.go @@ -61,8 +61,8 @@ type MachineChangedEvent struct { UserName string `json:"userName"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` } func (e *MachineChangedEvent) Data() interface{} { diff --git a/internal/v2/repository/user/v1.go b/internal/v2/repository/user/v1.go index 1605251659..17b624cfc8 100644 --- a/internal/v2/repository/user/v1.go +++ b/internal/v2/repository/user/v1.go @@ -190,8 +190,8 @@ func NewUserV1PasswordChangedEvent( ctx context.Context, secret *crypto.CryptoValue, changeRequired bool, -) *HumanPasswordChangedChangedEvent { - return &HumanPasswordChangedChangedEvent{ +) *HumanPasswordChangedEvent { + return &HumanPasswordChangedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, UserV1PasswordChangedType, @@ -360,24 +360,12 @@ func NewUserV1PhoneCodeSentEvent(ctx context.Context) *HumanPhoneCodeSentEvent { func NewUserV1ProfileChangedEvent( ctx context.Context, - firstName, - lastName, - nickName, - displayName string, - preferredLanguage language.Tag, - gender domain.Gender, ) *HumanProfileChangedEvent { return &HumanProfileChangedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, UserV1ProfileChangedType, ), - FirstName: firstName, - LastName: lastName, - NickName: nickName, - DisplayName: displayName, - PreferredLanguage: preferredLanguage, - Gender: gender, } } @@ -394,11 +382,6 @@ func NewUserV1AddressChangedEvent( ctx, UserV1AddressChangedType, ), - Country: country, - Locality: locality, - PostalCode: postalCode, - Region: region, - StreetAddress: streetAddress, } } diff --git a/pkg/grpc/management/proto/management.proto b/pkg/grpc/management/proto/management.proto index a1a723e9fb..21f06ab9d7 100644 --- a/pkg/grpc/management/proto/management.proto +++ b/pkg/grpc/management/proto/management.proto @@ -1842,6 +1842,7 @@ message MachineView { message UpdateMachineRequest { string id = 1 [(validate.rules).string.min_len = 1]; string description = 2 [(validate.rules).string.max_len = 500]; + string name = 3 [(validate.rules).string = {min_len: 1, max_len: 200}]; } message AddMachineKeyRequest {