fix: set userAgentID in password change event if available (#7319)

(cherry picked from commit c20204d84d513ee20b25a943fc2f44bd9f9310a0)
This commit is contained in:
Livio Spring 2024-01-30 15:36:34 +01:00
parent d3bb9c9b3b
commit ddeacd2f88
No known key found for this signature in database
GPG Key ID: 26BB1C2FA5952CF0
10 changed files with 257 additions and 26 deletions

View File

@ -11,7 +11,7 @@ import (
func (s *Server) UpdateMyPassword(ctx context.Context, req *auth_pb.UpdateMyPasswordRequest) (*auth_pb.UpdateMyPasswordResponse, error) { func (s *Server) UpdateMyPassword(ctx context.Context, req *auth_pb.UpdateMyPasswordRequest) (*auth_pb.UpdateMyPasswordResponse, error) {
ctxData := authz.GetCtxData(ctx) ctxData := authz.GetCtxData(ctx)
objectDetails, err := s.command.ChangePassword(ctx, ctxData.ResourceOwner, ctxData.UserID, req.OldPassword, req.NewPassword) objectDetails, err := s.command.ChangePassword(ctx, ctxData.ResourceOwner, ctxData.UserID, req.OldPassword, req.NewPassword, "")
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -53,9 +53,9 @@ func (s *Server) SetPassword(ctx context.Context, req *user.SetPasswordRequest)
switch v := req.GetVerification().(type) { switch v := req.GetVerification().(type) {
case *user.SetPasswordRequest_CurrentPassword: case *user.SetPasswordRequest_CurrentPassword:
details, err = s.command.ChangePassword(ctx, resourceOwner, req.GetUserId(), v.CurrentPassword, req.GetNewPassword().GetPassword()) details, err = s.command.ChangePassword(ctx, resourceOwner, req.GetUserId(), v.CurrentPassword, req.GetNewPassword().GetPassword(), "")
case *user.SetPasswordRequest_VerificationCode: case *user.SetPasswordRequest_VerificationCode:
details, err = s.command.SetPasswordWithVerifyCode(ctx, resourceOwner, req.GetUserId(), v.VerificationCode, req.GetNewPassword().GetPassword()) details, err = s.command.SetPasswordWithVerifyCode(ctx, resourceOwner, req.GetUserId(), v.VerificationCode, req.GetNewPassword().GetPassword(), "")
case nil: case nil:
details, err = s.command.SetPassword(ctx, resourceOwner, req.GetUserId(), req.GetNewPassword().GetPassword(), req.GetNewPassword().GetChangeRequired()) details, err = s.command.SetPassword(ctx, resourceOwner, req.GetUserId(), req.GetNewPassword().GetPassword(), req.GetNewPassword().GetChangeRequired())
default: default:

View File

@ -3,6 +3,7 @@ package login
import ( import (
"net/http" "net/http"
http_mw "github.com/zitadel/zitadel/internal/api/http/middleware"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
) )
@ -24,7 +25,8 @@ func (l *Login) handleChangePassword(w http.ResponseWriter, r *http.Request) {
l.renderError(w, r, authReq, err) l.renderError(w, r, authReq, err)
return return
} }
_, err = l.command.ChangePassword(setContext(r.Context(), authReq.UserOrgID), authReq.UserOrgID, authReq.UserID, data.OldPassword, data.NewPassword) userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
_, err = l.command.ChangePassword(setContext(r.Context(), authReq.UserOrgID), authReq.UserOrgID, authReq.UserID, data.OldPassword, data.NewPassword, userAgentID)
if err != nil { if err != nil {
l.renderChangePassword(w, r, authReq, err) l.renderChangePassword(w, r, authReq, err)
return return

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
http_mw "github.com/zitadel/zitadel/internal/api/http/middleware"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors" "github.com/zitadel/zitadel/internal/zerrors"
) )
@ -71,7 +72,8 @@ func (l *Login) checkPWCode(w http.ResponseWriter, r *http.Request, authReq *dom
if authReq != nil { if authReq != nil {
userOrg = authReq.UserOrgID userOrg = authReq.UserOrgID
} }
_, err := l.command.SetPasswordWithVerifyCode(setContext(r.Context(), userOrg), userOrg, data.UserID, data.Code, data.Password) userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
_, err := l.command.SetPasswordWithVerifyCode(setContext(r.Context(), userOrg), userOrg, data.UserID, data.Code, data.Password, userAgentID)
if err != nil { if err != nil {
l.renderInitPassword(w, r, authReq, data.UserID, "", err) l.renderInitPassword(w, r, authReq, data.UserID, "", err)
return return

View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"strconv" "strconv"
http_mw "github.com/zitadel/zitadel/internal/api/http/middleware"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors" "github.com/zitadel/zitadel/internal/zerrors"
) )
@ -85,7 +86,8 @@ func (l *Login) checkUserInitCode(w http.ResponseWriter, r *http.Request, authRe
l.renderInitUser(w, r, authReq, data.UserID, data.LoginName, "", data.PasswordSet, err) l.renderInitUser(w, r, authReq, data.UserID, data.LoginName, "", data.PasswordSet, err)
return return
} }
err = l.command.HumanVerifyInitCode(setContext(r.Context(), userOrgID), data.UserID, userOrgID, data.Code, data.Password, initCodeGenerator) userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.command.HumanVerifyInitCode(setContext(r.Context(), userOrgID), data.UserID, userOrgID, data.Code, data.Password, userAgentID, initCodeGenerator)
if err != nil { if err != nil {
l.renderInitUser(w, r, authReq, data.UserID, data.LoginName, "", data.PasswordSet, err) l.renderInitUser(w, r, authReq, data.UserID, data.LoginName, "", data.PasswordSet, err)
return return

View File

@ -50,7 +50,7 @@ func (c *Commands) ResendInitialMail(ctx context.Context, userID string, email d
return writeModelToObjectDetails(&existingCode.WriteModel), nil return writeModelToObjectDetails(&existingCode.WriteModel), nil
} }
func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwner, code, password string, initCodeGenerator crypto.Generator) error { func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwner, code, password, userAgentID string, initCodeGenerator crypto.Generator) error {
if userID == "" { if userID == "" {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-mkM9f", "Errors.User.UserIDMissing") return zerrors.ThrowInvalidArgument(nil, "COMMAND-mkM9f", "Errors.User.UserIDMissing")
} }
@ -80,7 +80,7 @@ func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwne
commands = append(commands, user.NewHumanEmailVerifiedEvent(ctx, userAgg)) commands = append(commands, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
} }
if password != "" { if password != "" {
passwordCommand, err := c.setPasswordCommand(ctx, userAgg, domain.UserStateActive, password, false, false) passwordCommand, err := c.setPasswordCommand(ctx, userAgg, domain.UserStateActive, password, userAgentID, false, false)
if err != nil { if err != nil {
return err return err
} }

View File

@ -300,6 +300,7 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
code string code string
resourceOwner string resourceOwner string
password string password string
userAgentID string
secretGenerator crypto.Generator secretGenerator crypto.Generator
} }
type res struct { type res struct {
@ -578,6 +579,83 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
}, },
}, },
}, },
{
name: "valid code with password and userAgentID, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanEmailVerifiedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate)),
eventFromEventPusherWithCreationDateNow(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
1,
false,
false,
false,
false,
),
),
),
expectPush(
user.NewHumanInitializedCheckSucceededEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
user.NewHumanPasswordChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"$plain$x$password",
false,
"userAgent1",
),
),
),
userPasswordHasher: mockPasswordHasher("x"),
},
args: args{
ctx: context.Background(),
userID: "user1",
code: "a",
resourceOwner: "org1",
password: "password",
userAgentID: "userAgent1",
secretGenerator: GetMockSecretGenerator(t),
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -585,7 +663,7 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
eventstore: tt.fields.eventstore, eventstore: tt.fields.eventstore,
userPasswordHasher: tt.fields.userPasswordHasher, userPasswordHasher: tt.fields.userPasswordHasher,
} }
err := r.HumanVerifyInitCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.code, tt.args.password, tt.args.secretGenerator) err := r.HumanVerifyInitCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.code, tt.args.password, tt.args.userAgentID, tt.args.secretGenerator)
if tt.res.err == nil { if tt.res.err == nil {
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -31,10 +31,10 @@ func (c *Commands) SetPassword(ctx context.Context, orgID, userID, password stri
if err = c.checkPermission(ctx, domain.PermissionUserWrite, wm.ResourceOwner, userID); err != nil { if err = c.checkPermission(ctx, domain.PermissionUserWrite, wm.ResourceOwner, userID); err != nil {
return nil, err return nil, err
} }
return c.setPassword(ctx, wm, password, oneTime) return c.setPassword(ctx, wm, password, "", oneTime)
} }
func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID, code, password string) (objectDetails *domain.ObjectDetails, err error) { func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID, code, password, userAgentID string) (objectDetails *domain.ObjectDetails, err error) {
ctx, span := tracing.NewSpan(ctx) ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }() defer func() { span.EndWithError(err) }()
@ -58,13 +58,13 @@ func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID,
return nil, err return nil, err
} }
return c.setPassword(ctx, wm, password, false) return c.setPassword(ctx, wm, password, userAgentID, false)
} }
// setEncodedPassword add change event from already encoded password to HumanPasswordWriteModel and return the necessary object details for response // setEncodedPassword add change event from already encoded password to HumanPasswordWriteModel and return the necessary object details for response
func (c *Commands) setEncodedPassword(ctx context.Context, wm *HumanPasswordWriteModel, password string, changeRequired bool) (objectDetails *domain.ObjectDetails, err error) { func (c *Commands) setEncodedPassword(ctx context.Context, wm *HumanPasswordWriteModel, password, userAgentID string, changeRequired bool) (objectDetails *domain.ObjectDetails, err error) {
agg := user.NewAggregate(wm.AggregateID, wm.ResourceOwner) agg := user.NewAggregate(wm.AggregateID, wm.ResourceOwner)
command, err := c.setPasswordCommand(ctx, &agg.Aggregate, wm.UserState, password, changeRequired, true) command, err := c.setPasswordCommand(ctx, &agg.Aggregate, wm.UserState, password, userAgentID, changeRequired, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -76,9 +76,9 @@ func (c *Commands) setEncodedPassword(ctx context.Context, wm *HumanPasswordWrit
} }
// setPassword add change event to HumanPasswordWriteModel and return the necessary object details for response // setPassword add change event to HumanPasswordWriteModel and return the necessary object details for response
func (c *Commands) setPassword(ctx context.Context, wm *HumanPasswordWriteModel, password string, changeRequired bool) (objectDetails *domain.ObjectDetails, err error) { func (c *Commands) setPassword(ctx context.Context, wm *HumanPasswordWriteModel, password, userAgentID string, changeRequired bool) (objectDetails *domain.ObjectDetails, err error) {
agg := user.NewAggregate(wm.AggregateID, wm.ResourceOwner) agg := user.NewAggregate(wm.AggregateID, wm.ResourceOwner)
command, err := c.setPasswordCommand(ctx, &agg.Aggregate, wm.UserState, password, changeRequired, false) command, err := c.setPasswordCommand(ctx, &agg.Aggregate, wm.UserState, password, userAgentID, changeRequired, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -89,7 +89,7 @@ func (c *Commands) setPassword(ctx context.Context, wm *HumanPasswordWriteModel,
return writeModelToObjectDetails(&wm.WriteModel), nil return writeModelToObjectDetails(&wm.WriteModel), nil
} }
func (c *Commands) setPasswordCommand(ctx context.Context, agg *eventstore.Aggregate, userState domain.UserState, password string, changeRequired, encoded bool) (_ eventstore.Command, err error) { func (c *Commands) setPasswordCommand(ctx context.Context, agg *eventstore.Aggregate, userState domain.UserState, password, userAgentID string, changeRequired, encoded bool) (_ eventstore.Command, err error) {
if err = c.canUpdatePassword(ctx, password, agg.ResourceOwner, userState); err != nil { if err = c.canUpdatePassword(ctx, password, agg.ResourceOwner, userState); err != nil {
return nil, err return nil, err
} }
@ -101,13 +101,13 @@ func (c *Commands) setPasswordCommand(ctx context.Context, agg *eventstore.Aggre
if err = convertPasswapErr(err); err != nil { if err = convertPasswapErr(err); err != nil {
return nil, err return nil, err
} }
return user.NewHumanPasswordChangedEvent(ctx, agg, encodedPassword, changeRequired, ""), nil return user.NewHumanPasswordChangedEvent(ctx, agg, encodedPassword, changeRequired, userAgentID), nil
} }
return user.NewHumanPasswordChangedEvent(ctx, agg, password, changeRequired, ""), nil return user.NewHumanPasswordChangedEvent(ctx, agg, password, changeRequired, userAgentID), nil
} }
// ChangePassword change password of existing user // ChangePassword change password of existing user
func (c *Commands) ChangePassword(ctx context.Context, orgID, userID, oldPassword, newPassword string) (objectDetails *domain.ObjectDetails, err error) { func (c *Commands) ChangePassword(ctx context.Context, orgID, userID, oldPassword, newPassword, userAgentID string) (objectDetails *domain.ObjectDetails, err error) {
ctx, span := tracing.NewSpan(ctx) ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }() defer func() { span.EndWithError(err) }()
@ -126,7 +126,7 @@ func (c *Commands) ChangePassword(ctx context.Context, orgID, userID, oldPasswor
if err != nil { if err != nil {
return nil, err return nil, err
} }
return c.setEncodedPassword(ctx, wm, newPasswordHash, false) return c.setEncodedPassword(ctx, wm, newPasswordHash, userAgentID, false)
} }
// verifyAndUpdatePassword verify if the old password is correct with the encoded hash and // verifyAndUpdatePassword verify if the old password is correct with the encoded hash and

View File

@ -278,6 +278,7 @@ func TestCommandSide_SetPasswordWithVerifyCode(t *testing.T) {
code string code string
resourceOwner string resourceOwner string
password string password string
userAgentID string
} }
type res struct { type res struct {
want *domain.ObjectDetails want *domain.ObjectDetails
@ -496,6 +497,83 @@ func TestCommandSide_SetPasswordWithVerifyCode(t *testing.T) {
}, },
}, },
}, },
{
name: "set password with userAgentID, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanEmailVerifiedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
),
eventFromEventPusherWithCreationDateNow(
user.NewHumanPasswordCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
domain.NotificationTypeEmail,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
1,
false,
false,
false,
false,
),
),
),
expectPush(
user.NewHumanPasswordChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"$plain$x$password",
false,
"userAgent1",
),
),
),
userPasswordHasher: mockPasswordHasher("x"),
userEncryption: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
password: "password",
code: "a",
userAgentID: "userAgent1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -504,7 +582,7 @@ func TestCommandSide_SetPasswordWithVerifyCode(t *testing.T) {
userPasswordHasher: tt.fields.userPasswordHasher, userPasswordHasher: tt.fields.userPasswordHasher,
userEncryption: tt.fields.userEncryption, userEncryption: tt.fields.userEncryption,
} }
got, err := r.SetPasswordWithVerifyCode(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password) got, err := r.SetPasswordWithVerifyCode(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password, tt.args.userAgentID)
if tt.res.err == nil { if tt.res.err == nil {
assert.NoError(t, err) assert.NoError(t, err)
} }
@ -528,6 +606,7 @@ func TestCommandSide_ChangePassword(t *testing.T) {
resourceOwner string resourceOwner string
oldPassword string oldPassword string
newPassword string newPassword string
userAgentID string
} }
type res struct { type res struct {
want *domain.ObjectDetails want *domain.ObjectDetails
@ -745,6 +824,74 @@ func TestCommandSide_ChangePassword(t *testing.T) {
}, },
}, },
}, },
{
name: "change password with userAgentID, ok",
fields: fields{
userPasswordHasher: mockPasswordHasher("x"),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
oldPassword: "password",
newPassword: "password1",
userAgentID: "userAgent1",
},
expect: []expect{
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanEmailVerifiedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
),
eventFromEventPusher(
user.NewHumanPasswordChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"$plain$x$password",
false,
"")),
),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
1,
false,
false,
false,
false,
),
),
),
expectPush(
user.NewHumanPasswordChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"$plain$x$password1",
false,
"userAgent1",
),
),
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -752,7 +899,7 @@ func TestCommandSide_ChangePassword(t *testing.T) {
eventstore: eventstoreExpect(t, tt.expect...), eventstore: eventstoreExpect(t, tt.expect...),
userPasswordHasher: tt.fields.userPasswordHasher, userPasswordHasher: tt.fields.userPasswordHasher,
} }
got, err := r.ChangePassword(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.oldPassword, tt.args.newPassword) got, err := r.ChangePassword(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.oldPassword, tt.args.newPassword, tt.args.userAgentID)
if tt.res.err == nil { if tt.res.err == nil {
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -394,7 +394,7 @@ func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Com
// password already hashed in request // password already hashed in request
if password.EncodedPasswordHash != nil { if password.EncodedPasswordHash != nil {
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.EncodedPasswordHash, password.ChangeRequired, true) cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.EncodedPasswordHash, "", password.ChangeRequired, true)
if cmd != nil { if cmd != nil {
return append(cmds, cmd), err return append(cmds, cmd), err
} }
@ -402,7 +402,7 @@ func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Com
} }
// password already hashed in verify // password already hashed in verify
if encodedPassword != "" { if encodedPassword != "" {
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, encodedPassword, password.ChangeRequired, true) cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, encodedPassword, "", password.ChangeRequired, true)
if cmd != nil { if cmd != nil {
return append(cmds, cmd), err return append(cmds, cmd), err
} }
@ -410,7 +410,7 @@ func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Com
} }
// password still to be hashed // password still to be hashed
if password.Password != nil { if password.Password != nil {
cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.Password, password.ChangeRequired, false) cmd, err := c.setPasswordCommand(ctx, &wm.Aggregate().Aggregate, wm.UserState, *password.Password, "", password.ChangeRequired, false)
if cmd != nil { if cmd != nil {
return append(cmds, cmd), err return append(cmds, cmd), err
} }