mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 00:17:24 +00:00
fix: set password in management api (#1766)
* fix: set password in management api * comment Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
parent
8d163163f1
commit
c0d9d86b09
@ -298,7 +298,18 @@ An sms will be sent to the given phone number to finish the phone verification p
|
|||||||
> **rpc** SetHumanInitialPassword([SetHumanInitialPasswordRequest](#sethumaninitialpasswordrequest))
|
> **rpc** SetHumanInitialPassword([SetHumanInitialPasswordRequest](#sethumaninitialpasswordrequest))
|
||||||
[SetHumanInitialPasswordResponse](#sethumaninitialpasswordresponse)
|
[SetHumanInitialPasswordResponse](#sethumaninitialpasswordresponse)
|
||||||
|
|
||||||
A Manager is only allowed to set an initial password, on the next login the user has to change his password
|
deprecated: use SetHumanPassword
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetHumanPassword
|
||||||
|
|
||||||
|
> **rpc** SetHumanPassword([SetHumanPasswordRequest](#sethumanpasswordrequest))
|
||||||
|
[SetHumanPasswordResponse](#sethumanpasswordresponse)
|
||||||
|
|
||||||
|
Set a new password for a user, on default the user has to change the password on the next login
|
||||||
|
Set no_change_required to true if the user does not have to change the password on the next login
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -4862,6 +4873,30 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetHumanPasswordRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| user_id | string | - | string.min_len: 1<br /> |
|
||||||
|
| password | string | - | string.min_len: 1<br /> string.max_len: 72<br /> |
|
||||||
|
| no_change_required | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetHumanPasswordResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SetPrimaryOrgDomainRequest
|
### SetPrimaryOrgDomainRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ func (s *Server) ResendHumanPhoneVerification(ctx context.Context, req *mgmt_pb.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetHumanInitialPassword(ctx context.Context, req *mgmt_pb.SetHumanInitialPasswordRequest) (*mgmt_pb.SetHumanInitialPasswordResponse, error) {
|
func (s *Server) SetHumanInitialPassword(ctx context.Context, req *mgmt_pb.SetHumanInitialPasswordRequest) (*mgmt_pb.SetHumanInitialPasswordResponse, error) {
|
||||||
objectDetails, err := s.command.SetOneTimePassword(ctx, authz.GetCtxData(ctx).OrgID, req.UserId, req.Password)
|
objectDetails, err := s.command.SetPassword(ctx, authz.GetCtxData(ctx).OrgID, req.UserId, req.Password, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -333,6 +333,16 @@ func (s *Server) SetHumanInitialPassword(ctx context.Context, req *mgmt_pb.SetHu
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetHumanPassword(ctx context.Context, req *mgmt_pb.SetHumanPasswordRequest) (*mgmt_pb.SetHumanPasswordResponse, error) {
|
||||||
|
objectDetails, err := s.command.SetPassword(ctx, authz.GetCtxData(ctx).OrgID, req.UserId, req.Password, !req.NoChangeRequired)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetHumanPasswordResponse{
|
||||||
|
Details: obj_grpc.DomainToChangeDetailsPb(objectDetails),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) SendHumanResetPasswordNotification(ctx context.Context, req *mgmt_pb.SendHumanResetPasswordNotificationRequest) (*mgmt_pb.SendHumanResetPasswordNotificationResponse, error) {
|
func (s *Server) SendHumanResetPasswordNotification(ctx context.Context, req *mgmt_pb.SendHumanResetPasswordNotificationRequest) (*mgmt_pb.SendHumanResetPasswordNotificationResponse, error) {
|
||||||
objectDetails, err := s.command.RequestSetPassword(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, notifyTypeToDomain(req.Type))
|
objectDetails, err := s.command.RequestSetPassword(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, notifyTypeToDomain(req.Type))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Commands) SetOneTimePassword(ctx context.Context, orgID, userID, passwordString string) (objectDetails *domain.ObjectDetails, err error) {
|
func (c *Commands) SetPassword(ctx context.Context, orgID, userID, passwordString string, oneTime bool) (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) }()
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
@ -26,7 +26,7 @@ func (c *Commands) SetOneTimePassword(ctx context.Context, orgID, userID, passwo
|
|||||||
}
|
}
|
||||||
password := &domain.Password{
|
password := &domain.Password{
|
||||||
SecretString: passwordString,
|
SecretString: passwordString,
|
||||||
ChangeRequired: true,
|
ChangeRequired: oneTime,
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingPassword.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingPassword.WriteModel)
|
||||||
passwordEvent, err := c.changePassword(ctx, "", password, userAgg, existingPassword)
|
passwordEvent, err := c.changePassword(ctx, "", password, userAgg, existingPassword)
|
||||||
@ -44,7 +44,7 @@ func (c *Commands) SetOneTimePassword(ctx context.Context, orgID, userID, passwo
|
|||||||
return writeModelToObjectDetails(&existingPassword.WriteModel), nil
|
return writeModelToObjectDetails(&existingPassword.WriteModel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) SetPassword(ctx context.Context, orgID, userID, code, passwordString, userAgentID string) (err error) {
|
func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID, code, passwordString, userAgentID string) (err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ func TestCommandSide_SetOneTimePassword(t *testing.T) {
|
|||||||
userID string
|
userID string
|
||||||
resourceOwner string
|
resourceOwner string
|
||||||
password string
|
password string
|
||||||
|
oneTime bool
|
||||||
}
|
}
|
||||||
type res struct {
|
type res struct {
|
||||||
want *domain.ObjectDetails
|
want *domain.ObjectDetails
|
||||||
@ -72,7 +73,7 @@ func TestCommandSide_SetOneTimePassword(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "change password, ok",
|
name: "change password onetime, ok",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
eventstore: eventstoreExpect(
|
eventstore: eventstoreExpect(
|
||||||
t,
|
t,
|
||||||
@ -134,6 +135,78 @@ func TestCommandSide_SetOneTimePassword(t *testing.T) {
|
|||||||
userID: "user1",
|
userID: "user1",
|
||||||
resourceOwner: "org1",
|
resourceOwner: "org1",
|
||||||
password: "password",
|
password: "password",
|
||||||
|
oneTime: true,
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change password no one time, 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||||
|
&user.NewAggregate("user1", "org1").Aggregate,
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
user.NewHumanPasswordChangedEvent(context.Background(),
|
||||||
|
&user.NewAggregate("user1", "org1").Aggregate,
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeHash,
|
||||||
|
Algorithm: "hash",
|
||||||
|
KeyID: "",
|
||||||
|
Crypted: []byte("password"),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
userID: "user1",
|
||||||
|
resourceOwner: "org1",
|
||||||
|
password: "password",
|
||||||
|
oneTime: false,
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
want: &domain.ObjectDetails{
|
want: &domain.ObjectDetails{
|
||||||
@ -148,7 +221,7 @@ func TestCommandSide_SetOneTimePassword(t *testing.T) {
|
|||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore,
|
||||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||||
}
|
}
|
||||||
got, err := r.SetOneTimePassword(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.password)
|
got, err := r.SetPassword(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.password, tt.args.oneTime)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
@ -410,7 +483,7 @@ func TestCommandSide_SetPassword(t *testing.T) {
|
|||||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||||
passwordVerificationCode: tt.fields.secretGenerator,
|
passwordVerificationCode: tt.fields.secretGenerator,
|
||||||
}
|
}
|
||||||
err := r.SetPassword(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password, tt.args.agentID)
|
err := r.SetPasswordWithVerifyCode(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password, tt.args.agentID)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func (l *Login) checkPWCode(w http.ResponseWriter, r *http.Request, authReq *dom
|
|||||||
userOrg = authReq.UserOrgID
|
userOrg = authReq.UserOrgID
|
||||||
}
|
}
|
||||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||||
err = l.command.SetPassword(setContext(r.Context(), userOrg), userOrg, data.UserID, data.Code, data.Password, userAgentID)
|
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
|
||||||
|
@ -392,7 +392,7 @@ service ManagementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Manager is only allowed to set an initial password, on the next login the user has to change his password
|
// deprecated: use SetHumanPassword
|
||||||
rpc SetHumanInitialPassword(SetHumanInitialPasswordRequest) returns (SetHumanInitialPasswordResponse) {
|
rpc SetHumanInitialPassword(SetHumanInitialPasswordRequest) returns (SetHumanInitialPasswordResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/users/{user_id}/password/_initialize"
|
post: "/users/{user_id}/password/_initialize"
|
||||||
@ -404,6 +404,19 @@ service ManagementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a new password for a user, on default the user has to change the password on the next login
|
||||||
|
// Set no_change_required to true if the user does not have to change the password on the next login
|
||||||
|
rpc SetHumanPassword(SetHumanPasswordRequest) returns (SetHumanPasswordResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/users/{user_id}/password"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "user.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// An email will be sent to the given address to reset the password of the user
|
// An email will be sent to the given address to reset the password of the user
|
||||||
rpc SendHumanResetPasswordNotification(SendHumanResetPasswordNotificationRequest) returns (SendHumanResetPasswordNotificationResponse) {
|
rpc SendHumanResetPasswordNotification(SendHumanResetPasswordNotificationRequest) returns (SendHumanResetPasswordNotificationResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -2380,6 +2393,16 @@ message SetHumanInitialPasswordResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SetHumanPasswordRequest {
|
||||||
|
string user_id = 1 [(validate.rules).string.min_len = 1];
|
||||||
|
string password = 2 [(validate.rules).string = {min_len: 1, max_len: 72}];
|
||||||
|
bool no_change_required = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SetHumanPasswordResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message SendHumanResetPasswordNotificationRequest {
|
message SendHumanResetPasswordNotificationRequest {
|
||||||
enum Type {
|
enum Type {
|
||||||
TYPE_EMAIL = 0;
|
TYPE_EMAIL = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user