mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
feat(domain): Instance APIs with relational tables (#10953)
# Which Problems Are Solved This PR implements the endpoints listed in https://github.com/zitadel/zitadel/issues/10443 . # How the Problems Are Solved The implementation follows the same pattern as the Organization one. There are no peculiarities to this PR. The `Update`, `Delete` are implementing the `Commander` interface, while `Get` and `List` instance(s) endpoints are implementing the `Querier` interace. # Additional Context - Closes #10443 - Depends on #10445
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/cmd/build"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
/*
|
||||
* Domain Model to GRPC v2
|
||||
*/
|
||||
|
||||
func DomainInstanceListModelToGRPCResponse(instances []*domain.Instance) []*instance.Instance {
|
||||
toReturn := make([]*instance.Instance, len(instances))
|
||||
|
||||
for i, inst := range instances {
|
||||
toReturn[i] = DomainInstanceModelToGRPCResponse(inst)
|
||||
}
|
||||
|
||||
return toReturn
|
||||
}
|
||||
|
||||
func DomainInstanceModelToGRPCResponse(inst *domain.Instance) *instance.Instance {
|
||||
return &instance.Instance{
|
||||
Id: inst.ID,
|
||||
ChangeDate: timestamppb.New(inst.UpdatedAt),
|
||||
CreationDate: timestamppb.New(inst.CreatedAt),
|
||||
State: instance.State_STATE_RUNNING, // TODO(IAM-Marco): Not sure what to put here
|
||||
Name: inst.Name,
|
||||
Version: build.Version(),
|
||||
Domains: domainInstanceDomainListModelToGRPCResponse(inst.Domains),
|
||||
}
|
||||
}
|
||||
|
||||
func domainInstanceDomainListModelToGRPCResponse(dms []*domain.InstanceDomain) []*instance.Domain {
|
||||
toReturn := make([]*instance.Domain, len(dms))
|
||||
for i, domain := range dms {
|
||||
isGenerated := domain.IsGenerated != nil && *domain.IsGenerated
|
||||
isPrimary := domain.IsPrimary != nil && *domain.IsPrimary
|
||||
toReturn[i] = &instance.Domain{
|
||||
InstanceId: domain.InstanceID,
|
||||
CreationDate: timestamppb.New(domain.CreatedAt),
|
||||
Domain: domain.Domain,
|
||||
Primary: isPrimary,
|
||||
Generated: isGenerated,
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
func TestDomainInstanceModelToGRPCResponse(t *testing.T) {
|
||||
// Given
|
||||
t.Parallel()
|
||||
|
||||
now := time.Now().UTC()
|
||||
yesterday := now.AddDate(0, 0, -1)
|
||||
|
||||
inputInstance := &domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "Instance One",
|
||||
CreatedAt: yesterday,
|
||||
UpdatedAt: now,
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{
|
||||
InstanceID: "instance-1",
|
||||
Domain: "d1.example.com",
|
||||
IsPrimary: gu.Ptr(true),
|
||||
CreatedAt: yesterday,
|
||||
},
|
||||
{
|
||||
InstanceID: "instance-1",
|
||||
Domain: "d2.example.com",
|
||||
IsGenerated: gu.Ptr(true),
|
||||
CreatedAt: yesterday,
|
||||
},
|
||||
{
|
||||
InstanceID: "instance-1",
|
||||
Domain: "d3.example.com",
|
||||
IsPrimary: gu.Ptr(true),
|
||||
IsGenerated: gu.Ptr(false),
|
||||
CreatedAt: yesterday,
|
||||
},
|
||||
{
|
||||
InstanceID: "instance-1",
|
||||
Domain: "d4.example.com",
|
||||
IsPrimary: gu.Ptr(false),
|
||||
IsGenerated: gu.Ptr(true),
|
||||
CreatedAt: yesterday,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedInstance := &instance.Instance{
|
||||
Id: "instance-1",
|
||||
ChangeDate: timestamppb.New(now),
|
||||
CreationDate: timestamppb.New(yesterday),
|
||||
State: instance.State_STATE_RUNNING,
|
||||
Name: "Instance One",
|
||||
Version: "",
|
||||
Domains: []*instance.Domain{
|
||||
{
|
||||
InstanceId: "instance-1",
|
||||
CreationDate: timestamppb.New(yesterday),
|
||||
Domain: "d1.example.com",
|
||||
Primary: true,
|
||||
Generated: false,
|
||||
},
|
||||
{
|
||||
InstanceId: "instance-1",
|
||||
CreationDate: timestamppb.New(yesterday),
|
||||
Domain: "d2.example.com",
|
||||
Primary: false,
|
||||
Generated: true,
|
||||
},
|
||||
{
|
||||
InstanceId: "instance-1",
|
||||
CreationDate: timestamppb.New(yesterday),
|
||||
Domain: "d3.example.com",
|
||||
Primary: true,
|
||||
Generated: false,
|
||||
},
|
||||
{
|
||||
InstanceId: "instance-1",
|
||||
CreationDate: timestamppb.New(yesterday),
|
||||
Domain: "d4.example.com",
|
||||
Primary: false,
|
||||
Generated: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Test
|
||||
res := DomainInstanceModelToGRPCResponse(inputInstance)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, expectedInstance, res)
|
||||
}
|
||||
|
||||
func TestDomainInstanceListModelToGRPCResponse(t *testing.T) {
|
||||
t.Parallel()
|
||||
now := time.Now()
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputResult []*domain.Instance
|
||||
expectedResult []*instance.Instance
|
||||
}{
|
||||
{
|
||||
testName: "empty result",
|
||||
inputResult: []*domain.Instance{},
|
||||
expectedResult: []*instance.Instance{},
|
||||
},
|
||||
{
|
||||
testName: "single instance without domains",
|
||||
inputResult: []*domain.Instance{
|
||||
{
|
||||
ID: "instance1",
|
||||
Name: "test-instance",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Domains: nil,
|
||||
},
|
||||
},
|
||||
expectedResult: []*instance.Instance{
|
||||
{
|
||||
Id: "instance1",
|
||||
Name: "test-instance",
|
||||
CreationDate: timestamppb.New(now),
|
||||
ChangeDate: timestamppb.New(now),
|
||||
State: instance.State_STATE_RUNNING,
|
||||
Domains: []*instance.Domain{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "multiple instances with domains",
|
||||
inputResult: []*domain.Instance{
|
||||
{
|
||||
ID: "instance1",
|
||||
Name: "test-instance-1",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{
|
||||
InstanceID: "instance1",
|
||||
Domain: "domain1.com",
|
||||
CreatedAt: now,
|
||||
IsPrimary: gu.Ptr(true),
|
||||
IsGenerated: gu.Ptr(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "instance2",
|
||||
Name: "test-instance-2",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
Domains: nil,
|
||||
},
|
||||
},
|
||||
expectedResult: []*instance.Instance{
|
||||
{
|
||||
Id: "instance1",
|
||||
Name: "test-instance-1",
|
||||
CreationDate: timestamppb.New(now),
|
||||
ChangeDate: timestamppb.New(now),
|
||||
State: instance.State_STATE_RUNNING,
|
||||
Domains: []*instance.Domain{
|
||||
{
|
||||
InstanceId: "instance1",
|
||||
Domain: "domain1.com",
|
||||
CreationDate: timestamppb.New(now),
|
||||
Primary: true,
|
||||
Generated: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: "instance2",
|
||||
Name: "test-instance-2",
|
||||
CreationDate: timestamppb.New(now),
|
||||
ChangeDate: timestamppb.New(now),
|
||||
State: instance.State_STATE_RUNNING,
|
||||
Domains: []*instance.Domain{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Test
|
||||
result := DomainInstanceListModelToGRPCResponse(tc.inputResult)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package instancev2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/api/instance/v2/convert"
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
filter "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
func DeleteInstance(ctx context.Context, request *connect.Request[instance.DeleteInstanceRequest]) (*connect.Response[instance.DeleteInstanceResponse], error) {
|
||||
instanceDeleteCmd := domain.NewDeleteInstanceCommand(request.Msg.GetInstanceId())
|
||||
|
||||
err := domain.Invoke(ctx, instanceDeleteCmd, domain.WithInstanceRepo(repository.InstanceRepository()))
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, &database.NoRowFoundError{}) {
|
||||
return nil, zerrors.ThrowNotFound(err, "INST-QVrUwc", "instance not found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &connect.Response[instance.DeleteInstanceResponse]{
|
||||
Msg: &instance.DeleteInstanceResponse{
|
||||
// TODO(IAM-Marco): Change this with the real update date when OrganizationRepo.Update()
|
||||
// returns the timestamp
|
||||
DeletionDate: timestamppb.Now(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetInstance(ctx context.Context, request *connect.Request[instance.GetInstanceRequest]) (*connect.Response[instance.GetInstanceResponse], error) {
|
||||
instanceGetCmd := domain.NewGetInstanceCommand(request.Msg.GetInstanceId())
|
||||
|
||||
err := domain.Invoke(ctx, instanceGetCmd, domain.WithInstanceRepo(repository.InstanceRepository()))
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, &database.NoRowFoundError{}) {
|
||||
return nil, zerrors.ThrowNotFound(err, "INST-QVrUwc", "instance not found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &connect.Response[instance.GetInstanceResponse]{
|
||||
Msg: &instance.GetInstanceResponse{
|
||||
Instance: convert.DomainInstanceModelToGRPCResponse(instanceGetCmd.Result()),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func UpdateInstance(ctx context.Context, request *connect.Request[instance.UpdateInstanceRequest]) (*connect.Response[instance.UpdateInstanceResponse], error) {
|
||||
instanceUpdateCmd := domain.NewUpdateInstanceCommand(request.Msg.GetInstanceId(), request.Msg.GetInstanceName())
|
||||
|
||||
err := domain.Invoke(ctx, instanceUpdateCmd, domain.WithInstanceRepo(repository.InstanceRepository()))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &connect.Response[instance.UpdateInstanceResponse]{
|
||||
Msg: &instance.UpdateInstanceResponse{
|
||||
// TODO(IAM-Marco): Change this with the real update date when InstanceRepo.Update()
|
||||
// returns the timestamp
|
||||
ChangeDate: timestamppb.Now(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ListInstances(ctx context.Context, request *connect.Request[instance.ListInstancesRequest]) (*connect.Response[instance.ListInstancesResponse], error) {
|
||||
instancesListCmd := domain.NewListInstancesCommand(request.Msg)
|
||||
|
||||
err := domain.Invoke(
|
||||
ctx,
|
||||
instancesListCmd,
|
||||
domain.WithInstanceRepo(repository.InstanceRepository()),
|
||||
domain.WithInstanceDomainRepo(repository.InstanceDomainRepository()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instances := instancesListCmd.Result()
|
||||
return &connect.Response[instance.ListInstancesResponse]{
|
||||
Msg: &instance.ListInstancesResponse{
|
||||
Instances: convert.DomainInstanceListModelToGRPCResponse(instances),
|
||||
Pagination: &filter.PaginationResponse{
|
||||
// TODO(IAM-Marco): return correct value. Tracked in https://github.com/zitadel/zitadel/issues/10955
|
||||
TotalResult: uint64(len(instances)),
|
||||
AppliedLimit: uint64(request.Msg.GetPagination().GetLimit()),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package v2
|
||||
|
||||
// this file has been commented out to pass the linter
|
||||
|
||||
// import (
|
||||
// "github.com/zitadel/zitadel/backend/v3/telemetry/logging"
|
||||
// "github.com/zitadel/zitadel/backend/v3/telemetry/tracing"
|
||||
// )
|
||||
|
||||
// var (
|
||||
// logger logging.Logger
|
||||
// tracer tracing.Tracer
|
||||
// )
|
||||
|
||||
// func SetLogger(l logging.Logger) {
|
||||
// logger = l
|
||||
// }
|
||||
|
||||
// func SetTracer(t tracing.Tracer) {
|
||||
// tracer = t
|
||||
// }
|
||||
@@ -1,21 +0,0 @@
|
||||
package orgv2
|
||||
|
||||
// this file has been commented out to pass the linter
|
||||
|
||||
// import (
|
||||
// "github.com/zitadel/zitadel/backend/v3/telemetry/logging"
|
||||
// "github.com/zitadel/zitadel/backend/v3/telemetry/tracing"
|
||||
// )
|
||||
|
||||
// var (
|
||||
// logger logging.Logger
|
||||
// tracer tracing.Tracer
|
||||
// )
|
||||
|
||||
// func SetLogger(l logging.Logger) {
|
||||
// logger = l
|
||||
// }
|
||||
|
||||
// func SetTracer(t tracing.Tracer) {
|
||||
// tracer = t
|
||||
// }
|
||||
@@ -94,6 +94,8 @@ type instanceChanges interface {
|
||||
}
|
||||
|
||||
// InstanceRepository is the interface for the instance repository.
|
||||
//
|
||||
//go:generate mockgen -typed -package domainmock -destination ./mock/instance.mock.go . InstanceRepository
|
||||
type InstanceRepository interface {
|
||||
Repository
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/milestone"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type DeleteInstanceCommand struct {
|
||||
ID string `json:"id"`
|
||||
|
||||
// InstanceDomains is public for testing purposes
|
||||
// do not use this field
|
||||
InstanceDomains []string
|
||||
// InstanceName is public for testing purposes
|
||||
// do not use this field
|
||||
InstanceName string
|
||||
}
|
||||
|
||||
// RequiresTransaction implements [Transactional].
|
||||
func (d *DeleteInstanceCommand) RequiresTransaction() {}
|
||||
|
||||
func NewDeleteInstanceCommand(instanceID string) *DeleteInstanceCommand {
|
||||
return &DeleteInstanceCommand{ID: instanceID}
|
||||
}
|
||||
|
||||
// Events implements [Commander].
|
||||
func (d *DeleteInstanceCommand) Events(ctx context.Context, opts *InvokeOpts) ([]eventstore.Command, error) {
|
||||
milestoneAggregate := milestone.NewInstanceAggregate(d.ID)
|
||||
instanceAggregate := instance.NewAggregate(d.ID)
|
||||
|
||||
return []eventstore.Command{
|
||||
instance.NewInstanceRemovedEvent(ctx, &instanceAggregate.Aggregate, d.InstanceName, d.InstanceDomains),
|
||||
milestone.NewReachedEvent(ctx, milestoneAggregate, milestone.InstanceDeleted),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Execute implements [Commander].
|
||||
func (d *DeleteInstanceCommand) Execute(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
instanceRepo := opts.instanceRepo.LoadDomains()
|
||||
|
||||
instanceToDelete, err := instanceRepo.Get(ctx, opts.DB(), database.WithCondition(instanceRepo.IDCondition(d.ID)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.InstanceDomains = make([]string, len(instanceToDelete.Domains))
|
||||
for i, domain := range instanceToDelete.Domains {
|
||||
d.InstanceDomains[i] = domain.Domain
|
||||
}
|
||||
|
||||
d.InstanceName = instanceToDelete.Name
|
||||
|
||||
deletedRows, err := instanceRepo.Delete(ctx, opts.DB(), instanceToDelete.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if deletedRows > 1 {
|
||||
err = zerrors.ThrowInternalf(nil, "DOM-Od04Jx", "expecting 1 row deleted, got %d", deletedRows)
|
||||
return err
|
||||
}
|
||||
|
||||
if deletedRows < 1 {
|
||||
err = zerrors.ThrowNotFound(nil, "DOM-daglwD", "instance not found")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// String implements [Commander].
|
||||
func (d *DeleteInstanceCommand) String() string {
|
||||
return "DeleteInstanceCommand"
|
||||
}
|
||||
|
||||
// Validate implements [Commander].
|
||||
func (d *DeleteInstanceCommand) Validate(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
if d.ID = strings.TrimSpace(d.ID); d.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-VpQ9lF", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
if authZErr := opts.Permissions.CheckInstancePermission(ctx, InstanceWritePermission); authZErr != nil {
|
||||
return zerrors.ThrowPermissionDenied(authZErr, "DOM-Yz8f1X", "permission denied")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ Commander = (*DeleteInstanceCommand)(nil)
|
||||
_ Transactional = (*DeleteInstanceCommand)(nil)
|
||||
)
|
||||
@@ -0,0 +1,340 @@
|
||||
package domain_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
domainmock "github.com/zitadel/zitadel/backend/v3/domain/mock"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dbmock"
|
||||
noopdb "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/noop"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/milestone"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestDeleteInstanceCommand_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
permissionErr := errors.New("permission error")
|
||||
tt := []struct {
|
||||
name string
|
||||
permissionChecker func(ctrl *gomock.Controller) domain.PermissionChecker
|
||||
inputID string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "empty id",
|
||||
inputID: "",
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-VpQ9lF", "Errors.Invalid.Argument"),
|
||||
},
|
||||
{
|
||||
name: "whitespace id",
|
||||
inputID: " ",
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-VpQ9lF", "Errors.Invalid.Argument"),
|
||||
},
|
||||
{
|
||||
name: "when user is missing permission should return permission denied",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(permissionErr)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
expectedError: zerrors.ThrowPermissionDenied(permissionErr, "DOM-Yz8f1X", "permission denied"),
|
||||
inputID: "instance-1",
|
||||
},
|
||||
{
|
||||
name: "valid id",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
inputID: "instance-1",
|
||||
},
|
||||
}
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
d := &domain.DeleteInstanceCommand{ID: tc.inputID}
|
||||
|
||||
cmdOpts := &domain.InvokeOpts{}
|
||||
if tc.permissionChecker != nil {
|
||||
ctrl := gomock.NewController(t)
|
||||
cmdOpts.Permissions = tc.permissionChecker(ctrl)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := d.Validate(context.Background(), cmdOpts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteInstanceCommand_Events(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
cmd := domain.NewDeleteInstanceCommand("instance-1")
|
||||
expectedEvents := []eventstore.Command{
|
||||
instance.NewInstanceRemovedEvent(context.Background(), &instance.NewAggregate("instance-1").Aggregate, "instance-1", []string{}),
|
||||
milestone.NewReachedEvent(context.Background(), milestone.NewInstanceAggregate("instance-1"), milestone.InstanceDeleted),
|
||||
}
|
||||
|
||||
// Test
|
||||
events, err := cmd.Events(context.Background(), nil)
|
||||
|
||||
// Verify
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, events, len(expectedEvents))
|
||||
assert.IsType(t, &instance.InstanceRemovedEvent{}, events[0])
|
||||
assert.IsType(t, &milestone.ReachedEvent{}, events[1])
|
||||
}
|
||||
|
||||
func TestDeleteInstanceCommand_Execute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := authz.NewMockContext("inst-1", "org-1", gofakeit.UUID())
|
||||
deleteErr := errors.New("delete error")
|
||||
getErr := errors.New("get error")
|
||||
|
||||
tests := []struct {
|
||||
testName string
|
||||
instanceRepo func(ctrl *gomock.Controller) domain.InstanceRepository
|
||||
|
||||
inputInstanceID string
|
||||
|
||||
expectedError error
|
||||
expectedInstanceName string
|
||||
expectedInstanceDomains []string
|
||||
}{
|
||||
{
|
||||
testName: "when retrieving instance fails should return error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(nil, getErr)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedError: getErr,
|
||||
},
|
||||
{
|
||||
testName: "when delete instance fails should return error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Delete(gomock.Any(), gomock.Any(), "instance-1").
|
||||
Times(1).
|
||||
Return(int64(0), deleteErr)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedError: deleteErr,
|
||||
expectedInstanceName: "My instance 1",
|
||||
expectedInstanceDomains: []string{"d1.example.com", "d2.example.com", "d3.example.com"},
|
||||
},
|
||||
{
|
||||
testName: "when more than one row deleted should return internal error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Delete(gomock.Any(), gomock.Any(), "instance-1").
|
||||
Times(1).
|
||||
Return(int64(2), nil)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedError: zerrors.ThrowInternalf(nil, "DOM-Od04Jx", "expecting 1 row deleted, got %d", 2),
|
||||
expectedInstanceName: "My instance 1",
|
||||
expectedInstanceDomains: []string{"d1.example.com", "d2.example.com", "d3.example.com"},
|
||||
},
|
||||
{
|
||||
testName: "when no rows deleted should return not found error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Delete(gomock.Any(), gomock.Any(), "instance-1").
|
||||
Times(1).
|
||||
Return(int64(0), nil)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedError: zerrors.ThrowNotFound(nil, "DOM-daglwD", "instance not found"),
|
||||
expectedInstanceName: "My instance 1",
|
||||
expectedInstanceDomains: []string{"d1.example.com", "d2.example.com", "d3.example.com"},
|
||||
},
|
||||
{
|
||||
testName: "when one row deleted should execute successfully",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Delete(gomock.Any(), gomock.Any(), "instance-1").
|
||||
Times(1).
|
||||
Return(int64(1), nil)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedInstanceName: "My instance 1",
|
||||
expectedInstanceDomains: []string{"d1.example.com", "d2.example.com", "d3.example.com"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
d := domain.NewDeleteInstanceCommand(tc.inputInstanceID)
|
||||
ctrl := gomock.NewController(t)
|
||||
opts := &domain.InvokeOpts{
|
||||
Invoker: domain.NewTransactionInvoker(nil),
|
||||
}
|
||||
domain.WithQueryExecutor(new(noopdb.Pool))(opts)
|
||||
|
||||
if tc.instanceRepo != nil {
|
||||
domain.WithInstanceRepo(tc.instanceRepo(ctrl))(opts)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := d.Execute(ctx, opts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
assert.Equal(t, tc.expectedInstanceName, d.InstanceName)
|
||||
assert.ElementsMatch(t, tc.expectedInstanceDomains, d.InstanceDomains)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@ type instanceDomainChanges interface {
|
||||
SetType(typ DomainType) database.Change
|
||||
}
|
||||
|
||||
//go:generate mockgen -typed -package domainmock -destination ./mock/instance_domain.mock.go . InstanceDomainRepository
|
||||
type InstanceDomainRepository interface {
|
||||
Repository
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type GetInstanceQuery struct {
|
||||
ID string `json:"id"`
|
||||
returnedInstance *Instance
|
||||
}
|
||||
|
||||
// Result implements [Querier].
|
||||
func (g *GetInstanceQuery) Result() *Instance {
|
||||
return g.returnedInstance
|
||||
}
|
||||
|
||||
func NewGetInstanceCommand(instanceID string) *GetInstanceQuery {
|
||||
return &GetInstanceQuery{ID: instanceID}
|
||||
}
|
||||
|
||||
// Execute implements [Executor].
|
||||
func (g *GetInstanceQuery) Execute(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
instanceRepo := opts.instanceRepo.LoadDomains()
|
||||
|
||||
instance, err := instanceRepo.Get(ctx, opts.DB(), database.WithCondition(instanceRepo.IDCondition(g.ID)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.returnedInstance = instance
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements [Executor].
|
||||
func (g *GetInstanceQuery) String() string {
|
||||
return "GetInstanceCommand"
|
||||
}
|
||||
|
||||
// Validate implements [Validator].
|
||||
func (g *GetInstanceQuery) Validate(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
g.ID = strings.TrimSpace(g.ID)
|
||||
if g.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-32a0o2", "invalid instance ID")
|
||||
}
|
||||
if g.ID != authz.GetInstance(ctx).InstanceID() {
|
||||
return zerrors.ThrowPermissionDenied(nil, "DOM-n0SvVB", "input instance ID doesn't match context instance")
|
||||
}
|
||||
|
||||
if authZErr := opts.Permissions.CheckInstancePermission(ctx, InstanceReadPermission); authZErr != nil {
|
||||
return zerrors.ThrowPermissionDenied(authZErr, "DOM-Uq6b00", "permission denied")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Querier[*Instance] = (*GetInstanceQuery)(nil)
|
||||
@@ -0,0 +1,213 @@
|
||||
package domain_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
domainmock "github.com/zitadel/zitadel/backend/v3/domain/mock"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dbmock"
|
||||
noopdb "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/noop"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestGetInstanceCommand_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
permissionErr := errors.New("permission error")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
permissionChecker func(ctrl *gomock.Controller) domain.PermissionChecker
|
||||
inputInstanceID string
|
||||
ctx context.Context
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "empty instance id, error",
|
||||
inputInstanceID: "",
|
||||
ctx: context.Background(),
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-32a0o2", "invalid instance ID"),
|
||||
},
|
||||
{
|
||||
name: "whitespace instance id, error",
|
||||
inputInstanceID: " ",
|
||||
ctx: context.Background(),
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-32a0o2", "invalid instance ID"),
|
||||
},
|
||||
{
|
||||
name: "instance id mismatch, error",
|
||||
inputInstanceID: "instance1",
|
||||
ctx: authz.NewMockContext("instance2", "", ""),
|
||||
expectedError: zerrors.ThrowPermissionDenied(nil, "DOM-n0SvVB", "input instance ID doesn't match context instance"),
|
||||
},
|
||||
{
|
||||
name: "when user is missing permission should return permission denied",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceReadPermission).
|
||||
Times(1).
|
||||
Return(permissionErr)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
inputInstanceID: "instance1",
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
expectedError: zerrors.ThrowPermissionDenied(permissionErr, "DOM-Uq6b00", "permission denied"),
|
||||
},
|
||||
{
|
||||
name: "valid instance id, success",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceReadPermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
inputInstanceID: "instance1",
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
cmd := domain.NewGetInstanceCommand(tt.inputInstanceID)
|
||||
|
||||
cmdOpts := &domain.InvokeOpts{}
|
||||
if tt.permissionChecker != nil {
|
||||
ctrl := gomock.NewController(t)
|
||||
cmdOpts.Permissions = tt.permissionChecker(ctrl)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := cmd.Validate(tt.ctx, cmdOpts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tt.expectedError, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstanceCommand_Execute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := authz.NewMockContext("inst-1", "org-1", gofakeit.UUID())
|
||||
getErr := errors.New("get error")
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
|
||||
instanceRepo func(ctrl *gomock.Controller) domain.InstanceRepository
|
||||
|
||||
inputInstanceID string
|
||||
|
||||
expectedError error
|
||||
expectedInstance *domain.Instance
|
||||
}{
|
||||
{
|
||||
testName: "when retrieving instance fails should return error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(nil, getErr)
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedError: getErr,
|
||||
},
|
||||
{
|
||||
testName: "when retrieving instance succeeds should set instance on struct and return no error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
Get(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
dbmock.QueryOptions(database.WithCondition(
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
)),
|
||||
).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
return instanceRepo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
expectedInstance: &domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "My instance 1",
|
||||
Domains: []*domain.InstanceDomain{
|
||||
{Domain: "d1.example.com"},
|
||||
{Domain: "d2.example.com"},
|
||||
{Domain: "d3.example.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
g := domain.NewGetInstanceCommand(tc.inputInstanceID)
|
||||
ctrl := gomock.NewController(t)
|
||||
opts := &domain.InvokeOpts{
|
||||
Invoker: domain.NewTransactionInvoker(nil),
|
||||
}
|
||||
domain.WithQueryExecutor(new(noopdb.Pool))(opts)
|
||||
|
||||
if tc.instanceRepo != nil {
|
||||
domain.WithInstanceRepo(tc.instanceRepo(ctrl))(opts)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := g.Execute(ctx, opts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
assert.Equal(t, tc.expectedInstance, g.Result())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
type ListInstancesQuery struct {
|
||||
Request *instance.ListInstancesRequest
|
||||
|
||||
toReturn []*Instance
|
||||
}
|
||||
|
||||
// Result implements Querier.
|
||||
func (l *ListInstancesQuery) Result() []*Instance {
|
||||
return l.toReturn
|
||||
}
|
||||
|
||||
var _ Querier[[]*Instance] = (*ListInstancesQuery)(nil)
|
||||
|
||||
func NewListInstancesCommand(inputRequest *instance.ListInstancesRequest) *ListInstancesQuery {
|
||||
return &ListInstancesQuery{
|
||||
Request: inputRequest,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute implements [Querier].
|
||||
func (l *ListInstancesQuery) Execute(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
instanceRepo := opts.instanceRepo.LoadDomains()
|
||||
domainRepo := opts.instanceDomainRepo
|
||||
|
||||
sorting := l.Sorting(instanceRepo)
|
||||
limit, offset := l.Pagination()
|
||||
conds, err := l.conditions(instanceRepo, domainRepo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
instances, err := instanceRepo.List(ctx, opts.DB(), conds, sorting, limit, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.toReturn = instances
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ListInstancesQuery) Pagination() (database.QueryOption, database.QueryOption) {
|
||||
return database.WithLimit(l.Request.GetPagination().GetLimit()),
|
||||
database.WithOffset(uint32(l.Request.GetPagination().GetOffset()))
|
||||
}
|
||||
|
||||
func (l *ListInstancesQuery) conditions(instanceRepo InstanceRepository, domainRepo InstanceDomainRepository) (database.QueryOption, error) {
|
||||
conditions := make([]database.Condition, len(l.Request.GetQueries()))
|
||||
for i, query := range l.Request.GetQueries() {
|
||||
switch assertedType := query.GetQuery().(type) {
|
||||
case *instance.Query_DomainQuery:
|
||||
domainConditions := make([]database.Condition, len(assertedType.DomainQuery.GetDomains()))
|
||||
for j, domain := range assertedType.DomainQuery.GetDomains() {
|
||||
domainConditions[j] = domainRepo.DomainCondition(database.TextOperationEqual, domain)
|
||||
}
|
||||
conditions[i] = instanceRepo.ExistsDomain(
|
||||
database.Or(domainConditions...),
|
||||
)
|
||||
case *instance.Query_IdQuery:
|
||||
idConditions := make([]database.Condition, len(assertedType.IdQuery.GetIds()))
|
||||
for j, id := range assertedType.IdQuery.GetIds() {
|
||||
idConditions[j] = instanceRepo.IDCondition(id)
|
||||
}
|
||||
conditions[i] = database.Or(idConditions...)
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgument(NewUnexpectedQueryTypeError(assertedType), "DOM-AU99kR", "List.Query.Invalid")
|
||||
}
|
||||
}
|
||||
|
||||
return database.WithCondition(database.And(conditions...)), nil
|
||||
}
|
||||
|
||||
func (l *ListInstancesQuery) Sorting(instanceRepo InstanceRepository) database.QueryOption {
|
||||
var sortingCol database.Column
|
||||
|
||||
switch l.Request.GetSortingColumn() {
|
||||
case instance.FieldName_FIELD_NAME_CREATION_DATE:
|
||||
sortingCol = instanceRepo.CreatedAtColumn()
|
||||
case instance.FieldName_FIELD_NAME_ID:
|
||||
sortingCol = instanceRepo.IDColumn()
|
||||
case instance.FieldName_FIELD_NAME_NAME:
|
||||
sortingCol = instanceRepo.NameColumn()
|
||||
case instance.FieldName_FIELD_NAME_UNSPECIFIED:
|
||||
fallthrough
|
||||
default:
|
||||
return func(opts *database.QueryOpts) {}
|
||||
}
|
||||
|
||||
orderDirection := database.OrderDirectionDesc
|
||||
if l.Request.GetPagination().GetAsc() {
|
||||
orderDirection = database.OrderDirectionAsc
|
||||
}
|
||||
|
||||
return database.WithOrderBy(orderDirection, sortingCol)
|
||||
}
|
||||
|
||||
// String implements [Querier].
|
||||
func (l *ListInstancesQuery) String() string {
|
||||
return "ListInstancesCommand"
|
||||
}
|
||||
|
||||
// Validate implements [Querier].
|
||||
func (l *ListInstancesQuery) Validate(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
// TODO(IAM-Marco): This is likely wrong, because it's checking the read permission of
|
||||
// the instance in context. In here, instead we should probably loop through all retrieved
|
||||
// instances and check their permissions.
|
||||
if authZErr := opts.Permissions.CheckInstancePermission(ctx, InstanceReadPermission); authZErr != nil {
|
||||
return zerrors.ThrowPermissionDenied(authZErr, "DOM-cuT6Ws", "permission denied")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
package domain_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
domainmock "github.com/zitadel/zitadel/backend/v3/domain/mock"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dbmock"
|
||||
noopdb "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/noop"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
filter "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
func TestListInstancesCommand_Sorting(t *testing.T) {
|
||||
t.Parallel()
|
||||
tt := []struct {
|
||||
name string
|
||||
request *instance.ListInstancesRequest
|
||||
|
||||
expectedSortingDirection database.OrderDirection
|
||||
expectedOrderBy database.Columns
|
||||
}{
|
||||
{
|
||||
name: "sort by creation date DESC",
|
||||
request: &instance.ListInstancesRequest{
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_CREATION_DATE.Enum(),
|
||||
},
|
||||
|
||||
expectedSortingDirection: database.OrderDirectionDesc,
|
||||
expectedOrderBy: database.Columns{database.NewColumn("instances", "created_at")},
|
||||
},
|
||||
{
|
||||
name: "sort by creation date ASC",
|
||||
request: &instance.ListInstancesRequest{
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_CREATION_DATE.Enum(),
|
||||
Pagination: &filter.PaginationRequest{Asc: true},
|
||||
},
|
||||
|
||||
expectedSortingDirection: database.OrderDirectionAsc,
|
||||
expectedOrderBy: database.Columns{database.NewColumn("instances", "created_at")},
|
||||
},
|
||||
{
|
||||
name: "sort by id DESC",
|
||||
request: &instance.ListInstancesRequest{
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_ID.Enum(),
|
||||
},
|
||||
expectedSortingDirection: database.OrderDirectionDesc,
|
||||
expectedOrderBy: database.Columns{database.NewColumn("instances", "id")},
|
||||
},
|
||||
{
|
||||
name: "sort by id ASC",
|
||||
request: &instance.ListInstancesRequest{
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_ID.Enum(),
|
||||
Pagination: &filter.PaginationRequest{Asc: true},
|
||||
},
|
||||
expectedSortingDirection: database.OrderDirectionAsc,
|
||||
expectedOrderBy: database.Columns{database.NewColumn("instances", "id")},
|
||||
},
|
||||
{
|
||||
name: "unspecified field",
|
||||
request: &instance.ListInstancesRequest{
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_UNSPECIFIED.Enum(),
|
||||
},
|
||||
expectedSortingDirection: database.OrderDirectionAsc,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
mockCtrl := gomock.NewController(t)
|
||||
mockRepo := domainmock.NewInstanceRepo(mockCtrl)
|
||||
|
||||
cmd := domain.NewListInstancesCommand(tc.request)
|
||||
opts := &database.QueryOpts{}
|
||||
|
||||
// Test
|
||||
queryOpt := cmd.Sorting(mockRepo)
|
||||
queryOpt(opts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedOrderBy, opts.OrderBy)
|
||||
assert.Equal(t, tc.expectedSortingDirection, opts.Ordering)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListInstancesCommand_Execute(t *testing.T) {
|
||||
t.Parallel()
|
||||
listErr := errors.New("list mock error")
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
|
||||
repos func(ctrl *gomock.Controller, queryParams ...database.QueryOption) (domain.InstanceRepository, domain.InstanceDomainRepository)
|
||||
|
||||
queryParams []database.QueryOption
|
||||
inputRequest *instance.ListInstancesRequest
|
||||
|
||||
expectedInstances []*domain.Instance
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
testName: "when listing instances fails should return error",
|
||||
repos: func(ctrl *gomock.Controller, _ ...database.QueryOption) (domain.InstanceRepository, domain.InstanceDomainRepository) {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
domainRepo := domainmock.NewInstancesDomainRepo(ctrl)
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
domainExistsORedConditions := instanceRepo.ExistsDomain(
|
||||
database.Or([]database.Condition{
|
||||
domainRepo.DomainCondition(database.TextOperationEqual, "domain1.example.com"),
|
||||
domainRepo.DomainCondition(database.TextOperationEqual, "domain2.example.com"),
|
||||
}...),
|
||||
)
|
||||
|
||||
idConditions := database.Or(
|
||||
[]database.Condition{
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
instanceRepo.IDCondition("instance-2"),
|
||||
}...,
|
||||
)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
List(gomock.Any(), gomock.Any(),
|
||||
dbmock.QueryOptions(
|
||||
database.WithCondition(database.And(
|
||||
idConditions, domainExistsORedConditions,
|
||||
)),
|
||||
),
|
||||
dbmock.QueryOptions(database.WithOrderBy(database.OrderDirectionDesc, instanceRepo.NameColumn())),
|
||||
dbmock.QueryOptions(database.WithLimit(2)),
|
||||
dbmock.QueryOptions(database.WithOffset(1)),
|
||||
).
|
||||
Times(1).
|
||||
Return(nil, listErr)
|
||||
|
||||
return instanceRepo, domainRepo
|
||||
},
|
||||
inputRequest: &instance.ListInstancesRequest{
|
||||
Pagination: &filter.PaginationRequest{Limit: 2, Offset: 1, Asc: false},
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_NAME.Enum(),
|
||||
Queries: []*instance.Query{
|
||||
{Query: &instance.Query_IdQuery{IdQuery: &instance.IdsQuery{
|
||||
Ids: []string{"instance-1", "instance-2"},
|
||||
}}},
|
||||
{Query: &instance.Query_DomainQuery{DomainQuery: &instance.DomainsQuery{
|
||||
Domains: []string{"domain1.example.com", "domain2.example.com"},
|
||||
}}},
|
||||
},
|
||||
},
|
||||
expectedError: listErr,
|
||||
},
|
||||
{
|
||||
testName: "when listing instances succeeds should save into result and return nil",
|
||||
repos: func(ctrl *gomock.Controller, _ ...database.QueryOption) (domain.InstanceRepository, domain.InstanceDomainRepository) {
|
||||
instanceRepo := domainmock.NewInstanceRepo(ctrl)
|
||||
domainRepo := domainmock.NewInstancesDomainRepo(ctrl)
|
||||
instanceRepo.EXPECT().
|
||||
LoadDomains().
|
||||
Times(1).
|
||||
Return(instanceRepo)
|
||||
|
||||
domainExistsORedConditions := instanceRepo.ExistsDomain(
|
||||
database.Or([]database.Condition{
|
||||
domainRepo.DomainCondition(database.TextOperationEqual, "domain1.example.com"),
|
||||
domainRepo.DomainCondition(database.TextOperationEqual, "domain2.example.com"),
|
||||
}...),
|
||||
)
|
||||
|
||||
idConditions := database.Or(
|
||||
[]database.Condition{
|
||||
instanceRepo.IDCondition("instance-1"),
|
||||
instanceRepo.IDCondition("instance-2"),
|
||||
}...,
|
||||
)
|
||||
|
||||
instanceRepo.EXPECT().
|
||||
List(gomock.Any(), gomock.Any(),
|
||||
dbmock.QueryOptions(
|
||||
database.WithCondition(database.And(
|
||||
idConditions, domainExistsORedConditions,
|
||||
)),
|
||||
),
|
||||
dbmock.QueryOptions(database.WithOrderBy(database.OrderDirectionDesc, instanceRepo.NameColumn())),
|
||||
dbmock.QueryOptions(database.WithLimit(2)),
|
||||
dbmock.QueryOptions(database.WithOffset(1)),
|
||||
).
|
||||
Times(1).
|
||||
Return([]*domain.Instance{
|
||||
{
|
||||
ID: "instance-2",
|
||||
Name: "Instance Two",
|
||||
Domains: []*domain.InstanceDomain{{Domain: "domain1.example.com"}},
|
||||
},
|
||||
{
|
||||
ID: "instance-1",
|
||||
Name: "Instance One",
|
||||
Domains: []*domain.InstanceDomain{{Domain: "domain2.example.com"}},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
return instanceRepo, domainRepo
|
||||
},
|
||||
inputRequest: &instance.ListInstancesRequest{
|
||||
Pagination: &filter.PaginationRequest{Limit: 2, Offset: 1, Asc: false},
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_NAME.Enum(),
|
||||
Queries: []*instance.Query{
|
||||
{Query: &instance.Query_IdQuery{IdQuery: &instance.IdsQuery{
|
||||
Ids: []string{"instance-1", "instance-2"},
|
||||
}}},
|
||||
{Query: &instance.Query_DomainQuery{DomainQuery: &instance.DomainsQuery{
|
||||
Domains: []string{"domain1.example.com", "domain2.example.com"},
|
||||
}}},
|
||||
},
|
||||
},
|
||||
expectedInstances: []*domain.Instance{
|
||||
{
|
||||
ID: "instance-2",
|
||||
Name: "Instance Two",
|
||||
Domains: []*domain.InstanceDomain{{Domain: "domain1.example.com"}},
|
||||
},
|
||||
{
|
||||
ID: "instance-1",
|
||||
Name: "Instance One",
|
||||
Domains: []*domain.InstanceDomain{{Domain: "domain2.example.com"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
ctx := authz.NewMockContext("instance-1", "org-1", "")
|
||||
ctrl := gomock.NewController(t)
|
||||
cmd := domain.NewListInstancesCommand(tc.inputRequest)
|
||||
opts := &domain.InvokeOpts{
|
||||
Invoker: domain.NewTransactionInvoker(nil),
|
||||
}
|
||||
domain.WithQueryExecutor(new(noopdb.Pool))(opts)
|
||||
if tc.repos != nil {
|
||||
inst, instDomain := tc.repos(ctrl, tc.queryParams...)
|
||||
domain.WithInstanceRepo(inst)(opts)
|
||||
domain.WithInstanceDomainRepo(instDomain)(opts)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := cmd.Execute(ctx, opts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
assert.ElementsMatch(t, tc.expectedInstances, cmd.Result())
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListInstancesCommand_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
permissionErr := errors.New("permission error")
|
||||
tt := []struct {
|
||||
name string
|
||||
permissionChecker func(ctrl *gomock.Controller) domain.PermissionChecker
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "when user is missing permission should return permission denied",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceReadPermission).
|
||||
Times(1).
|
||||
Return(permissionErr)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
expectedError: zerrors.ThrowPermissionDenied(permissionErr, "DOM-cuT6Ws", "permission denied"),
|
||||
},
|
||||
{
|
||||
name: "when valid permission should return no error",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceReadPermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
l := &domain.ListInstancesQuery{}
|
||||
|
||||
cmdOpts := &domain.InvokeOpts{}
|
||||
if tc.permissionChecker != nil {
|
||||
ctrl := gomock.NewController(t)
|
||||
cmdOpts.Permissions = tc.permissionChecker(ctrl)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := l.Validate(context.Background(), cmdOpts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type UpdateInstanceCommand struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// RequiresTransaction implements [Transactional].
|
||||
func (u *UpdateInstanceCommand) RequiresTransaction() {}
|
||||
|
||||
// Events implements Commander.
|
||||
func (u *UpdateInstanceCommand) Events(ctx context.Context, _ *InvokeOpts) ([]eventstore.Command, error) {
|
||||
return []eventstore.Command{
|
||||
instance.NewInstanceChangedEvent(ctx, &instance.NewAggregate(u.ID).Aggregate, u.Name),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ Commander = (*UpdateInstanceCommand)(nil)
|
||||
_ Transactional = (*UpdateInstanceCommand)(nil)
|
||||
)
|
||||
|
||||
func NewUpdateInstanceCommand(id, name string) *UpdateInstanceCommand {
|
||||
return &UpdateInstanceCommand{
|
||||
ID: id,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute implements [Commander]
|
||||
func (u *UpdateInstanceCommand) Execute(ctx context.Context, opts *InvokeOpts) (err error) {
|
||||
instanceRepo := opts.instanceRepo
|
||||
|
||||
updateCount, err := instanceRepo.Update(
|
||||
ctx,
|
||||
opts.DB(),
|
||||
u.ID,
|
||||
database.NewChange(instanceRepo.NameColumn(), u.Name),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updateCount == 0 {
|
||||
err = zerrors.ThrowNotFound(nil, "DOM-ghfov1", "Errors.Instance.NotFound")
|
||||
return err
|
||||
}
|
||||
if updateCount > 1 {
|
||||
err = zerrors.ThrowInternal(NewMultipleObjectsUpdatedError(1, updateCount), "DOM-HlrNmD", "unexpected number of rows updated")
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// String implements [Commander]
|
||||
func (u *UpdateInstanceCommand) String() string {
|
||||
return "UpdateInstanceCommand"
|
||||
}
|
||||
|
||||
// Validate implements [Commander]
|
||||
func (u *UpdateInstanceCommand) Validate(ctx context.Context, opts *InvokeOpts) error {
|
||||
if u.ID = strings.TrimSpace(u.ID); u.ID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-wSs6kG", "invalid instance ID")
|
||||
}
|
||||
if u.Name = strings.TrimSpace(u.Name); u.Name == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "DOM-FPJcLC", "invalid instance name")
|
||||
}
|
||||
|
||||
if authZErr := opts.Permissions.CheckInstancePermission(ctx, InstanceWritePermission); authZErr != nil {
|
||||
return zerrors.ThrowPermissionDenied(authZErr, "DOM-M5ObLP", "permission denied")
|
||||
}
|
||||
|
||||
instanceRepo := opts.instanceRepo
|
||||
|
||||
instance, err := instanceRepo.Get(ctx, opts.DB(), database.WithCondition(instanceRepo.IDCondition(u.ID)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if instance.Name == u.Name {
|
||||
err = zerrors.ThrowPreconditionFailed(nil, "DOM-5MrT21", "Errors.Instance.NotChanged")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package domain_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||
domainmock "github.com/zitadel/zitadel/backend/v3/domain/mock"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dbmock"
|
||||
noopdb "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/noop"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestUpdateInstanceCommand_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
getErr := errors.New("get error")
|
||||
permissionErr := errors.New("permission error")
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
instanceRepo func(ctrl *gomock.Controller) domain.InstanceRepository
|
||||
permissionChecker func(ctrl *gomock.Controller) domain.PermissionChecker
|
||||
inputInstanceID string
|
||||
inputInstanceName string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
testName: "when no ID should return invalid argument error",
|
||||
inputInstanceID: "",
|
||||
inputInstanceName: "test-name",
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-wSs6kG", "invalid instance ID"),
|
||||
},
|
||||
{
|
||||
testName: "when no name shuld return invalid argument error",
|
||||
inputInstanceID: "test-id",
|
||||
inputInstanceName: "",
|
||||
expectedError: zerrors.ThrowInvalidArgument(nil, "DOM-FPJcLC", "invalid instance name"),
|
||||
},
|
||||
{
|
||||
testName: "when user is missing permission should return permission denied",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(permissionErr)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
inputInstanceName: "test instance update",
|
||||
expectedError: zerrors.ThrowPermissionDenied(permissionErr, "DOM-M5ObLP", "permission denied"),
|
||||
},
|
||||
{
|
||||
testName: "when retrieving instance fails should return error",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Get(gomock.Any(), gomock.Any(), dbmock.QueryOptions(
|
||||
database.WithCondition(
|
||||
repo.IDCondition("instance-1"),
|
||||
),
|
||||
)).
|
||||
Times(1).
|
||||
Return(nil, getErr)
|
||||
return repo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
inputInstanceName: "test instance update",
|
||||
expectedError: getErr,
|
||||
},
|
||||
{
|
||||
testName: "when instance name is not changed should return name not changed error",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Get(gomock.Any(), gomock.Any(), dbmock.QueryOptions(database.WithCondition(
|
||||
repo.IDCondition("instance-1"),
|
||||
))).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "test instance update",
|
||||
}, nil)
|
||||
return repo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
inputInstanceName: "test instance update",
|
||||
expectedError: zerrors.ThrowPreconditionFailed(nil, "DOM-5MrT21", "Errors.Instance.NotChanged"),
|
||||
},
|
||||
{
|
||||
testName: "when instance name is changed should validate successfully and return no error",
|
||||
permissionChecker: func(ctrl *gomock.Controller) domain.PermissionChecker {
|
||||
permChecker := domainmock.NewMockPermissionChecker(ctrl)
|
||||
|
||||
permChecker.EXPECT().
|
||||
CheckInstancePermission(gomock.Any(), domain.InstanceWritePermission).
|
||||
Times(1).
|
||||
Return(nil)
|
||||
|
||||
return permChecker
|
||||
},
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Get(gomock.Any(), gomock.Any(), dbmock.QueryOptions(database.WithCondition(
|
||||
repo.IDCondition("instance-1"),
|
||||
))).
|
||||
Times(1).
|
||||
Return(&domain.Instance{
|
||||
ID: "instance-1",
|
||||
Name: "old instance name",
|
||||
}, nil)
|
||||
return repo
|
||||
},
|
||||
inputInstanceID: "instance-1",
|
||||
inputInstanceName: "test instance update",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
ctx := authz.NewMockContext("instance-1", "", "")
|
||||
ctrl := gomock.NewController(t)
|
||||
cmd := domain.NewUpdateInstanceCommand(tc.inputInstanceID, tc.inputInstanceName)
|
||||
|
||||
opts := &domain.InvokeOpts{
|
||||
Invoker: domain.NewTransactionInvoker(nil),
|
||||
}
|
||||
domain.WithQueryExecutor(new(noopdb.Pool))(opts)
|
||||
if tc.instanceRepo != nil {
|
||||
domain.WithInstanceRepo(tc.instanceRepo(ctrl))(opts)
|
||||
}
|
||||
if tc.permissionChecker != nil {
|
||||
opts.Permissions = tc.permissionChecker(ctrl)
|
||||
}
|
||||
|
||||
err := cmd.Validate(ctx, opts)
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateInstanceCommand_Execute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
updateErr := errors.New("update error")
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
|
||||
instanceRepo func(ctrl *gomock.Controller) domain.InstanceRepository
|
||||
|
||||
inputID string
|
||||
inputName string
|
||||
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
testName: "when instance update fails should return error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Update(gomock.Any(), gomock.Any(),
|
||||
"instance-1",
|
||||
repo.SetName("test instance update"),
|
||||
).
|
||||
Times(1).
|
||||
Return(int64(0), updateErr)
|
||||
return repo
|
||||
},
|
||||
inputID: "instance-1",
|
||||
inputName: "test instance update",
|
||||
expectedError: updateErr,
|
||||
},
|
||||
{
|
||||
testName: "when instance update returns 0 rows updated should return not found error",
|
||||
inputID: "instance-1",
|
||||
inputName: "test instance update",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Update(gomock.Any(), gomock.Any(),
|
||||
"instance-1",
|
||||
repo.SetName("test instance update"),
|
||||
).
|
||||
Times(1).
|
||||
Return(int64(0), nil)
|
||||
return repo
|
||||
},
|
||||
expectedError: zerrors.ThrowNotFound(nil, "DOM-ghfov1", "Errors.Instance.NotFound"),
|
||||
},
|
||||
{
|
||||
testName: "when instance update returns more than 1 row updated should return internal error",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
repo.EXPECT().
|
||||
Update(gomock.Any(), gomock.Any(),
|
||||
"instance-1",
|
||||
repo.SetName("test instance update"),
|
||||
).
|
||||
Times(1).
|
||||
Return(int64(2), nil)
|
||||
return repo
|
||||
},
|
||||
inputID: "instance-1",
|
||||
inputName: "test instance update",
|
||||
expectedError: zerrors.ThrowInternal(domain.NewMultipleObjectsUpdatedError(1, 2), "DOM-HlrNmD", "unexpected number of rows updated"),
|
||||
},
|
||||
{
|
||||
testName: "when instance update returns 1 row updated should return no error and set non-primary verified domain",
|
||||
instanceRepo: func(ctrl *gomock.Controller) domain.InstanceRepository {
|
||||
repo := domainmock.NewInstanceRepo(ctrl)
|
||||
|
||||
repo.EXPECT().
|
||||
Update(gomock.Any(), gomock.Any(),
|
||||
"instance-1",
|
||||
repo.SetName("test instance update"),
|
||||
).
|
||||
Times(1).
|
||||
Return(int64(1), nil)
|
||||
return repo
|
||||
},
|
||||
inputID: "instance-1",
|
||||
inputName: "test instance update",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
ctx := authz.NewMockContext("instance-1", "", "")
|
||||
ctrl := gomock.NewController(t)
|
||||
cmd := domain.NewUpdateInstanceCommand(tc.inputID, tc.inputName)
|
||||
|
||||
opts := &domain.InvokeOpts{
|
||||
Invoker: domain.NewTransactionInvoker(nil),
|
||||
}
|
||||
domain.WithQueryExecutor(new(noopdb.Pool))(opts)
|
||||
if tc.instanceRepo != nil {
|
||||
domain.WithInstanceRepo(tc.instanceRepo(ctrl))(opts)
|
||||
}
|
||||
|
||||
// Test
|
||||
err := cmd.Execute(ctx, opts)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedError, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestUpdateInstanceCommand_Events(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Given
|
||||
ctx := authz.NewMockContext("instance-1", "", "")
|
||||
cmd := domain.NewUpdateInstanceCommand("instance-1", "test-name")
|
||||
|
||||
// Test
|
||||
events, err := cmd.Events(ctx, &domain.InvokeOpts{})
|
||||
|
||||
// Verify
|
||||
assert.NoError(t, err)
|
||||
require.Len(t, events, 1)
|
||||
|
||||
event := events[0].(*instance.InstanceChangedEvent)
|
||||
assert.Equal(t, "instance-1", event.Aggregate().ID)
|
||||
assert.Equal(t, "test-name", event.Name)
|
||||
}
|
||||
@@ -27,6 +27,18 @@ func WithProjectRepo(repo ProjectRepository) InvokeOpt {
|
||||
}
|
||||
}
|
||||
|
||||
func WithInstanceRepo(repo InstanceRepository) InvokeOpt {
|
||||
return func(opts *InvokeOpts) {
|
||||
opts.instanceRepo = repo
|
||||
}
|
||||
}
|
||||
|
||||
func WithInstanceDomainRepo(repo InstanceDomainRepository) InvokeOpt {
|
||||
return func(opts *InvokeOpts) {
|
||||
opts.instanceDomainRepo = repo
|
||||
}
|
||||
}
|
||||
|
||||
// WithQueryExecutor sets the database client to be used by the command.
|
||||
// If not set, the default pool will be used.
|
||||
// This is mainly used for testing.
|
||||
@@ -59,6 +71,8 @@ type InvokeOpts struct {
|
||||
organizationRepo OrganizationRepository
|
||||
organizationDomainRepo OrganizationDomainRepository
|
||||
projectRepo ProjectRepository
|
||||
instanceRepo InstanceRepository
|
||||
instanceDomainRepo InstanceDomainRepository
|
||||
}
|
||||
|
||||
func (o *InvokeOpts) DB() database.QueryExecutor {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,860 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/backend/v3/domain (interfaces: InstanceDomainRepository)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -typed -package domainmock -destination ./mock/instance_domain.mock.go . InstanceDomainRepository
|
||||
//
|
||||
|
||||
// Package domainmock is a generated GoMock package.
|
||||
package domainmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
domain "github.com/zitadel/zitadel/backend/v3/domain"
|
||||
database "github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockInstanceDomainRepository is a mock of InstanceDomainRepository interface.
|
||||
type MockInstanceDomainRepository struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockInstanceDomainRepositoryMockRecorder
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryMockRecorder is the mock recorder for MockInstanceDomainRepository.
|
||||
type MockInstanceDomainRepositoryMockRecorder struct {
|
||||
mock *MockInstanceDomainRepository
|
||||
}
|
||||
|
||||
// NewMockInstanceDomainRepository creates a new mock instance.
|
||||
func NewMockInstanceDomainRepository(ctrl *gomock.Controller) *MockInstanceDomainRepository {
|
||||
mock := &MockInstanceDomainRepository{ctrl: ctrl}
|
||||
mock.recorder = &MockInstanceDomainRepositoryMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockInstanceDomainRepository) EXPECT() *MockInstanceDomainRepositoryMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Add mocks base method.
|
||||
func (m *MockInstanceDomainRepository) Add(arg0 context.Context, arg1 database.QueryExecutor, arg2 *domain.AddInstanceDomain) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Add", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Add indicates an expected call of Add.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) Add(arg0, arg1, arg2 any) *MockInstanceDomainRepositoryAddCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockInstanceDomainRepository)(nil).Add), arg0, arg1, arg2)
|
||||
return &MockInstanceDomainRepositoryAddCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryAddCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryAddCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryAddCall) Return(arg0 error) *MockInstanceDomainRepositoryAddCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryAddCall) Do(f func(context.Context, database.QueryExecutor, *domain.AddInstanceDomain) error) *MockInstanceDomainRepositoryAddCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryAddCall) DoAndReturn(f func(context.Context, database.QueryExecutor, *domain.AddInstanceDomain) error) *MockInstanceDomainRepositoryAddCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// CreatedAtColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) CreatedAtColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreatedAtColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreatedAtColumn indicates an expected call of CreatedAtColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) CreatedAtColumn() *MockInstanceDomainRepositoryCreatedAtColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreatedAtColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).CreatedAtColumn))
|
||||
return &MockInstanceDomainRepositoryCreatedAtColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryCreatedAtColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryCreatedAtColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryCreatedAtColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryCreatedAtColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryCreatedAtColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryCreatedAtColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DomainColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) DomainColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DomainColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DomainColumn indicates an expected call of DomainColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) DomainColumn() *MockInstanceDomainRepositoryDomainColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DomainColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).DomainColumn))
|
||||
return &MockInstanceDomainRepositoryDomainColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryDomainColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryDomainColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryDomainColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryDomainColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryDomainColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryDomainColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryDomainColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryDomainColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DomainCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) DomainCondition(arg0 database.TextOperation, arg1 string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DomainCondition", arg0, arg1)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DomainCondition indicates an expected call of DomainCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) DomainCondition(arg0, arg1 any) *MockInstanceDomainRepositoryDomainConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DomainCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).DomainCondition), arg0, arg1)
|
||||
return &MockInstanceDomainRepositoryDomainConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryDomainConditionCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryDomainConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryDomainConditionCall) Return(arg0 database.Condition) *MockInstanceDomainRepositoryDomainConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryDomainConditionCall) Do(f func(database.TextOperation, string) database.Condition) *MockInstanceDomainRepositoryDomainConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryDomainConditionCall) DoAndReturn(f func(database.TextOperation, string) database.Condition) *MockInstanceDomainRepositoryDomainConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockInstanceDomainRepository) Get(arg0 context.Context, arg1 database.QueryExecutor, arg2 ...database.QueryOption) (*domain.InstanceDomain, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Get", varargs...)
|
||||
ret0, _ := ret[0].(*domain.InstanceDomain)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) Get(arg0, arg1 any, arg2 ...any) *MockInstanceDomainRepositoryGetCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1}, arg2...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInstanceDomainRepository)(nil).Get), varargs...)
|
||||
return &MockInstanceDomainRepositoryGetCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryGetCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryGetCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryGetCall) Return(arg0 *domain.InstanceDomain, arg1 error) *MockInstanceDomainRepositoryGetCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryGetCall) Do(f func(context.Context, database.QueryExecutor, ...database.QueryOption) (*domain.InstanceDomain, error)) *MockInstanceDomainRepositoryGetCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryGetCall) DoAndReturn(f func(context.Context, database.QueryExecutor, ...database.QueryOption) (*domain.InstanceDomain, error)) *MockInstanceDomainRepositoryGetCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) InstanceIDColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDColumn indicates an expected call of InstanceIDColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) InstanceIDColumn() *MockInstanceDomainRepositoryInstanceIDColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).InstanceIDColumn))
|
||||
return &MockInstanceDomainRepositoryInstanceIDColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryInstanceIDColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryInstanceIDColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryInstanceIDColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// InstanceIDCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) InstanceIDCondition(arg0 string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InstanceIDCondition", arg0)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InstanceIDCondition indicates an expected call of InstanceIDCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) InstanceIDCondition(arg0 any) *MockInstanceDomainRepositoryInstanceIDConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIDCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).InstanceIDCondition), arg0)
|
||||
return &MockInstanceDomainRepositoryInstanceIDConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryInstanceIDConditionCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryInstanceIDConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDConditionCall) Return(arg0 database.Condition) *MockInstanceDomainRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDConditionCall) Do(f func(string) database.Condition) *MockInstanceDomainRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryInstanceIDConditionCall) DoAndReturn(f func(string) database.Condition) *MockInstanceDomainRepositoryInstanceIDConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IsGeneratedColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) IsGeneratedColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsGeneratedColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsGeneratedColumn indicates an expected call of IsGeneratedColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) IsGeneratedColumn() *MockInstanceDomainRepositoryIsGeneratedColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsGeneratedColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).IsGeneratedColumn))
|
||||
return &MockInstanceDomainRepositoryIsGeneratedColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryIsGeneratedColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryIsGeneratedColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryIsGeneratedColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryIsGeneratedColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryIsGeneratedColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryIsGeneratedColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryIsGeneratedColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryIsGeneratedColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IsPrimaryColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) IsPrimaryColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsPrimaryColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsPrimaryColumn indicates an expected call of IsPrimaryColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) IsPrimaryColumn() *MockInstanceDomainRepositoryIsPrimaryColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPrimaryColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).IsPrimaryColumn))
|
||||
return &MockInstanceDomainRepositoryIsPrimaryColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryIsPrimaryColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryIsPrimaryColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryIsPrimaryColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryIsPrimaryColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryIsPrimaryColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// IsPrimaryCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) IsPrimaryCondition(arg0 bool) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsPrimaryCondition", arg0)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsPrimaryCondition indicates an expected call of IsPrimaryCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) IsPrimaryCondition(arg0 any) *MockInstanceDomainRepositoryIsPrimaryConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPrimaryCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).IsPrimaryCondition), arg0)
|
||||
return &MockInstanceDomainRepositoryIsPrimaryConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryIsPrimaryConditionCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryIsPrimaryConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryConditionCall) Return(arg0 database.Condition) *MockInstanceDomainRepositoryIsPrimaryConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryConditionCall) Do(f func(bool) database.Condition) *MockInstanceDomainRepositoryIsPrimaryConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryIsPrimaryConditionCall) DoAndReturn(f func(bool) database.Condition) *MockInstanceDomainRepositoryIsPrimaryConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// List mocks base method.
|
||||
func (m *MockInstanceDomainRepository) List(arg0 context.Context, arg1 database.QueryExecutor, arg2 ...database.QueryOption) ([]*domain.InstanceDomain, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "List", varargs...)
|
||||
ret0, _ := ret[0].([]*domain.InstanceDomain)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) List(arg0, arg1 any, arg2 ...any) *MockInstanceDomainRepositoryListCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1}, arg2...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInstanceDomainRepository)(nil).List), varargs...)
|
||||
return &MockInstanceDomainRepositoryListCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryListCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryListCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryListCall) Return(arg0 []*domain.InstanceDomain, arg1 error) *MockInstanceDomainRepositoryListCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryListCall) Do(f func(context.Context, database.QueryExecutor, ...database.QueryOption) ([]*domain.InstanceDomain, error)) *MockInstanceDomainRepositoryListCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryListCall) DoAndReturn(f func(context.Context, database.QueryExecutor, ...database.QueryOption) ([]*domain.InstanceDomain, error)) *MockInstanceDomainRepositoryListCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// PrimaryKeyColumns mocks base method.
|
||||
func (m *MockInstanceDomainRepository) PrimaryKeyColumns() []database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyColumns")
|
||||
ret0, _ := ret[0].([]database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PrimaryKeyColumns indicates an expected call of PrimaryKeyColumns.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) PrimaryKeyColumns() *MockInstanceDomainRepositoryPrimaryKeyColumnsCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyColumns", reflect.TypeOf((*MockInstanceDomainRepository)(nil).PrimaryKeyColumns))
|
||||
return &MockInstanceDomainRepositoryPrimaryKeyColumnsCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryPrimaryKeyColumnsCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryPrimaryKeyColumnsCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyColumnsCall) Return(arg0 []database.Column) *MockInstanceDomainRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyColumnsCall) Do(f func() []database.Column) *MockInstanceDomainRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyColumnsCall) DoAndReturn(f func() []database.Column) *MockInstanceDomainRepositoryPrimaryKeyColumnsCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) PrimaryKeyCondition(arg0 string) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PrimaryKeyCondition", arg0)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PrimaryKeyCondition indicates an expected call of PrimaryKeyCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) PrimaryKeyCondition(arg0 any) *MockInstanceDomainRepositoryPrimaryKeyConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrimaryKeyCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).PrimaryKeyCondition), arg0)
|
||||
return &MockInstanceDomainRepositoryPrimaryKeyConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryPrimaryKeyConditionCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryPrimaryKeyConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyConditionCall) Return(arg0 database.Condition) *MockInstanceDomainRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyConditionCall) Do(f func(string) database.Condition) *MockInstanceDomainRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryPrimaryKeyConditionCall) DoAndReturn(f func(string) database.Condition) *MockInstanceDomainRepositoryPrimaryKeyConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Remove mocks base method.
|
||||
func (m *MockInstanceDomainRepository) Remove(arg0 context.Context, arg1 database.QueryExecutor, arg2 database.Condition) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Remove", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) Remove(arg0, arg1, arg2 any) *MockInstanceDomainRepositoryRemoveCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockInstanceDomainRepository)(nil).Remove), arg0, arg1, arg2)
|
||||
return &MockInstanceDomainRepositoryRemoveCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryRemoveCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryRemoveCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryRemoveCall) Return(arg0 int64, arg1 error) *MockInstanceDomainRepositoryRemoveCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryRemoveCall) Do(f func(context.Context, database.QueryExecutor, database.Condition) (int64, error)) *MockInstanceDomainRepositoryRemoveCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryRemoveCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition) (int64, error)) *MockInstanceDomainRepositoryRemoveCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetPrimary mocks base method.
|
||||
func (m *MockInstanceDomainRepository) SetPrimary() database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetPrimary")
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetPrimary indicates an expected call of SetPrimary.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) SetPrimary() *MockInstanceDomainRepositorySetPrimaryCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPrimary", reflect.TypeOf((*MockInstanceDomainRepository)(nil).SetPrimary))
|
||||
return &MockInstanceDomainRepositorySetPrimaryCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositorySetPrimaryCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositorySetPrimaryCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositorySetPrimaryCall) Return(arg0 database.Change) *MockInstanceDomainRepositorySetPrimaryCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositorySetPrimaryCall) Do(f func() database.Change) *MockInstanceDomainRepositorySetPrimaryCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositorySetPrimaryCall) DoAndReturn(f func() database.Change) *MockInstanceDomainRepositorySetPrimaryCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetType mocks base method.
|
||||
func (m *MockInstanceDomainRepository) SetType(arg0 domain.DomainType) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetType", arg0)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetType indicates an expected call of SetType.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) SetType(arg0 any) *MockInstanceDomainRepositorySetTypeCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetType", reflect.TypeOf((*MockInstanceDomainRepository)(nil).SetType), arg0)
|
||||
return &MockInstanceDomainRepositorySetTypeCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositorySetTypeCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositorySetTypeCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositorySetTypeCall) Return(arg0 database.Change) *MockInstanceDomainRepositorySetTypeCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositorySetTypeCall) Do(f func(domain.DomainType) database.Change) *MockInstanceDomainRepositorySetTypeCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositorySetTypeCall) DoAndReturn(f func(domain.DomainType) database.Change) *MockInstanceDomainRepositorySetTypeCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// SetUpdatedAt mocks base method.
|
||||
func (m *MockInstanceDomainRepository) SetUpdatedAt(arg0 time.Time) database.Change {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetUpdatedAt", arg0)
|
||||
ret0, _ := ret[0].(database.Change)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetUpdatedAt indicates an expected call of SetUpdatedAt.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) SetUpdatedAt(arg0 any) *MockInstanceDomainRepositorySetUpdatedAtCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetUpdatedAt", reflect.TypeOf((*MockInstanceDomainRepository)(nil).SetUpdatedAt), arg0)
|
||||
return &MockInstanceDomainRepositorySetUpdatedAtCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositorySetUpdatedAtCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositorySetUpdatedAtCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositorySetUpdatedAtCall) Return(arg0 database.Change) *MockInstanceDomainRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositorySetUpdatedAtCall) Do(f func(time.Time) database.Change) *MockInstanceDomainRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositorySetUpdatedAtCall) DoAndReturn(f func(time.Time) database.Change) *MockInstanceDomainRepositorySetUpdatedAtCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) TypeColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TypeColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TypeColumn indicates an expected call of TypeColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) TypeColumn() *MockInstanceDomainRepositoryTypeColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TypeColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).TypeColumn))
|
||||
return &MockInstanceDomainRepositoryTypeColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryTypeColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryTypeColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryTypeColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryTypeColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryTypeColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryTypeColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// TypeCondition mocks base method.
|
||||
func (m *MockInstanceDomainRepository) TypeCondition(arg0 domain.DomainType) database.Condition {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TypeCondition", arg0)
|
||||
ret0, _ := ret[0].(database.Condition)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TypeCondition indicates an expected call of TypeCondition.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) TypeCondition(arg0 any) *MockInstanceDomainRepositoryTypeConditionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TypeCondition", reflect.TypeOf((*MockInstanceDomainRepository)(nil).TypeCondition), arg0)
|
||||
return &MockInstanceDomainRepositoryTypeConditionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryTypeConditionCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryTypeConditionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryTypeConditionCall) Return(arg0 database.Condition) *MockInstanceDomainRepositoryTypeConditionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryTypeConditionCall) Do(f func(domain.DomainType) database.Condition) *MockInstanceDomainRepositoryTypeConditionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryTypeConditionCall) DoAndReturn(f func(domain.DomainType) database.Condition) *MockInstanceDomainRepositoryTypeConditionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockInstanceDomainRepository) Update(arg0 context.Context, arg1 database.QueryExecutor, arg2 database.Condition, arg3 ...database.Change) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{arg0, arg1, arg2}
|
||||
for _, a := range arg3 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "Update", varargs...)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) Update(arg0, arg1, arg2 any, arg3 ...any) *MockInstanceDomainRepositoryUpdateCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]any{arg0, arg1, arg2}, arg3...)
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInstanceDomainRepository)(nil).Update), varargs...)
|
||||
return &MockInstanceDomainRepositoryUpdateCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryUpdateCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryUpdateCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryUpdateCall) Return(arg0 int64, arg1 error) *MockInstanceDomainRepositoryUpdateCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryUpdateCall) Do(f func(context.Context, database.QueryExecutor, database.Condition, ...database.Change) (int64, error)) *MockInstanceDomainRepositoryUpdateCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryUpdateCall) DoAndReturn(f func(context.Context, database.QueryExecutor, database.Condition, ...database.Change) (int64, error)) *MockInstanceDomainRepositoryUpdateCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdatedAtColumn mocks base method.
|
||||
func (m *MockInstanceDomainRepository) UpdatedAtColumn() database.Column {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdatedAtColumn")
|
||||
ret0, _ := ret[0].(database.Column)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdatedAtColumn indicates an expected call of UpdatedAtColumn.
|
||||
func (mr *MockInstanceDomainRepositoryMockRecorder) UpdatedAtColumn() *MockInstanceDomainRepositoryUpdatedAtColumnCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatedAtColumn", reflect.TypeOf((*MockInstanceDomainRepository)(nil).UpdatedAtColumn))
|
||||
return &MockInstanceDomainRepositoryUpdatedAtColumnCall{Call: call}
|
||||
}
|
||||
|
||||
// MockInstanceDomainRepositoryUpdatedAtColumnCall wrap *gomock.Call
|
||||
type MockInstanceDomainRepositoryUpdatedAtColumnCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockInstanceDomainRepositoryUpdatedAtColumnCall) Return(arg0 database.Column) *MockInstanceDomainRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockInstanceDomainRepositoryUpdatedAtColumnCall) Do(f func() database.Column) *MockInstanceDomainRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockInstanceDomainRepositoryUpdatedAtColumnCall) DoAndReturn(f func() database.Column) *MockInstanceDomainRepositoryUpdatedAtColumnCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package domainmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
domain "github.com/zitadel/zitadel/backend/v3/domain"
|
||||
database "github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
)
|
||||
|
||||
type InstancesDomainRepo struct {
|
||||
domain.InstanceDomainRepository
|
||||
mock *MockInstanceDomainRepository
|
||||
}
|
||||
|
||||
func NewInstancesDomainRepo(ctrl *gomock.Controller) *InstancesDomainRepo {
|
||||
return &InstancesDomainRepo{
|
||||
mock: NewMockInstanceDomainRepository(ctrl),
|
||||
InstanceDomainRepository: repository.InstanceDomainRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) EXPECT() *MockInstanceDomainRepositoryMockRecorder {
|
||||
return r.mock.EXPECT()
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.InstanceDomain, error) {
|
||||
return r.mock.Get(ctx, client, opts...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.InstanceDomain, error) {
|
||||
return r.mock.List(ctx, client, opts...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) Add(ctx context.Context, client database.QueryExecutor, domain *domain.AddInstanceDomain) error {
|
||||
return r.mock.Add(ctx, client, domain)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error) {
|
||||
return r.mock.Update(ctx, client, condition, changes...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstancesDomainRepo) Remove(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error) {
|
||||
return r.mock.Remove(ctx, client, condition)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package domainmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
domain "github.com/zitadel/zitadel/backend/v3/domain"
|
||||
database "github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||
)
|
||||
|
||||
type InstanceRepo struct {
|
||||
domain.InstanceRepository
|
||||
mock *MockInstanceRepository
|
||||
}
|
||||
|
||||
func NewInstanceRepo(ctrl *gomock.Controller) *InstanceRepo {
|
||||
return &InstanceRepo{
|
||||
mock: NewMockInstanceRepository(ctrl),
|
||||
InstanceRepository: repository.InstanceRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) EXPECT() *MockInstanceRepositoryMockRecorder {
|
||||
return r.mock.EXPECT()
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.Instance, error) {
|
||||
return r.mock.Get(ctx, client, opts...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.Instance, error) {
|
||||
return r.mock.List(ctx, client, opts...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) Create(ctx context.Context, client database.QueryExecutor, instance *domain.Instance) error {
|
||||
return r.mock.Create(ctx, client, instance)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) Update(ctx context.Context, client database.QueryExecutor, instanceID string, changes ...database.Change) (int64, error) {
|
||||
return r.mock.Update(ctx, client, instanceID, changes...)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) Delete(ctx context.Context, client database.QueryExecutor, instanceID string) (int64, error) {
|
||||
return r.mock.Delete(ctx, client, instanceID)
|
||||
|
||||
}
|
||||
|
||||
func (r *InstanceRepo) LoadDomains() domain.InstanceRepository {
|
||||
return r.mock.LoadDomains()
|
||||
}
|
||||
@@ -22,6 +22,10 @@ func NewOrgDomainRepo(ctrl *gomock.Controller) *OrgDomainRepo {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *OrgDomainRepo) EXPECT() *MockOrganizationDomainRepositoryMockRecorder {
|
||||
return r.mock.EXPECT()
|
||||
}
|
||||
|
||||
func (r *OrgDomainRepo) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.OrganizationDomain, error) {
|
||||
return r.mock.Get(ctx, client, opts...)
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/backend/v3/domain (interfaces: PermissionChecker)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -typed -package domainmock -destination ./mock/permission.mock.go . PermissionChecker
|
||||
//
|
||||
|
||||
// Package domainmock is a generated GoMock package.
|
||||
package domainmock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockPermissionChecker is a mock of PermissionChecker interface.
|
||||
type MockPermissionChecker struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPermissionCheckerMockRecorder
|
||||
}
|
||||
|
||||
// MockPermissionCheckerMockRecorder is the mock recorder for MockPermissionChecker.
|
||||
type MockPermissionCheckerMockRecorder struct {
|
||||
mock *MockPermissionChecker
|
||||
}
|
||||
|
||||
// NewMockPermissionChecker creates a new mock instance.
|
||||
func NewMockPermissionChecker(ctrl *gomock.Controller) *MockPermissionChecker {
|
||||
mock := &MockPermissionChecker{ctrl: ctrl}
|
||||
mock.recorder = &MockPermissionCheckerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPermissionChecker) EXPECT() *MockPermissionCheckerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// CheckInstancePermission mocks base method.
|
||||
func (m *MockPermissionChecker) CheckInstancePermission(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CheckInstancePermission", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CheckInstancePermission indicates an expected call of CheckInstancePermission.
|
||||
func (mr *MockPermissionCheckerMockRecorder) CheckInstancePermission(arg0, arg1 any) *MockPermissionCheckerCheckInstancePermissionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckInstancePermission", reflect.TypeOf((*MockPermissionChecker)(nil).CheckInstancePermission), arg0, arg1)
|
||||
return &MockPermissionCheckerCheckInstancePermissionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockPermissionCheckerCheckInstancePermissionCall wrap *gomock.Call
|
||||
type MockPermissionCheckerCheckInstancePermissionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockPermissionCheckerCheckInstancePermissionCall) Return(arg0 error) *MockPermissionCheckerCheckInstancePermissionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockPermissionCheckerCheckInstancePermissionCall) Do(f func(context.Context, string) error) *MockPermissionCheckerCheckInstancePermissionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockPermissionCheckerCheckInstancePermissionCall) DoAndReturn(f func(context.Context, string) error) *MockPermissionCheckerCheckInstancePermissionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// CheckOrganizationPermission mocks base method.
|
||||
func (m *MockPermissionChecker) CheckOrganizationPermission(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CheckOrganizationPermission", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CheckOrganizationPermission indicates an expected call of CheckOrganizationPermission.
|
||||
func (mr *MockPermissionCheckerMockRecorder) CheckOrganizationPermission(arg0, arg1, arg2 any) *MockPermissionCheckerCheckOrganizationPermissionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckOrganizationPermission", reflect.TypeOf((*MockPermissionChecker)(nil).CheckOrganizationPermission), arg0, arg1, arg2)
|
||||
return &MockPermissionCheckerCheckOrganizationPermissionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockPermissionCheckerCheckOrganizationPermissionCall wrap *gomock.Call
|
||||
type MockPermissionCheckerCheckOrganizationPermissionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockPermissionCheckerCheckOrganizationPermissionCall) Return(arg0 error) *MockPermissionCheckerCheckOrganizationPermissionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockPermissionCheckerCheckOrganizationPermissionCall) Do(f func(context.Context, string, string) error) *MockPermissionCheckerCheckOrganizationPermissionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockPermissionCheckerCheckOrganizationPermissionCall) DoAndReturn(f func(context.Context, string, string) error) *MockPermissionCheckerCheckOrganizationPermissionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// CheckProjectGrantPermission mocks base method.
|
||||
func (m *MockPermissionChecker) CheckProjectGrantPermission(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CheckProjectGrantPermission", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CheckProjectGrantPermission indicates an expected call of CheckProjectGrantPermission.
|
||||
func (mr *MockPermissionCheckerMockRecorder) CheckProjectGrantPermission(arg0, arg1, arg2 any) *MockPermissionCheckerCheckProjectGrantPermissionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckProjectGrantPermission", reflect.TypeOf((*MockPermissionChecker)(nil).CheckProjectGrantPermission), arg0, arg1, arg2)
|
||||
return &MockPermissionCheckerCheckProjectGrantPermissionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockPermissionCheckerCheckProjectGrantPermissionCall wrap *gomock.Call
|
||||
type MockPermissionCheckerCheckProjectGrantPermissionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockPermissionCheckerCheckProjectGrantPermissionCall) Return(arg0 error) *MockPermissionCheckerCheckProjectGrantPermissionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockPermissionCheckerCheckProjectGrantPermissionCall) Do(f func(context.Context, string, string) error) *MockPermissionCheckerCheckProjectGrantPermissionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockPermissionCheckerCheckProjectGrantPermissionCall) DoAndReturn(f func(context.Context, string, string) error) *MockPermissionCheckerCheckProjectGrantPermissionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// CheckProjectPermission mocks base method.
|
||||
func (m *MockPermissionChecker) CheckProjectPermission(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CheckProjectPermission", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CheckProjectPermission indicates an expected call of CheckProjectPermission.
|
||||
func (mr *MockPermissionCheckerMockRecorder) CheckProjectPermission(arg0, arg1, arg2 any) *MockPermissionCheckerCheckProjectPermissionCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckProjectPermission", reflect.TypeOf((*MockPermissionChecker)(nil).CheckProjectPermission), arg0, arg1, arg2)
|
||||
return &MockPermissionCheckerCheckProjectPermissionCall{Call: call}
|
||||
}
|
||||
|
||||
// MockPermissionCheckerCheckProjectPermissionCall wrap *gomock.Call
|
||||
type MockPermissionCheckerCheckProjectPermissionCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockPermissionCheckerCheckProjectPermissionCall) Return(arg0 error) *MockPermissionCheckerCheckProjectPermissionCall {
|
||||
c.Call = c.Call.Return(arg0)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockPermissionCheckerCheckProjectPermissionCall) Do(f func(context.Context, string, string) error) *MockPermissionCheckerCheckProjectPermissionCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockPermissionCheckerCheckProjectPermissionCall) DoAndReturn(f func(context.Context, string, string) error) *MockPermissionCheckerCheckProjectPermissionCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
@@ -2,6 +2,13 @@ package domain
|
||||
|
||||
import "context"
|
||||
|
||||
const (
|
||||
InstanceReadPermission = "instance.read"
|
||||
InstanceWritePermission = "instance.write"
|
||||
OrganizationReadPermission = "organization.read"
|
||||
OrganizationWritePermission = "organization.write"
|
||||
)
|
||||
|
||||
// PermissionRepository is the interface that manages and checks Zitadel permissions.
|
||||
//
|
||||
// TODO(muhlemmer): This just defines the checker methods, rest to be done later.
|
||||
@@ -10,6 +17,8 @@ type PermissionRepository interface {
|
||||
}
|
||||
|
||||
// PermissionChecker defines the methods needed to check permissions.
|
||||
//
|
||||
//go:generate mockgen -typed -package domainmock -destination ./mock/permission.mock.go . PermissionChecker
|
||||
type PermissionChecker interface {
|
||||
// Check if the authenticated user has the given permission on instance level.
|
||||
CheckInstancePermission(ctx context.Context, permission string) error
|
||||
|
||||
@@ -6,10 +6,16 @@ import (
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
instancev2 "github.com/zitadel/zitadel/backend/v3/api/instance/v2"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
func (s *Server) DeleteInstance(ctx context.Context, request *connect.Request[instance.DeleteInstanceRequest]) (*connect.Response[instance.DeleteInstanceResponse], error) {
|
||||
if authz.GetFeatures(ctx).EnableRelationalTables {
|
||||
return instancev2.DeleteInstance(ctx, request)
|
||||
}
|
||||
|
||||
obj, err := s.command.RemoveInstance(ctx, request.Msg.GetInstanceId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -22,6 +28,10 @@ func (s *Server) DeleteInstance(ctx context.Context, request *connect.Request[in
|
||||
}
|
||||
|
||||
func (s *Server) UpdateInstance(ctx context.Context, request *connect.Request[instance.UpdateInstanceRequest]) (*connect.Response[instance.UpdateInstanceResponse], error) {
|
||||
if authz.GetFeatures(ctx).EnableRelationalTables {
|
||||
return instancev2.UpdateInstance(ctx, request)
|
||||
}
|
||||
|
||||
obj, err := s.command.UpdateInstance(ctx, request.Msg.GetInstanceName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -4,15 +4,18 @@ package instance_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
@@ -20,66 +23,77 @@ func TestDeleteInstace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Given
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instEventStore := integration.NewInstance(ctxWithSysAuthZ)
|
||||
|
||||
t.Cleanup(func() {
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
instRelational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.DeleteInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedInstanceID string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when invalid input should return invalid argument error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "Instance not found (COMMA-AE3GS)",
|
||||
},
|
||||
{
|
||||
testName: "when delete succeeds should return deletion date",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstanceID: inst.ID(),
|
||||
},
|
||||
instances := []*integration.Instance{
|
||||
instEventStore,
|
||||
instRelational,
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
instRelational.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational.ID()})
|
||||
instEventStore.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instEventStore.ID()})
|
||||
})
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.DeleteInstance(tc.inputContext, tc.inputRequest)
|
||||
for _, inst := range instances {
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.DeleteInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedInstanceID string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when invalid input should return invalid argument error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "not found",
|
||||
},
|
||||
{
|
||||
testName: "when delete succeeds should return deletion date",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstanceID: inst.ID(),
|
||||
},
|
||||
}
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.DeleteInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
require.NotEmpty(t, res.GetDeletionDate())
|
||||
}
|
||||
})
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Contains(t, status.Convert(err).Message(), tc.expectedErrorMsg)
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
require.NotEmpty(t, res.GetDeletionDate())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,72 +106,90 @@ func TestUpdateInstace(t *testing.T) {
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
orgOwnerCtx := inst.WithAuthorization(context.Background(), integration.UserTypeOrgOwner)
|
||||
instEventStore := integration.NewInstance(ctxWithSysAuthZ)
|
||||
orgOwnerESCtx := instEventStore.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
instRelational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
orgOwnerRelationalCtx := instRelational.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
instances := []struct {
|
||||
instance *integration.Instance
|
||||
ctx context.Context
|
||||
}{
|
||||
{instance: instEventStore, ctx: orgOwnerESCtx},
|
||||
{instance: instRelational, ctx: orgOwnerRelationalCtx},
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
instEventStore.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instEventStore.ID()})
|
||||
instRelational.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational.ID()})
|
||||
})
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.UpdateInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedNewName string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: " ",
|
||||
for i, inst := range instances {
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.UpdateInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedNewName string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.instance.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when unauthZ context should return unauthZ error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: " ",
|
||||
{
|
||||
testName: "when unauthZ context should return unauthZ error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.instance.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: inst.ctx,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
},
|
||||
inputContext: orgOwnerCtx,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
},
|
||||
{
|
||||
testName: "when update succeeds should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: "an-updated-name",
|
||||
{
|
||||
testName: "when update succeeds should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.instance.ID(),
|
||||
InstanceName: fmt.Sprintf("an-updated-name %d", i),
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedNewName: fmt.Sprintf("an-updated-name %d", i),
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedNewName: "an-updated-name",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.UpdateInstance(tc.inputContext, tc.inputRequest)
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.instance.Client.InstanceV2Beta.UpdateInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
|
||||
require.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.GetChangeDate())
|
||||
require.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.GetChangeDate())
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.inputContext, time.Minute)
|
||||
require.EventuallyWithT(t, func(tt *assert.CollectT) {
|
||||
retrievedInstance, err := inst.instance.Client.InstanceV2Beta.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: inst.instance.ID()})
|
||||
require.Nil(tt, err)
|
||||
assert.Equal(tt, tc.expectedNewName, retrievedInstance.GetInstance().GetName())
|
||||
}, retryDuration, tick, "timeout waiting for expected execution result")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.inputContext, time.Minute)
|
||||
require.EventuallyWithT(t, func(tt *assert.CollectT) {
|
||||
retrievedInstance, err := inst.Client.InstanceV2Beta.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: inst.ID()})
|
||||
require.Nil(tt, err)
|
||||
assert.Equal(tt, tc.expectedNewName, retrievedInstance.GetInstance().GetName())
|
||||
}, retryDuration, tick, "timeout waiting for expected execution result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,18 @@ package instance_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
|
||||
filter "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
|
||||
@@ -27,43 +29,76 @@ func TestGetInstance(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
orgOwnerCtx := inst.WithAuthorization(context.Background(), integration.UserTypeOrgOwner)
|
||||
instEventStore := integration.NewInstance(ctxWithSysAuthZ)
|
||||
orgOwnerCtxES := instEventStore.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
instRelational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
orgOwnerCtxREL := instRelational.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.GetEnableRelationalTables().GetEnabled())
|
||||
})
|
||||
|
||||
t.Cleanup(func() {
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
instRelational.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational.ID()})
|
||||
instEventStore.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instEventStore.ID()})
|
||||
})
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
instance *integration.Instance
|
||||
inputContext context.Context
|
||||
expectedInstanceID string
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
}{
|
||||
{
|
||||
testName: "when unauthN context should return unauthN error",
|
||||
testName: "eventstore instance - when unauthN context should return unauthN error",
|
||||
inputContext: context.Background(),
|
||||
instance: instEventStore,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when unauthZ context should return unauthZ error",
|
||||
inputContext: orgOwnerCtx,
|
||||
testName: "eventstore instance - when unauthZ context should return unauthZ error",
|
||||
inputContext: orgOwnerCtxES,
|
||||
instance: instEventStore,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
},
|
||||
{
|
||||
testName: "when request succeeds should return matching instance",
|
||||
testName: "eventstore instance - when request succeeds should return matching instance",
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstanceID: inst.ID(),
|
||||
instance: instEventStore,
|
||||
expectedInstanceID: instEventStore.ID(),
|
||||
},
|
||||
|
||||
// Relational
|
||||
{
|
||||
testName: "relational instance - when unauthN context should return unauthN error",
|
||||
inputContext: context.Background(),
|
||||
instance: instRelational,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "relational instance - when unauthZ context should return unauthZ error",
|
||||
inputContext: orgOwnerCtxREL,
|
||||
instance: instRelational,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
},
|
||||
{
|
||||
testName: "relational instance - when request succeeds should return matching instance",
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
instance: instRelational,
|
||||
expectedInstanceID: instRelational.ID(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: inst.ID()})
|
||||
res, err := tc.instance.Client.InstanceV2Beta.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: tc.instance.ID()})
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
@@ -86,26 +121,26 @@ func TestListInstances(t *testing.T) {
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
|
||||
instances := make([]*integration.Instance, 2)
|
||||
instances := make([]*integration.Instance, 5)
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
inst2 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instances[0], instances[1] = inst, inst2
|
||||
inst3 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
inst4 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
inst5 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instances[0], instances[1], instances[2], instances[3], instances[4] = inst, inst2, inst3, inst4, inst5
|
||||
|
||||
t.Cleanup(func() {
|
||||
inst.Client.FeatureV2.ResetInstanceFeatures(ctxWithSysAuthZ, &feature.ResetInstanceFeaturesRequest{})
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2.ID()})
|
||||
inst2.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2.ID()})
|
||||
inst3.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst3.ID()})
|
||||
inst4.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst4.ID()})
|
||||
inst5.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst5.ID()})
|
||||
})
|
||||
|
||||
// Sort in descending order
|
||||
slices.SortFunc(instances, func(i1, i2 *integration.Instance) int {
|
||||
res := i1.Instance.Details.CreationDate.AsTime().Compare(i2.Instance.Details.CreationDate.AsTime())
|
||||
if res == 0 {
|
||||
return res
|
||||
}
|
||||
return -res
|
||||
})
|
||||
orgOwnerCtx := inst.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
orgOwnerCtx := inst.WithAuthorization(context.Background(), integration.UserTypeOrgOwner)
|
||||
relTableState := integration.RelationalTablesEnableMatrix()
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
@@ -136,43 +171,57 @@ func TestListInstances(t *testing.T) {
|
||||
{
|
||||
testName: "when valid request with filter should return paginated response",
|
||||
inputRequest: &instance.ListInstancesRequest{
|
||||
Pagination: &filter.PaginationRequest{Offset: 0, Limit: 10},
|
||||
Pagination: &filter.PaginationRequest{Offset: 1, Limit: 3},
|
||||
SortingColumn: instance.FieldName_FIELD_NAME_CREATION_DATE.Enum(),
|
||||
Queries: []*instance.Query{
|
||||
{
|
||||
Query: &instance.Query_IdQuery{
|
||||
IdQuery: &instance.IdsQuery{
|
||||
Ids: []string{inst.ID(), inst2.ID()},
|
||||
Ids: []string{inst.ID(), inst2.ID(), inst3.ID(), inst4.ID(), inst5.ID()},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Query: &instance.Query_DomainQuery{
|
||||
DomainQuery: &instance.DomainsQuery{
|
||||
Domains: []string{inst4.Domain, inst3.Domain, inst2.Domain, inst.Domain},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstances: []string{inst2.ID(), inst.ID()},
|
||||
expectedInstances: []string{inst3.ID(), inst2.ID(), inst.ID()},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.ListInstances(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
|
||||
require.Len(t, res.GetInstances(), len(tc.expectedInstances))
|
||||
|
||||
for i, ins := range res.GetInstances() {
|
||||
assert.Equal(t, tc.expectedInstances[i], ins.GetId())
|
||||
}
|
||||
}
|
||||
for _, stateCase := range relTableState {
|
||||
integration.EnsureInstanceFeature(t, ctx, inst, stateCase.FeatureSet, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.Equal(tCollect, stateCase.FeatureSet.GetEnableRelationalTables(), got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(fmt.Sprintf("%s - %s", stateCase.State, tc.testName), func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.ListInstances(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
|
||||
require.Len(t, res.GetInstances(), len(tc.expectedInstances))
|
||||
|
||||
for i, ins := range res.GetInstances() {
|
||||
assert.Equal(t, tc.expectedInstances[i], ins.GetId())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestListCustomDomains(t *testing.T) {
|
||||
|
||||
@@ -5,11 +5,17 @@ import (
|
||||
|
||||
"connectrpc.com/connect"
|
||||
|
||||
instancev2 "github.com/zitadel/zitadel/backend/v3/api/instance/v2"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
filter "github.com/zitadel/zitadel/internal/api/grpc/filter/v2beta"
|
||||
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||
)
|
||||
|
||||
func (s *Server) GetInstance(ctx context.Context, _ *connect.Request[instance.GetInstanceRequest]) (*connect.Response[instance.GetInstanceResponse], error) {
|
||||
func (s *Server) GetInstance(ctx context.Context, request *connect.Request[instance.GetInstanceRequest]) (*connect.Response[instance.GetInstanceResponse], error) {
|
||||
if authz.GetFeatures(ctx).EnableRelationalTables {
|
||||
return instancev2.GetInstance(ctx, request)
|
||||
}
|
||||
|
||||
inst, err := s.query.Instance(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -21,6 +27,10 @@ func (s *Server) GetInstance(ctx context.Context, _ *connect.Request[instance.Ge
|
||||
}
|
||||
|
||||
func (s *Server) ListInstances(ctx context.Context, req *connect.Request[instance.ListInstancesRequest]) (*connect.Response[instance.ListInstancesResponse], error) {
|
||||
if authz.GetFeatures(ctx).EnableRelationalTables {
|
||||
return instancev2.ListInstances(ctx, req)
|
||||
}
|
||||
|
||||
queries, err := ListInstancesRequestToModel(req.Msg, s.systemDefaults)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -38,13 +38,13 @@ type RelationalTableFeatureMatrix struct {
|
||||
// TODO(IAM-Marco): Once we have gotten rid of eventstore, this can be removed
|
||||
func RelationalTablesEnableMatrix() []RelationalTableFeatureMatrix {
|
||||
return []RelationalTableFeatureMatrix{
|
||||
{
|
||||
State: "when relational tables are enabled",
|
||||
FeatureSet: &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)},
|
||||
},
|
||||
{
|
||||
State: "when relational tables are disabled",
|
||||
FeatureSet: &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(false)},
|
||||
},
|
||||
{
|
||||
State: "when relational tables are enabled",
|
||||
FeatureSet: &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user