feat: ResetPassword endpoint

This commit is contained in:
Stefan Benz
2024-09-24 20:42:20 +02:00
parent 04f5ed8d1c
commit 50e0c758de
17 changed files with 1275 additions and 89 deletions

View File

@@ -62,7 +62,7 @@ func TestServer_SetPassword(t *testing.T) {
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -85,7 +85,7 @@ func TestServer_SetPassword(t *testing.T) {
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -131,7 +131,7 @@ func TestServer_SetPassword(t *testing.T) {
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -139,7 +139,7 @@ func TestServer_SetPassword(t *testing.T) {
wantErr: true,
},
{
name: "username add, user not existing",
name: "password set, user not existing",
ctx: isolatedIAMOwnerCTX,
req: &user.SetPasswordRequest{
@@ -151,7 +151,7 @@ func TestServer_SetPassword(t *testing.T) {
Id: "not existing",
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -174,7 +174,7 @@ func TestServer_SetPassword(t *testing.T) {
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -200,7 +200,7 @@ func TestServer_SetPassword(t *testing.T) {
req: &user.SetPasswordRequest{
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: gofakeit.Password(true, true, true, true, false, 12),
Password: fakePassword(),
},
ChangeRequired: false,
},
@@ -215,6 +215,174 @@ func TestServer_SetPassword(t *testing.T) {
},
},
},
{
name: "password set, code, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
passwordResp := instance.RequestAuthenticatorPasswordReset(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id)
req.NewPassword.Verification = &user.SetPassword_VerificationCode{VerificationCode: passwordResp.GetVerificationCode()}
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password set, code, failed",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
instance.RequestAuthenticatorPasswordReset(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id)
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
Verification: &user.SetPassword_VerificationCode{VerificationCode: "notreally"},
},
},
wantErr: true,
},
{
name: "password set, code, no set",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
Verification: &user.SetPassword_VerificationCode{VerificationCode: "notreally"},
},
},
wantErr: true,
},
{
name: "password set, current password, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
password := fakePassword()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, password)
req.NewPassword.Verification = &user.SetPassword_CurrentPassword{CurrentPassword: password}
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password set, current password, failed",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
Verification: &user.SetPassword_CurrentPassword{CurrentPassword: fakePassword()},
},
},
wantErr: true,
},
{
name: "password set, current password, not set",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.SetPasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.SetPasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
NewPassword: &user.SetPassword{
Type: &user.SetPassword_Password{
Password: fakePassword(),
},
ChangeRequired: false,
Verification: &user.SetPassword_CurrentPassword{CurrentPassword: fakePassword()},
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -232,3 +400,428 @@ func TestServer_SetPassword(t *testing.T) {
})
}
}
func fakePassword() string {
return gofakeit.Password(true, true, true, true, false, 5) + "Password1!"
}
func TestServer_RequestPasswordReset(t *testing.T) {
t.Parallel()
instance := integration.NewInstance(CTX)
ensureFeatureEnabled(t, instance)
isolatedIAMOwnerCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
schema := []byte(`{
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}`)
schemaResp := instance.CreateUserSchema(isolatedIAMOwnerCTX, schema)
orgResp := instance.CreateOrganization(isolatedIAMOwnerCTX, gofakeit.Name(), gofakeit.Email())
type res struct {
want *resource_object.Details
code bool
}
tests := []struct {
name string
ctx context.Context
dep func(req *user.RequestPasswordResetRequest) error
req *user.RequestPasswordResetRequest
res res
wantErr bool
}{
{
name: "password reset, no context",
ctx: context.Background(),
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
wantErr: true,
},
{
name: "password reset, no permission",
ctx: instance.WithAuthorization(CTX, integration.UserTypeLogin),
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
wantErr: true,
},
{
name: "password reset, no password set",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
wantErr: true,
},
{
name: "password reset, user not existing in org",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: "notexisting",
},
},
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
wantErr: true,
},
{
name: "password reset, user not existing",
ctx: isolatedIAMOwnerCTX,
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: "notexisting",
},
},
Id: "not existing",
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
wantErr: true,
},
{
name: "password reset, email, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password reset, no org, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Medium: &user.RequestPasswordResetRequest_SendEmail{},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password reset, phone, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_SendSms{},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password reset, code, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RequestPasswordResetRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RequestPasswordResetRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Medium: &user.RequestPasswordResetRequest_ReturnCode{},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
code: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.dep != nil {
err := tt.dep(tt.req)
assert.NoError(t, err)
}
got, err := instance.Client.UserV3Alpha.RequestPasswordReset(tt.ctx, tt.req)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
if tt.res.code {
require.NotEmpty(t, got.VerificationCode)
}
})
}
}
func TestServer_RemovePassword(t *testing.T) {
t.Parallel()
instance := integration.NewInstance(CTX)
ensureFeatureEnabled(t, instance)
isolatedIAMOwnerCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
schema := []byte(`{
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}`)
schemaResp := instance.CreateUserSchema(isolatedIAMOwnerCTX, schema)
orgResp := instance.CreateOrganization(isolatedIAMOwnerCTX, gofakeit.Name(), gofakeit.Email())
type res struct {
want *resource_object.Details
}
tests := []struct {
name string
ctx context.Context
dep func(req *user.RemovePasswordRequest) error
req *user.RemovePasswordRequest
res res
wantErr bool
}{
{
name: "password remove, no context",
ctx: context.Background(),
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
{
name: "password remove, no permission",
ctx: instance.WithAuthorization(CTX, integration.UserTypeLogin),
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
{
name: "password remove, no password set",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
{
name: "password remove, user not existing in org",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: "notexisting",
},
},
},
wantErr: true,
},
{
name: "password remove, user not existing",
ctx: isolatedIAMOwnerCTX,
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: "notexisting",
},
},
Id: "not existing",
},
wantErr: true,
},
{
name: "password remove, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RemovePasswordRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "password remove, no org, ok",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemovePasswordRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
instance.SetAuthenticatorPassword(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, fakePassword())
return nil
},
req: &user.RemovePasswordRequest{},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.dep != nil {
err := tt.dep(tt.req)
assert.NoError(t, err)
}
got, err := instance.Client.UserV3Alpha.RemovePassword(tt.ctx, tt.req)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
})
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/brianvoe/gofakeit/v6"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/logging"
"google.golang.org/protobuf/types/known/structpb"
@@ -212,16 +213,16 @@ func TestServer_CreateUser(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got, err := instance.Client.UserV3Alpha.CreateUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
if tt.res.returnCodeEmail {
require.NotNil(t, got.EmailCode)
assert.NotNil(t, got.EmailCode)
}
if tt.res.returnCodePhone {
require.NotNil(t, got.PhoneCode)
assert.NotNil(t, got.PhoneCode)
}
})
}
@@ -628,16 +629,16 @@ func TestServer_PatchUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.PatchUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
if tt.res.returnCodeEmail {
require.NotNil(t, got.EmailCode)
assert.NotNil(t, got.EmailCode)
}
if tt.res.returnCodePhone {
require.NotNil(t, got.PhoneCode)
assert.NotNil(t, got.PhoneCode)
}
})
}
@@ -843,10 +844,10 @@ func TestServer_DeleteUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.DeleteUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}
@@ -1054,10 +1055,10 @@ func TestServer_LockUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.LockUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}
@@ -1237,10 +1238,10 @@ func TestServer_UnlockUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.UnlockUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}
@@ -1439,10 +1440,10 @@ func TestServer_DeactivateUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.DeactivateUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}
@@ -1622,10 +1623,10 @@ func TestServer_ActivateUser(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.ActivateUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}

