mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-16 12:58:00 +00:00
444 lines
12 KiB
Go
444 lines
12 KiB
Go
|
//go:build integration
|
||
|
|
||
|
package org_test
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"strconv"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"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"
|
||
|
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
|
||
|
"github.com/zitadel/zitadel/pkg/grpc/org/v2"
|
||
|
)
|
||
|
|
||
|
type orgAttr struct {
|
||
|
ID string
|
||
|
Name string
|
||
|
Details *object.Details
|
||
|
}
|
||
|
|
||
|
func TestServer_ListOrganizations(t *testing.T) {
|
||
|
type args struct {
|
||
|
ctx context.Context
|
||
|
req *org.ListOrganizationsRequest
|
||
|
dep func(ctx context.Context, request *org.ListOrganizationsRequest) ([]orgAttr, error)
|
||
|
}
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
args args
|
||
|
want *org.ListOrganizationsResponse
|
||
|
wantErr bool
|
||
|
}{
|
||
|
{
|
||
|
name: "list org by id, ok, multiple",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationIdQuery(Tester.Organisation.ID),
|
||
|
},
|
||
|
},
|
||
|
func(ctx context.Context, request *org.ListOrganizationsRequest) ([]orgAttr, error) {
|
||
|
count := 3
|
||
|
orgs := make([]orgAttr, count)
|
||
|
prefix := fmt.Sprintf("ListOrgs%d", time.Now().UnixNano())
|
||
|
for i := 0; i < count; i++ {
|
||
|
name := prefix + strconv.Itoa(i)
|
||
|
orgResp := Tester.CreateOrganization(ctx, name, fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()))
|
||
|
orgs[i] = orgAttr{
|
||
|
ID: orgResp.GetOrganizationId(),
|
||
|
Name: name,
|
||
|
Details: orgResp.GetDetails(),
|
||
|
}
|
||
|
}
|
||
|
request.Queries = []*org.SearchQuery{
|
||
|
OrganizationNamePrefixQuery(prefix),
|
||
|
}
|
||
|
return orgs, nil
|
||
|
},
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 3,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
},
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
},
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org by id, ok",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationIdQuery(Tester.Organisation.ID),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
Name: Tester.Organisation.Name,
|
||
|
Details: &object.Details{
|
||
|
Sequence: Tester.Organisation.Sequence,
|
||
|
ChangeDate: timestamppb.New(Tester.Organisation.ChangeDate),
|
||
|
ResourceOwner: Tester.Organisation.ResourceOwner,
|
||
|
},
|
||
|
Id: Tester.Organisation.ID,
|
||
|
PrimaryDomain: Tester.Organisation.Domain,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org by name, ok",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationNameQuery(Tester.Organisation.Name),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
Name: Tester.Organisation.Name,
|
||
|
Details: &object.Details{
|
||
|
Sequence: Tester.Organisation.Sequence,
|
||
|
ChangeDate: timestamppb.New(Tester.Organisation.ChangeDate),
|
||
|
ResourceOwner: Tester.Organisation.ResourceOwner,
|
||
|
},
|
||
|
Id: Tester.Organisation.ID,
|
||
|
PrimaryDomain: Tester.Organisation.Domain,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org by domain, ok",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationDomainQuery(Tester.Organisation.Domain),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
Name: Tester.Organisation.Name,
|
||
|
Details: &object.Details{
|
||
|
Sequence: Tester.Organisation.Sequence,
|
||
|
ChangeDate: timestamppb.New(Tester.Organisation.ChangeDate),
|
||
|
ResourceOwner: Tester.Organisation.ResourceOwner,
|
||
|
},
|
||
|
Id: Tester.Organisation.ID,
|
||
|
PrimaryDomain: Tester.Organisation.Domain,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org by inactive state, ok",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{},
|
||
|
},
|
||
|
func(ctx context.Context, request *org.ListOrganizationsRequest) ([]orgAttr, error) {
|
||
|
name := gofakeit.Name()
|
||
|
orgResp := Tester.CreateOrganization(ctx, name, gofakeit.Email())
|
||
|
deactivateOrgResp := Tester.DeactivateOrganization(ctx, orgResp.GetOrganizationId())
|
||
|
request.Queries = []*org.SearchQuery{
|
||
|
OrganizationIdQuery(orgResp.GetOrganizationId()),
|
||
|
OrganizationStateQuery(org.OrganizationState_ORGANIZATION_STATE_INACTIVE),
|
||
|
}
|
||
|
return []orgAttr{{
|
||
|
ID: orgResp.GetOrganizationId(),
|
||
|
Name: name,
|
||
|
Details: &object.Details{
|
||
|
ResourceOwner: deactivateOrgResp.GetDetails().GetResourceOwner(),
|
||
|
Sequence: deactivateOrgResp.GetDetails().GetSequence(),
|
||
|
ChangeDate: deactivateOrgResp.GetDetails().GetChangeDate(),
|
||
|
},
|
||
|
}}, nil
|
||
|
},
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_INACTIVE,
|
||
|
Details: &object.Details{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org by domain, ok, sorted",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationDomainQuery(Tester.Organisation.Domain),
|
||
|
},
|
||
|
SortingColumn: org.OrganizationFieldName_ORGANIZATION_FIELD_NAME_NAME,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 1,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
Name: Tester.Organisation.Name,
|
||
|
Details: &object.Details{
|
||
|
Sequence: Tester.Organisation.Sequence,
|
||
|
ChangeDate: timestamppb.New(Tester.Organisation.ChangeDate),
|
||
|
ResourceOwner: Tester.Organisation.ResourceOwner,
|
||
|
},
|
||
|
Id: Tester.Organisation.ID,
|
||
|
PrimaryDomain: Tester.Organisation.Domain,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org, no result",
|
||
|
args: args{
|
||
|
CTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationDomainQuery("notexisting"),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 0,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 0,
|
||
|
Result: []*org.Organization{},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org, no login",
|
||
|
args: args{
|
||
|
context.Background(),
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationDomainQuery("nopermission"),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
wantErr: true,
|
||
|
},
|
||
|
{
|
||
|
name: "list org, no permission",
|
||
|
args: args{
|
||
|
UserCTX,
|
||
|
&org.ListOrganizationsRequest{},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 0,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 1,
|
||
|
Result: []*org.Organization{},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org, no permission org owner",
|
||
|
args: args{
|
||
|
OwnerCTX,
|
||
|
&org.ListOrganizationsRequest{
|
||
|
Queries: []*org.SearchQuery{
|
||
|
OrganizationDomainQuery("nopermission"),
|
||
|
},
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 0,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 1,
|
||
|
Result: []*org.Organization{},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "list org, org owner",
|
||
|
args: args{
|
||
|
OwnerCTX,
|
||
|
&org.ListOrganizationsRequest{},
|
||
|
nil,
|
||
|
},
|
||
|
want: &org.ListOrganizationsResponse{
|
||
|
Details: &object.ListDetails{
|
||
|
TotalResult: 1,
|
||
|
Timestamp: timestamppb.Now(),
|
||
|
},
|
||
|
SortingColumn: 1,
|
||
|
Result: []*org.Organization{
|
||
|
{
|
||
|
State: org.OrganizationState_ORGANIZATION_STATE_ACTIVE,
|
||
|
Name: Tester.Organisation.Name,
|
||
|
Details: &object.Details{
|
||
|
Sequence: Tester.Organisation.Sequence,
|
||
|
ChangeDate: timestamppb.New(Tester.Organisation.ChangeDate),
|
||
|
ResourceOwner: Tester.Organisation.ResourceOwner,
|
||
|
},
|
||
|
Id: Tester.Organisation.ID,
|
||
|
PrimaryDomain: Tester.Organisation.Domain,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
for _, tt := range tests {
|
||
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
if tt.args.dep != nil {
|
||
|
orgs, err := tt.args.dep(tt.args.ctx, tt.args.req)
|
||
|
require.NoError(t, err)
|
||
|
if len(orgs) > 0 {
|
||
|
for i, org := range orgs {
|
||
|
tt.want.Result[i].Name = org.Name
|
||
|
tt.want.Result[i].Id = org.ID
|
||
|
tt.want.Result[i].Details = org.Details
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
retryDuration := time.Minute
|
||
|
if ctxDeadline, ok := CTX.Deadline(); ok {
|
||
|
retryDuration = time.Until(ctxDeadline)
|
||
|
}
|
||
|
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||
|
got, listErr := Client.ListOrganizations(tt.args.ctx, tt.args.req)
|
||
|
assertErr := assert.NoError
|
||
|
if tt.wantErr {
|
||
|
assertErr = assert.Error
|
||
|
}
|
||
|
assertErr(ttt, listErr)
|
||
|
if listErr != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// totalResult is unrelated to the tests here so gets carried over, can vary from the count of results due to permissions
|
||
|
tt.want.Details.TotalResult = got.Details.TotalResult
|
||
|
// always first check length, otherwise its failed anyway
|
||
|
assert.Len(ttt, got.Result, len(tt.want.Result))
|
||
|
|
||
|
for i := range tt.want.Result {
|
||
|
// domain from result, as it is generated though the create
|
||
|
tt.want.Result[i].PrimaryDomain = got.Result[i].PrimaryDomain
|
||
|
// sequence from result, as it can be with different sequence from create
|
||
|
tt.want.Result[i].Details.Sequence = got.Result[i].Details.Sequence
|
||
|
}
|
||
|
|
||
|
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 user result")
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func OrganizationIdQuery(resourceowner string) *org.SearchQuery {
|
||
|
return &org.SearchQuery{Query: &org.SearchQuery_IdQuery{
|
||
|
IdQuery: &org.OrganizationIDQuery{
|
||
|
Id: resourceowner,
|
||
|
},
|
||
|
}}
|
||
|
}
|
||
|
|
||
|
func OrganizationNameQuery(name string) *org.SearchQuery {
|
||
|
return &org.SearchQuery{Query: &org.SearchQuery_NameQuery{
|
||
|
NameQuery: &org.OrganizationNameQuery{
|
||
|
Name: name,
|
||
|
},
|
||
|
}}
|
||
|
}
|
||
|
|
||
|
func OrganizationNamePrefixQuery(name string) *org.SearchQuery {
|
||
|
return &org.SearchQuery{Query: &org.SearchQuery_NameQuery{
|
||
|
NameQuery: &org.OrganizationNameQuery{
|
||
|
Name: name,
|
||
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_STARTS_WITH,
|
||
|
},
|
||
|
}}
|
||
|
}
|
||
|
|
||
|
func OrganizationDomainQuery(domain string) *org.SearchQuery {
|
||
|
return &org.SearchQuery{Query: &org.SearchQuery_DomainQuery{
|
||
|
DomainQuery: &org.OrganizationDomainQuery{
|
||
|
Domain: domain,
|
||
|
},
|
||
|
}}
|
||
|
}
|
||
|
|
||
|
func OrganizationStateQuery(state org.OrganizationState) *org.SearchQuery {
|
||
|
return &org.SearchQuery{Query: &org.SearchQuery_StateQuery{
|
||
|
StateQuery: &org.OrganizationStateQuery{
|
||
|
State: state,
|
||
|
},
|
||
|
}}
|
||
|
}
|