zitadel/internal/api/grpc/resources/user/v3alpha/user_integration_test.go
Stefan Benz 41ae35f2ef
feat: add schema user create and remove (#8494)
# Which Problems Are Solved

Added functionality that user with a userschema can be created and
removed.

# How the Problems Are Solved

Added logic and moved APIs so that everything is API v3 conform.

# Additional Changes

- move of user and userschema API to resources folder
- changed testing and parameters
- some renaming

# Additional Context

closes #7308

---------

Co-authored-by: Elio Bischof <elio@zitadel.com>
2024-08-28 19:46:45 +00:00

355 lines
9.1 KiB
Go

//go:build integration
package user_test
import (
"context"
"testing"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/require"
"github.com/zitadel/logging"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/zitadel/zitadel/internal/integration"
object "github.com/zitadel/zitadel/pkg/grpc/object/v3alpha"
resource_object "github.com/zitadel/zitadel/pkg/grpc/resources/object/v3alpha"
user "github.com/zitadel/zitadel/pkg/grpc/resources/user/v3alpha"
)
func TestServer_CreateUser(t *testing.T) {
ensureFeatureEnabled(t, IAMOwnerCTX)
schema := []byte(`{
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}`)
schemaResp := Tester.CreateUserSchema(IAMOwnerCTX, schema)
permissionSchema := []byte(`{
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"name": {
"urn:zitadel:schema:permission": {
"owner": "r",
"self": "r"
},
"type": "string"
}
}
}`)
permissionSchemaResp := Tester.CreateUserSchema(IAMOwnerCTX, permissionSchema)
orgResp := Tester.CreateOrganization(IAMOwnerCTX, gofakeit.Name(), gofakeit.Email())
type res struct {
want *resource_object.Details
returnCodeEmail bool
returnCodePhone bool
}
tests := []struct {
name string
ctx context.Context
req *user.CreateUserRequest
res res
wantErr bool
}{
{
name: "user create, no schemaID",
ctx: IAMOwnerCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{Data: unmarshalJSON("{\"name\": \"user\"}")},
},
wantErr: true,
},
{
name: "user create, no context",
ctx: context.Background(),
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: schemaResp.GetDetails().GetId(),
Data: unmarshalJSON("{\"name\": \"user\"}"),
},
},
wantErr: true,
},
{
name: "user create, no permission",
ctx: UserCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: schemaResp.GetDetails().GetId(),
Data: unmarshalJSON("{\"name\": \"user\"}"),
},
},
wantErr: true,
},
{
name: "user create, invalid schema permission, owner",
ctx: IAMOwnerCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: permissionSchemaResp.GetDetails().GetId(),
Data: unmarshalJSON("{\"name\": \"user\"}"),
},
},
wantErr: true,
},
{
name: "user create, no user data",
ctx: IAMOwnerCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: schemaResp.GetDetails().GetId(),
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
},
{
name: "user create, ok",
ctx: IAMOwnerCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: schemaResp.GetDetails().GetId(),
Data: unmarshalJSON("{\"name\": \"user\"}"),
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
},
}, {
name: "user create, full contact, ok",
ctx: IAMOwnerCTX,
req: &user.CreateUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
User: &user.CreateUser{
SchemaId: schemaResp.GetDetails().GetId(),
Data: unmarshalJSON("{\"name\": \"user\"}"),
Contact: &user.SetContact{
Email: &user.SetEmail{
Address: gofakeit.Email(),
Verification: &user.SetEmail_ReturnCode{ReturnCode: &user.ReturnEmailVerificationCode{}},
},
Phone: &user.SetPhone{
Number: gofakeit.Phone(),
Verification: &user.SetPhone_ReturnCode{ReturnCode: &user.ReturnPhoneVerificationCode{}},
},
},
},
},
res: res{
want: &resource_object.Details{
Changed: timestamppb.Now(),
Owner: &object.Owner{
Type: object.OwnerType_OWNER_TYPE_ORG,
Id: orgResp.GetOrganizationId(),
},
},
returnCodePhone: true,
returnCodeEmail: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Tester.Client.UserV3Alpha.CreateUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
integration.AssertResourceDetails(t, tt.res.want, got.Details)
if tt.res.returnCodeEmail {
require.NotNil(t, got.EmailCode)
}
if tt.res.returnCodePhone {
require.NotNil(t, got.PhoneCode)
}
})
}
}
func TestServer_DeleteUser(t *testing.T) {
ensureFeatureEnabled(t, IAMOwnerCTX)
schema := []byte(`{
"$schema": "urn:zitadel:schema:v1",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}`)
schemaResp := Tester.CreateUserSchema(IAMOwnerCTX, schema)
orgResp := Tester.CreateOrganization(IAMOwnerCTX, gofakeit.Name(), gofakeit.Email())
tests := []struct {
name string
ctx context.Context
dep func(ctx context.Context, req *user.DeleteUserRequest) error
req *user.DeleteUserRequest
want *resource_object.Details
wantErr bool
}{
{
name: "user delete, no userID",
ctx: IAMOwnerCTX,
req: &user.DeleteUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
UserId: "",
},
wantErr: true,
},
{
name: "user delete, not existing",
ctx: IAMOwnerCTX,
req: &user.DeleteUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
UserId: "notexisting",
},
wantErr: true,
},
{
name: "user delete, no context",
ctx: context.Background(),
dep: func(ctx context.Context, req *user.DeleteUserRequest) error {
userResp := Tester.CreateSchemaUser(IAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.UserId = userResp.GetDetails().GetId()
return nil
},
req: &user.DeleteUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
{
name: "user delete, no permission",
ctx: UserCTX,
dep: func(ctx context.Context, req *user.DeleteUserRequest) error {
userResp := Tester.CreateSchemaUser(IAMOwnerCTX, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.UserId = userResp.GetDetails().GetId()
return nil
},
req: &user.DeleteUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
wantErr: true,
},
{
name: "user delete, ok",
ctx: IAMOwnerCTX,
dep: func(ctx context.Context, req *user.DeleteUserRequest) error {
userResp := Tester.CreateSchemaUser(ctx, orgResp.GetOrganizationId(), schemaResp.GetDetails().GetId(), []byte("{\"name\": \"user\"}"))
req.UserId = userResp.GetDetails().GetId()
return nil
},
req: &user.DeleteUserRequest{
Organization: &object.Organization{
Property: &object.Organization_OrgId{
OrgId: orgResp.GetOrganizationId(),
},
},
},
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.ctx, tt.req)
require.NoError(t, err)
}
got, err := Tester.Client.UserV3Alpha.DeleteUser(tt.ctx, tt.req)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
integration.AssertResourceDetails(t, tt.want, got.Details)
})
}
}
func unmarshalJSON(data string) *structpb.Struct {
user := new(structpb.Struct)
err := user.UnmarshalJSON([]byte(data))
if err != nil {
logging.OnError(err).Fatal("unmarshalling user json")
}
return user
}