zitadel/internal/api/grpc/user/v2beta/phone_integration_test.go
Stefan Benz ce29a78d1b
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>
(cherry picked from commit 7d2d85f57c)
2024-07-29 12:50:41 +02:00

345 lines
8.1 KiB
Go

//go:build integration
package user_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
"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_SetPhone(t *testing.T) {
userID := Tester.CreateHumanUser(CTX).GetUserId()
tests := []struct {
name string
req *user.SetPhoneRequest
want *user.SetPhoneResponse
wantErr bool
}{
{
name: "default verification",
req: &user.SetPhoneRequest{
UserId: userID,
Phone: "+41791234568",
},
want: &user.SetPhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
},
{
name: "send verification",
req: &user.SetPhoneRequest{
UserId: userID,
Phone: "+41791234569",
Verification: &user.SetPhoneRequest_SendCode{
SendCode: &user.SendPhoneVerificationCode{},
},
},
want: &user.SetPhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
},
{
name: "return code",
req: &user.SetPhoneRequest{
UserId: userID,
Phone: "+41791234566",
Verification: &user.SetPhoneRequest_ReturnCode{
ReturnCode: &user.ReturnPhoneVerificationCode{},
},
},
want: &user.SetPhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
VerificationCode: gu.Ptr("xxx"),
},
},
{
name: "is verified true",
req: &user.SetPhoneRequest{
UserId: userID,
Phone: "+41791234565",
Verification: &user.SetPhoneRequest_IsVerified{
IsVerified: true,
},
},
want: &user.SetPhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
},
{
name: "is verified false",
req: &user.SetPhoneRequest{
UserId: userID,
Phone: "+41791234564",
Verification: &user.SetPhoneRequest_IsVerified{
IsVerified: false,
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.SetPhone(CTX, tt.req)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
integration.AssertDetails(t, tt.want, got)
if tt.want.GetVerificationCode() != "" {
assert.NotEmpty(t, got.GetVerificationCode())
}
})
}
}
func TestServer_ResendPhoneCode(t *testing.T) {
userID := Tester.CreateHumanUser(CTX).GetUserId()
verifiedUserID := Tester.CreateHumanUserVerified(CTX, Tester.Organisation.ID, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano())).GetUserId()
tests := []struct {
name string
req *user.ResendPhoneCodeRequest
want *user.ResendPhoneCodeResponse
wantErr bool
}{
{
name: "user not existing",
req: &user.ResendPhoneCodeRequest{
UserId: "xxx",
},
wantErr: true,
},
{
name: "user not existing",
req: &user.ResendPhoneCodeRequest{
UserId: verifiedUserID,
},
wantErr: true,
},
{
name: "resend code",
req: &user.ResendPhoneCodeRequest{
UserId: userID,
Verification: &user.ResendPhoneCodeRequest_SendCode{
SendCode: &user.SendPhoneVerificationCode{},
},
},
want: &user.ResendPhoneCodeResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
},
{
name: "return code",
req: &user.ResendPhoneCodeRequest{
UserId: userID,
Verification: &user.ResendPhoneCodeRequest_ReturnCode{
ReturnCode: &user.ReturnPhoneVerificationCode{},
},
},
want: &user.ResendPhoneCodeResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
VerificationCode: gu.Ptr("xxx"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.ResendPhoneCode(CTX, tt.req)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
integration.AssertDetails(t, tt.want, got)
if tt.want.GetVerificationCode() != "" {
assert.NotEmpty(t, got.GetVerificationCode())
}
})
}
}
func TestServer_VerifyPhone(t *testing.T) {
userResp := Tester.CreateHumanUser(CTX)
tests := []struct {
name string
req *user.VerifyPhoneRequest
want *user.VerifyPhoneResponse
wantErr bool
}{
{
name: "wrong code",
req: &user.VerifyPhoneRequest{
UserId: userResp.GetUserId(),
VerificationCode: "xxx",
},
wantErr: true,
},
{
name: "wrong user",
req: &user.VerifyPhoneRequest{
UserId: "xxx",
VerificationCode: userResp.GetPhoneCode(),
},
wantErr: true,
},
{
name: "verify user",
req: &user.VerifyPhoneRequest{
UserId: userResp.GetUserId(),
VerificationCode: userResp.GetPhoneCode(),
},
want: &user.VerifyPhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Client.VerifyPhone(CTX, tt.req)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
integration.AssertDetails(t, tt.want, got)
})
}
}
func TestServer_RemovePhone(t *testing.T) {
userResp := Tester.CreateHumanUser(CTX)
failResp := Tester.CreateHumanUserNoPhone(CTX)
otherUser := Tester.CreateHumanUser(CTX).GetUserId()
doubleRemoveUser := Tester.CreateHumanUser(CTX)
Tester.RegisterUserPasskey(CTX, otherUser)
_, sessionTokenOtherUser, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, otherUser)
tests := []struct {
name string
ctx context.Context
req *user.RemovePhoneRequest
want *user.RemovePhoneResponse
wantErr bool
dep func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error)
}{
{
name: "remove phone",
ctx: CTX,
req: &user.RemovePhoneRequest{
UserId: userResp.GetUserId(),
},
want: &user.RemovePhoneResponse{
Details: &object.Details{
Sequence: 1,
ChangeDate: timestamppb.Now(),
ResourceOwner: Tester.Organisation.ID,
},
},
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
return nil, nil
},
},
{
name: "user without phone",
ctx: CTX,
req: &user.RemovePhoneRequest{
UserId: failResp.GetUserId(),
},
wantErr: true,
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
return nil, nil
},
},
{
name: "remove previously deleted phone",
ctx: CTX,
req: &user.RemovePhoneRequest{
UserId: doubleRemoveUser.GetUserId(),
},
wantErr: true,
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
return Client.RemovePhone(ctx, &user.RemovePhoneRequest{
UserId: doubleRemoveUser.GetUserId(),
})
},
},
{
name: "no user id",
ctx: CTX,
req: &user.RemovePhoneRequest{},
wantErr: true,
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
return nil, nil
},
},
{
name: "other user, no permission",
ctx: Tester.WithAuthorizationToken(CTX, sessionTokenOtherUser),
req: &user.RemovePhoneRequest{
UserId: userResp.GetUserId(),
},
wantErr: true,
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
return nil, nil
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, depErr := tt.dep(tt.ctx, tt.req.UserId)
require.NoError(t, depErr)
got, err := Client.RemovePhone(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
integration.AssertDetails(t, tt.want, got)
})
}
}