Files
zitadel/internal/api/grpc/instance/v2/converter_test.go

406 lines
11 KiB
Go
Raw Normal View History

package instance
import (
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2025-04-29 10:47:04 +02:00
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/zitadel/cmd/build"
2025-04-29 10:47:04 +02:00
z_oidc "github.com/zitadel/zitadel/internal/api/oidc"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/config/systemdefaults"
2025-04-29 10:47:04 +02:00
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/zerrors"
2025-04-29 10:47:04 +02:00
authn "github.com/zitadel/zitadel/pkg/grpc/authn/v2beta"
filter "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
2025-04-28 17:15:23 +02:00
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
2025-04-29 10:47:04 +02:00
"golang.org/x/text/language"
"google.golang.org/protobuf/types/known/timestamppb"
)
func Test_InstancesToPb(t *testing.T) {
instances := []*query.Instance{
{
ID: "instance1",
Name: "Instance One",
Domains: []*query.InstanceDomain{
{
Domain: "example.com",
IsPrimary: true,
IsGenerated: false,
Sequence: 1,
CreationDate: time.Unix(123, 0),
ChangeDate: time.Unix(124, 0),
InstanceID: "instance1",
},
},
Sequence: 1,
CreationDate: time.Unix(123, 0),
ChangeDate: time.Unix(124, 0),
},
}
want := []*instance.Instance{
{
Id: "instance1",
Name: "Instance One",
Domains: []*instance.Domain{
{
Domain: "example.com",
Primary: true,
Generated: false,
Details: &object.Details{
Sequence: 1,
ChangeDate: &timestamppb.Timestamp{Seconds: 124},
CreationDate: &timestamppb.Timestamp{Seconds: 123},
ResourceOwner: "instance1",
},
},
},
Version: build.Version(),
Details: &object.Details{
Sequence: 1,
ChangeDate: &timestamppb.Timestamp{Seconds: 124},
CreationDate: &timestamppb.Timestamp{Seconds: 123},
ResourceOwner: "instance1",
},
},
}
got := InstancesToPb(instances)
assert.Equal(t, want, got)
}
func Test_ListInstancesRequestToModel(t *testing.T) {
t.Parallel()
searchInstanceByID, err := query.NewInstanceIDsListSearchQuery("instance1", "instance2")
require.Nil(t, err)
tt := []struct {
testName string
inputRequest *instance.ListInstancesRequest
maxQueryLimit uint64
expectedResult *query.InstanceSearchQueries
expectedError error
}{
{
testName: "when query limit exceeds max query limit should return invalid argument error",
maxQueryLimit: 1,
inputRequest: &instance.ListInstancesRequest{
Pagination: &filter.PaginationRequest{Limit: 10, Offset: 0, Asc: true},
SortingColumn: instance.FieldName_FIELD_NAME_ID,
Queries: []*instance.Query{{Query: &instance.Query_IdQuery{IdQuery: &instance.IdsQuery{Ids: []string{"instance1", "instance2"}}}}},
},
expectedError: zerrors.ThrowInvalidArgumentf(errors.New("given: 10, allowed: 1"), "QUERY-4M0fs", "Errors.Query.LimitExceeded"),
},
{
testName: "when valid request should return instance search query model",
inputRequest: &instance.ListInstancesRequest{
Pagination: &filter.PaginationRequest{Limit: 10, Offset: 0, Asc: true},
SortingColumn: instance.FieldName_FIELD_NAME_ID,
Queries: []*instance.Query{{Query: &instance.Query_IdQuery{IdQuery: &instance.IdsQuery{Ids: []string{"instance1", "instance2"}}}}},
},
expectedResult: &query.InstanceSearchQueries{
SearchRequest: query.SearchRequest{
Offset: 0,
Limit: 10,
Asc: true,
SortingColumn: query.InstanceColumnID,
},
Queries: []query.SearchQuery{searchInstanceByID},
},
},
}
for _, tc := range tt {
t.Run(tc.testName, func(t *testing.T) {
t.Parallel()
sysDefaults := systemdefaults.SystemDefaults{MaxQueryLimit: tc.maxQueryLimit}
got, err := ListInstancesRequestToModel(tc.inputRequest, sysDefaults)
assert.Equal(t, tc.expectedError, err)
assert.Equal(t, tc.expectedResult, got)
})
}
}
func Test_fieldNameToInstanceColumn(t *testing.T) {
t.Parallel()
tests := []struct {
name string
fieldName instance.FieldName
want query.Column
}{
{
name: "ID field",
fieldName: instance.FieldName_FIELD_NAME_ID,
want: query.InstanceColumnID,
},
{
name: "Name field",
fieldName: instance.FieldName_FIELD_NAME_NAME,
want: query.InstanceColumnName,
},
{
name: "Creation Date field",
fieldName: instance.FieldName_FIELD_NAME_CREATION_DATE,
want: query.InstanceColumnCreationDate,
},
{
name: "Unknown field",
fieldName: instance.FieldName(99),
want: query.Column{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := fieldNameToInstanceColumn(tt.fieldName)
assert.Equal(t, tt.want, got)
})
}
}
func Test_instanceQueryToModel(t *testing.T) {
t.Parallel()
searchInstanceByID, err := query.NewInstanceIDsListSearchQuery("instance1")
require.Nil(t, err)
searchInstanceByDomain, err := query.NewInstanceDomainsListSearchQuery("example.com")
require.Nil(t, err)
tests := []struct {
name string
searchQuery *instance.Query
want query.SearchQuery
wantErr bool
}{
{
name: "ID Query",
searchQuery: &instance.Query{
Query: &instance.Query_IdQuery{
IdQuery: &instance.IdsQuery{
Ids: []string{"instance1"},
},
},
},
want: searchInstanceByID,
wantErr: false,
},
{
name: "Domain Query",
searchQuery: &instance.Query{
Query: &instance.Query_DomainQuery{
DomainQuery: &instance.DomainsQuery{
Domains: []string{"example.com"},
},
},
},
want: searchInstanceByDomain,
wantErr: false,
},
{
name: "Invalid Query",
searchQuery: &instance.Query{
Query: nil,
},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := instanceQueryToModel(tt.searchQuery)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
}
})
}
}
2025-04-29 10:47:04 +02:00
func Test_CreateInstancePbToSetupInstance(t *testing.T) {
t.Parallel()
nowTS := timestamppb.Now()
tests := []struct {
name string
req *instance.CreateInstanceRequest
defaultInstance command.InstanceSetup
externalDomain string
want *command.InstanceSetup
}{
{
name: "Set instance name, custom domain and organization name",
req: &instance.CreateInstanceRequest{
InstanceName: " TestInstance",
CustomDomain: "test.com ",
FirstOrgName: " org ",
},
defaultInstance: command.InstanceSetup{},
externalDomain: "external.com",
want: &command.InstanceSetup{
InstanceName: "TestInstance",
CustomDomain: "test.com",
Org: command.InstanceOrgSetup{
Name: "org",
},
},
},
{
name: "Set machine user with PAT",
req: &instance.CreateInstanceRequest{
Owner: &instance.CreateInstanceRequest_Machine_{
Machine: &instance.CreateInstanceRequest_Machine{
UserName: "machine-user",
Name: "Machine Name",
PersonalAccessToken: &instance.CreateInstanceRequest_PersonalAccessToken{
ExpirationDate: nowTS,
},
MachineKey: &instance.CreateInstanceRequest_MachineKey{
Type: authn.KeyType(authn.KeyType_KEY_TYPE_JSON),
ExpirationDate: nowTS,
},
},
},
},
defaultInstance: command.InstanceSetup{
Org: command.InstanceOrgSetup{},
},
externalDomain: "external.com",
want: &command.InstanceSetup{
Org: command.InstanceOrgSetup{
Machine: &command.AddMachine{
Machine: &command.Machine{
Username: "machine-user",
Name: "Machine Name",
},
Pat: &command.AddPat{
ExpirationDate: nowTS.AsTime(),
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeProfile, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner},
},
MachineKey: &command.AddMachineKey{
Type: domain.AuthNKeyTypeJSON,
ExpirationDate: nowTS.AsTime(),
},
},
},
},
},
{
name: "Set machine user with default machine PAT",
req: &instance.CreateInstanceRequest{
Owner: &instance.CreateInstanceRequest_Machine_{
Machine: &instance.CreateInstanceRequest_Machine{
UserName: "machine-user",
Name: "Machine Name",
PersonalAccessToken: &instance.CreateInstanceRequest_PersonalAccessToken{},
MachineKey: &instance.CreateInstanceRequest_MachineKey{},
},
},
},
defaultInstance: command.InstanceSetup{
Org: command.InstanceOrgSetup{
Machine: &command.AddMachine{
Pat: &command.AddPat{
ExpirationDate: nowTS.AsTime(),
},
MachineKey: &command.AddMachineKey{
Type: domain.AuthNKeyTypeJSON,
ExpirationDate: nowTS.AsTime(),
},
},
},
},
externalDomain: "external.com",
want: &command.InstanceSetup{
Org: command.InstanceOrgSetup{
Machine: &command.AddMachine{
Machine: &command.Machine{
Username: "machine-user",
Name: "Machine Name",
},
Pat: &command.AddPat{
ExpirationDate: nowTS.AsTime(),
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeProfile, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner},
},
MachineKey: &command.AddMachineKey{
Type: domain.AuthNKeyTypeJSON,
ExpirationDate: nowTS.AsTime(),
},
},
},
},
},
{
name: "Set human user",
req: &instance.CreateInstanceRequest{
Owner: &instance.CreateInstanceRequest_Human_{
Human: &instance.CreateInstanceRequest_Human{
UserName: "human-user ",
Email: &instance.CreateInstanceRequest_Email{
Email: "john.doe@example.com",
},
Profile: &instance.CreateInstanceRequest_Profile{
FirstName: "John ",
LastName: " Doe",
PreferredLanguage: "it ",
},
Password: &instance.CreateInstanceRequest_Password{},
},
},
},
defaultInstance: command.InstanceSetup{
Org: command.InstanceOrgSetup{Human: &command.AddHuman{}},
},
externalDomain: "external.com",
want: &command.InstanceSetup{
Org: command.InstanceOrgSetup{
Human: &command.AddHuman{
Username: "human-user",
FirstName: "John",
LastName: "Doe",
Email: command.Email{
Address: "john.doe@example.com",
},
PreferredLanguage: language.Italian,
},
},
},
},
{
name: "Set default language",
req: &instance.CreateInstanceRequest{
DefaultLanguage: " en ",
},
defaultInstance: command.InstanceSetup{},
externalDomain: "external.com",
want: &command.InstanceSetup{
DefaultLanguage: language.English,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := CreateInstancePbToSetupInstance(tt.req, tt.defaultInstance, tt.externalDomain)
assert.Equal(t, tt.want, got)
})
}
}