mirror of
https://github.com/zitadel/zitadel.git
synced 2025-11-16 08:13:11 +00:00
feat: api v2beta to api v2 (#8283)
# Which Problems Are Solved The v2beta services are stable but not GA. # How the Problems Are Solved The v2beta services are copied to v2. The corresponding v1 and v2beta services are deprecated. # Additional Context Closes #7236 --------- Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
@@ -5,6 +5,7 @@ package user_test
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -12,9 +13,10 @@ import (
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
user "github.com/zitadel/zitadel/pkg/grpc/user/v2beta"
|
||||
)
|
||||
|
||||
func TestServer_RegisterPasskey(t *testing.T) {
|
||||
@@ -138,19 +140,7 @@ func TestServer_RegisterPasskey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_VerifyPasskeyRegistration(t *testing.T) {
|
||||
userID := Tester.CreateHumanUser(CTX).GetUserId()
|
||||
reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{
|
||||
UserId: userID,
|
||||
Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pkr, err := Client.RegisterPasskey(CTX, &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
Code: reg.GetCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, pkr.GetPasskeyId())
|
||||
require.NotEmpty(t, pkr.GetPublicKeyCredentialCreationOptions())
|
||||
userID, pkr := userWithPasskeyRegistered(t)
|
||||
|
||||
attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions())
|
||||
require.NoError(t, err)
|
||||
@@ -317,3 +307,291 @@ func TestServer_CreatePasskeyRegistrationLink(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func userWithPasskeyRegistered(t *testing.T) (string, *user.RegisterPasskeyResponse) {
|
||||
userID := Tester.CreateHumanUser(CTX).GetUserId()
|
||||
return userID, passkeyRegister(t, userID)
|
||||
}
|
||||
|
||||
func userWithPasskeyVerified(t *testing.T) (string, string) {
|
||||
userID, pkr := userWithPasskeyRegistered(t)
|
||||
return userID, passkeyVerify(t, userID, pkr)
|
||||
}
|
||||
|
||||
func passkeyRegister(t *testing.T, userID string) *user.RegisterPasskeyResponse {
|
||||
reg, err := Client.CreatePasskeyRegistrationLink(CTX, &user.CreatePasskeyRegistrationLinkRequest{
|
||||
UserId: userID,
|
||||
Medium: &user.CreatePasskeyRegistrationLinkRequest_ReturnCode{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pkr, err := Client.RegisterPasskey(CTX, &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
Code: reg.GetCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, pkr.GetPasskeyId())
|
||||
require.NotEmpty(t, pkr.GetPublicKeyCredentialCreationOptions())
|
||||
return pkr
|
||||
}
|
||||
|
||||
func passkeyVerify(t *testing.T, userID string, pkr *user.RegisterPasskeyResponse) string {
|
||||
attestationResponse, err := Tester.WebAuthN.CreateAttestationResponse(pkr.GetPublicKeyCredentialCreationOptions())
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = Client.VerifyPasskeyRegistration(CTX, &user.VerifyPasskeyRegistrationRequest{
|
||||
UserId: userID,
|
||||
PasskeyId: pkr.GetPasskeyId(),
|
||||
PublicKeyCredential: attestationResponse,
|
||||
PasskeyName: "nice name",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return pkr.GetPasskeyId()
|
||||
}
|
||||
|
||||
func TestServer_RemovePasskey(t *testing.T) {
|
||||
userIDWithout := Tester.CreateHumanUser(CTX).GetUserId()
|
||||
userIDRegistered, pkrRegistered := userWithPasskeyRegistered(t)
|
||||
userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t)
|
||||
userIDVerifiedPermission, passkeyIDVerifiedPermission := userWithPasskeyVerified(t)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *user.RemovePasskeyRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *user.RemovePasskeyResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "missing user id",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
PasskeyId: "123",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing passkey id",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
UserId: "123",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, registered",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
UserId: userIDRegistered,
|
||||
PasskeyId: pkrRegistered.GetPasskeyId(),
|
||||
},
|
||||
},
|
||||
want: &user.RemovePasskeyResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Tester.Organisation.ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no passkey, error",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
UserId: userIDWithout,
|
||||
PasskeyId: pkrRegistered.GetPasskeyId(),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, verified",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
UserId: userIDVerified,
|
||||
PasskeyId: passkeyIDVerified,
|
||||
},
|
||||
},
|
||||
want: &user.RemovePasskeyResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Tester.Organisation.ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "verified, permission error",
|
||||
args: args{
|
||||
ctx: UserCTX,
|
||||
req: &user.RemovePasskeyRequest{
|
||||
UserId: userIDVerifiedPermission,
|
||||
PasskeyId: passkeyIDVerifiedPermission,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := Client.RemovePasskey(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_ListPasskeys(t *testing.T) {
|
||||
userIDWithout := Tester.CreateHumanUser(CTX).GetUserId()
|
||||
userIDRegistered, _ := userWithPasskeyRegistered(t)
|
||||
userIDVerified, passkeyIDVerified := userWithPasskeyVerified(t)
|
||||
|
||||
userIDMulti, passkeyIDMulti1 := userWithPasskeyVerified(t)
|
||||
passkeyIDMulti2 := passkeyVerify(t, userIDMulti, passkeyRegister(t, userIDMulti))
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *user.ListPasskeysRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *user.ListPasskeysResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list passkeys, no permission",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDVerified,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list passkeys, none",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDWithout,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list passkeys, registered",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDRegistered,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list passkeys, ok",
|
||||
args: args{
|
||||
IamCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDVerified,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{
|
||||
{
|
||||
Id: passkeyIDVerified,
|
||||
State: user.AuthFactorState_AUTH_FACTOR_STATE_READY,
|
||||
Name: "nice name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list idp links, multi, ok",
|
||||
args: args{
|
||||
IamCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDMulti,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 2,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{
|
||||
{
|
||||
Id: passkeyIDMulti1,
|
||||
State: user.AuthFactorState_AUTH_FACTOR_STATE_READY,
|
||||
Name: "nice name",
|
||||
},
|
||||
{
|
||||
Id: passkeyIDMulti2,
|
||||
State: user.AuthFactorState_AUTH_FACTOR_STATE_READY,
|
||||
Name: "nice name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
retryDuration := time.Minute
|
||||
if ctxDeadline, ok := CTX.Deadline(); ok {
|
||||
retryDuration = time.Until(ctxDeadline)
|
||||
}
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, listErr := Client.ListPasskeys(tt.args.ctx, tt.args.req)
|
||||
assertErr := assert.NoError
|
||||
if tt.wantErr {
|
||||
assertErr = assert.Error
|
||||
}
|
||||
assertErr(ttt, listErr)
|
||||
if listErr != nil {
|
||||
return
|
||||
}
|
||||
// always first check length, otherwise its failed anyway
|
||||
assert.Len(ttt, got.Result, len(tt.want.Result))
|
||||
for i := range tt.want.Result {
|
||||
assert.Contains(ttt, got.Result, tt.want.Result[i])
|
||||
}
|
||||
integration.AssertListDetails(t, tt.want, got)
|
||||
}, retryDuration, time.Millisecond*100, "timeout waiting for expected idplinks result")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user