View File

@@ -8,7 +8,6 @@ import (
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
@@ -369,10 +368,10 @@ func TestServer_AddUsername(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.AddUsername(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
})
}
@@ -412,8 +411,9 @@ func TestServer_DeleteUsername(t *testing.T) {
ctx: context.Background(),
dep: func(req *user.RemoveUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
usernameResp := instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), gofakeit.Username(), false)
req.Id = usernameResp.GetUsernameId()
req.UsernameId = usernameResp.GetUsernameId()
return nil
},
req: &user.RemoveUsernameRequest{
@@ -430,8 +430,9 @@ func TestServer_DeleteUsername(t *testing.T) {
ctx: instance.WithAuthorization(CTX, integration.UserTypeLogin),
dep: func(req *user.RemoveUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
usernameResp := instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), gofakeit.Username(), false)
req.Id = usernameResp.GetUsernameId()
req.UsernameId = usernameResp.GetUsernameId()
return nil
},
req: &user.RemoveUsernameRequest{
@@ -452,6 +453,20 @@ func TestServer_DeleteUsername(t *testing.T) {
OrgId: orgResp.GetOrganizationId(),
},
},
UsernameId: "notempty",
},
wantErr: true,
},
{
name: "username delete, userid empty",
ctx: instance.WithAuthorization(CTX, integration.UserTypeLogin),
req: &user.RemoveUsernameRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
Id: "notempty",
},
wantErr: true,
},
@@ -464,7 +479,25 @@ func TestServer_DeleteUsername(t *testing.T) {
OrgId: orgResp.GetOrganizationId(),
},
},
Id: "notexisting",
UsernameId: "notempty",
Id: "notexisting",
},
wantErr: true,
},
{
name: "username remove, no username",
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemoveUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
return nil
},
req: &user.RemoveUsernameRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
@@ -473,8 +506,9 @@ func TestServer_DeleteUsername(t *testing.T) {
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemoveUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
usernameResp := instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), gofakeit.Username(), false)
req.Id = usernameResp.GetUsernameId()
req.UsernameId = usernameResp.GetUsernameId()
return nil
},
req: &user.RemoveUsernameRequest{
@@ -501,8 +535,8 @@ func TestServer_DeleteUsername(t *testing.T) {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
resp := instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, gofakeit.Username(), false)
req.Id = resp.GetUsernameId()
instance.RemoveAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), resp.GetUsernameId())
req.UsernameId = resp.GetUsernameId()
instance.RemoveAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), req.Id, req.UsernameId)
return nil
},
req: &user.RemoveUsernameRequest{
@@ -519,8 +553,9 @@ func TestServer_DeleteUsername(t *testing.T) {
ctx: isolatedIAMOwnerCTX,
dep: func(req *user.RemoveUsernameRequest) error {
userResp := instance.CreateSchemaUser(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.Id = userResp.GetDetails().GetId()
usernameResp := instance.AddAuthenticatorUsername(isolatedIAMOwnerCTX, orgResp.GetOrganizationId(), userResp.GetDetails().GetId(), gofakeit.Username(), true)
req.Id = usernameResp.GetUsernameId()
req.UsernameId = usernameResp.GetUsernameId()
return nil
},
req: &user.RemoveUsernameRequest{
@@ -549,11 +584,13 @@ func TestServer_DeleteUsername(t *testing.T) {
}
got, err := instance.Client.UserV3Alpha.RemoveUsername(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
})
}
}

View File

@@ -3,8 +3,11 @@ package user
import (
"context"
"github.com/muhlemmer/gu"
resource_object "github.com/zitadel/zitadel/internal/api/grpc/resources/object/v3alpha"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
object "github.com/zitadel/zitadel/pkg/grpc/object/v3alpha"
user "github.com/zitadel/zitadel/pkg/grpc/resources/user/v3alpha"
)
@@ -29,23 +32,11 @@ func setPasswordRequestToSetSchemaUserPassword(req *user.SetPasswordRequest) *co
Password: req.GetNewPassword().GetPassword(),
EncodedPasswordHash: req.GetNewPassword().GetHash(),
ChangeRequired: req.GetNewPassword().GetChangeRequired(),
VerificationCode: req.GetNewPassword().GetVerificationCode(),
CurrentPassword: req.GetNewPassword().GetCurrentPassword(),
}
}
/*
func (s *Server) RemovePassword(ctx context.Context, req *user.RemovePasswordRequest) (_ *user.RemovePasswordResponse, err error) {
if err := checkUserSchemaEnabled(ctx); err != nil {
return nil, err
}
details, err := s.command.DeleteSchemaUserPassword(ctx, organizationToUpdateResourceOwner(req.Organization), req.GetId())
if err != nil {
return nil, err
}
return &user.RemovePasswordResponse{
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
}, nil
}
func (s *Server) RemovePassword(ctx context.Context, req *user.RemovePasswordRequest) (_ *user.RemovePasswordResponse, err error) {
if err := checkUserSchemaEnabled(ctx); err != nil {
return nil, err
@@ -58,4 +49,35 @@ func (s *Server) RemovePassword(ctx context.Context, req *user.RemovePasswordReq
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
}, nil
}
*/
func (s *Server) RequestPasswordReset(ctx context.Context, req *user.RequestPasswordResetRequest) (_ *user.RequestPasswordResetResponse, err error) {
if err := checkUserSchemaEnabled(ctx); err != nil {
return nil, err
}
schemauser := requestPasswordResetRequestToRequestSchemaUserPasswordReset(req)
details, err := s.command.RequestSchemaUserPasswordReset(ctx, schemauser)
if err != nil {
return nil, err
}
return &user.RequestPasswordResetResponse{
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
VerificationCode: gu.Ptr(schemauser.PlainCode),
}, nil
}
func requestPasswordResetRequestToRequestSchemaUserPasswordReset(req *user.RequestPasswordResetRequest) *command.RequestSchemaUserPasswordReset {
var notificationType domain.NotificationType
if req.GetSendEmail() != nil {
notificationType = domain.NotificationTypeEmail
}
if req.GetSendSms() != nil {
notificationType = domain.NotificationTypeSms
}
return &command.RequestSchemaUserPasswordReset{
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
UserID: req.GetId(),
URLTemplate: req.GetSendEmail().GetUrlTemplate(),
ReturnCode: req.GetReturnCode() != nil,
NotificationType: notificationType,
}
}

View File

@@ -32,11 +32,11 @@ func addUsernameRequestToAddUsername(req *user.AddUsernameRequest) *command.AddU
}
}
func (s *Server) DeleteUsername(ctx context.Context, req *user.RemoveUsernameRequest) (_ *user.RemoveUsernameResponse, err error) {
func (s *Server) RemoveUsername(ctx context.Context, req *user.RemoveUsernameRequest) (_ *user.RemoveUsernameResponse, err error) {
if err := checkUserSchemaEnabled(ctx); err != nil {
return nil, err
}
details, err := s.command.DeleteUsername(ctx, organizationToUpdateResourceOwner(req.Organization), req.GetId())
details, err := s.command.DeleteUsername(ctx, organizationToUpdateResourceOwner(req.Organization), req.GetId(), req.GetUsernameId())
if err != nil {
return nil, err
}