mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 15:49:35 +00:00
instance custom domain event tests done
This commit is contained in:
@@ -13,6 +13,13 @@ const (
|
|||||||
DomainValidationTypeHTTP DomainValidationType = "http"
|
DomainValidationTypeHTTP DomainValidationType = "http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DomainType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DomainTypeCustom DomainType = "custom"
|
||||||
|
DomainTypeTrusted DomainType = "trusted"
|
||||||
|
)
|
||||||
|
|
||||||
type domainColumns interface {
|
type domainColumns interface {
|
||||||
// InstanceIDColumn returns the column for the instance id field.
|
// InstanceIDColumn returns the column for the instance id field.
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
@@ -20,15 +27,9 @@ type domainColumns interface {
|
|||||||
// DomainColumn returns the column for the domain field.
|
// DomainColumn returns the column for the domain field.
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
DomainColumn(qualified bool) database.Column
|
DomainColumn(qualified bool) database.Column
|
||||||
// IsVerifiedColumn returns the column for the is verified field.
|
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
|
||||||
IsVerifiedColumn(qualified bool) database.Column
|
|
||||||
// IsPrimaryColumn returns the column for the is primary field.
|
// IsPrimaryColumn returns the column for the is primary field.
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
IsPrimaryColumn(qualified bool) database.Column
|
IsPrimaryColumn(qualified bool) database.Column
|
||||||
// ValidationTypeColumn returns the column for the verification type field.
|
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
|
||||||
ValidationTypeColumn(qualified bool) database.Column
|
|
||||||
// CreatedAtColumn returns the column for the created at field.
|
// CreatedAtColumn returns the column for the created at field.
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
CreatedAtColumn(qualified bool) database.Column
|
CreatedAtColumn(qualified bool) database.Column
|
||||||
@@ -44,13 +45,9 @@ type domainConditions interface {
|
|||||||
DomainCondition(op database.TextOperation, domain string) database.Condition
|
DomainCondition(op database.TextOperation, domain string) database.Condition
|
||||||
// IsPrimaryCondition returns a filter on the is primary field.
|
// IsPrimaryCondition returns a filter on the is primary field.
|
||||||
IsPrimaryCondition(isPrimary bool) database.Condition
|
IsPrimaryCondition(isPrimary bool) database.Condition
|
||||||
// IsVerifiedCondition returns a filter on the is verified field.
|
|
||||||
IsVerifiedCondition(isVerified bool) database.Condition
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type domainChanges interface {
|
type domainChanges interface {
|
||||||
// SetVerified sets the is verified column to true.
|
|
||||||
SetVerified() database.Change
|
|
||||||
// SetPrimary sets a domain as primary based on the condition.
|
// SetPrimary sets a domain as primary based on the condition.
|
||||||
// All other domains will be set to non-primary.
|
// All other domains will be set to non-primary.
|
||||||
//
|
//
|
||||||
@@ -62,9 +59,6 @@ type domainChanges interface {
|
|||||||
// - The domain is already primary.
|
// - The domain is already primary.
|
||||||
// - No domain matches the condition.
|
// - No domain matches the condition.
|
||||||
SetPrimary() database.Change
|
SetPrimary() database.Change
|
||||||
// SetValidationType sets the verification type column.
|
|
||||||
// If the domain is already verified, this is a no-op.
|
|
||||||
SetValidationType(verificationType DomainValidationType) database.Change
|
|
||||||
// SetUpdatedAt sets the updated at column.
|
// SetUpdatedAt sets the updated at column.
|
||||||
// This is used for reducing events.
|
// This is used for reducing events.
|
||||||
SetUpdatedAt(t time.Time) database.Change
|
SetUpdatedAt(t time.Time) database.Change
|
||||||
|
@@ -10,9 +10,8 @@ import (
|
|||||||
type InstanceDomain struct {
|
type InstanceDomain struct {
|
||||||
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
|
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
|
||||||
Domain string `json:"domain,omitempty" db:"domain"`
|
Domain string `json:"domain,omitempty" db:"domain"`
|
||||||
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
|
|
||||||
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
|
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
|
||||||
ValidationType *DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
|
Type DomainType `json:"type,omitempty" db:"type"`
|
||||||
|
|
||||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
||||||
@@ -21,17 +20,16 @@ type InstanceDomain struct {
|
|||||||
type AddInstanceDomain struct {
|
type AddInstanceDomain struct {
|
||||||
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
|
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
|
||||||
Domain string `json:"domain,omitempty" db:"domain"`
|
Domain string `json:"domain,omitempty" db:"domain"`
|
||||||
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
|
|
||||||
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
|
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
|
||||||
IsGenerated bool `json:"isGenerated,omitempty" db:"is_generated"`
|
IsGenerated bool `json:"isGenerated,omitempty" db:"is_generated"`
|
||||||
ValidationType *DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
|
Type DomainType `json:"type,omitempty" db:"type"`
|
||||||
|
|
||||||
// CreatedAt is the time when the domain was added.
|
// CreatedAt is the time when the domain was added.
|
||||||
// It is set by the repository and should not be set by the caller.
|
// It is set by the repository and should not be set by the caller.
|
||||||
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
|
CreatedAt *time.Time `json:"createdAt,omitzero" db:"created_at"`
|
||||||
// UpdatedAt is the time when the domain was last updated.
|
// UpdatedAt is the time when the domain was last updated.
|
||||||
// It is set by the repository and should not be set by the caller.
|
// It is set by the repository and should not be set by the caller.
|
||||||
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
UpdatedAt *time.Time `json:"updatedAt,omitzero" db:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type instanceDomainColumns interface {
|
type instanceDomainColumns interface {
|
||||||
@@ -39,14 +37,21 @@ type instanceDomainColumns interface {
|
|||||||
// IsGeneratedColumn returns the column for the is generated field.
|
// IsGeneratedColumn returns the column for the is generated field.
|
||||||
// `qualified` indicates if the column should be qualified with the table name.
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
IsGeneratedColumn(qualified bool) database.Column
|
IsGeneratedColumn(qualified bool) database.Column
|
||||||
|
// TypeColumn returns the column for the type field.
|
||||||
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
|
TypeColumn(qualified bool) database.Column
|
||||||
}
|
}
|
||||||
|
|
||||||
type instanceDomainConditions interface {
|
type instanceDomainConditions interface {
|
||||||
domainConditions
|
domainConditions
|
||||||
|
// TypeCondition returns a filter for the type field.
|
||||||
|
TypeCondition(typ DomainType) database.Condition
|
||||||
}
|
}
|
||||||
|
|
||||||
type instanceDomainChanges interface {
|
type instanceDomainChanges interface {
|
||||||
domainChanges
|
domainChanges
|
||||||
|
// SetType sets the type column.
|
||||||
|
SetType(typ DomainType) database.Change
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceDomainRepository interface {
|
type InstanceDomainRepository interface {
|
||||||
|
@@ -38,17 +38,31 @@ type AddOrganizationDomain struct {
|
|||||||
type organizationDomainColumns interface {
|
type organizationDomainColumns interface {
|
||||||
domainColumns
|
domainColumns
|
||||||
// OrgIDColumn returns the column for the org id field.
|
// OrgIDColumn returns the column for the org id field.
|
||||||
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
OrgIDColumn(qualified bool) database.Column
|
OrgIDColumn(qualified bool) database.Column
|
||||||
|
// IsVerifiedColumn returns the column for the is verified field.
|
||||||
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
|
IsVerifiedColumn(qualified bool) database.Column
|
||||||
|
// ValidationTypeColumn returns the column for the verification type field.
|
||||||
|
// `qualified` indicates if the column should be qualified with the table name.
|
||||||
|
ValidationTypeColumn(qualified bool) database.Column
|
||||||
}
|
}
|
||||||
|
|
||||||
type organizationDomainConditions interface {
|
type organizationDomainConditions interface {
|
||||||
domainConditions
|
domainConditions
|
||||||
// OrgIDCondition returns a filter on the org id field.
|
// OrgIDCondition returns a filter on the org id field.
|
||||||
OrgIDCondition(orgID string) database.Condition
|
OrgIDCondition(orgID string) database.Condition
|
||||||
|
// IsVerifiedCondition returns a filter on the is verified field.
|
||||||
|
IsVerifiedCondition(isVerified bool) database.Condition
|
||||||
}
|
}
|
||||||
|
|
||||||
type organizationDomainChanges interface {
|
type organizationDomainChanges interface {
|
||||||
domainChanges
|
domainChanges
|
||||||
|
// SetVerified sets the is verified column to true.
|
||||||
|
SetVerified() database.Change
|
||||||
|
// SetValidationType sets the verification type column.
|
||||||
|
// If the domain is already verified, this is a no-op.
|
||||||
|
SetValidationType(verificationType DomainValidationType) database.Change
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrganizationDomainRepository interface {
|
type OrganizationDomainRepository interface {
|
||||||
|
@@ -3,20 +3,28 @@ CREATE TYPE zitadel.domain_validation_type AS ENUM (
|
|||||||
, 'dns'
|
, 'dns'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TYPE zitadel.domain_type AS ENUM (
|
||||||
|
'custom'
|
||||||
|
, 'trusted'
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE zitadel.instance_domains(
|
CREATE TABLE zitadel.instance_domains(
|
||||||
instance_id TEXT NOT NULL
|
instance_id TEXT NOT NULL
|
||||||
, domain TEXT NOT NULL CHECK (LENGTH(domain) BETWEEN 1 AND 255)
|
, domain TEXT NOT NULL CHECK (LENGTH(domain) BETWEEN 1 AND 255)
|
||||||
, is_verified BOOLEAN NOT NULL DEFAULT FALSE
|
, is_primary BOOLEAN
|
||||||
, is_primary BOOLEAN NOT NULL DEFAULT FALSE
|
, is_generated BOOLEAN
|
||||||
, is_generated BOOLEAN NOT NULL DEFAULT FALSE
|
, type zitadel.domain_type NOT NULL
|
||||||
, validation_type zitadel.domain_validation_type
|
|
||||||
|
|
||||||
, created_at TIMESTAMP DEFAULT NOW()
|
, created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
, updated_at TIMESTAMP DEFAULT NOW()
|
, updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
|
||||||
, PRIMARY KEY (domain)
|
, PRIMARY KEY (domain)
|
||||||
|
|
||||||
, FOREIGN KEY (instance_id) REFERENCES zitadel.instances(id) ON DELETE CASCADE
|
, FOREIGN KEY (instance_id) REFERENCES zitadel.instances(id) ON DELETE CASCADE
|
||||||
|
|
||||||
|
, CONSTRAINT primary_cannot_be_trusted CHECK (is_primary IS NULL OR type != 'trusted')
|
||||||
|
, CONSTRAINT generated_cannot_be_trusted CHECK (is_generated IS NULL OR type != 'trusted')
|
||||||
|
, CONSTRAINT custom_values_set CHECK (type = 'custom' AND is_primary IS NOT NULL AND is_generated IS NOT NULL)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_instance_domain_instance ON zitadel.instance_domains(instance_id);
|
CREATE INDEX idx_instance_domain_instance ON zitadel.instance_domains(instance_id);
|
||||||
@@ -29,8 +37,8 @@ CREATE TABLE zitadel.org_domains(
|
|||||||
, is_primary BOOLEAN NOT NULL DEFAULT FALSE
|
, is_primary BOOLEAN NOT NULL DEFAULT FALSE
|
||||||
, validation_type zitadel.domain_validation_type
|
, validation_type zitadel.domain_validation_type
|
||||||
|
|
||||||
, created_at TIMESTAMP DEFAULT NOW()
|
, created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
, updated_at TIMESTAMP DEFAULT NOW()
|
, updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
|
||||||
, PRIMARY KEY (instance_id, org_id, domain)
|
, PRIMARY KEY (instance_id, org_id, domain)
|
||||||
|
|
||||||
@@ -91,7 +99,8 @@ BEGIN
|
|||||||
SET is_primary = FALSE, updated_at = NOW()
|
SET is_primary = FALSE, updated_at = NOW()
|
||||||
WHERE instance_id = NEW.instance_id
|
WHERE instance_id = NEW.instance_id
|
||||||
AND domain != NEW.domain
|
AND domain != NEW.domain
|
||||||
AND is_primary = TRUE;
|
AND is_primary = TRUE
|
||||||
|
AND type = 'custom';
|
||||||
|
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END;
|
END;
|
||||||
|
@@ -4,6 +4,7 @@ package events_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,11 +15,12 @@ import (
|
|||||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||||
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres"
|
"github.com/zitadel/zitadel/backend/v3/storage/database/dialect/postgres"
|
||||||
"github.com/zitadel/zitadel/internal/integration"
|
"github.com/zitadel/zitadel/internal/integration"
|
||||||
|
v2beta "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||||
v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
|
v2beta_org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta"
|
||||||
"github.com/zitadel/zitadel/pkg/grpc/system"
|
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ConnString = "host=localhost port=5432 user=zitadel dbname=zitadel sslmode=disable"
|
const ConnString = "host=localhost port=5432 user=zitadel password=zitadel dbname=zitadel sslmode=disable"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dbPool *pgxpool.Pool
|
dbPool *pgxpool.Pool
|
||||||
@@ -35,12 +37,21 @@ func TestMain(m *testing.M) {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
Instance = integration.NewInstance(ctx)
|
CTX = integration.WithSystemAuthorization(ctx)
|
||||||
|
Instance = integration.NewInstance(CTX)
|
||||||
|
|
||||||
CTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
|
|
||||||
SystemClient = integration.SystemClient()
|
SystemClient = integration.SystemClient()
|
||||||
OrgClient = Instance.Client.OrgV2beta
|
OrgClient = Instance.Client.OrgV2beta
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_, err := Instance.Client.InstanceV2Beta.DeleteInstance(CTX, &v2beta.DeleteInstanceRequest{
|
||||||
|
InstanceId: Instance.Instance.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to delete instance on cleanup: %v\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
dbConfig, err := pgxpool.ParseConfig(ConnString)
|
dbConfig, err := pgxpool.ParseConfig(ConnString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -0,0 +1,224 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package events_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/brianvoe/gofakeit/v6"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||||
|
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||||
|
"github.com/zitadel/zitadel/internal/integration"
|
||||||
|
v2beta "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
|
||||||
|
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServer_TestInstanceDomainReduces(t *testing.T) {
|
||||||
|
instance := integration.NewInstance(CTX)
|
||||||
|
|
||||||
|
instanceRepo := repository.InstanceRepository(pool)
|
||||||
|
instanceDomainRepo := instanceRepo.Domains(true)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err := instance.Client.InstanceV2Beta.DeleteInstance(CTX, &v2beta.DeleteInstanceRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Wait for instance to be created
|
||||||
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
_, err := instanceRepo.Get(CTX,
|
||||||
|
database.WithCondition(instanceRepo.IDCondition(instance.Instance.Id)),
|
||||||
|
)
|
||||||
|
assert.NoError(ttt, err)
|
||||||
|
}, retryDuration, tick)
|
||||||
|
|
||||||
|
t.Run("test instance domain add reduces", func(t *testing.T) {
|
||||||
|
// Add a domain to the instance
|
||||||
|
domainName := gofakeit.DomainName()
|
||||||
|
beforeAdd := time.Now()
|
||||||
|
_, err := instance.Client.InstanceV2Beta.AddCustomDomain(CTX, &v2beta.AddCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
afterAdd := time.Now()
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err := instance.Client.InstanceV2Beta.RemoveCustomDomain(CTX, &v2beta.RemoveCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance domain on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test that domain add reduces
|
||||||
|
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
domain, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
require.NoError(ttt, err)
|
||||||
|
// event instance.domain.added
|
||||||
|
assert.Equal(ttt, domainName, domain.Domain)
|
||||||
|
assert.Equal(ttt, instance.Instance.Id, domain.InstanceID)
|
||||||
|
assert.False(ttt, domain.IsPrimary)
|
||||||
|
log.Printf("created at %v\n", domain.CreatedAt)
|
||||||
|
log.Printf("after %v\n", afterAdd)
|
||||||
|
log.Printf("before %v\n", beforeAdd)
|
||||||
|
assert.WithinRange(ttt, domain.CreatedAt, beforeAdd, afterAdd)
|
||||||
|
assert.WithinRange(ttt, domain.UpdatedAt, beforeAdd, afterAdd)
|
||||||
|
}, retryDuration, tick)
|
||||||
|
})
|
||||||
|
t.Run("test instance domain set primary reduces", func(t *testing.T) {
|
||||||
|
// Add a domain to the instance
|
||||||
|
domainName := gofakeit.DomainName()
|
||||||
|
_, err := instance.Client.InstanceV2Beta.AddCustomDomain(CTX, &v2beta.AddCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
// first we change the primary domain to something else
|
||||||
|
domain, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.IsPrimaryCondition(false),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
database.WithLimit(1),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = SystemClient.SetPrimaryDomain(CTX, &system.SetPrimaryDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domain.Domain,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = instance.Client.InstanceV2Beta.RemoveCustomDomain(CTX, &v2beta.RemoveCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance domain on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Wait for domain to be created
|
||||||
|
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
domain, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.DomainCondition(database.TextOperationEqual, domainName)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
require.NoError(ttt, err)
|
||||||
|
require.False(ttt, domain.IsPrimary)
|
||||||
|
assert.Equal(ttt, domainName, domain.Domain)
|
||||||
|
}, retryDuration, tick)
|
||||||
|
|
||||||
|
// Set domain as primary
|
||||||
|
beforeSetPrimary := time.Now()
|
||||||
|
_, err = SystemClient.SetPrimaryDomain(CTX, &system.SetPrimaryDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
afterSetPrimary := time.Now()
|
||||||
|
|
||||||
|
// Test that set primary reduces
|
||||||
|
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
domain, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.IsPrimaryCondition(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
require.NoError(ttt, err)
|
||||||
|
// event instance.domain.primary.set
|
||||||
|
assert.Equal(ttt, domainName, domain.Domain)
|
||||||
|
assert.True(ttt, domain.IsPrimary)
|
||||||
|
assert.WithinRange(ttt, domain.UpdatedAt, beforeSetPrimary, afterSetPrimary)
|
||||||
|
}, retryDuration, tick)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test instance domain remove reduces", func(t *testing.T) {
|
||||||
|
// Add a domain to the instance
|
||||||
|
domainName := gofakeit.DomainName()
|
||||||
|
_, err := instance.Client.InstanceV2Beta.AddCustomDomain(CTX, &v2beta.AddCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err := instance.Client.InstanceV2Beta.RemoveCustomDomain(CTX, &v2beta.RemoveCustomDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance domain on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Wait for domain to be created and verify it exists
|
||||||
|
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
_, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
require.NoError(ttt, err)
|
||||||
|
}, retryDuration, tick)
|
||||||
|
|
||||||
|
// Remove the domain
|
||||||
|
_, err = SystemClient.RemoveDomain(CTX, &system.RemoveDomainRequest{
|
||||||
|
InstanceId: instance.Instance.Id,
|
||||||
|
Domain: domainName,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Test that domain remove reduces
|
||||||
|
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
domain, err := instanceDomainRepo.Get(CTX,
|
||||||
|
database.WithCondition(
|
||||||
|
database.And(
|
||||||
|
instanceDomainRepo.InstanceIDCondition(instance.Instance.Id),
|
||||||
|
instanceDomainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// event instance.domain.removed
|
||||||
|
assert.Nil(ttt, domain)
|
||||||
|
require.ErrorIs(ttt, err, new(database.NoRowFoundError))
|
||||||
|
}, retryDuration, tick)
|
||||||
|
})
|
||||||
|
}
|
@@ -17,6 +17,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestServer_TestInstanceReduces(t *testing.T) {
|
func TestServer_TestInstanceReduces(t *testing.T) {
|
||||||
|
instanceRepo := repository.InstanceRepository(pool)
|
||||||
|
|
||||||
t.Run("test instance add reduces", func(t *testing.T) {
|
t.Run("test instance add reduces", func(t *testing.T) {
|
||||||
instanceName := gofakeit.Name()
|
instanceName := gofakeit.Name()
|
||||||
beforeCreate := time.Now()
|
beforeCreate := time.Now()
|
||||||
@@ -33,8 +35,15 @@ func TestServer_TestInstanceReduces(t *testing.T) {
|
|||||||
afterCreate := time.Now()
|
afterCreate := time.Now()
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err = SystemClient.RemoveInstance(CTX, &system.RemoveInstanceRequest{
|
||||||
|
InstanceId: instance.GetInstanceId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
instanceRepo := repository.InstanceRepository(pool)
|
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
instance, err := instanceRepo.Get(CTX,
|
instance, err := instanceRepo.Get(CTX,
|
||||||
@@ -71,6 +80,14 @@ func TestServer_TestInstanceReduces(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err = SystemClient.RemoveInstance(CTX, &system.RemoveInstanceRequest{
|
||||||
|
InstanceId: res.GetInstanceId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete instance on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
instanceName += "new"
|
instanceName += "new"
|
||||||
beforeUpdate := time.Now()
|
beforeUpdate := time.Now()
|
||||||
@@ -78,10 +95,9 @@ func TestServer_TestInstanceReduces(t *testing.T) {
|
|||||||
InstanceId: res.InstanceId,
|
InstanceId: res.InstanceId,
|
||||||
InstanceName: instanceName,
|
InstanceName: instanceName,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
|
||||||
afterUpdate := time.Now()
|
afterUpdate := time.Now()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
instanceRepo := repository.InstanceRepository(pool)
|
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
instance, err := instanceRepo.Get(CTX,
|
instance, err := instanceRepo.Get(CTX,
|
||||||
@@ -108,8 +124,6 @@ func TestServer_TestInstanceReduces(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
instanceRepo := repository.InstanceRepository(pool)
|
|
||||||
|
|
||||||
// check instance exists
|
// check instance exists
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||||
|
@@ -19,25 +19,33 @@ import (
|
|||||||
|
|
||||||
func TestServer_TestOrganizationReduces(t *testing.T) {
|
func TestServer_TestOrganizationReduces(t *testing.T) {
|
||||||
instanceID := Instance.ID()
|
instanceID := Instance.ID()
|
||||||
|
orgRepo := repository.OrganizationRepository(pool)
|
||||||
|
|
||||||
t.Run("test org add reduces", func(t *testing.T) {
|
t.Run("test org add reduces", func(t *testing.T) {
|
||||||
beforeCreate := time.Now()
|
beforeCreate := time.Now()
|
||||||
orgName := gofakeit.Name()
|
orgName := gofakeit.Name()
|
||||||
|
|
||||||
_, err := OrgClient.CreateOrganization(CTX, &v2beta_org.CreateOrganizationRequest{
|
org, err := OrgClient.CreateOrganization(CTX, &v2beta_org.CreateOrganizationRequest{
|
||||||
Name: orgName,
|
Name: orgName,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
afterCreate := time.Now()
|
afterCreate := time.Now()
|
||||||
|
|
||||||
orgRepo := repository.OrganizationRepository(pool)
|
t.Cleanup(func() {
|
||||||
|
_, err = OrgClient.DeleteOrganization(CTX, &v2beta_org.DeleteOrganizationRequest{
|
||||||
|
Id: org.GetId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete organization on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(tt *assert.CollectT) {
|
assert.EventuallyWithT(t, func(tt *assert.CollectT) {
|
||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(org.GetId()),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -63,6 +71,15 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_, err = OrgClient.DeleteOrganization(CTX, &v2beta_org.DeleteOrganizationRequest{
|
||||||
|
Id: organization.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete organization on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 2. update org name
|
// 2. update org name
|
||||||
beforeUpdate := time.Now()
|
beforeUpdate := time.Now()
|
||||||
orgName = orgName + "_new"
|
orgName = orgName + "_new"
|
||||||
@@ -73,14 +90,12 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
afterUpdate := time.Now()
|
afterUpdate := time.Now()
|
||||||
|
|
||||||
orgRepo := repository.OrganizationRepository(pool)
|
|
||||||
|
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -101,6 +116,15 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
Name: orgName,
|
Name: orgName,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
// Cleanup: delete the organization
|
||||||
|
_, err = OrgClient.DeleteOrganization(CTX, &v2beta_org.DeleteOrganizationRequest{
|
||||||
|
Id: organization.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete organization on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 2. deactivate org name
|
// 2. deactivate org name
|
||||||
beforeDeactivate := time.Now()
|
beforeDeactivate := time.Now()
|
||||||
@@ -111,14 +135,12 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
afterDeactivate := time.Now()
|
afterDeactivate := time.Now()
|
||||||
|
|
||||||
orgRepo := repository.OrganizationRepository(pool)
|
|
||||||
|
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -126,7 +148,6 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// event org.deactivate
|
// event org.deactivate
|
||||||
assert.Equal(t, orgName, organization.Name)
|
|
||||||
assert.Equal(t, domain.OrgStateInactive, organization.State)
|
assert.Equal(t, domain.OrgStateInactive, organization.State)
|
||||||
assert.WithinRange(t, organization.UpdatedAt, beforeDeactivate, afterDeactivate)
|
assert.WithinRange(t, organization.UpdatedAt, beforeDeactivate, afterDeactivate)
|
||||||
}, retryDuration, tick)
|
}, retryDuration, tick)
|
||||||
@@ -140,6 +161,15 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
Name: orgName,
|
Name: orgName,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
// Cleanup: delete the organization
|
||||||
|
_, err = OrgClient.DeleteOrganization(CTX, &v2beta_org.DeleteOrganizationRequest{
|
||||||
|
Id: organization.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Failed to delete organization on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 2. deactivate org name
|
// 2. deactivate org name
|
||||||
_, err = OrgClient.DeactivateOrganization(CTX, &v2beta_org.DeactivateOrganizationRequest{
|
_, err = OrgClient.DeactivateOrganization(CTX, &v2beta_org.DeactivateOrganizationRequest{
|
||||||
@@ -154,14 +184,12 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, orgName, organization.Name)
|
|
||||||
assert.Equal(t, domain.OrgStateInactive, organization.State)
|
assert.Equal(t, domain.OrgStateInactive, organization.State)
|
||||||
}, retryDuration, tick)
|
}, retryDuration, tick)
|
||||||
|
|
||||||
@@ -178,7 +206,7 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -201,24 +229,19 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// 2. check org retrivable
|
// 2. check org retrievable
|
||||||
orgRepo := repository.OrganizationRepository(pool)
|
orgRepo := repository.OrganizationRepository(pool)
|
||||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTX, time.Minute)
|
||||||
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
assert.EventuallyWithT(t, func(t *assert.CollectT) {
|
||||||
organization, err := orgRepo.Get(CTX,
|
_, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if organization == nil {
|
|
||||||
assert.Fail(t, "this error is here because of a race condition")
|
|
||||||
}
|
|
||||||
assert.Equal(t, orgName, organization.Name)
|
|
||||||
}, retryDuration, tick)
|
}, retryDuration, tick)
|
||||||
|
|
||||||
// 3. delete org
|
// 3. delete org
|
||||||
@@ -232,7 +255,7 @@ func TestServer_TestOrganizationReduces(t *testing.T) {
|
|||||||
organization, err := orgRepo.Get(CTX,
|
organization, err := orgRepo.Get(CTX,
|
||||||
database.WithCondition(
|
database.WithCondition(
|
||||||
database.And(
|
database.And(
|
||||||
orgRepo.NameCondition(orgName),
|
orgRepo.IDCondition(organization.Id),
|
||||||
orgRepo.InstanceIDCondition(instanceID),
|
orgRepo.InstanceIDCondition(instanceID),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -30,7 +30,7 @@ func InstanceRepository(client database.QueryExecutor) domain.InstanceRepository
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
queryInstanceStmt = `SELECT instances.id, instances.name, instances.default_org_id, instances.iam_project_id, instances.console_client_id, instances.console_app_id, instances.default_language, instances.created_at, instances.updated_at` +
|
queryInstanceStmt = `SELECT instances.id, instances.name, instances.default_org_id, instances.iam_project_id, instances.console_client_id, instances.console_app_id, instances.default_language, instances.created_at, instances.updated_at` +
|
||||||
` , CASE WHEN count(instance_domains.domain) > 0 THEN jsonb_agg(json_build_object('domain', instance_domains.domain, 'isVerified', instance_domains.is_verified, 'isPrimary', instance_domains.is_primary, 'isGenerated', instance_domains.is_generated, 'validationType', instance_domains.validation_type, 'createdAt', instance_domains.created_at, 'updatedAt', instance_domains.updated_at)) ELSE NULL::JSONB END domains` +
|
` , CASE WHEN count(instance_domains.domain) > 0 THEN jsonb_agg(json_build_object('domain', instance_domains.domain, 'isPrimary', instance_domains.is_primary, 'isGenerated', instance_domains.is_generated, 'createdAt', instance_domains.created_at, 'updatedAt', instance_domains.updated_at)) ELSE NULL::JSONB END domains` +
|
||||||
` FROM zitadel.instances`
|
` FROM zitadel.instances`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ type instanceDomain struct {
|
|||||||
// repository
|
// repository
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
|
|
||||||
const queryInstanceDomainStmt = `SELECT instance_domains.instance_id, instance_domains.domain, instance_domains.is_verified, instance_domains.is_primary, instance_domains.validation_type, instance_domains.created_at, instance_domains.updated_at ` +
|
const queryInstanceDomainStmt = `SELECT instance_domains.instance_id, instance_domains.domain, instance_domains.is_primary, instance_domains.created_at, instance_domains.updated_at ` +
|
||||||
`FROM zitadel.instance_domains`
|
`FROM zitadel.instance_domains`
|
||||||
|
|
||||||
// Get implements [domain.InstanceDomainRepository].
|
// Get implements [domain.InstanceDomainRepository].
|
||||||
@@ -56,11 +56,11 @@ func (i *instanceDomain) List(ctx context.Context, opts ...database.QueryOption)
|
|||||||
func (i *instanceDomain) Add(ctx context.Context, domain *domain.AddInstanceDomain) error {
|
func (i *instanceDomain) Add(ctx context.Context, domain *domain.AddInstanceDomain) error {
|
||||||
var builder database.StatementBuilder
|
var builder database.StatementBuilder
|
||||||
|
|
||||||
builder.WriteString(`INSERT INTO zitadel.instance_domains (instance_id, domain, is_verified, is_primary, validation_type) VALUES (`)
|
builder.WriteString(`INSERT INTO zitadel.instance_domains (instance_id, domain, is_primary, is_generated, type, created_at, updated_at) VALUES (`)
|
||||||
builder.WriteArgs(domain.InstanceID, domain.Domain, domain.IsVerified, domain.IsPrimary, domain.ValidationType)
|
builder.WriteArgs(domain.InstanceID, domain.Domain, domain.IsPrimary, domain.IsGenerated, domain.Type, domain.CreatedAt, domain.UpdatedAt)
|
||||||
builder.WriteString(`) RETURNING created_at, updated_at`)
|
builder.WriteString(`) RETURNING created_at, updated_at`)
|
||||||
|
|
||||||
return i.client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&domain.CreatedAt, &domain.UpdatedAt)
|
return i.client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(domain.CreatedAt, domain.UpdatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove implements [domain.InstanceDomainRepository].
|
// Remove implements [domain.InstanceDomainRepository].
|
||||||
@@ -93,26 +93,21 @@ func (i *instanceDomain) Update(ctx context.Context, condition database.Conditio
|
|||||||
// changes
|
// changes
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
|
|
||||||
// SetValidationType implements [domain.InstanceDomainRepository].
|
|
||||||
func (i instanceDomain) SetValidationType(verificationType domain.DomainValidationType) database.Change {
|
|
||||||
return database.NewChange(i.ValidationTypeColumn(false), verificationType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetPrimary implements [domain.InstanceDomainRepository].
|
// SetPrimary implements [domain.InstanceDomainRepository].
|
||||||
func (i instanceDomain) SetPrimary() database.Change {
|
func (i instanceDomain) SetPrimary() database.Change {
|
||||||
return database.NewChange(i.IsPrimaryColumn(false), true)
|
return database.NewChange(i.IsPrimaryColumn(false), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVerified implements [domain.InstanceDomainRepository].
|
|
||||||
func (i instanceDomain) SetVerified() database.Change {
|
|
||||||
return database.NewChange(i.IsVerifiedColumn(false), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetUpdatedAt implements [domain.OrganizationDomainRepository].
|
// SetUpdatedAt implements [domain.OrganizationDomainRepository].
|
||||||
func (i instanceDomain) SetUpdatedAt(updatedAt time.Time) database.Change {
|
func (i instanceDomain) SetUpdatedAt(updatedAt time.Time) database.Change {
|
||||||
return database.NewChange(i.UpdatedAtColumn(false), updatedAt)
|
return database.NewChange(i.UpdatedAtColumn(false), updatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetType implements [domain.InstanceDomainRepository].
|
||||||
|
func (i instanceDomain) SetType(typ domain.DomainType) database.Change {
|
||||||
|
return database.NewChange(i.TypeColumn(false), typ)
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// conditions
|
// conditions
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
@@ -132,9 +127,9 @@ func (i instanceDomain) IsPrimaryCondition(isPrimary bool) database.Condition {
|
|||||||
return database.NewBooleanCondition(i.IsPrimaryColumn(true), isPrimary)
|
return database.NewBooleanCondition(i.IsPrimaryColumn(true), isPrimary)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVerifiedCondition implements [domain.InstanceDomainRepository].
|
// TypeCondition implements [domain.InstanceDomainRepository].
|
||||||
func (i instanceDomain) IsVerifiedCondition(isVerified bool) database.Condition {
|
func (i instanceDomain) TypeCondition(typ domain.DomainType) database.Condition {
|
||||||
return database.NewBooleanCondition(i.IsVerifiedColumn(true), isVerified)
|
return database.NewTextCondition(i.TypeColumn(true), database.TextOperationEqual, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
@@ -174,14 +169,6 @@ func (instanceDomain) IsPrimaryColumn(qualified bool) database.Column {
|
|||||||
return database.NewColumn("is_primary")
|
return database.NewColumn("is_primary")
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVerifiedColumn implements [domain.InstanceDomainRepository].
|
|
||||||
func (instanceDomain) IsVerifiedColumn(qualified bool) database.Column {
|
|
||||||
if qualified {
|
|
||||||
return database.NewColumn("instance_domains.is_verified")
|
|
||||||
}
|
|
||||||
return database.NewColumn("is_verified")
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatedAtColumn implements [domain.InstanceDomainRepository].
|
// UpdatedAtColumn implements [domain.InstanceDomainRepository].
|
||||||
// Subtle: this method shadows the method ([domain.InstanceRepository]).UpdatedAtColumn of instanceDomain.instance.
|
// Subtle: this method shadows the method ([domain.InstanceRepository]).UpdatedAtColumn of instanceDomain.instance.
|
||||||
func (instanceDomain) UpdatedAtColumn(qualified bool) database.Column {
|
func (instanceDomain) UpdatedAtColumn(qualified bool) database.Column {
|
||||||
@@ -191,14 +178,6 @@ func (instanceDomain) UpdatedAtColumn(qualified bool) database.Column {
|
|||||||
return database.NewColumn("updated_at")
|
return database.NewColumn("updated_at")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidationTypeColumn implements [domain.InstanceDomainRepository].
|
|
||||||
func (instanceDomain) ValidationTypeColumn(qualified bool) database.Column {
|
|
||||||
if qualified {
|
|
||||||
return database.NewColumn("instance_domains.validation_type")
|
|
||||||
}
|
|
||||||
return database.NewColumn("validation_type")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsGeneratedColumn implements [domain.InstanceDomainRepository].
|
// IsGeneratedColumn implements [domain.InstanceDomainRepository].
|
||||||
func (instanceDomain) IsGeneratedColumn(qualified bool) database.Column {
|
func (instanceDomain) IsGeneratedColumn(qualified bool) database.Column {
|
||||||
if qualified {
|
if qualified {
|
||||||
@@ -207,6 +186,14 @@ func (instanceDomain) IsGeneratedColumn(qualified bool) database.Column {
|
|||||||
return database.NewColumn("is_generated")
|
return database.NewColumn("is_generated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TypeColumn implements [domain.InstanceDomainRepository].
|
||||||
|
func (instanceDomain) TypeColumn(qualified bool) database.Column {
|
||||||
|
if qualified {
|
||||||
|
return database.NewColumn("instance_domains.type")
|
||||||
|
}
|
||||||
|
return database.NewColumn("type")
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// scanners
|
// scanners
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/brianvoe/gofakeit/v6"
|
"github.com/brianvoe/gofakeit/v6"
|
||||||
"github.com/muhlemmer/gu"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
@@ -41,19 +40,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain: domain.AddInstanceDomain{
|
instanceDomain: domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "add verified domain",
|
|
||||||
instanceDomain: domain.AddInstanceDomain{
|
|
||||||
InstanceID: instanceID,
|
|
||||||
Domain: gofakeit.DomainName(),
|
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: false,
|
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -61,9 +48,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain: domain.AddInstanceDomain{
|
instanceDomain: domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -71,9 +56,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain: domain.AddInstanceDomain{
|
instanceDomain: domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: "",
|
Domain: "",
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
err: new(database.CheckError),
|
err: new(database.CheckError),
|
||||||
},
|
},
|
||||||
@@ -85,9 +68,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain := &domain.AddInstanceDomain{
|
instanceDomain := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName,
|
Domain: domainName,
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := domainRepo.Add(ctx, instanceDomain)
|
err := domainRepo.Add(ctx, instanceDomain)
|
||||||
@@ -97,9 +78,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
return &domain.AddInstanceDomain{
|
return &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName,
|
Domain: domainName,
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
err: new(database.UniqueError),
|
err: new(database.UniqueError),
|
||||||
@@ -109,9 +88,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain: domain.AddInstanceDomain{
|
instanceDomain: domain.AddInstanceDomain{
|
||||||
InstanceID: "non-existent-instance",
|
InstanceID: "non-existent-instance",
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
err: new(database.ForeignKeyError),
|
err: new(database.ForeignKeyError),
|
||||||
},
|
},
|
||||||
@@ -119,9 +96,7 @@ func TestAddInstanceDomain(t *testing.T) {
|
|||||||
name: "add domain without instance id",
|
name: "add domain without instance id",
|
||||||
instanceDomain: domain.AddInstanceDomain{
|
instanceDomain: domain.AddInstanceDomain{
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
err: new(database.ForeignKeyError),
|
err: new(database.ForeignKeyError),
|
||||||
},
|
},
|
||||||
@@ -188,16 +163,12 @@ func TestGetInstanceDomain(t *testing.T) {
|
|||||||
domain1 := &domain.AddInstanceDomain{
|
domain1 := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName1,
|
Domain: domainName1,
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
}
|
}
|
||||||
domain2 := &domain.AddInstanceDomain{
|
domain2 := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName2,
|
Domain: domainName2,
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = domainRepo.Add(t.Context(), domain1)
|
err = domainRepo.Add(t.Context(), domain1)
|
||||||
@@ -219,9 +190,7 @@ func TestGetInstanceDomain(t *testing.T) {
|
|||||||
expected: &domain.InstanceDomain{
|
expected: &domain.InstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName1,
|
Domain: domainName1,
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -232,22 +201,7 @@ func TestGetInstanceDomain(t *testing.T) {
|
|||||||
expected: &domain.InstanceDomain{
|
expected: &domain.InstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName2,
|
Domain: domainName2,
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "get verified domain",
|
|
||||||
opts: []database.QueryOption{
|
|
||||||
database.WithCondition(domainRepo.IsVerifiedCondition(true)),
|
|
||||||
},
|
|
||||||
expected: &domain.InstanceDomain{
|
|
||||||
InstanceID: instanceID,
|
|
||||||
Domain: domainName1,
|
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -272,9 +226,7 @@ func TestGetInstanceDomain(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, test.expected.InstanceID, result.InstanceID)
|
assert.Equal(t, test.expected.InstanceID, result.InstanceID)
|
||||||
assert.Equal(t, test.expected.Domain, result.Domain)
|
assert.Equal(t, test.expected.Domain, result.Domain)
|
||||||
assert.Equal(t, test.expected.IsVerified, result.IsVerified)
|
|
||||||
assert.Equal(t, test.expected.IsPrimary, result.IsPrimary)
|
assert.Equal(t, test.expected.IsPrimary, result.IsPrimary)
|
||||||
assert.Equal(t, test.expected.ValidationType, result.ValidationType)
|
|
||||||
assert.NotEmpty(t, result.CreatedAt)
|
assert.NotEmpty(t, result.CreatedAt)
|
||||||
assert.NotEmpty(t, result.UpdatedAt)
|
assert.NotEmpty(t, result.UpdatedAt)
|
||||||
})
|
})
|
||||||
@@ -309,23 +261,17 @@ func TestListInstanceDomains(t *testing.T) {
|
|||||||
{
|
{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: gofakeit.DomainName(),
|
Domain: gofakeit.DomainName(),
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,13 +290,6 @@ func TestListInstanceDomains(t *testing.T) {
|
|||||||
opts: []database.QueryOption{},
|
opts: []database.QueryOption{},
|
||||||
expectedCount: 3,
|
expectedCount: 3,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "list verified domains",
|
|
||||||
opts: []database.QueryOption{
|
|
||||||
database.WithCondition(domainRepo.IsVerifiedCondition(true)),
|
|
||||||
},
|
|
||||||
expectedCount: 2,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "list primary domains",
|
name: "list primary domains",
|
||||||
opts: []database.QueryOption{
|
opts: []database.QueryOption{
|
||||||
@@ -421,9 +360,7 @@ func TestUpdateInstanceDomain(t *testing.T) {
|
|||||||
instanceDomain := &domain.AddInstanceDomain{
|
instanceDomain := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName,
|
Domain: domainName,
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = domainRepo.Add(t.Context(), instanceDomain)
|
err = domainRepo.Add(t.Context(), instanceDomain)
|
||||||
@@ -436,38 +373,16 @@ func TestUpdateInstanceDomain(t *testing.T) {
|
|||||||
expected int64
|
expected int64
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "set verified",
|
|
||||||
condition: domainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
|
||||||
changes: []database.Change{domainRepo.SetVerified()},
|
|
||||||
expected: 1,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "set primary",
|
name: "set primary",
|
||||||
condition: domainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
condition: domainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
||||||
changes: []database.Change{domainRepo.SetPrimary()},
|
changes: []database.Change{domainRepo.SetPrimary()},
|
||||||
expected: 1,
|
expected: 1,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "set validation type",
|
|
||||||
condition: domainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
|
||||||
changes: []database.Change{domainRepo.SetValidationType(domain.DomainValidationTypeHTTP)},
|
|
||||||
expected: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multiple changes",
|
|
||||||
condition: domainRepo.DomainCondition(database.TextOperationEqual, domainName),
|
|
||||||
changes: []database.Change{
|
|
||||||
domainRepo.SetVerified(),
|
|
||||||
domainRepo.SetPrimary(),
|
|
||||||
domainRepo.SetValidationType(domain.DomainValidationTypeDNS),
|
|
||||||
},
|
|
||||||
expected: 1,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "update non-existent domain",
|
name: "update non-existent domain",
|
||||||
condition: domainRepo.DomainCondition(database.TextOperationEqual, "non-existent.com"),
|
condition: domainRepo.DomainCondition(database.TextOperationEqual, "non-existent.com"),
|
||||||
changes: []database.Change{domainRepo.SetVerified()},
|
changes: []database.Change{domainRepo.SetPrimary()},
|
||||||
expected: 0,
|
expected: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -535,16 +450,12 @@ func TestRemoveInstanceDomain(t *testing.T) {
|
|||||||
domain1 := &domain.AddInstanceDomain{
|
domain1 := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName1,
|
Domain: domainName1,
|
||||||
IsVerified: true,
|
|
||||||
IsPrimary: true,
|
IsPrimary: true,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeDNS),
|
|
||||||
}
|
}
|
||||||
domain2 := &domain.AddInstanceDomain{
|
domain2 := &domain.AddInstanceDomain{
|
||||||
InstanceID: instanceID,
|
InstanceID: instanceID,
|
||||||
Domain: domainName2,
|
Domain: domainName2,
|
||||||
IsVerified: false,
|
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
ValidationType: gu.Ptr(domain.DomainValidationTypeHTTP),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = domainRepo.Add(t.Context(), domain1)
|
err = domainRepo.Add(t.Context(), domain1)
|
||||||
@@ -628,16 +539,6 @@ func TestInstanceDomainConditions(t *testing.T) {
|
|||||||
condition: domainRepo.IsPrimaryCondition(false),
|
condition: domainRepo.IsPrimaryCondition(false),
|
||||||
expected: "instance_domains.is_primary = $1",
|
expected: "instance_domains.is_primary = $1",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "is verified true",
|
|
||||||
condition: domainRepo.IsVerifiedCondition(true),
|
|
||||||
expected: "instance_domains.is_verified = $1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "is verified false",
|
|
||||||
condition: domainRepo.IsVerifiedCondition(false),
|
|
||||||
expected: "instance_domains.is_verified = $1",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -658,26 +559,11 @@ func TestInstanceDomainChanges(t *testing.T) {
|
|||||||
change database.Change
|
change database.Change
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "set verified",
|
|
||||||
change: domainRepo.SetVerified(),
|
|
||||||
expected: "is_verified = $1",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "set primary",
|
name: "set primary",
|
||||||
change: domainRepo.SetPrimary(),
|
change: domainRepo.SetPrimary(),
|
||||||
expected: "is_primary = $1",
|
expected: "is_primary = $1",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "set validation type DNS",
|
|
||||||
change: domainRepo.SetValidationType(domain.DomainValidationTypeDNS),
|
|
||||||
expected: "validation_type = $1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "set validation type HTTP",
|
|
||||||
change: domainRepo.SetValidationType(domain.DomainValidationTypeHTTP),
|
|
||||||
expected: "validation_type = $1",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@@ -9,6 +9,7 @@ Database:
|
|||||||
SSL:
|
SSL:
|
||||||
Mode: disable
|
Mode: disable
|
||||||
Admin:
|
Admin:
|
||||||
Username: zitadel
|
Username: adlerhurst
|
||||||
|
Password: password
|
||||||
SSL:
|
SSL:
|
||||||
Mode: disable
|
Mode: disable
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/muhlemmer/gu"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/backend/v3/domain"
|
"github.com/zitadel/zitadel/backend/v3/domain"
|
||||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||||
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
|
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
|
||||||
@@ -31,7 +33,7 @@ func (p *instanceDomainRelationalProjection) Reducers() []handler.AggregateReduc
|
|||||||
EventReducers: []handler.EventReducer{
|
EventReducers: []handler.EventReducer{
|
||||||
{
|
{
|
||||||
Event: instance.InstanceDomainAddedEventType,
|
Event: instance.InstanceDomainAddedEventType,
|
||||||
Reduce: p.reduceDomainAdded,
|
Reduce: p.reduceCustomDomainAdded,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: instance.InstanceDomainPrimarySetEventType,
|
Event: instance.InstanceDomainPrimarySetEventType,
|
||||||
@@ -39,14 +41,22 @@ func (p *instanceDomainRelationalProjection) Reducers() []handler.AggregateReduc
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: instance.InstanceDomainRemovedEventType,
|
Event: instance.InstanceDomainRemovedEventType,
|
||||||
Reduce: p.reduceDomainRemoved,
|
Reduce: p.reduceCustomDomainRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: instance.TrustedDomainAddedEventType,
|
||||||
|
Reduce: p.reduceTrustedDomainAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: instance.TrustedDomainRemovedEventType,
|
||||||
|
Reduce: p.reduceTrustedDomainRemoved,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *instanceDomainRelationalProjection) reduceDomainAdded(event eventstore.Event) (*handler.Statement, error) {
|
func (p *instanceDomainRelationalProjection) reduceCustomDomainAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
e, ok := event.(*instance.DomainAddedEvent)
|
e, ok := event.(*instance.DomainAddedEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-DU0xF", "reduce.wrong.event.type %s", instance.InstanceDomainAddedEventType)
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-DU0xF", "reduce.wrong.event.type %s", instance.InstanceDomainAddedEventType)
|
||||||
@@ -60,8 +70,9 @@ func (p *instanceDomainRelationalProjection) reduceDomainAdded(event eventstore.
|
|||||||
InstanceID: e.Aggregate().InstanceID,
|
InstanceID: e.Aggregate().InstanceID,
|
||||||
Domain: e.Domain,
|
Domain: e.Domain,
|
||||||
IsGenerated: e.Generated,
|
IsGenerated: e.Generated,
|
||||||
CreatedAt: e.CreationDate(),
|
Type: domain.DomainTypeCustom,
|
||||||
UpdatedAt: e.CreationDate(),
|
CreatedAt: gu.Ptr(e.CreationDate()),
|
||||||
|
UpdatedAt: gu.Ptr(e.CreationDate()),
|
||||||
})
|
})
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
@@ -81,6 +92,7 @@ func (p *instanceDomainRelationalProjection) reduceDomainPrimarySet(event events
|
|||||||
database.And(
|
database.And(
|
||||||
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
||||||
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
||||||
|
domainRepo.TypeCondition(domain.DomainTypeCustom),
|
||||||
),
|
),
|
||||||
domainRepo.SetPrimary(),
|
domainRepo.SetPrimary(),
|
||||||
domainRepo.SetUpdatedAt(e.CreationDate()),
|
domainRepo.SetUpdatedAt(e.CreationDate()),
|
||||||
@@ -89,7 +101,7 @@ func (p *instanceDomainRelationalProjection) reduceDomainPrimarySet(event events
|
|||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *instanceDomainRelationalProjection) reduceDomainRemoved(event eventstore.Event) (*handler.Statement, error) {
|
func (p *instanceDomainRelationalProjection) reduceCustomDomainRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||||
e, ok := event.(*instance.DomainRemovedEvent)
|
e, ok := event.(*instance.DomainRemovedEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-Hhcdl", "reduce.wrong.event.type %s", instance.InstanceDomainRemovedEventType)
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-Hhcdl", "reduce.wrong.event.type %s", instance.InstanceDomainRemovedEventType)
|
||||||
@@ -104,6 +116,49 @@ func (p *instanceDomainRelationalProjection) reduceDomainRemoved(event eventstor
|
|||||||
database.And(
|
database.And(
|
||||||
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
||||||
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
||||||
|
domainRepo.TypeCondition(domain.DomainTypeCustom),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *instanceDomainRelationalProjection) reduceTrustedDomainAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
e, ok := event.(*instance.TrustedDomainAddedEvent)
|
||||||
|
if !ok {
|
||||||
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-svHDh", "reduce.wrong.event.type %s", instance.TrustedDomainAddedEventType)
|
||||||
|
}
|
||||||
|
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
|
||||||
|
tx, ok := ex.(*sql.Tx)
|
||||||
|
if !ok {
|
||||||
|
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-gx7tQ", "reduce.wrong.db.pool %T", ex)
|
||||||
|
}
|
||||||
|
return repository.InstanceRepository(v3_sql.SQLTx(tx)).Domains(false).Add(ctx, &domain.AddInstanceDomain{
|
||||||
|
InstanceID: e.Aggregate().InstanceID,
|
||||||
|
Domain: e.Domain,
|
||||||
|
Type: domain.DomainTypeCustom,
|
||||||
|
CreatedAt: gu.Ptr(e.CreationDate()),
|
||||||
|
UpdatedAt: gu.Ptr(e.CreationDate()),
|
||||||
|
})
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *instanceDomainRelationalProjection) reduceTrustedDomainRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
e, ok := event.(*instance.TrustedDomainRemovedEvent)
|
||||||
|
if !ok {
|
||||||
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-4K74E", "reduce.wrong.event.type %s", instance.TrustedDomainRemovedEventType)
|
||||||
|
}
|
||||||
|
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
|
||||||
|
tx, ok := ex.(*sql.Tx)
|
||||||
|
if !ok {
|
||||||
|
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-D68ap", "reduce.wrong.db.pool %T", ex)
|
||||||
|
}
|
||||||
|
domainRepo := repository.InstanceRepository(v3_sql.SQLTx(tx)).Domains(false)
|
||||||
|
_, err := domainRepo.Remove(ctx,
|
||||||
|
database.And(
|
||||||
|
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
||||||
|
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
||||||
|
domainRepo.TypeCondition(domain.DomainTypeTrusted),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
||||||
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
|
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
|
||||||
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
||||||
|
old_domain "github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||||
"github.com/zitadel/zitadel/internal/repository/org"
|
"github.com/zitadel/zitadel/internal/repository/org"
|
||||||
@@ -31,22 +32,30 @@ func (p *orgDomainRelationalProjection) Reducers() []handler.AggregateReducer {
|
|||||||
EventReducers: []handler.EventReducer{
|
EventReducers: []handler.EventReducer{
|
||||||
{
|
{
|
||||||
Event: org.OrgDomainAddedEventType,
|
Event: org.OrgDomainAddedEventType,
|
||||||
Reduce: p.reduceDomainAdded,
|
Reduce: p.reduceAdded,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: org.OrgDomainPrimarySetEventType,
|
Event: org.OrgDomainPrimarySetEventType,
|
||||||
Reduce: p.reduceDomainPrimarySet,
|
Reduce: p.reducePrimarySet,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: org.OrgDomainRemovedEventType,
|
Event: org.OrgDomainRemovedEventType,
|
||||||
Reduce: p.reduceDomainRemoved,
|
Reduce: p.reduceRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: org.OrgDomainVerificationAddedEventType,
|
||||||
|
Reduce: p.reduceVerificationAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: org.OrgDomainVerifiedEventType,
|
||||||
|
Reduce: p.reduceVerified,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *orgDomainRelationalProjection) reduceDomainAdded(event eventstore.Event) (*handler.Statement, error) {
|
func (p *orgDomainRelationalProjection) reduceAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
e, ok := event.(*org.DomainAddedEvent)
|
e, ok := event.(*org.DomainAddedEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-ZX9Fw", "reduce.wrong.event.type %s", org.OrgDomainAddedEventType)
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-ZX9Fw", "reduce.wrong.event.type %s", org.OrgDomainAddedEventType)
|
||||||
@@ -66,7 +75,7 @@ func (p *orgDomainRelationalProjection) reduceDomainAdded(event eventstore.Event
|
|||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *orgDomainRelationalProjection) reduceDomainPrimarySet(event eventstore.Event) (*handler.Statement, error) {
|
func (p *orgDomainRelationalProjection) reducePrimarySet(event eventstore.Event) (*handler.Statement, error) {
|
||||||
e, ok := event.(*org.DomainPrimarySetEvent)
|
e, ok := event.(*org.DomainPrimarySetEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-dmFdb", "reduce.wrong.event.type %s", org.OrgDomainPrimarySetEventType)
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-dmFdb", "reduce.wrong.event.type %s", org.OrgDomainPrimarySetEventType)
|
||||||
@@ -90,7 +99,7 @@ func (p *orgDomainRelationalProjection) reduceDomainPrimarySet(event eventstore.
|
|||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *orgDomainRelationalProjection) reduceDomainRemoved(event eventstore.Event) (*handler.Statement, error) {
|
func (p *orgDomainRelationalProjection) reduceRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||||
e, ok := event.(*org.DomainRemovedEvent)
|
e, ok := event.(*org.DomainRemovedEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-MzC0n", "reduce.wrong.event.type %s", org.OrgDomainRemovedEventType)
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-MzC0n", "reduce.wrong.event.type %s", org.OrgDomainRemovedEventType)
|
||||||
@@ -111,3 +120,58 @@ func (p *orgDomainRelationalProjection) reduceDomainRemoved(event eventstore.Eve
|
|||||||
return err
|
return err
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *orgDomainRelationalProjection) reduceVerificationAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
e, ok := event.(*org.DomainVerificationAddedEvent)
|
||||||
|
if !ok {
|
||||||
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-oGzip", "reduce.wrong.event.type %s", org.OrgDomainVerificationAddedEventType)
|
||||||
|
}
|
||||||
|
var validationType domain.DomainValidationType
|
||||||
|
switch e.ValidationType {
|
||||||
|
case old_domain.OrgDomainValidationTypeDNS:
|
||||||
|
validationType = domain.DomainValidationTypeDNS
|
||||||
|
case old_domain.OrgDomainValidationTypeHTTP:
|
||||||
|
validationType = domain.DomainValidationTypeHTTP
|
||||||
|
case old_domain.OrgDomainValidationTypeUnspecified:
|
||||||
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-FJfKB", "reduce.unsupported.validation.type %v", e.ValidationType)
|
||||||
|
}
|
||||||
|
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
|
||||||
|
tx, ok := ex.(*sql.Tx)
|
||||||
|
if !ok {
|
||||||
|
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-yF03i", "reduce.wrong.db.pool %T", ex)
|
||||||
|
}
|
||||||
|
domainRepo := repository.OrganizationRepository(v3_sql.SQLTx(tx)).Domains(false)
|
||||||
|
_, err := domainRepo.Update(ctx,
|
||||||
|
database.And(
|
||||||
|
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
||||||
|
domainRepo.OrgIDCondition(e.Aggregate().ResourceOwner),
|
||||||
|
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
||||||
|
),
|
||||||
|
domainRepo.SetValidationType(validationType),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *orgDomainRelationalProjection) reduceVerified(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
e, ok := event.(*org.DomainVerifiedEvent)
|
||||||
|
if !ok {
|
||||||
|
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-7WrI2", "reduce.wrong.event.type %s", org.OrgDomainVerifiedEventType)
|
||||||
|
}
|
||||||
|
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
|
||||||
|
tx, ok := ex.(*sql.Tx)
|
||||||
|
if !ok {
|
||||||
|
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-0ZGqC", "reduce.wrong.db.pool %T", ex)
|
||||||
|
}
|
||||||
|
domainRepo := repository.OrganizationRepository(v3_sql.SQLTx(tx)).Domains(false)
|
||||||
|
_, err := domainRepo.Update(ctx,
|
||||||
|
database.And(
|
||||||
|
domainRepo.InstanceIDCondition(e.Aggregate().InstanceID),
|
||||||
|
domainRepo.OrgIDCondition(e.Aggregate().ResourceOwner),
|
||||||
|
domainRepo.DomainCondition(database.TextOperationEqual, e.Domain),
|
||||||
|
),
|
||||||
|
domainRepo.SetVerified(),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user