From a377f2816c42d3141bf1ff270c89606451e945d9 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Wed, 8 Jun 2022 13:46:24 +0200 Subject: [PATCH] feat: return instance domains on list instances, fix: login policy and avatar url in oidc responses (#3785) * feat: return instance domains on list instances * fix: filter login policy idps correctly * remove debug * fix: absolute avatar url in oidc responses --- docs/docs/apis/proto/instance.md | 1 + internal/api/grpc/instance/converter.go | 5 +- internal/api/oidc/client.go | 2 +- internal/api/oidc/op.go | 8 +- internal/query/idp_login_policy_link.go | 4 + internal/query/instance.go | 91 +++++-- internal/query/instance_test.go | 340 ++++++++++++++++++++++++ internal/query/login_policy.go | 2 +- internal/query/login_policy_test.go | 6 +- internal/view/repository/requests.go | 2 +- proto/zitadel/instance.proto | 1 + 11 files changed, 432 insertions(+), 30 deletions(-) diff --git a/docs/docs/apis/proto/instance.md b/docs/docs/apis/proto/instance.md index 43152e5cea..d024ed6450 100644 --- a/docs/docs/apis/proto/instance.md +++ b/docs/docs/apis/proto/instance.md @@ -92,6 +92,7 @@ IdQuery is always equals | state | State | - | | | name | string | - | | | version | string | - | | +| domains | repeated Domain | - | | diff --git a/internal/api/grpc/instance/converter.go b/internal/api/grpc/instance/converter.go index bb410316aa..3feb9e675d 100644 --- a/internal/api/grpc/instance/converter.go +++ b/internal/api/grpc/instance/converter.go @@ -23,8 +23,9 @@ func InstanceToPb(instance *query.Instance) *instance_pb.Instance { instance.ChangeDate, instance.InstanceID(), ), - Id: instance.InstanceID(), - Name: instance.Name, + Id: instance.InstanceID(), + Name: instance.Name, + Domains: DomainsToPb(instance.Domains), } } diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index 93fb24ce2b..298066aa31 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -209,7 +209,7 @@ func (o *OPStorage) setUserinfo(ctx context.Context, userInfo oidc.UserInfoSette userInfo.SetNickname(user.Human.NickName) userInfo.SetGender(getGender(user.Human.Gender)) userInfo.SetLocale(user.Human.PreferredLanguage) - userInfo.SetPicture(domain.AvatarURL(o.assetAPIPrefix, user.ResourceOwner, user.Human.AvatarKey)) + userInfo.SetPicture(domain.AvatarURL(o.assetAPIPrefix(ctx), user.ResourceOwner, user.Human.AvatarKey)) } else { userInfo.SetName(user.Machine.Name) } diff --git a/internal/api/oidc/op.go b/internal/api/oidc/op.go index a194fa0c40..b2db6c5233 100644 --- a/internal/api/oidc/op.go +++ b/internal/api/oidc/op.go @@ -70,7 +70,7 @@ type OPStorage struct { defaultRefreshTokenExpiration time.Duration encAlg crypto.EncryptionAlgorithm locker crdb.Locker - assetAPIPrefix string + assetAPIPrefix func(ctx context.Context) string } func NewProvider(ctx context.Context, config Config, defaultLogoutRedirectURI string, externalSecure bool, command *command.Commands, query *query.Queries, repo repository.Repository, encryptionAlg crypto.EncryptionAlgorithm, cryptoKey []byte, es *eventstore.Eventstore, projections *sql.DB, userAgentCookie, instanceHandler func(http.Handler) http.Handler) (op.OpenIDProvider, error) { @@ -78,7 +78,7 @@ func NewProvider(ctx context.Context, config Config, defaultLogoutRedirectURI st if err != nil { return nil, caos_errs.ThrowInternal(err, "OIDC-EGrqd", "cannot create op config: %w") } - storage := newStorage(config, command, query, repo, encryptionAlg, es, projections) + storage := newStorage(config, command, query, repo, encryptionAlg, es, projections, externalSecure) options, err := createOptions(config, externalSecure, userAgentCookie, instanceHandler) if err != nil { return nil, caos_errs.ThrowInternal(err, "OIDC-D3gq1", "cannot create options: %w") @@ -168,7 +168,7 @@ func customEndpoints(endpointConfig *EndpointConfig) []op.Option { return options } -func newStorage(config Config, command *command.Commands, query *query.Queries, repo repository.Repository, encAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, projections *sql.DB) *OPStorage { +func newStorage(config Config, command *command.Commands, query *query.Queries, repo repository.Repository, encAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, projections *sql.DB, externalSecure bool) *OPStorage { return &OPStorage{ repo: repo, command: command, @@ -182,7 +182,7 @@ func newStorage(config Config, command *command.Commands, query *query.Queries, defaultRefreshTokenExpiration: config.DefaultRefreshTokenExpiration, encAlg: encAlg, locker: crdb.NewLocker(projections, locksTable, signingKey), - assetAPIPrefix: assets.HandlerPrefix, + assetAPIPrefix: assets.AssetAPI(externalSecure), } } diff --git a/internal/query/idp_login_policy_link.go b/internal/query/idp_login_policy_link.go index 0ab280d44c..e4095064d6 100644 --- a/internal/query/idp_login_policy_link.go +++ b/internal/query/idp_login_policy_link.go @@ -56,6 +56,10 @@ var ( name: projection.IDPLoginPolicyLinkSequenceCol, table: idpLoginPolicyLinkTable, } + IDPLoginPolicyLinkAggregateIDCol = Column{ + name: projection.IDPLoginPolicyLinkAggregateIDCol, + table: idpLoginPolicyLinkTable, + } IDPLoginPolicyLinkResourceOwnerCol = Column{ name: projection.IDPLoginPolicyLinkResourceOwnerCol, table: idpLoginPolicyLinkTable, diff --git a/internal/query/instance.go b/internal/query/instance.go index 5b5c05b74a..91a30d6fbe 100644 --- a/internal/query/instance.go +++ b/internal/query/instance.go @@ -15,6 +15,10 @@ import ( "github.com/zitadel/zitadel/internal/query/projection" ) +const ( + InstancesFilterTableAlias = "f" +) + var ( instanceTable = table{ name: projection.InstanceProjectionTable, @@ -136,8 +140,8 @@ func (q *InstanceSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder } func (q *Queries) SearchInstances(ctx context.Context, queries *InstanceSearchQueries) (instances *Instances, err error) { - query, scan := prepareInstancesQuery() - stmt, args, err := queries.toQuery(query).ToSql() + filter, query, scan := prepareInstancesQuery() + stmt, args, err := query(queries.toQuery(filter)).ToSql() if err != nil { return nil, errors.ThrowInvalidArgument(err, "QUERY-M9fow", "Errors.Query.SQLStatement") } @@ -232,27 +236,55 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta } } -func prepareInstancesQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { +func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + instanceFilterTable := instanceTable.setAlias(InstancesFilterTableAlias) + instanceFilterIDColumn := InstanceColumnID.setTable(instanceFilterTable) + instanceFilterCountColumn := InstancesFilterTableAlias + ".count" return sq.Select( InstanceColumnID.identifier(), - InstanceColumnCreationDate.identifier(), - InstanceColumnChangeDate.identifier(), - InstanceColumnSequence.identifier(), - InstanceColumnName.identifier(), - InstanceColumnDefaultOrgID.identifier(), - InstanceColumnProjectID.identifier(), - InstanceColumnConsoleID.identifier(), - InstanceColumnConsoleAppID.identifier(), - InstanceColumnDefaultLanguage.identifier(), countColumn.identifier(), - ).From(instanceTable.identifier()).PlaceholderFormat(sq.Dollar), + ).From(instanceTable.identifier()), + func(builder sq.SelectBuilder) sq.SelectBuilder { + return sq.Select( + instanceFilterCountColumn, + instanceFilterIDColumn.identifier(), + InstanceColumnCreationDate.identifier(), + InstanceColumnChangeDate.identifier(), + InstanceColumnSequence.identifier(), + InstanceColumnName.identifier(), + InstanceColumnDefaultOrgID.identifier(), + InstanceColumnProjectID.identifier(), + InstanceColumnConsoleID.identifier(), + InstanceColumnConsoleAppID.identifier(), + InstanceColumnDefaultLanguage.identifier(), + InstanceDomainDomainCol.identifier(), + InstanceDomainIsPrimaryCol.identifier(), + InstanceDomainIsGeneratedCol.identifier(), + InstanceDomainCreationDateCol.identifier(), + InstanceDomainChangeDateCol.identifier(), + InstanceDomainSequenceCol.identifier(), + ).FromSelect(builder, InstancesFilterTableAlias). + LeftJoin(join(InstanceColumnID, instanceFilterIDColumn)). + LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn)). + PlaceholderFormat(sq.Dollar) + }, func(rows *sql.Rows) (*Instances, error) { instances := make([]*Instance, 0) + var lastInstance *Instance var count uint64 for rows.Next() { instance := new(Instance) lang := "" + var ( + domain sql.NullString + isPrimary sql.NullBool + isGenerated sql.NullBool + changeDate sql.NullTime + creationDate sql.NullTime + sequence sql.NullInt64 + ) err := rows.Scan( + &count, &instance.ID, &instance.CreationDate, &instance.ChangeDate, @@ -263,12 +295,35 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instances, err &instance.ConsoleID, &instance.ConsoleAppID, &lang, - &count, + &domain, + &isPrimary, + &isGenerated, + &changeDate, + &creationDate, + &sequence, ) - instance.DefaultLang = language.Make(lang) if err != nil { return nil, err } + if instance.ID == "" || !domain.Valid { + continue + } + instance.DefaultLang = language.Make(lang) + instanceDomain := &InstanceDomain{ + CreationDate: creationDate.Time, + ChangeDate: changeDate.Time, + Sequence: uint64(sequence.Int64), + Domain: domain.String, + IsPrimary: isPrimary.Bool, + IsGenerated: isGenerated.Bool, + InstanceID: instance.ID, + } + if lastInstance != nil && instance.ID == lastInstance.ID { + lastInstance.Domains = append(lastInstance.Domains, instanceDomain) + continue + } + lastInstance = instance + instance.Domains = append(instance.Domains, instanceDomain) instances = append(instances, instance) } @@ -320,7 +375,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) isGenerated sql.NullBool changeDate sql.NullTime creationDate sql.NullTime - sequecne sql.NullInt64 + sequence sql.NullInt64 ) err := rows.Scan( &instance.ID, @@ -338,7 +393,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) &isGenerated, &changeDate, &creationDate, - &sequecne, + &sequence, ) if err != nil { if errs.Is(err, sql.ErrNoRows) { @@ -352,7 +407,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) instance.Domains = append(instance.Domains, &InstanceDomain{ CreationDate: creationDate.Time, ChangeDate: changeDate.Time, - Sequence: uint64(sequecne.Int64), + Sequence: uint64(sequence.Int64), Domain: domain.String, IsPrimary: isPrimary.Bool, IsGenerated: isGenerated.Bool, diff --git a/internal/query/instance_test.go b/internal/query/instance_test.go index 9fc79e2a49..caca2673b0 100644 --- a/internal/query/instance_test.go +++ b/internal/query/instance_test.go @@ -135,6 +135,346 @@ func Test_InstancePrepares(t *testing.T) { }, object: nil, }, + { + name: "prepareInstancesQuery no result", + prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery() + return query(filter), scan + }, + want: want{ + sqlExpectations: mockQueries( + regexp.QuoteMeta(`SELECT f.count, f.id,`+ + ` projections.instances.creation_date,`+ + ` projections.instances.change_date,`+ + ` projections.instances.sequence,`+ + ` projections.instances.name,`+ + ` projections.instances.default_org_id,`+ + ` projections.instances.iam_project_id,`+ + ` projections.instances.console_client_id,`+ + ` projections.instances.console_app_id,`+ + ` projections.instances.default_language,`+ + ` projections.instance_domains.domain,`+ + ` projections.instance_domains.is_primary,`+ + ` projections.instance_domains.is_generated,`+ + ` projections.instance_domains.creation_date,`+ + ` projections.instance_domains.change_date, `+ + ` projections.instance_domains.sequence`+ + ` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f`+ + ` LEFT JOIN projections.instances ON f.id = projections.instances.id`+ + ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id`), + nil, + nil, + ), + }, + object: &Instances{Instances: []*Instance{}}, + }, + { + name: "prepareInstancesQuery one result", + prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery() + return query(filter), scan + }, + want: want{ + sqlExpectations: mockQueries( + regexp.QuoteMeta(`SELECT f.count, f.id,`+ + ` projections.instances.creation_date,`+ + ` projections.instances.change_date,`+ + ` projections.instances.sequence,`+ + ` projections.instances.name,`+ + ` projections.instances.default_org_id,`+ + ` projections.instances.iam_project_id,`+ + ` projections.instances.console_client_id,`+ + ` projections.instances.console_app_id,`+ + ` projections.instances.default_language,`+ + ` projections.instance_domains.domain,`+ + ` projections.instance_domains.is_primary,`+ + ` projections.instance_domains.is_generated,`+ + ` projections.instance_domains.creation_date,`+ + ` projections.instance_domains.change_date, `+ + ` projections.instance_domains.sequence`+ + ` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f`+ + ` LEFT JOIN projections.instances ON f.id = projections.instances.id`+ + ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id`), + []string{ + "count", + "id", + "creation_date", + "change_date", + "sequence", + "name", + "default_org_id", + "iam_project_id", + "console_client_id", + "console_app_id", + "default_language", + "domain", + "is_primary", + "is_generated", + "creation_date", + "change_date", + "sequence", + }, + [][]driver.Value{ + { + "1", + "id", + testNow, + testNow, + uint64(20211108), + "test", + "global-org-id", + "project-id", + "client-id", + "app-id", + "en", + "test.zitadel.cloud", + true, + true, + testNow, + testNow, + uint64(20211108), + }, + }, + ), + }, + object: &Instances{ + SearchResponse: SearchResponse{ + Count: 1, + }, + Instances: []*Instance{ + { + ID: "id", + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Name: "test", + DefaultOrgID: "global-org-id", + IAMProjectID: "project-id", + ConsoleID: "client-id", + ConsoleAppID: "app-id", + DefaultLang: language.English, + Domains: []*InstanceDomain{ + { + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + InstanceID: "id", + Domain: "test.zitadel.cloud", + IsGenerated: true, + IsPrimary: true, + }, + }, + }, + }, + }, + }, + { + name: "prepareInstancesQuery multiple results", + prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery() + return query(filter), scan + }, + want: want{ + sqlExpectations: mockQueries( + regexp.QuoteMeta(`SELECT f.count, f.id,`+ + ` projections.instances.creation_date,`+ + ` projections.instances.change_date,`+ + ` projections.instances.sequence,`+ + ` projections.instances.name,`+ + ` projections.instances.default_org_id,`+ + ` projections.instances.iam_project_id,`+ + ` projections.instances.console_client_id,`+ + ` projections.instances.console_app_id,`+ + ` projections.instances.default_language,`+ + ` projections.instance_domains.domain,`+ + ` projections.instance_domains.is_primary,`+ + ` projections.instance_domains.is_generated,`+ + ` projections.instance_domains.creation_date,`+ + ` projections.instance_domains.change_date, `+ + ` projections.instance_domains.sequence`+ + ` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f`+ + ` LEFT JOIN projections.instances ON f.id = projections.instances.id`+ + ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id`), + []string{ + "count", + "id", + "creation_date", + "change_date", + "sequence", + "name", + "default_org_id", + "iam_project_id", + "console_client_id", + "console_app_id", + "default_language", + "domain", + "is_primary", + "is_generated", + "creation_date", + "change_date", + "sequence", + }, + [][]driver.Value{ + { + 2, + "id", + testNow, + testNow, + uint64(20211108), + "test", + "global-org-id", + "project-id", + "client-id", + "app-id", + "en", + "test.zitadel.cloud", + false, + true, + testNow, + testNow, + uint64(20211108), + }, + { + 2, + "id", + testNow, + testNow, + uint64(20211108), + "test", + "global-org-id", + "project-id", + "client-id", + "app-id", + "en", + "zitadel.cloud", + true, + false, + testNow, + testNow, + uint64(20211108), + }, + { + 2, + "id2", + testNow, + testNow, + uint64(20211108), + "test2", + "global-org-id", + "project-id", + "client-id", + "app-id", + "en", + "test2.zitadel.cloud", + true, + true, + testNow, + testNow, + uint64(20211108), + }, + }, + ), + }, + object: &Instances{ + SearchResponse: SearchResponse{ + Count: 2, + }, + Instances: []*Instance{ + { + ID: "id", + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Name: "test", + DefaultOrgID: "global-org-id", + IAMProjectID: "project-id", + ConsoleID: "client-id", + ConsoleAppID: "app-id", + DefaultLang: language.English, + Domains: []*InstanceDomain{ + { + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Domain: "test.zitadel.cloud", + InstanceID: "id", + IsGenerated: true, + IsPrimary: false, + }, + { + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Domain: "zitadel.cloud", + InstanceID: "id", + IsGenerated: false, + IsPrimary: true, + }, + }, + }, { + ID: "id2", + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Name: "test2", + DefaultOrgID: "global-org-id", + IAMProjectID: "project-id", + ConsoleID: "client-id", + ConsoleAppID: "app-id", + DefaultLang: language.English, + Domains: []*InstanceDomain{ + { + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211108, + Domain: "test2.zitadel.cloud", + InstanceID: "id2", + IsGenerated: true, + IsPrimary: true, + }, + }, + }, + }, + }, + }, + { + name: "prepareInstancesQuery sql err", + prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery() + return query(filter), scan + }, + want: want{ + sqlExpectations: mockQueryErr( + regexp.QuoteMeta(`SELECT f.count, f.id,`+ + ` projections.instances.creation_date,`+ + ` projections.instances.change_date,`+ + ` projections.instances.sequence,`+ + ` projections.instances.name,`+ + ` projections.instances.default_org_id,`+ + ` projections.instances.iam_project_id,`+ + ` projections.instances.console_client_id,`+ + ` projections.instances.console_app_id,`+ + ` projections.instances.default_language,`+ + ` projections.instance_domains.domain,`+ + ` projections.instance_domains.is_primary,`+ + ` projections.instance_domains.is_generated,`+ + ` projections.instance_domains.creation_date,`+ + ` projections.instance_domains.change_date, `+ + ` projections.instance_domains.sequence`+ + ` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f`+ + ` LEFT JOIN projections.instances ON f.id = projections.instances.id`+ + ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id`), + sql.ErrConnDone, + ), + err: func(err error) (error, bool) { + if !errors.Is(err, sql.ErrConnDone) { + return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false + } + return nil, true + }, + }, + object: nil, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/query/login_policy.go b/internal/query/login_policy.go index 86a8284b86..09465e5356 100644 --- a/internal/query/login_policy.go +++ b/internal/query/login_policy.go @@ -311,7 +311,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, IDPNameCol.identifier(), IDPTypeCol.identifier(), ).From(loginPolicyTable.identifier()). - LeftJoin(join(IDPLoginPolicyLinkIDPIDCol, LoginPolicyColumnOrgID)). + LeftJoin(join(IDPLoginPolicyLinkAggregateIDCol, LoginPolicyColumnOrgID)). LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol)). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*LoginPolicy, error) { diff --git a/internal/query/login_policy_test.go b/internal/query/login_policy_test.go index ecefa8fa95..6f097c0a58 100644 --- a/internal/query/login_policy_test.go +++ b/internal/query/login_policy_test.go @@ -56,7 +56,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.idps.type`+ ` FROM projections.login_policies`+ ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.idp_id`+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ ` LEFT JOIN projections.idps ON`+ ` projections.idp_login_policy_links.idp_id = projections.idps.id`), nil, @@ -101,7 +101,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.idps.type`+ ` FROM projections.login_policies`+ ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.idp_id`+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ ` LEFT JOIN projections.idps ON`+ ` projections.idp_login_policy_links.idp_id = projections.idps.id`), []string{ @@ -216,7 +216,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.idps.type`+ ` FROM projections.login_policies`+ ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.idp_id`+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ ` LEFT JOIN projections.idps ON`+ ` projections.idp_login_policy_links.idp_id = projections.idps.id`), sql.ErrConnDone, diff --git a/internal/view/repository/requests.go b/internal/view/repository/requests.go index 4dc22dea76..29f28b25a9 100644 --- a/internal/view/repository/requests.go +++ b/internal/view/repository/requests.go @@ -39,7 +39,7 @@ func PrepareGetByQuery(table string, queries ...SearchQuery) func(db *gorm.DB, r } } - err := query.Debug().Take(res).Error + err := query.Take(res).Error if err == nil { return nil } diff --git a/proto/zitadel/instance.proto b/proto/zitadel/instance.proto index e75dd89bf6..3205d614cb 100644 --- a/proto/zitadel/instance.proto +++ b/proto/zitadel/instance.proto @@ -30,6 +30,7 @@ message Instance { example: "\"1.0.0\""; } ]; + repeated Domain domains = 6; } message InstanceDetail {