mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-09 07:35:13 +00:00
fix(repo): correct mapping for domains (#10653)
This pull request fixes an issue where the repository would fail to scan organization or instance structs if the `domains` column was `NULL`. ## Which problems are solved If the `domains` column of `orgs` or `instances` was `NULL`, the repository failed scanning into the structs. This happened because the scanning mechanism did not correctly handle `NULL` JSONB columns. ## How the problems are solved A new generic type `JSONArray[T]` is introduced, which implements the `sql.Scanner` interface. This type can correctly scan JSON arrays from the database, including handling `NULL` values gracefully. The repositories for instances and organizations have been updated to use this new type for the domains field. The SQL queries have also been improved to use `FILTER` with `jsonb_agg` for better readability and performance when aggregating domains. ## Additional changes * An unnecessary cleanup step in the organization domain tests for already removed domains has been removed. * The `pgxscan` library has been replaced with `sqlscan` for scanning `database/sql`.Rows. * Minor cleanups in integration tests.
This commit is contained in:
@@ -2,8 +2,6 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
@@ -34,7 +32,7 @@ func InstanceRepository(client database.QueryExecutor) domain.InstanceRepository
|
||||
|
||||
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, '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` +
|
||||
` , 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)) FILTER (WHERE instance_domains.instance_id IS NOT NULL) AS domains` +
|
||||
` FROM zitadel.instances`
|
||||
)
|
||||
|
||||
@@ -236,9 +234,13 @@ func (instance) UpdatedAtColumn() database.Column {
|
||||
return database.NewColumn("instances", "updated_at")
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// scanners
|
||||
// -------------------------------------------------------------
|
||||
|
||||
type rawInstance struct {
|
||||
*domain.Instance
|
||||
RawDomains sql.Null[json.RawMessage] `json:"domains,omitzero" db:"domains"`
|
||||
Domains JSONArray[domain.InstanceDomain] `json:"domains,omitempty" db:"domains"`
|
||||
}
|
||||
|
||||
func scanInstance(ctx context.Context, querier database.Querier, builder *database.StatementBuilder) (*domain.Instance, error) {
|
||||
@@ -251,12 +253,7 @@ func scanInstance(ctx context.Context, querier database.Querier, builder *databa
|
||||
if err := rows.(database.CollectableRows).CollectExactlyOneRow(&instance); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if instance.RawDomains.Valid {
|
||||
if err := json.Unmarshal(instance.RawDomains.V, &instance.Domains); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
instance.Instance.Domains = instance.Domains
|
||||
|
||||
return instance.Instance, nil
|
||||
}
|
||||
@@ -267,21 +264,18 @@ func scanInstances(ctx context.Context, querier database.Querier, builder *datab
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rawInstances []*rawInstance
|
||||
if err := rows.(database.CollectableRows).Collect(&rawInstances); err != nil {
|
||||
var instances []*rawInstance
|
||||
if err := rows.(database.CollectableRows).Collect(&instances); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instances := make([]*domain.Instance, len(rawInstances))
|
||||
for i, instance := range rawInstances {
|
||||
if instance.RawDomains.Valid {
|
||||
if err := json.Unmarshal(instance.RawDomains.V, &instance.Domains); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
instances[i] = instance.Instance
|
||||
result := make([]*domain.Instance, len(instances))
|
||||
for i, inst := range instances {
|
||||
result[i] = inst.Instance
|
||||
result[i].Domains = inst.Domains
|
||||
}
|
||||
return instances, nil
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user