This commit is contained in:
adlerhurst
2025-07-23 09:47:04 +02:00
parent ef0722e352
commit ca3dbd4d9d
15 changed files with 424 additions and 304 deletions

View File

@@ -110,11 +110,3 @@ type InstanceRepository interface {
type CreateInstance struct {
Name string `json:"name"`
}
type InstanceQueryOption func(*InstanceQueryOpts)
type InstanceQueryOpts struct {
database.QueryOpts
JoinDomains bool
}

View File

@@ -2,22 +2,16 @@ package domain
import (
"context"
"encoding/json"
"time"
"github.com/zitadel/zitadel/backend/v3/storage/database"
)
type InstanceDomains struct {
domains []*InstanceDomain
Raw json.RawMessage
}
type InstanceDomain struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
ValidationType DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
CreatedAt string `json:"createdAt,omitempty" db:"created_at"`
@@ -25,10 +19,10 @@ type InstanceDomain struct {
}
type AddInstanceDomain struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
VerificationType DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
// CreatedAt is the time when the domain was added.

View File

@@ -103,4 +103,3 @@ type MemberRepository interface {
SetMemberRoles(ctx context.Context, orgID, userID string, roles []string) error
RemoveMember(ctx context.Context, orgID, userID string) error
}

View File

@@ -8,11 +8,11 @@ import (
)
type OrganizationDomain struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID string `json:"orgId,omitempty" db:"org_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID string `json:"orgId,omitempty" db:"org_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
ValidationType DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
CreatedAt string `json:"createdAt,omitempty" db:"created_at"`
@@ -20,11 +20,11 @@ type OrganizationDomain struct {
}
type AddOrganizationDomain struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID string `json:"orgId,omitempty" db:"org_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID string `json:"orgId,omitempty" db:"org_id"`
Domain string `json:"domain,omitempty" db:"domain"`
IsVerified bool `json:"isVerified,omitempty" db:"is_verified"`
IsPrimary bool `json:"isPrimary,omitempty" db:"is_primary"`
ValidationType DomainValidationType `json:"validationType,omitempty" db:"validation_type"`
// CreatedAt is the time when the domain was added.

View File

@@ -53,6 +53,6 @@ type ignoreCaseCol struct {
// WriteIgnoreCase implements [ignoreCaseColumn].
func (c ignoreCaseCol) WriteIgnoreCase(builder *StatementBuilder) {
c.column.Write(builder)
c.Write(builder)
builder.WriteString(c.suffix)
}

View File

@@ -23,7 +23,7 @@ func (c *pgxConn) Release(_ context.Context) error {
// Begin implements [database.Client].
func (c *pgxConn) Begin(ctx context.Context, opts *database.TransactionOptions) (database.Transaction, error) {
tx, err := c.Conn.BeginTx(ctx, transactionOptionsToPgx(opts))
tx, err := c.BeginTx(ctx, transactionOptionsToPgx(opts))
if err != nil {
return nil, wrapError(err)
}

View File

@@ -58,7 +58,7 @@ func (c *pgxPool) Exec(ctx context.Context, sql string, args ...any) (int64, err
// Begin implements [database.Pool].
func (c *pgxPool) Begin(ctx context.Context, opts *database.TransactionOptions) (database.Transaction, error) {
tx, err := c.Pool.BeginTx(ctx, transactionOptionsToPgx(opts))
tx, err := c.BeginTx(ctx, transactionOptionsToPgx(opts))
if err != nil {
return nil, wrapError(err)
}

View File

@@ -51,7 +51,7 @@ func WithLeftJoin(table string, columns Condition) QueryOption {
type joinType string
const (
JoinTypeLeft joinType = "LEFT"
JoinTypeLeft joinType = "LEFT"
)
type join struct {
@@ -68,13 +68,13 @@ type QueryOpts struct {
Condition Condition
// OrderBy is the columns to order the results by.
// It is used to build the ORDER BY clause of the SQL statement.
OrderBy Columns
OrderBy Columns
// Limit is the maximum number of results to return.
// It is used to build the LIMIT clause of the SQL statement.
Limit uint32
Limit uint32
// Offset is the number of results to skip before returning the results.
// It is used to build the OFFSET clause of the SQL statement.
Offset uint32
Offset uint32
// GroupBy is the columns to group the results by.
// It is used to build the GROUP BY clause of the SQL statement.
GroupBy Columns
@@ -83,7 +83,6 @@ type QueryOpts struct {
Joins []join
}
func (opts *QueryOpts) Write(builder *StatementBuilder) {
opts.WriteLeftJoins(builder)
opts.WriteCondition(builder)
@@ -145,4 +144,4 @@ func (opts *QueryOpts) WriteLeftJoins(builder *StatementBuilder) {
builder.WriteString(" ON ")
join.columns.Write(builder)
}
}
}

View File

@@ -24,24 +24,23 @@ func InstanceRepository(client database.QueryExecutor) domain.InstanceRepository
}
}
// -------------------------------------------------------------
// repository
// -------------------------------------------------------------
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` +
` , 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` +
` FROM zitadel.instances`
` , 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` +
` FROM zitadel.instances`
)
// Get implements [domain.InstanceRepository].
func (i *instance) Get(ctx context.Context, opts ...database.QueryOption) (*domain.Instance, error) {
opts = append(opts,
i.joinDomains(),
opts = append(opts,
i.joinDomains(),
database.WithGroupBy(i.IDColumn(true)),
)
options := new(database.QueryOpts)
for _, opt := range opts {
opt(options)
@@ -56,11 +55,11 @@ func (i *instance) Get(ctx context.Context, opts ...database.QueryOption) (*doma
// List implements [domain.InstanceRepository].
func (i *instance) List(ctx context.Context, opts ...database.QueryOption) ([]*domain.Instance, error) {
opts = append(opts,
i.joinDomains(),
opts = append(opts,
i.joinDomains(),
database.WithGroupBy(i.IDColumn(true)),
)
options := new(database.QueryOpts)
for _, opt := range opts {
opt(options)
@@ -243,7 +242,7 @@ func scanInstance(ctx context.Context, querier database.Querier, builder *databa
if err != nil {
return nil, err
}
var instance rawInstance
if err := rows.(database.CollectableRows).CollectExactlyOneRow(&instance); err != nil {
return nil, err

View File

@@ -229,4 +229,4 @@ func scanInstanceDomain(ctx context.Context, querier database.Querier, builder *
}
return instanceDomain, nil
}
}

View File

@@ -58,12 +58,12 @@ func (o *org) List(ctx context.Context, opts ...database.QueryOption) ([]*domain
database.WithGroupBy(o.InstanceIDColumn(true), o.IDColumn(true)),
)
options := new(database.QueryOpts)
options := new(database.QueryOpts)
for _, opt := range opts {
opt(options)
}
var builder database.StatementBuilder
var builder database.StatementBuilder
builder.WriteString(queryOrganizationStmt)
options.Write(&builder)
@@ -72,7 +72,7 @@ func (o *org) List(ctx context.Context, opts ...database.QueryOption) ([]*domain
func (o *org) joinDomains() database.QueryOption {
columns := make([]database.Condition, 0, 3)
columns = append(columns,
columns = append(columns,
database.NewColumnCondition(o.InstanceIDColumn(true), o.Domains(false).InstanceIDColumn(true)),
database.NewColumnCondition(o.IDColumn(true), o.Domains(false).OrgIDColumn(true)),
)
@@ -89,7 +89,6 @@ func (o *org) joinDomains() database.QueryOption {
)
}
const createOrganizationStmt = `INSERT INTO zitadel.organizations (id, name, instance_id, state)` +
` VALUES ($1, $2, $3, $4)` +
` RETURNING created_at, updated_at`
@@ -103,7 +102,6 @@ func (o *org) Create(ctx context.Context, organization *domain.Organization) err
return o.client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&organization.CreatedAt, &organization.UpdatedAt)
}
// Update implements [domain.OrganizationRepository].
func (o *org) Update(ctx context.Context, id domain.OrgIdentifierCondition, instanceID string, changes ...database.Change) (int64, error) {
if len(changes) == 0 {
@@ -266,7 +264,7 @@ func scanOrganizations(ctx context.Context, querier database.Querier, builder *d
if err := rows.(database.CollectableRows).Collect(&rawOrgs); err != nil {
return nil, err
}
organizations := make([]*domain.Organization, len(rawOrgs))
for i, org := range rawOrgs {
if len(org.RawDomains) > 0 {

View File

@@ -14,8 +14,6 @@ type orgDomain struct {
*org
}
// -------------------------------------------------------------
// repository
// -------------------------------------------------------------
@@ -146,7 +144,7 @@ func (o orgDomain) OrgIDCondition(orgID string) database.Condition {
// Subtle: this method shadows the method ([domain.OrganizationRepository]).CreatedAtColumn of orgDomain.org.
func (orgDomain) CreatedAtColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.created_at")
return database.NewColumn("org_domains.created_at")
}
return database.NewColumn("created_at")
}
@@ -154,7 +152,7 @@ func (orgDomain) CreatedAtColumn(qualified bool) database.Column {
// DomainColumn implements [domain.OrganizationDomainRepository].
func (orgDomain) DomainColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.domain")
return database.NewColumn("org_domains.domain")
}
return database.NewColumn("domain")
}
@@ -163,7 +161,7 @@ func (orgDomain) DomainColumn(qualified bool) database.Column {
// Subtle: this method shadows the method ([domain.OrganizationRepository]).InstanceIDColumn of orgDomain.org.
func (orgDomain) InstanceIDColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.instance_id")
return database.NewColumn("org_domains.instance_id")
}
return database.NewColumn("instance_id")
}
@@ -171,7 +169,7 @@ func (orgDomain) InstanceIDColumn(qualified bool) database.Column {
// IsPrimaryColumn implements [domain.OrganizationDomainRepository].
func (orgDomain) IsPrimaryColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.is_primary")
return database.NewColumn("org_domains.is_primary")
}
return database.NewColumn("is_primary")
}
@@ -179,7 +177,7 @@ func (orgDomain) IsPrimaryColumn(qualified bool) database.Column {
// IsVerifiedColumn implements [domain.OrganizationDomainRepository].
func (orgDomain) IsVerifiedColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.is_verified")
return database.NewColumn("org_domains.is_verified")
}
return database.NewColumn("is_verified")
}
@@ -187,7 +185,7 @@ func (orgDomain) IsVerifiedColumn(qualified bool) database.Column {
// OrgIDColumn implements [domain.OrganizationDomainRepository].
func (orgDomain) OrgIDColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.org_id")
return database.NewColumn("org_domains.org_id")
}
return database.NewColumn("org_id")
}
@@ -196,7 +194,7 @@ func (orgDomain) OrgIDColumn(qualified bool) database.Column {
// Subtle: this method shadows the method ([domain.OrganizationRepository]).UpdatedAtColumn of orgDomain.org.
func (orgDomain) UpdatedAtColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.updated_at")
return database.NewColumn("org_domains.updated_at")
}
return database.NewColumn("updated_at")
}
@@ -204,7 +202,7 @@ func (orgDomain) UpdatedAtColumn(qualified bool) database.Column {
// ValidationTypeColumn implements [domain.OrganizationDomainRepository].
func (orgDomain) ValidationTypeColumn(qualified bool) database.Column {
if qualified {
return database.NewColumn("org_domains.validation_type")
return database.NewColumn("org_domains.validation_type")
}
return database.NewColumn("validation_type")
}
@@ -218,7 +216,7 @@ func scanOrganizationDomain(ctx context.Context, client database.Querier, builde
if err != nil {
return nil, err
}
organizationDomain := &domain.OrganizationDomain{}
if err := rows.(database.CollectableRows).CollectExactlyOneRow(organizationDomain); err != nil {
return nil, err

View File

@@ -74,4 +74,3 @@ package repository_test
// user.Human().Update(context.Background(), user.IDCondition("test"), user.SetUsername("test"))
// })
// }