mirror of
https://github.com/zitadel/zitadel.git
synced 2025-06-03 14:38:21 +00:00
perf: query data AS OF SYSTEM TIME
(#5231)
Queries the data in the storage layser at the timestamp when the call hit the API layer
This commit is contained in:
parent
80003939ad
commit
e38abdcdf3
@ -93,102 +93,4 @@ protoc \
|
|||||||
mv ${ZITADEL_PATH}/pkg/grpc/auth/zitadel/* ${ZITADEL_PATH}/pkg/grpc/auth
|
mv ${ZITADEL_PATH}/pkg/grpc/auth/zitadel/* ${ZITADEL_PATH}/pkg/grpc/auth
|
||||||
rm -r ${ZITADEL_PATH}/pkg/grpc/auth/zitadel
|
rm -r ${ZITADEL_PATH}/pkg/grpc/auth/zitadel
|
||||||
|
|
||||||
## generate docs
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,system.md \
|
|
||||||
${PROTO_PATH}/system.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,auth.md \
|
|
||||||
${PROTO_PATH}/auth.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,management.md \
|
|
||||||
${PROTO_PATH}/management.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,admin.md \
|
|
||||||
${PROTO_PATH}/admin.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,action.md \
|
|
||||||
${PROTO_PATH}/action.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,app.md \
|
|
||||||
${PROTO_PATH}/app.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,auth_n_key.md \
|
|
||||||
${PROTO_PATH}/auth_n_key.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,change.md \
|
|
||||||
${PROTO_PATH}/change.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,event.md \
|
|
||||||
${PROTO_PATH}/event.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,idp.md \
|
|
||||||
${PROTO_PATH}/idp.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,instance.md \
|
|
||||||
${PROTO_PATH}/instance.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,member.md \
|
|
||||||
${PROTO_PATH}/member.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,message.md \
|
|
||||||
${PROTO_PATH}/message.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,metadata.md \
|
|
||||||
${PROTO_PATH}/metadata.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,object.md \
|
|
||||||
${PROTO_PATH}/object.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,options.md \
|
|
||||||
${PROTO_PATH}/options.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,org.md \
|
|
||||||
${PROTO_PATH}/org.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,policy.md \
|
|
||||||
${PROTO_PATH}/policy.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,project.md \
|
|
||||||
${PROTO_PATH}/project.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,settings.md \
|
|
||||||
${PROTO_PATH}/settings.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,text.md \
|
|
||||||
${PROTO_PATH}/text.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,user.md \
|
|
||||||
${PROTO_PATH}/user.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,settings.md \
|
|
||||||
${PROTO_PATH}/settings.proto
|
|
||||||
protoc \
|
|
||||||
-I=/proto/include \
|
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,v1.md \
|
|
||||||
${PROTO_PATH}/v1.proto
|
|
||||||
|
|
||||||
echo "done generating grpc"
|
echo "done generating grpc"
|
||||||
|
@ -59,8 +59,8 @@ The user provided by flags needs privileges to
|
|||||||
func InitAll(config *Config) {
|
func InitAll(config *Config) {
|
||||||
err := initialise(config.Database,
|
err := initialise(config.Database,
|
||||||
VerifyUser(config.Database.Username(), config.Database.Password()),
|
VerifyUser(config.Database.Username(), config.Database.Password()),
|
||||||
VerifyDatabase(config.Database.Database()),
|
VerifyDatabase(config.Database.DatabaseName()),
|
||||||
VerifyGrant(config.Database.Database(), config.Database.Username()),
|
VerifyGrant(config.Database.DatabaseName(), config.Database.Username()),
|
||||||
)
|
)
|
||||||
logging.OnError(err).Fatal("unable to initialize the database")
|
logging.OnError(err).Fatal("unable to initialize the database")
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ func initialise(config database.Config, steps ...func(*sql.DB) error) error {
|
|||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
return Init(db, steps...)
|
return Init(db.DB, steps...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(db *sql.DB, steps ...func(*sql.DB) error) error {
|
func Init(db *sql.DB, steps ...func(*sql.DB) error) error {
|
||||||
|
@ -27,7 +27,7 @@ The user provided by flags needs priviledge to
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
config := MustNewConfig(viper.GetViper())
|
config := MustNewConfig(viper.GetViper())
|
||||||
|
|
||||||
err := initialise(config.Database, VerifyDatabase(config.Database.Database()))
|
err := initialise(config.Database, VerifyDatabase(config.Database.DatabaseName()))
|
||||||
logging.OnError(err).Fatal("unable to initialize the database")
|
logging.OnError(err).Fatal("unable to initialize the database")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ Prereqesits:
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
config := MustNewConfig(viper.GetViper())
|
config := MustNewConfig(viper.GetViper())
|
||||||
|
|
||||||
err := initialise(config.Database, VerifyGrant(config.Database.Database(), config.Database.Username()))
|
err := initialise(config.Database, VerifyGrant(config.Database.DatabaseName(), config.Database.Username()))
|
||||||
logging.OnError(err).Fatal("unable to set grant")
|
logging.OnError(err).Fatal("unable to set grant")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -66,14 +66,14 @@ func VerifyZitadel(db *sql.DB, config database.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func verifyZitadel(config database.Config) error {
|
func verifyZitadel(config database.Config) error {
|
||||||
logging.WithFields("database", config.Database()).Info("verify zitadel")
|
logging.WithFields("database", config.DatabaseName()).Info("verify zitadel")
|
||||||
|
|
||||||
db, err := database.Connect(config, false)
|
db, err := database.Connect(config, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := VerifyZitadel(db, config); err != nil {
|
if err := VerifyZitadel(db.DB, config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,5 +128,5 @@ func keyStorage(config database.Config, masterKey string) (crypto.KeyStorage, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return cryptoDB.NewKeyStorage(db, masterKey)
|
return cryptoDB.NewKeyStorage(db.DB, masterKey)
|
||||||
}
|
}
|
||||||
|
@ -66,14 +66,14 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
|||||||
logging.OnError(err).Fatal("unable to start eventstore")
|
logging.OnError(err).Fatal("unable to start eventstore")
|
||||||
migration.RegisterMappers(eventstoreClient)
|
migration.RegisterMappers(eventstoreClient)
|
||||||
|
|
||||||
steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient}
|
steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient.DB}
|
||||||
steps.s2AssetsTable = &AssetTable{dbClient: dbClient}
|
steps.s2AssetsTable = &AssetTable{dbClient: dbClient.DB}
|
||||||
|
|
||||||
steps.FirstInstance.instanceSetup = config.DefaultInstance
|
steps.FirstInstance.instanceSetup = config.DefaultInstance
|
||||||
steps.FirstInstance.userEncryptionKey = config.EncryptionKeys.User
|
steps.FirstInstance.userEncryptionKey = config.EncryptionKeys.User
|
||||||
steps.FirstInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP
|
steps.FirstInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP
|
||||||
steps.FirstInstance.masterKey = masterKey
|
steps.FirstInstance.masterKey = masterKey
|
||||||
steps.FirstInstance.db = dbClient
|
steps.FirstInstance.db = dbClient.DB
|
||||||
steps.FirstInstance.es = eventstoreClient
|
steps.FirstInstance.es = eventstoreClient
|
||||||
steps.FirstInstance.defaults = config.SystemDefaults
|
steps.FirstInstance.defaults = config.SystemDefaults
|
||||||
steps.FirstInstance.zitadelRoles = config.InternalAuthZ.RolePermissionMappings
|
steps.FirstInstance.zitadelRoles = config.InternalAuthZ.RolePermissionMappings
|
||||||
@ -81,11 +81,11 @@ func Setup(config *Config, steps *Steps, masterKey string) {
|
|||||||
steps.FirstInstance.externalSecure = config.ExternalSecure
|
steps.FirstInstance.externalSecure = config.ExternalSecure
|
||||||
steps.FirstInstance.externalPort = config.ExternalPort
|
steps.FirstInstance.externalPort = config.ExternalPort
|
||||||
|
|
||||||
steps.s4EventstoreIndexes = &EventstoreIndexes{dbClient: dbClient, dbType: config.Database.Type()}
|
steps.s4EventstoreIndexes = &EventstoreIndexes{dbClient: dbClient.DB, dbType: config.Database.Type()}
|
||||||
steps.s5LastFailed = &LastFailed{dbClient: dbClient}
|
steps.s5LastFailed = &LastFailed{dbClient: dbClient.DB}
|
||||||
steps.s6OwnerRemoveColumns = &OwnerRemoveColumns{dbClient: dbClient}
|
steps.s6OwnerRemoveColumns = &OwnerRemoveColumns{dbClient: dbClient.DB}
|
||||||
steps.s7LogstoreTables = &LogstoreTables{dbClient: dbClient, username: config.Database.Username(), dbType: config.Database.Type()}
|
steps.s7LogstoreTables = &LogstoreTables{dbClient: dbClient.DB, username: config.Database.Username(), dbType: config.Database.Type()}
|
||||||
steps.s8AuthTokens = &AuthTokenIndexes{dbClient: dbClient}
|
steps.s8AuthTokens = &AuthTokenIndexes{dbClient: dbClient.DB}
|
||||||
|
|
||||||
err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil)
|
err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil)
|
||||||
logging.OnError(err).Fatal("unable to start projections")
|
logging.OnError(err).Fatal("unable to start projections")
|
||||||
|
@ -3,7 +3,6 @@ package start
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"database/sql"
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -95,7 +94,7 @@ func startZitadel(config *Config, masterKey string) error {
|
|||||||
return fmt.Errorf("cannot start client for projection: %w", err)
|
return fmt.Errorf("cannot start client for projection: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
keyStorage, err := cryptoDB.NewKeyStorage(dbClient, masterKey)
|
keyStorage, err := cryptoDB.NewKeyStorage(dbClient.DB, masterKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot start key storage: %w", err)
|
return fmt.Errorf("cannot start key storage: %w", err)
|
||||||
}
|
}
|
||||||
@ -120,7 +119,7 @@ func startZitadel(config *Config, masterKey string) error {
|
|||||||
return fmt.Errorf("error starting authz repo: %w", err)
|
return fmt.Errorf("error starting authz repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storage, err := config.AssetStorage.NewStorage(dbClient)
|
storage, err := config.AssetStorage.NewStorage(dbClient.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot start asset storage client: %w", err)
|
return fmt.Errorf("cannot start asset storage client: %w", err)
|
||||||
}
|
}
|
||||||
@ -162,7 +161,7 @@ func startZitadel(config *Config, masterKey string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
usageReporter := logstore.UsageReporterFunc(commands.ReportUsage)
|
usageReporter := logstore.UsageReporterFunc(commands.ReportUsage)
|
||||||
actionsLogstoreSvc := logstore.New(commands, usageReporter, actionsExecutionDBEmitter, actionsExecutionStdoutEmitter)
|
actionsLogstoreSvc := logstore.New(queries, usageReporter, actionsExecutionDBEmitter, actionsExecutionStdoutEmitter)
|
||||||
if actionsLogstoreSvc.Enabled() {
|
if actionsLogstoreSvc.Enabled() {
|
||||||
logging.Warn("execution logs are currently in beta")
|
logging.Warn("execution logs are currently in beta")
|
||||||
}
|
}
|
||||||
@ -175,7 +174,7 @@ func startZitadel(config *Config, masterKey string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = startAPIs(ctx, clock, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys, commands, usageReporter)
|
err = startAPIs(ctx, clock, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys, queries, usageReporter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -189,7 +188,7 @@ func startAPIs(
|
|||||||
commands *command.Commands,
|
commands *command.Commands,
|
||||||
queries *query.Queries,
|
queries *query.Queries,
|
||||||
eventstore *eventstore.Eventstore,
|
eventstore *eventstore.Eventstore,
|
||||||
dbClient *sql.DB,
|
dbClient *database.DB,
|
||||||
config *Config,
|
config *Config,
|
||||||
store static.Storage,
|
store static.Storage,
|
||||||
authZRepo authz_repo.Repository,
|
authZRepo authz_repo.Repository,
|
||||||
@ -233,10 +232,10 @@ func startAPIs(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error starting admin repo: %w", err)
|
return fmt.Errorf("error starting admin repo: %w", err)
|
||||||
}
|
}
|
||||||
if err := apis.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.Database.Database(), config.DefaultInstance, config.ExternalDomain)); err != nil {
|
if err := apis.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.Database.DatabaseName(), config.DefaultInstance, config.ExternalDomain)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := apis.RegisterServer(ctx, admin.CreateServer(config.Database.Database(), commands, queries, config.SystemDefaults, adminRepo, config.ExternalSecure, keys.User)); err != nil {
|
if err := apis.RegisterServer(ctx, admin.CreateServer(config.Database.DatabaseName(), commands, queries, config.SystemDefaults, adminRepo, config.ExternalSecure, keys.User)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, keys.User, config.ExternalSecure, config.AuditLogRetention)); err != nil {
|
if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, keys.User, config.ExternalSecure, config.AuditLogRetention)); err != nil {
|
||||||
@ -247,7 +246,7 @@ func startAPIs(
|
|||||||
}
|
}
|
||||||
instanceInterceptor := middleware.InstanceInterceptor(queries, config.HTTP1HostHeader, login.IgnoreInstanceEndpoints...)
|
instanceInterceptor := middleware.InstanceInterceptor(queries, config.HTTP1HostHeader, login.IgnoreInstanceEndpoints...)
|
||||||
assetsCache := middleware.AssetsCacheInterceptor(config.AssetStorage.Cache.MaxAge, config.AssetStorage.Cache.SharedMaxAge)
|
assetsCache := middleware.AssetsCacheInterceptor(config.AssetStorage.Cache.MaxAge, config.AssetStorage.Cache.SharedMaxAge)
|
||||||
apis.RegisterHandler(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, instanceInterceptor.Handler, assetsCache.Handler, accessInterceptor.Handle))
|
apis.RegisterHandler(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, middleware.CallDurationHandler, instanceInterceptor.Handler, assetsCache.Handler, accessInterceptor.Handle))
|
||||||
|
|
||||||
userAgentInterceptor, err := middleware.NewUserAgentHandler(config.UserAgentCookie, keys.UserAgentCookieKey, id.SonyFlakeGenerator(), config.ExternalSecure, login.EndpointResources)
|
userAgentInterceptor, err := middleware.NewUserAgentHandler(config.UserAgentCookie, keys.UserAgentCookieKey, id.SonyFlakeGenerator(), config.ExternalSecure, login.EndpointResources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -272,7 +271,7 @@ func startAPIs(
|
|||||||
}
|
}
|
||||||
apis.RegisterHandler(saml.HandlerPrefix, samlProvider.HttpHandler())
|
apis.RegisterHandler(saml.HandlerPrefix, samlProvider.HttpHandler())
|
||||||
|
|
||||||
c, err := console.Start(config.Console, config.ExternalSecure, oidcProvider.IssuerFromRequest, instanceInterceptor.Handler, accessInterceptor.Handle, config.CustomerPortal)
|
c, err := console.Start(config.Console, config.ExternalSecure, oidcProvider.IssuerFromRequest, middleware.CallDurationHandler, instanceInterceptor.Handler, accessInterceptor.Handle, config.CustomerPortal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to start console: %w", err)
|
return fmt.Errorf("unable to start console: %w", err)
|
||||||
}
|
}
|
||||||
|
173
go.mod
173
go.mod
@ -3,22 +3,22 @@ module github.com/zitadel/zitadel
|
|||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/storage v1.28.1
|
cloud.google.com/go/storage v1.29.0
|
||||||
github.com/BurntSushi/toml v0.4.1
|
github.com/BurntSushi/toml v1.2.1
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.11.2
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible
|
github.com/Masterminds/sprig v2.22.0+incompatible
|
||||||
github.com/Masterminds/squirrel v1.5.2
|
github.com/Masterminds/squirrel v1.5.3
|
||||||
github.com/VictoriaMetrics/fastcache v1.8.0
|
github.com/VictoriaMetrics/fastcache v1.12.1
|
||||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b
|
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b
|
||||||
github.com/allegro/bigcache v1.2.1
|
github.com/allegro/bigcache v1.2.1
|
||||||
github.com/benbjohnson/clock v1.2.0
|
github.com/benbjohnson/clock v1.3.0
|
||||||
github.com/boombuler/barcode v1.0.1
|
github.com/boombuler/barcode v1.0.1
|
||||||
github.com/cockroachdb/cockroach-go/v2 v2.2.18
|
github.com/cockroachdb/cockroach-go/v2 v2.2.20
|
||||||
github.com/dop251/goja v0.0.0-20220815083517-0c74f9139fd6
|
github.com/dop251/goja v0.0.0-20230216180835-5937a312edda
|
||||||
github.com/dop251/goja_nodejs v0.0.0-20220905124449-678b33ca5009
|
github.com/dop251/goja_nodejs v0.0.0-20230207183254-2229640ea097
|
||||||
github.com/drone/envsubst v1.0.3
|
github.com/drone/envsubst v1.0.3
|
||||||
github.com/duo-labs/webauthn v0.0.0-20211216225436-9a12cd078b8a
|
github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.9.1
|
github.com/envoyproxy/protoc-gen-validate v0.9.1
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4
|
github.com/go-ldap/ldap/v3 v3.4.4
|
||||||
github.com/golang/glog v1.0.0
|
github.com/golang/glog v1.0.0
|
||||||
@ -33,26 +33,26 @@ require (
|
|||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1
|
||||||
github.com/h2non/gock v1.2.0
|
github.com/h2non/gock v1.2.0
|
||||||
github.com/improbable-eng/grpc-web v0.15.0
|
github.com/improbable-eng/grpc-web v0.15.0
|
||||||
github.com/jackc/pgconn v1.12.1
|
github.com/jackc/pgconn v1.14.0
|
||||||
github.com/jackc/pgtype v1.11.0
|
github.com/jackc/pgtype v1.14.0
|
||||||
github.com/jackc/pgx/v4 v4.16.1
|
github.com/jackc/pgx/v4 v4.18.0
|
||||||
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52
|
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52
|
||||||
github.com/jinzhu/gorm v1.9.16
|
github.com/jinzhu/gorm v1.9.16
|
||||||
github.com/k3a/html2text v1.0.8
|
github.com/k3a/html2text v1.1.0
|
||||||
github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73
|
github.com/kevinburke/twilio-go v0.0.0-20221122012537-65f3dd7539e2
|
||||||
github.com/lib/pq v1.10.6
|
github.com/lib/pq v1.10.7
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||||
github.com/minio/minio-go/v7 v7.0.20
|
github.com/minio/minio-go/v7 v7.0.49
|
||||||
github.com/mitchellh/mapstructure v1.4.3
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/muesli/gamut v0.2.0
|
github.com/muesli/gamut v0.3.1
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.1.2
|
github.com/nicksnyder/go-i18n/v2 v2.2.1
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pquerna/otp v1.3.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/rakyll/statik v0.1.7
|
github.com/rakyll/statik v0.1.7
|
||||||
github.com/rs/cors v1.8.3
|
github.com/rs/cors v1.8.3
|
||||||
github.com/sony/sonyflake v1.0.0
|
github.com/sony/sonyflake v1.1.0
|
||||||
github.com/spf13/cobra v1.3.0
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/spf13/viper v1.10.1
|
github.com/spf13/viper v1.15.0
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203
|
github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203
|
||||||
github.com/ttacon/libphonenumber v1.2.1
|
github.com/ttacon/libphonenumber v1.2.1
|
||||||
@ -61,21 +61,21 @@ require (
|
|||||||
github.com/zitadel/saml v0.0.10
|
github.com/zitadel/saml v0.0.10
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0
|
||||||
go.opentelemetry.io/otel v1.2.0
|
go.opentelemetry.io/otel v1.11.2
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.25.0
|
go.opentelemetry.io/otel/exporters/prometheus v0.25.0
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0
|
||||||
go.opentelemetry.io/otel/metric v0.25.0
|
go.opentelemetry.io/otel/metric v0.25.0
|
||||||
go.opentelemetry.io/otel/sdk v1.2.0
|
go.opentelemetry.io/otel/sdk v1.11.2
|
||||||
go.opentelemetry.io/otel/sdk/export/metric v0.25.0
|
go.opentelemetry.io/otel/sdk/export/metric v0.25.0
|
||||||
go.opentelemetry.io/otel/sdk/metric v0.25.0
|
go.opentelemetry.io/otel/sdk/metric v0.25.0
|
||||||
go.opentelemetry.io/otel/trace v1.2.0
|
go.opentelemetry.io/otel/trace v1.11.2
|
||||||
golang.org/x/crypto v0.6.0
|
golang.org/x/crypto v0.6.0
|
||||||
golang.org/x/net v0.7.0
|
golang.org/x/net v0.7.0
|
||||||
golang.org/x/oauth2 v0.5.0
|
golang.org/x/oauth2 v0.5.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/text v0.7.0
|
golang.org/x/text v0.7.0
|
||||||
golang.org/x/tools v0.3.0
|
golang.org/x/tools v0.6.0
|
||||||
google.golang.org/api v0.110.0
|
google.golang.org/api v0.110.0
|
||||||
google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148
|
google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148
|
||||||
google.golang.org/grpc v1.53.0
|
google.golang.org/grpc v1.53.0
|
||||||
@ -85,119 +85,120 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.108.0 // indirect
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.35.2 // indirect
|
||||||
|
github.com/cloudflare/cfssl v1.6.3 // indirect
|
||||||
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
cloud.google.com/go v0.110.0 // indirect
|
||||||
cloud.google.com/go/compute v1.18.0 // indirect
|
cloud.google.com/go/compute v1.18.0 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
cloud.google.com/go/iam v0.11.0 // indirect
|
cloud.google.com/go/iam v0.12.0 // indirect
|
||||||
cloud.google.com/go/trace v1.4.0 // indirect
|
cloud.google.com/go/trace v1.8.0 // indirect
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/amdonov/xmlsig v0.1.0 // indirect
|
github.com/amdonov/xmlsig v0.1.0 // indirect
|
||||||
github.com/beevik/etree v1.1.0 // indirect
|
github.com/beevik/etree v1.1.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
github.com/dlclark/regexp2 v1.8.1 // indirect
|
||||||
github.com/dsoprea/go-exif v0.0.0-20210131231135-d154f10435cc // indirect
|
github.com/dsoprea/go-exif v0.0.0-20221012082141-d21ac8e2de85 // indirect
|
||||||
github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4 // indirect
|
github.com/dsoprea/go-exif/v2 v2.0.0-20221012082141-d21ac8e2de85 // indirect
|
||||||
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb // indirect
|
github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 // indirect
|
||||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210128210355-86b1014917f2 // indirect
|
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20221012074422-4f3f7e934102 // indirect
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d // indirect
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||||
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c // indirect
|
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect
|
||||||
github.com/dsoprea/go-png-image-structure v0.0.0-20200807080309-a98d4e94ac82 // indirect
|
github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d // indirect
|
||||||
github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176 // indirect
|
github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.2.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||||
github.com/go-errors/errors v1.0.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
|
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
|
||||||
github.com/gofrs/flock v0.8.1 // indirect
|
github.com/gofrs/flock v0.8.1 // indirect
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.1.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/certificate-transparency-go v1.0.21 // indirect
|
github.com/google/certificate-transparency-go v1.1.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.1 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/h2non/filetype v1.1.3 // indirect
|
||||||
github.com/h2non/filetype v1.1.1 // indirect
|
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.4.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.13 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||||
github.com/jackc/pgio v1.0.0 // indirect
|
github.com/jackc/pgio v1.0.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
|
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
github.com/jonboulle/clockwork v0.3.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect
|
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect
|
||||||
github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect
|
github.com/kevinburke/rest v0.0.0-20230118171807-ac09c3f0ec45 // indirect
|
||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.15.15 // indirect
|
||||||
github.com/klauspost/cpuid v1.3.1 // indirect
|
|
||||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/minio/md5-simd v1.1.0 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/minio/sha256-simd v0.1.1 // indirect
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 // indirect
|
github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 // indirect
|
||||||
github.com/muesli/kmeans v0.2.1 // indirect
|
github.com/muesli/kmeans v0.3.1 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
github.com/prometheus/client_golang v1.13.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.26.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/rs/xid v1.2.1 // indirect
|
github.com/rs/xid v1.4.0 // indirect
|
||||||
github.com/russellhaering/goxmldsig v1.2.0 // indirect
|
github.com/russellhaering/goxmldsig v1.2.0 // indirect
|
||||||
github.com/satori/go.uuid v1.2.0 // indirect
|
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/spf13/afero v1.9.2 // indirect
|
github.com/spf13/afero v1.9.3 // indirect
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.2.0 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
|
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.0 // indirect
|
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect
|
||||||
go.opentelemetry.io/otel/internal/metric v0.25.0 // indirect
|
go.opentelemetry.io/otel/internal/metric v0.25.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v0.10.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.15.0 // indirect
|
||||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/mod v0.7.0 // indirect
|
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
nhooyr.io/websocket v1.8.7 // indirect
|
nhooyr.io/websocket v1.8.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.4
|
replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.4
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@ package eventsourcing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/eventstore"
|
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/spooler"
|
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/spooler"
|
||||||
admin_view "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view"
|
admin_view "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
eventstore2 "github.com/zitadel/zitadel/internal/eventstore"
|
eventstore2 "github.com/zitadel/zitadel/internal/eventstore"
|
||||||
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
||||||
@ -23,7 +23,7 @@ type EsRepository struct {
|
|||||||
eventstore.AdministratorRepo
|
eventstore.AdministratorRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, conf Config, static static.Storage, dbClient *sql.DB, esV2 *eventstore2.Eventstore) (*EsRepository, error) {
|
func Start(ctx context.Context, conf Config, static static.Storage, dbClient *database.DB, esV2 *eventstore2.Eventstore) (*EsRepository, error) {
|
||||||
es, err := v1.Start(dbClient)
|
es, err := v1.Start(dbClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2,10 +2,10 @@ package spooler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/handler"
|
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/handler"
|
||||||
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view"
|
"github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
||||||
@ -20,11 +20,11 @@ type SpoolerConfig struct {
|
|||||||
Handlers handler.Configs
|
Handlers handler.Configs
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartSpooler(ctx context.Context, c SpoolerConfig, es v1.Eventstore, esV2 *eventstore.Eventstore, view *view.View, sql *sql.DB, static static.Storage) *spooler.Spooler {
|
func StartSpooler(ctx context.Context, c SpoolerConfig, es v1.Eventstore, esV2 *eventstore.Eventstore, view *view.View, sql *database.DB, static static.Storage) *spooler.Spooler {
|
||||||
spoolerConfig := spooler.Config{
|
spoolerConfig := spooler.Config{
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
EventstoreV2: esV2,
|
EventstoreV2: esV2,
|
||||||
Locker: &locker{dbClient: sql},
|
Locker: &locker{dbClient: sql.DB},
|
||||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||||
ConcurrentInstances: c.ConcurrentInstances,
|
ConcurrentInstances: c.ConcurrentInstances,
|
||||||
ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, static),
|
ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, static),
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
package view
|
package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
type View struct {
|
type View struct {
|
||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartView(sqlClient *sql.DB) (*View, error) {
|
func StartView(sqlClient *database.DB) (*View, error) {
|
||||||
gorm, err := gorm.Open("postgres", sqlClient)
|
gorm, err := gorm.Open("postgres", sqlClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -82,7 +82,7 @@ func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error, code
|
|||||||
http.Error(w, err.Error(), code)
|
http.Error(w, err.Error(), code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(commands *command.Commands, verifier *authz.TokenVerifier, authConfig authz.Config, idGenerator id.Generator, storage static.Storage, queries *query.Queries, instanceInterceptor, assetCacheInterceptor, accessInterceptor func(handler http.Handler) http.Handler) http.Handler {
|
func NewHandler(commands *command.Commands, verifier *authz.TokenVerifier, authConfig authz.Config, idGenerator id.Generator, storage static.Storage, queries *query.Queries, callDurationInterceptor, instanceInterceptor, assetCacheInterceptor, accessInterceptor func(handler http.Handler) http.Handler) http.Handler {
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
commands: commands,
|
commands: commands,
|
||||||
errorHandler: DefaultErrorHandler,
|
errorHandler: DefaultErrorHandler,
|
||||||
@ -94,7 +94,7 @@ func NewHandler(commands *command.Commands, verifier *authz.TokenVerifier, authC
|
|||||||
|
|
||||||
verifier.RegisterServer("Assets-API", "assets", AssetsService_AuthMethods)
|
verifier.RegisterServer("Assets-API", "assets", AssetsService_AuthMethods)
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
router.Use(instanceInterceptor, assetCacheInterceptor, accessInterceptor)
|
router.Use(callDurationInterceptor, instanceInterceptor, assetCacheInterceptor, accessInterceptor)
|
||||||
RegisterRoutes(router, h)
|
RegisterRoutes(router, h)
|
||||||
router.PathPrefix("/{owner}").Methods("GET").HandlerFunc(DownloadHandleFunc(h, h.GetFile()))
|
router.PathPrefix("/{owner}").Methods("GET").HandlerFunc(DownloadHandleFunc(h, h.GetFile()))
|
||||||
return http_util.CopyHeadersToContext(http_mw.CORSInterceptor(router))
|
return http_util.CopyHeadersToContext(http_mw.CORSInterceptor(router))
|
||||||
|
17
internal/api/authz/detach.go
Normal file
17
internal/api/authz/detach.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package authz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Detach(ctx context.Context) context.Context { return detachedContext{ctx} }
|
||||||
|
|
||||||
|
type detachedContext struct {
|
||||||
|
parent context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||||
|
func (v detachedContext) Done() <-chan struct{} { return nil }
|
||||||
|
func (v detachedContext) Err() error { return nil }
|
||||||
|
func (v detachedContext) Value(key interface{}) interface{} { return v.parent.Value(key) }
|
38
internal/api/call/duration.go
Normal file
38
internal/api/call/duration.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package call
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type durationKey struct{}
|
||||||
|
|
||||||
|
var key *durationKey = (*durationKey)(nil)
|
||||||
|
|
||||||
|
// WithTimestamp sets [time.Now()] adds the call field to the context
|
||||||
|
// if it's not already set
|
||||||
|
func WithTimestamp(parent context.Context) context.Context {
|
||||||
|
if parent.Value(key) != nil {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
return context.WithValue(parent, key, time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the [time.Time] the call hit the api
|
||||||
|
func FromContext(ctx context.Context) (t time.Time) {
|
||||||
|
value := ctx.Value(key)
|
||||||
|
if t, ok := value.(time.Time); ok {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Took returns the time the call took so far
|
||||||
|
func Took(ctx context.Context) time.Duration {
|
||||||
|
start := FromContext(ctx)
|
||||||
|
if start.IsZero() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return time.Since(start)
|
||||||
|
}
|
119
internal/api/call/duration_test.go
Normal file
119
internal/api/call/duration_test.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package call
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTook(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
startIsZero bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no start",
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
},
|
||||||
|
startIsZero: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with start",
|
||||||
|
args: args{
|
||||||
|
ctx: WithTimestamp(context.Background()),
|
||||||
|
},
|
||||||
|
startIsZero: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := Took(tt.args.ctx)
|
||||||
|
if tt.startIsZero && got != 0 {
|
||||||
|
t.Errorf("Duration should be 0 but was %v", got)
|
||||||
|
}
|
||||||
|
if !tt.startIsZero && got <= 0 {
|
||||||
|
t.Errorf("Duration should be greater 0 but was %d", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromContext(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
isZero bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no start",
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
},
|
||||||
|
isZero: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with start",
|
||||||
|
args: args{
|
||||||
|
ctx: WithTimestamp(context.Background()),
|
||||||
|
},
|
||||||
|
isZero: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := FromContext(tt.args.ctx)
|
||||||
|
if tt.isZero != got.IsZero() {
|
||||||
|
t.Errorf("Time is zero should be %v but was %v", tt.isZero, got.IsZero())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithTimestamp(t *testing.T) {
|
||||||
|
start := time.Date(2019, 4, 29, 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
noPrevious bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fresh context",
|
||||||
|
args: args{
|
||||||
|
ctx: context.WithValue(context.Background(), key, start),
|
||||||
|
},
|
||||||
|
noPrevious: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with start",
|
||||||
|
args: args{
|
||||||
|
ctx: WithTimestamp(context.Background()),
|
||||||
|
},
|
||||||
|
noPrevious: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := WithTimestamp(tt.args.ctx)
|
||||||
|
val := got.Value(key).(time.Time)
|
||||||
|
|
||||||
|
if !tt.noPrevious && val.Before(start) {
|
||||||
|
t.Errorf("time should be now not %v", val)
|
||||||
|
}
|
||||||
|
if tt.noPrevious && val.After(start) {
|
||||||
|
t.Errorf("time should be start not %v", val)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -88,17 +88,6 @@ func (c *count) getProgress() string {
|
|||||||
"project_grant_members " + strconv.Itoa(c.projectGrantMemberCount) + "/" + strconv.Itoa(c.projectGrantMemberLen)
|
"project_grant_members " + strconv.Itoa(c.projectGrantMemberCount) + "/" + strconv.Itoa(c.projectGrantMemberLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Detach(ctx context.Context) context.Context { return detachedContext{ctx} }
|
|
||||||
|
|
||||||
type detachedContext struct {
|
|
||||||
parent context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
|
||||||
func (v detachedContext) Done() <-chan struct{} { return nil }
|
|
||||||
func (v detachedContext) Err() error { return nil }
|
|
||||||
func (v detachedContext) Value(key interface{}) interface{} { return v.parent.Value(key) }
|
|
||||||
|
|
||||||
func (s *Server) ImportData(ctx context.Context, req *admin_pb.ImportDataRequest) (_ *admin_pb.ImportDataResponse, err error) {
|
func (s *Server) ImportData(ctx context.Context, req *admin_pb.ImportDataRequest) (_ *admin_pb.ImportDataResponse, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
@ -169,7 +158,7 @@ func (s *Server) ImportData(ctx context.Context, req *admin_pb.ImportDataRequest
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dctx := Detach(ctx)
|
dctx := authz.Detach(ctx)
|
||||||
go func() {
|
go func() {
|
||||||
ch := make(chan importResponse, 1)
|
ch := make(chan importResponse, 1)
|
||||||
ctxTimeout, cancel := context.WithTimeout(dctx, timeoutDuration)
|
ctxTimeout, cancel := context.WithTimeout(dctx, timeoutDuration)
|
||||||
|
@ -71,6 +71,7 @@ func CreateGateway(ctx context.Context, g Gateway, port uint16, http1HostName st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addInterceptors(handler http.Handler, http1HostName string) http.Handler {
|
func addInterceptors(handler http.Handler, http1HostName string) http.Handler {
|
||||||
|
handler = http_mw.CallDurationHandler(handler)
|
||||||
handler = http1Host(handler, http1HostName)
|
handler = http1Host(handler, http1HostName)
|
||||||
handler = http_mw.CORSInterceptor(handler)
|
handler = http_mw.CORSInterceptor(handler)
|
||||||
handler = http_mw.DefaultTelemetryHandler(handler)
|
handler = http_mw.DefaultTelemetryHandler(handler)
|
||||||
|
16
internal/api/grpc/server/middleware/call_interceptor.go
Normal file
16
internal/api/grpc/server/middleware/call_interceptor.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CallDurationHandler() grpc.UnaryServerInterceptor {
|
||||||
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
ctx = call.WithTimestamp(ctx)
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ func CreateServer(
|
|||||||
serverOptions := []grpc.ServerOption{
|
serverOptions := []grpc.ServerOption{
|
||||||
grpc.UnaryInterceptor(
|
grpc.UnaryInterceptor(
|
||||||
grpc_middleware.ChainUnaryServer(
|
grpc_middleware.ChainUnaryServer(
|
||||||
|
middleware.CallDurationHandler(),
|
||||||
middleware.DefaultTracingServer(),
|
middleware.DefaultTracingServer(),
|
||||||
middleware.MetricsHandler(metricTypes, grpc_api.Probes...),
|
middleware.MetricsHandler(metricTypes, grpc_api.Probes...),
|
||||||
middleware.NoCacheInterceptor(),
|
middleware.NoCacheInterceptor(),
|
||||||
|
13
internal/api/http/middleware/call_interceptor.go
Normal file
13
internal/api/http/middleware/call_interceptor.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CallDurationHandler(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
next.ServeHTTP(w, r.WithContext(call.WithTimestamp(r.Context())))
|
||||||
|
})
|
||||||
|
}
|
@ -187,6 +187,7 @@ func (o *OPStorage) getMaxKeySequence(ctx context.Context) (uint64, error) {
|
|||||||
return o.eventstore.LatestSequence(ctx,
|
return o.eventstore.LatestSequence(ctx,
|
||||||
eventstore.NewSearchQueryBuilder(eventstore.ColumnsMaxSequence).
|
eventstore.NewSearchQueryBuilder(eventstore.ColumnsMaxSequence).
|
||||||
ResourceOwner(authz.GetInstance(ctx).InstanceID()).
|
ResourceOwner(authz.GetInstance(ctx).InstanceID()).
|
||||||
|
AllowTimeTravel().
|
||||||
AddQuery().
|
AddQuery().
|
||||||
AggregateTypes(keypair.AggregateType, instance.AggregateType).
|
AggregateTypes(keypair.AggregateType, instance.AggregateType).
|
||||||
Builder(),
|
Builder(),
|
||||||
|
@ -2,7 +2,6 @@ package oidc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@ -18,6 +17,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/auth/repository"
|
"github.com/zitadel/zitadel/internal/auth/repository"
|
||||||
"github.com/zitadel/zitadel/internal/command"
|
"github.com/zitadel/zitadel/internal/command"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
||||||
@ -73,7 +73,7 @@ type OPStorage struct {
|
|||||||
assetAPIPrefix func(ctx context.Context) 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, accessHandler func(http.Handler) http.Handler) (op.OpenIDProvider, error) {
|
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 *database.DB, userAgentCookie, instanceHandler, accessHandler func(http.Handler) http.Handler) (op.OpenIDProvider, error) {
|
||||||
opConfig, err := createOPConfig(config, defaultLogoutRedirectURI, cryptoKey)
|
opConfig, err := createOPConfig(config, defaultLogoutRedirectURI, cryptoKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, caos_errs.ThrowInternal(err, "OIDC-EGrqd", "cannot create op config: %w")
|
return nil, caos_errs.ThrowInternal(err, "OIDC-EGrqd", "cannot create op config: %w")
|
||||||
@ -169,7 +169,7 @@ func customEndpoints(endpointConfig *EndpointConfig) []op.Option {
|
|||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
func newStorage(config Config, command *command.Commands, query *query.Queries, repo repository.Repository, encAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, db *database.DB, externalSecure bool) *OPStorage {
|
||||||
return &OPStorage{
|
return &OPStorage{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
command: command,
|
command: command,
|
||||||
@ -182,7 +182,7 @@ func newStorage(config Config, command *command.Commands, query *query.Queries,
|
|||||||
defaultRefreshTokenIdleExpiration: config.DefaultRefreshTokenIdleExpiration,
|
defaultRefreshTokenIdleExpiration: config.DefaultRefreshTokenIdleExpiration,
|
||||||
defaultRefreshTokenExpiration: config.DefaultRefreshTokenExpiration,
|
defaultRefreshTokenExpiration: config.DefaultRefreshTokenExpiration,
|
||||||
encAlg: encAlg,
|
encAlg: encAlg,
|
||||||
locker: crdb.NewLocker(projections, locksTable, signingKey),
|
locker: crdb.NewLocker(db.DB, locksTable, signingKey),
|
||||||
assetAPIPrefix: assets.AssetAPI(externalSecure),
|
assetAPIPrefix: assets.AssetAPI(externalSecure),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package saml
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@ -14,6 +13,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/auth/repository"
|
"github.com/zitadel/zitadel/internal/auth/repository"
|
||||||
"github.com/zitadel/zitadel/internal/command"
|
"github.com/zitadel/zitadel/internal/command"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
@ -38,7 +38,7 @@ func NewProvider(
|
|||||||
encAlg crypto.EncryptionAlgorithm,
|
encAlg crypto.EncryptionAlgorithm,
|
||||||
certEncAlg crypto.EncryptionAlgorithm,
|
certEncAlg crypto.EncryptionAlgorithm,
|
||||||
es *eventstore.Eventstore,
|
es *eventstore.Eventstore,
|
||||||
projections *sql.DB,
|
projections *database.DB,
|
||||||
instanceHandler,
|
instanceHandler,
|
||||||
userAgentCookie,
|
userAgentCookie,
|
||||||
accessHandler func(http.Handler) http.Handler,
|
accessHandler func(http.Handler) http.Handler,
|
||||||
@ -89,12 +89,12 @@ func newStorage(
|
|||||||
encAlg crypto.EncryptionAlgorithm,
|
encAlg crypto.EncryptionAlgorithm,
|
||||||
certEncAlg crypto.EncryptionAlgorithm,
|
certEncAlg crypto.EncryptionAlgorithm,
|
||||||
es *eventstore.Eventstore,
|
es *eventstore.Eventstore,
|
||||||
projections *sql.DB,
|
db *database.DB,
|
||||||
) (*Storage, error) {
|
) (*Storage, error) {
|
||||||
return &Storage{
|
return &Storage{
|
||||||
encAlg: encAlg,
|
encAlg: encAlg,
|
||||||
certEncAlg: certEncAlg,
|
certEncAlg: certEncAlg,
|
||||||
locker: crdb.NewLocker(projections, locksTable, signingKey),
|
locker: crdb.NewLocker(db.DB, locksTable, signingKey),
|
||||||
eventstore: es,
|
eventstore: es,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
command: command,
|
command: command,
|
||||||
|
@ -88,7 +88,7 @@ func (f *file) Stat() (_ fs.FileInfo, err error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(config Config, externalSecure bool, issuer op.IssuerFromRequest, instanceHandler, accessInterceptor func(http.Handler) http.Handler, customerPortal string) (http.Handler, error) {
|
func Start(config Config, externalSecure bool, issuer op.IssuerFromRequest, callDurationInterceptor, instanceHandler, accessInterceptor func(http.Handler) http.Handler, customerPortal string) (http.Handler, error) {
|
||||||
fSys, err := fs.Sub(static, "static")
|
fSys, err := fs.Sub(static, "static")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -103,7 +103,7 @@ func Start(config Config, externalSecure bool, issuer op.IssuerFromRequest, inst
|
|||||||
|
|
||||||
handler := mux.NewRouter()
|
handler := mux.NewRouter()
|
||||||
|
|
||||||
handler.Use(instanceHandler, security, accessInterceptor)
|
handler.Use(callDurationInterceptor, instanceHandler, security, accessInterceptor)
|
||||||
handler.Handle(envRequestPath, middleware.TelemetryHandler()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler.Handle(envRequestPath, middleware.TelemetryHandler()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
url := http_util.BuildOrigin(r.Host, externalSecure)
|
url := http_util.BuildOrigin(r.Host, externalSecure)
|
||||||
environmentJSON, err := createEnvironmentJSON(url, issuer(r), authz.GetInstance(r.Context()).ConsoleClientID(), customerPortal)
|
environmentJSON, err := createEnvironmentJSON(url, issuer(r), authz.GetInstance(r.Context()).ConsoleClientID(), customerPortal)
|
||||||
|
@ -67,8 +67,8 @@ func CreateLogin(config Config,
|
|||||||
userAgentCookie,
|
userAgentCookie,
|
||||||
issuerInterceptor,
|
issuerInterceptor,
|
||||||
oidcInstanceHandler,
|
oidcInstanceHandler,
|
||||||
samlInstanceHandler mux.MiddlewareFunc,
|
samlInstanceHandler,
|
||||||
assetCache mux.MiddlewareFunc,
|
assetCache,
|
||||||
accessHandler mux.MiddlewareFunc,
|
accessHandler mux.MiddlewareFunc,
|
||||||
userCodeAlg crypto.EncryptionAlgorithm,
|
userCodeAlg crypto.EncryptionAlgorithm,
|
||||||
idpConfigAlg crypto.EncryptionAlgorithm,
|
idpConfigAlg crypto.EncryptionAlgorithm,
|
||||||
|
@ -2,7 +2,6 @@ package eventsourcing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/eventstore"
|
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/spooler"
|
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/spooler"
|
||||||
@ -11,6 +10,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/command"
|
"github.com/zitadel/zitadel/internal/command"
|
||||||
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
eventstore2 "github.com/zitadel/zitadel/internal/eventstore"
|
eventstore2 "github.com/zitadel/zitadel/internal/eventstore"
|
||||||
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
||||||
@ -34,7 +34,7 @@ type EsRepository struct {
|
|||||||
eventstore.OrgRepository
|
eventstore.OrgRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, esV2 *eventstore2.Eventstore, oidcEncryption crypto.EncryptionAlgorithm, userEncryption crypto.EncryptionAlgorithm) (*EsRepository, error) {
|
func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *database.DB, esV2 *eventstore2.Eventstore, oidcEncryption crypto.EncryptionAlgorithm, userEncryption crypto.EncryptionAlgorithm) (*EsRepository, error) {
|
||||||
es, err := v1.Start(dbClient)
|
es, err := v1.Start(dbClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2,11 +2,11 @@ package spooler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/handler"
|
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/handler"
|
||||||
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
|
"github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
|
||||||
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/spooler"
|
||||||
@ -21,11 +21,11 @@ type SpoolerConfig struct {
|
|||||||
Handlers handler.Configs
|
Handlers handler.Configs
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartSpooler(ctx context.Context, c SpoolerConfig, es v1.Eventstore, esV2 *eventstore.Eventstore, view *view.View, client *sql.DB, systemDefaults sd.SystemDefaults, queries *query.Queries) *spooler.Spooler {
|
func StartSpooler(ctx context.Context, c SpoolerConfig, es v1.Eventstore, esV2 *eventstore.Eventstore, view *view.View, client *database.DB, systemDefaults sd.SystemDefaults, queries *query.Queries) *spooler.Spooler {
|
||||||
spoolerConfig := spooler.Config{
|
spoolerConfig := spooler.Config{
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
EventstoreV2: esV2,
|
EventstoreV2: esV2,
|
||||||
Locker: &locker{dbClient: client},
|
Locker: &locker{dbClient: client.DB},
|
||||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||||
ConcurrentInstances: c.ConcurrentInstances,
|
ConcurrentInstances: c.ConcurrentInstances,
|
||||||
ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults, queries),
|
ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults, queries),
|
||||||
|
@ -21,15 +21,6 @@ func (v *View) UserByID(userID, instanceID string) (*model.UserView, error) {
|
|||||||
return view.UserByID(v.Db, userTable, userID, instanceID)
|
return view.UserByID(v.Db, userTable, userID, instanceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *View) UserByUsername(userName, instanceID string) (*model.UserView, error) {
|
|
||||||
query, err := query.NewUserUsernameSearchQuery(userName, query.TextEquals)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.userByID(instanceID, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) UserByLoginName(loginName, instanceID string) (*model.UserView, error) {
|
func (v *View) UserByLoginName(loginName, instanceID string) (*model.UserView, error) {
|
||||||
loginNameQuery, err := query.NewUserLoginNamesSearchQuery(loginName)
|
loginNameQuery, err := query.NewUserLoginNamesSearchQuery(loginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package view
|
package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
eventstore "github.com/zitadel/zitadel/internal/eventstore/v1"
|
eventstore "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
"github.com/zitadel/zitadel/internal/id"
|
"github.com/zitadel/zitadel/internal/id"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
@ -19,7 +18,7 @@ type View struct {
|
|||||||
es eventstore.Eventstore
|
es eventstore.Eventstore
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartView(sqlClient *sql.DB, keyAlgorithm crypto.EncryptionAlgorithm, queries *query.Queries, idGenerator id.Generator, es eventstore.Eventstore) (*View, error) {
|
func StartView(sqlClient *database.DB, keyAlgorithm crypto.EncryptionAlgorithm, queries *query.Queries, idGenerator id.Generator, es eventstore.Eventstore) (*View, error) {
|
||||||
gorm, err := gorm.Open("postgres", sqlClient)
|
gorm, err := gorm.Open("postgres", sqlClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -9,15 +9,16 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthRequestCache struct {
|
type AuthRequestCache struct {
|
||||||
client *sql.DB
|
client *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(dbClient *sql.DB) *AuthRequestCache {
|
func Start(dbClient *database.DB) *AuthRequestCache {
|
||||||
return &AuthRequestCache{
|
return &AuthRequestCache{
|
||||||
client: dbClient,
|
client: dbClient,
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package authz
|
package authz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/authz/repository"
|
"github.com/zitadel/zitadel/internal/authz/repository"
|
||||||
"github.com/zitadel/zitadel/internal/authz/repository/eventsourcing"
|
"github.com/zitadel/zitadel/internal/authz/repository/eventsourcing"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Start(queries *query.Queries, dbClient *sql.DB, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, externalSecure bool) (repository.Repository, error) {
|
func Start(queries *query.Queries, dbClient *database.DB, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, externalSecure bool) (repository.Repository, error) {
|
||||||
return eventsourcing.Start(queries, dbClient, keyEncryptionAlgorithm, externalSecure)
|
return eventsourcing.Start(queries, dbClient, keyEncryptionAlgorithm, externalSecure)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ package eventsourcing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/authz/repository"
|
"github.com/zitadel/zitadel/internal/authz/repository"
|
||||||
"github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/eventstore"
|
"github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/eventstore"
|
||||||
authz_view "github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/view"
|
authz_view "github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/view"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
v1 "github.com/zitadel/zitadel/internal/eventstore/v1"
|
||||||
"github.com/zitadel/zitadel/internal/id"
|
"github.com/zitadel/zitadel/internal/id"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
@ -18,7 +18,7 @@ type EsRepository struct {
|
|||||||
eventstore.TokenVerifierRepo
|
eventstore.TokenVerifierRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(queries *query.Queries, dbClient *sql.DB, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, externalSecure bool) (repository.Repository, error) {
|
func Start(queries *query.Queries, dbClient *database.DB, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, externalSecure bool) (repository.Repository, error) {
|
||||||
es, err := v1.Start(dbClient)
|
es, err := v1.Start(dbClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package view
|
package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/id"
|
"github.com/zitadel/zitadel/internal/id"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
|
|
||||||
@ -15,7 +14,7 @@ type View struct {
|
|||||||
idGenerator id.Generator
|
idGenerator id.Generator
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartView(sqlClient *sql.DB, idGenerator id.Generator, queries *query.Queries) (*View, error) {
|
func StartView(sqlClient *database.DB, idGenerator id.Generator, queries *query.Queries) (*View, error) {
|
||||||
gorm, err := gorm.Open("postgres", sqlClient)
|
gorm, err := gorm.Open("postgres", sqlClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -9,7 +9,6 @@ type quotaWriteModel struct {
|
|||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
unit quota.Unit
|
unit quota.Unit
|
||||||
active bool
|
active bool
|
||||||
config *quota.AddedEvent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newQuotaWriteModel aggregateId is filled by reducing unit matching events
|
// newQuotaWriteModel aggregateId is filled by reducing unit matching events
|
||||||
@ -43,11 +42,9 @@ func (wm *quotaWriteModel) Reduce() error {
|
|||||||
case *quota.AddedEvent:
|
case *quota.AddedEvent:
|
||||||
wm.AggregateID = e.Aggregate().ID
|
wm.AggregateID = e.Aggregate().ID
|
||||||
wm.active = true
|
wm.active = true
|
||||||
wm.config = e
|
|
||||||
case *quota.RemovedEvent:
|
case *quota.RemovedEvent:
|
||||||
wm.AggregateID = e.Aggregate().ID
|
wm.AggregateID = e.Aggregate().ID
|
||||||
wm.active = false
|
wm.active = false
|
||||||
wm.config = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
|
||||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotaNotificationsWriteModel struct {
|
|
||||||
eventstore.WriteModel
|
|
||||||
periodStart time.Time
|
|
||||||
latestNotifiedThresholds map[string]uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
func newQuotaNotificationsWriteModel(aggregateId, instanceId, resourceOwner string, periodStart time.Time) *quotaNotificationsWriteModel {
|
|
||||||
return "aNotificationsWriteModel{
|
|
||||||
WriteModel: eventstore.WriteModel{
|
|
||||||
AggregateID: aggregateId,
|
|
||||||
InstanceID: instanceId,
|
|
||||||
ResourceOwner: resourceOwner,
|
|
||||||
},
|
|
||||||
periodStart: periodStart,
|
|
||||||
latestNotifiedThresholds: make(map[string]uint16),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *quotaNotificationsWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|
||||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
|
||||||
ResourceOwner(wm.ResourceOwner).
|
|
||||||
AddQuery().
|
|
||||||
InstanceID(wm.InstanceID).
|
|
||||||
AggregateTypes(quota.AggregateType).
|
|
||||||
AggregateIDs(wm.AggregateID).
|
|
||||||
CreationDateAfter(wm.periodStart).
|
|
||||||
EventTypes(quota.NotifiedEventType).Builder()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *quotaNotificationsWriteModel) Reduce() error {
|
|
||||||
for _, event := range wm.Events {
|
|
||||||
e := event.(*quota.NotifiedEvent)
|
|
||||||
wm.latestNotifiedThresholds[e.ID] = e.Threshold
|
|
||||||
}
|
|
||||||
return wm.WriteModel.Reduce()
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Commands) GetCurrentQuotaPeriod(ctx context.Context, instanceID string, unit quota.Unit) (*quota.AddedEvent, time.Time, error) {
|
|
||||||
wm, err := c.getQuotaWriteModel(ctx, instanceID, instanceID, unit)
|
|
||||||
if err != nil || !wm.active {
|
|
||||||
return nil, time.Time{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return wm.config, pushPeriodStart(wm.config.From, wm.config.ResetInterval, time.Now()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pushPeriodStart(from time.Time, interval time.Duration, now time.Time) time.Time {
|
|
||||||
next := from.Add(interval)
|
|
||||||
if next.After(now) {
|
|
||||||
return from
|
|
||||||
}
|
|
||||||
return pushPeriodStart(next, interval, now)
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package cockroach
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -89,6 +90,15 @@ func (c *Config) Type() string {
|
|||||||
return "cockroach"
|
return "cockroach"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) Timetravel(d time.Duration) string {
|
||||||
|
// verify that it is at least 1 micro second
|
||||||
|
if d < time.Microsecond {
|
||||||
|
d = time.Microsecond
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(" AS OF SYSTEM TIME '-%d µs' ", d.Microseconds())
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
|
61
internal/database/cockroach/config_test.go
Normal file
61
internal/database/cockroach/config_test.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package cockroach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfig_Timetravel(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
d time.Duration
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no duration",
|
||||||
|
args: args{
|
||||||
|
d: 0,
|
||||||
|
},
|
||||||
|
want: " AS OF SYSTEM TIME '-1 µs' ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "less than microsecond",
|
||||||
|
args: args{
|
||||||
|
d: 100 * time.Nanosecond,
|
||||||
|
},
|
||||||
|
want: " AS OF SYSTEM TIME '-1 µs' ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "10 microseconds",
|
||||||
|
args: args{
|
||||||
|
d: 10 * time.Microsecond,
|
||||||
|
},
|
||||||
|
want: " AS OF SYSTEM TIME '-10 µs' ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "10 milliseconds",
|
||||||
|
args: args{
|
||||||
|
d: 10 * time.Millisecond,
|
||||||
|
},
|
||||||
|
want: " AS OF SYSTEM TIME '-10000 µs' ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "1 second",
|
||||||
|
args: args{
|
||||||
|
d: 1 * time.Second,
|
||||||
|
},
|
||||||
|
want: " AS OF SYSTEM TIME '-1000000 µs' ",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
c := &Config{}
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := c.Timetravel(tt.args.d); got != tt.want {
|
||||||
|
t.Errorf("Config.Timetravel() = %q, want %q", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,12 @@ func (c *Config) SetConnector(connector dialect.Connector) {
|
|||||||
c.connector = connector
|
c.connector = connector
|
||||||
}
|
}
|
||||||
|
|
||||||
func Connect(config Config, useAdmin bool) (*sql.DB, error) {
|
type DB struct {
|
||||||
|
*sql.DB
|
||||||
|
dialect.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
func Connect(config Config, useAdmin bool) (*DB, error) {
|
||||||
client, err := config.connector.Connect(useAdmin)
|
client, err := config.connector.Connect(useAdmin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -29,7 +34,10 @@ func Connect(config Config, useAdmin bool) (*sql.DB, error) {
|
|||||||
return nil, errors.ThrowPreconditionFailed(err, "DATAB-0pIWD", "Errors.Database.Connection.Failed")
|
return nil, errors.ThrowPreconditionFailed(err, "DATAB-0pIWD", "Errors.Database.Connection.Failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, nil
|
return &DB{
|
||||||
|
DB: client,
|
||||||
|
Database: config.connector,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeHook(from, to reflect.Value) (interface{}, error) {
|
func DecodeHook(from, to reflect.Value) (interface{}, error) {
|
||||||
@ -61,7 +69,7 @@ func DecodeHook(from, to reflect.Value) (interface{}, error) {
|
|||||||
return Config{connector: connector}, nil
|
return Config{connector: connector}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) Database() string {
|
func (c Config) DatabaseName() string {
|
||||||
return c.connector.DatabaseName()
|
return c.connector.DatabaseName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package dialect
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -29,10 +30,15 @@ type Matcher interface {
|
|||||||
|
|
||||||
type Connector interface {
|
type Connector interface {
|
||||||
Connect(useAdmin bool) (*sql.DB, error)
|
Connect(useAdmin bool) (*sql.DB, error)
|
||||||
|
Password() string
|
||||||
|
Database
|
||||||
|
}
|
||||||
|
|
||||||
|
type Database interface {
|
||||||
DatabaseName() string
|
DatabaseName() string
|
||||||
Username() string
|
Username() string
|
||||||
Password() string
|
|
||||||
Type() string
|
Type() string
|
||||||
|
Timetravel(time.Duration) string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(matcher Matcher, config Connector, isDefault bool) {
|
func Register(matcher Matcher, config Connector, isDefault bool) {
|
||||||
|
@ -89,6 +89,10 @@ func (c *Config) Type() string {
|
|||||||
return "postgres"
|
return "postgres"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) Timetravel(time.Duration) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package eventstore
|
package eventstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
z_sql "github.com/zitadel/zitadel/internal/eventstore/repository/sql"
|
z_sql "github.com/zitadel/zitadel/internal/eventstore/repository/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
PushTimeout time.Duration
|
PushTimeout time.Duration
|
||||||
Client *sql.DB
|
Client *database.DB
|
||||||
|
|
||||||
repo repository.Repository
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||||
@ -19,7 +20,7 @@ var (
|
|||||||
type StatementHandlerConfig struct {
|
type StatementHandlerConfig struct {
|
||||||
handler.ProjectionHandlerConfig
|
handler.ProjectionHandlerConfig
|
||||||
|
|
||||||
Client *sql.DB
|
Client *database.DB
|
||||||
SequenceTable string
|
SequenceTable string
|
||||||
LockTable string
|
LockTable string
|
||||||
FailedEventsTable string
|
FailedEventsTable string
|
||||||
@ -34,7 +35,7 @@ type StatementHandler struct {
|
|||||||
*handler.ProjectionHandler
|
*handler.ProjectionHandler
|
||||||
Locker
|
Locker
|
||||||
|
|
||||||
client *sql.DB
|
client *database.DB
|
||||||
sequenceTable string
|
sequenceTable string
|
||||||
currentSequenceStmt string
|
currentSequenceStmt string
|
||||||
updateSequencesBaseStmt string
|
updateSequencesBaseStmt string
|
||||||
@ -74,7 +75,7 @@ func NewStatementHandler(
|
|||||||
aggregates: aggregateTypes,
|
aggregates: aggregateTypes,
|
||||||
reduces: reduces,
|
reduces: reduces,
|
||||||
bulkLimit: config.BulkLimit,
|
bulkLimit: config.BulkLimit,
|
||||||
Locker: NewLocker(config.Client, config.LockTable, config.ProjectionName),
|
Locker: NewLocker(config.Client.DB, config.LockTable, config.ProjectionName),
|
||||||
initCheck: config.InitCheck,
|
initCheck: config.InitCheck,
|
||||||
initialized: make(chan bool),
|
initialized: make(chan bool),
|
||||||
}
|
}
|
||||||
@ -96,7 +97,7 @@ func (h *StatementHandler) SearchQuery(ctx context.Context, instanceIDs []string
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
queryBuilder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(h.bulkLimit)
|
queryBuilder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(h.bulkLimit).AllowTimeTravel()
|
||||||
|
|
||||||
for _, aggregateType := range h.aggregates {
|
for _, aggregateType := range h.aggregates {
|
||||||
for _, instanceID := range instanceIDs {
|
for _, instanceID := range instanceIDs {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/DATA-DOG/go-sqlmock"
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
@ -114,6 +115,7 @@ func TestProjectionHandler_SearchQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SearchQueryBuilder: eventstore.
|
SearchQueryBuilder: eventstore.
|
||||||
NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||||
|
AllowTimeTravel().
|
||||||
AddQuery().
|
AddQuery().
|
||||||
AggregateTypes("testAgg").
|
AggregateTypes("testAgg").
|
||||||
SequenceGreater(5).
|
SequenceGreater(5).
|
||||||
@ -143,6 +145,7 @@ func TestProjectionHandler_SearchQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SearchQueryBuilder: eventstore.
|
SearchQueryBuilder: eventstore.
|
||||||
NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||||
|
AllowTimeTravel().
|
||||||
AddQuery().
|
AddQuery().
|
||||||
AggregateTypes("testAgg").
|
AggregateTypes("testAgg").
|
||||||
SequenceGreater(5).
|
SequenceGreater(5).
|
||||||
@ -171,7 +174,9 @@ func TestProjectionHandler_SearchQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SequenceTable: tt.fields.sequenceTable,
|
SequenceTable: tt.fields.sequenceTable,
|
||||||
BulkLimit: tt.fields.bulkLimit,
|
BulkLimit: tt.fields.bulkLimit,
|
||||||
Client: client,
|
Client: &database.DB{
|
||||||
|
DB: client,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
h.aggregates = tt.fields.aggregates
|
h.aggregates = tt.fields.aggregates
|
||||||
@ -549,7 +554,9 @@ func TestStatementHandler_Update(t *testing.T) {
|
|||||||
sequenceTable: "my_sequences",
|
sequenceTable: "my_sequences",
|
||||||
currentSequenceStmt: fmt.Sprintf(currentSequenceStmtFormat, "my_sequences"),
|
currentSequenceStmt: fmt.Sprintf(currentSequenceStmtFormat, "my_sequences"),
|
||||||
updateSequencesBaseStmt: fmt.Sprintf(updateCurrentSequencesStmtFormat, "my_sequences"),
|
updateSequencesBaseStmt: fmt.Sprintf(updateCurrentSequencesStmtFormat, "my_sequences"),
|
||||||
client: client,
|
client: &database.DB{
|
||||||
|
DB: client,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
h.aggregates = tt.fields.aggregates
|
h.aggregates = tt.fields.aggregates
|
||||||
@ -1121,7 +1128,9 @@ func TestStatementHandler_executeStmts(t *testing.T) {
|
|||||||
ProjectionName: tt.fields.projectionName,
|
ProjectionName: tt.fields.projectionName,
|
||||||
RequeueEvery: 0,
|
RequeueEvery: 0,
|
||||||
},
|
},
|
||||||
Client: client,
|
Client: &database.DB{
|
||||||
|
DB: client,
|
||||||
|
},
|
||||||
FailedEventsTable: tt.fields.failedEventsTable,
|
FailedEventsTable: tt.fields.failedEventsTable,
|
||||||
MaxFailureCount: tt.fields.maxFailureCount,
|
MaxFailureCount: tt.fields.maxFailureCount,
|
||||||
},
|
},
|
||||||
|
@ -194,7 +194,7 @@ func (h *ProjectionHandler) schedule(ctx context.Context) {
|
|||||||
var succeededOnce bool
|
var succeededOnce bool
|
||||||
var err error
|
var err error
|
||||||
// get every instance id except empty (system)
|
// get every instance id except empty (system)
|
||||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsInstanceIDs).AddQuery().ExcludedInstanceID("")
|
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsInstanceIDs).AllowTimeTravel().AddQuery().ExcludedInstanceID("")
|
||||||
for range h.triggerProjection.C {
|
for range h.triggerProjection.C {
|
||||||
if !succeededOnce {
|
if !succeededOnce {
|
||||||
// (re)check if it has succeeded in the meantime
|
// (re)check if it has succeeded in the meantime
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cockroachdb/cockroach-go/v2/testserver"
|
"github.com/cockroachdb/cockroach-go/v2/testserver"
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testCRDBClient *sql.DB
|
testCRDBClient *database.DB
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@ -23,7 +24,11 @@ func TestMain(m *testing.M) {
|
|||||||
logging.WithFields("error", err).Fatal("unable to start db")
|
logging.WithFields("error", err).Fatal("unable to start db")
|
||||||
}
|
}
|
||||||
|
|
||||||
testCRDBClient, err = sql.Open("postgres", ts.PGURL().String())
|
testCRDBClient = &database.DB{
|
||||||
|
Database: new(testDB),
|
||||||
|
}
|
||||||
|
|
||||||
|
testCRDBClient.DB, err = sql.Open("postgres", ts.PGURL().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.WithFields("error", err).Fatal("unable to connect to db")
|
logging.WithFields("error", err).Fatal("unable to connect to db")
|
||||||
}
|
}
|
||||||
@ -39,7 +44,7 @@ func TestMain(m *testing.M) {
|
|||||||
ts.Stop()
|
ts.Stop()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err = initDB(testCRDBClient); err != nil {
|
if err = initDB(testCRDBClient.DB); err != nil {
|
||||||
logging.WithFields("error", err).Fatal("migrations failed")
|
logging.WithFields("error", err).Fatal("migrations failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +62,20 @@ func initDB(db *sql.DB) error {
|
|||||||
})
|
})
|
||||||
err := initialise.Init(db,
|
err := initialise.Init(db,
|
||||||
initialise.VerifyUser(config.Username(), ""),
|
initialise.VerifyUser(config.Username(), ""),
|
||||||
initialise.VerifyDatabase(config.Database()),
|
initialise.VerifyDatabase(config.DatabaseName()),
|
||||||
initialise.VerifyGrant(config.Database(), config.Username()))
|
initialise.VerifyGrant(config.DatabaseName(), config.Username()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return initialise.VerifyZitadel(db, *config)
|
return initialise.VerifyZitadel(db, *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testDB struct{}
|
||||||
|
|
||||||
|
func (_ *testDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " }
|
||||||
|
|
||||||
|
func (*testDB) DatabaseName() string { return "db" }
|
||||||
|
|
||||||
|
func (*testDB) Username() string { return "user" }
|
||||||
|
|
||||||
|
func (*testDB) Type() string { return "type" }
|
||||||
|
@ -2,7 +2,7 @@ package eventstore
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//ReadModel is the minimum representation of a read model.
|
// ReadModel is the minimum representation of a read model.
|
||||||
// It implements a basic reducer
|
// It implements a basic reducer
|
||||||
// it might be saved in a database or in memory
|
// it might be saved in a database or in memory
|
||||||
type ReadModel struct {
|
type ReadModel struct {
|
||||||
@ -15,14 +15,13 @@ type ReadModel struct {
|
|||||||
InstanceID string `json:"-"`
|
InstanceID string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//AppendEvents adds all the events to the read model.
|
// AppendEvents adds all the events to the read model.
|
||||||
// The function doesn't compute the new state of the read model
|
// The function doesn't compute the new state of the read model
|
||||||
func (rm *ReadModel) AppendEvents(events ...Event) *ReadModel {
|
func (rm *ReadModel) AppendEvents(events ...Event) {
|
||||||
rm.Events = append(rm.Events, events...)
|
rm.Events = append(rm.Events, events...)
|
||||||
return rm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reduce is the basic implementation of reducer
|
// Reduce is the basic implementation of reducer
|
||||||
// If this function is extended the extending function should be the last step
|
// If this function is extended the extending function should be the last step
|
||||||
func (rm *ReadModel) Reduce() error {
|
func (rm *ReadModel) Reduce() error {
|
||||||
if len(rm.Events) == 0 {
|
if len(rm.Events) == 0 {
|
||||||
|
@ -8,11 +8,12 @@ import (
|
|||||||
|
|
||||||
// SearchQuery defines the which and how data are queried
|
// SearchQuery defines the which and how data are queried
|
||||||
type SearchQuery struct {
|
type SearchQuery struct {
|
||||||
Columns Columns
|
Columns Columns
|
||||||
Limit uint64
|
Limit uint64
|
||||||
Desc bool
|
Desc bool
|
||||||
Filters [][]*Filter
|
Filters [][]*Filter
|
||||||
Tx *sql.Tx
|
Tx *sql.Tx
|
||||||
|
AllowTimeTravel bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns defines which fields of the event are needed for the query
|
// Columns defines which fields of the event are needed for the query
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
)
|
)
|
||||||
@ -97,19 +98,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CRDB struct {
|
type CRDB struct {
|
||||||
client *sql.DB
|
*database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCRDB(client *sql.DB) *CRDB {
|
func NewCRDB(client *database.DB) *CRDB {
|
||||||
return &CRDB{client}
|
return &CRDB{client}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *CRDB) Health(ctx context.Context) error { return db.client.Ping() }
|
func (db *CRDB) Health(ctx context.Context) error { return db.Ping() }
|
||||||
|
|
||||||
// Push adds all events to the eventstreams of the aggregates.
|
// Push adds all events to the eventstreams of the aggregates.
|
||||||
// This call is transaction save. The transaction will be rolled back if one event fails
|
// This call is transaction save. The transaction will be rolled back if one event fails
|
||||||
func (db *CRDB) Push(ctx context.Context, events []*repository.Event, uniqueConstraints ...*repository.UniqueConstraint) error {
|
func (db *CRDB) Push(ctx context.Context, events []*repository.Event, uniqueConstraints ...*repository.UniqueConstraint) error {
|
||||||
err := crdb.ExecuteTx(ctx, db.client, nil, func(tx *sql.Tx) error {
|
err := crdb.ExecuteTx(ctx, db.DB.DB, nil, func(tx *sql.Tx) error {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
previousAggregateSequence Sequence
|
previousAggregateSequence Sequence
|
||||||
@ -159,7 +160,7 @@ func (db *CRDB) Push(ctx context.Context, events []*repository.Event, uniqueCons
|
|||||||
var instanceRegexp = regexp.MustCompile(`eventstore\.i_[0-9a-zA-Z]{1,}_seq`)
|
var instanceRegexp = regexp.MustCompile(`eventstore\.i_[0-9a-zA-Z]{1,}_seq`)
|
||||||
|
|
||||||
func (db *CRDB) CreateInstance(ctx context.Context, instanceID string) error {
|
func (db *CRDB) CreateInstance(ctx context.Context, instanceID string) error {
|
||||||
row := db.client.QueryRowContext(ctx, "SELECT CONCAT('eventstore.i_', $1::TEXT, '_seq')", instanceID)
|
row := db.QueryRowContext(ctx, "SELECT CONCAT('eventstore.i_', $1::TEXT, '_seq')", instanceID)
|
||||||
if row.Err() != nil {
|
if row.Err() != nil {
|
||||||
return caos_errs.ThrowInvalidArgument(row.Err(), "SQL-7gtFA", "Errors.InvalidArgument")
|
return caos_errs.ThrowInvalidArgument(row.Err(), "SQL-7gtFA", "Errors.InvalidArgument")
|
||||||
}
|
}
|
||||||
@ -168,7 +169,7 @@ func (db *CRDB) CreateInstance(ctx context.Context, instanceID string) error {
|
|||||||
return caos_errs.ThrowInvalidArgument(err, "SQL-7gtFA", "Errors.InvalidArgument")
|
return caos_errs.ThrowInvalidArgument(err, "SQL-7gtFA", "Errors.InvalidArgument")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := db.client.ExecContext(ctx, "CREATE SEQUENCE "+sequenceName); err != nil {
|
if _, err := db.ExecContext(ctx, "CREATE SEQUENCE "+sequenceName); err != nil {
|
||||||
return caos_errs.ThrowInternal(err, "SQL-7gtFA", "Errors.Internal")
|
return caos_errs.ThrowInternal(err, "SQL-7gtFA", "Errors.Internal")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +250,7 @@ func (db *CRDB) InstanceIDs(ctx context.Context, searchQuery *repository.SearchQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *CRDB) db() *sql.DB {
|
func (db *CRDB) db() *sql.DB {
|
||||||
return db.client
|
return db.DB.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *CRDB) orderByEventSequence(desc bool) string {
|
func (db *CRDB) orderByEventSequence(desc bool) string {
|
||||||
|
@ -437,7 +437,10 @@ func TestCRDB_Push_OneAggregate(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if tt.args.uniqueDataType != "" && tt.args.uniqueDataField != "" {
|
if tt.args.uniqueDataType != "" && tt.args.uniqueDataField != "" {
|
||||||
err := fillUniqueData(tt.args.uniqueDataType, tt.args.uniqueDataField, tt.args.uniqueDataInstanceID)
|
err := fillUniqueData(tt.args.uniqueDataType, tt.args.uniqueDataField, tt.args.uniqueDataInstanceID)
|
||||||
@ -561,7 +564,10 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if err := db.Push(context.Background(), tt.args.events); (err != nil) != tt.res.wantErr {
|
if err := db.Push(context.Background(), tt.args.events); (err != nil) != tt.res.wantErr {
|
||||||
t.Errorf("CRDB.Push() error = %v, wantErr %v", err, tt.res.wantErr)
|
t.Errorf("CRDB.Push() error = %v, wantErr %v", err, tt.res.wantErr)
|
||||||
@ -638,7 +644,7 @@ func TestCRDB_CreateInstance(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{DB: testCRDBClient},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.CreateInstance(context.Background(), tt.args.instanceID); (err != nil) != tt.res.wantErr {
|
if err := db.CreateInstance(context.Background(), tt.args.instanceID); (err != nil) != tt.res.wantErr {
|
||||||
@ -776,7 +782,10 @@ func TestCRDB_Push_Parallel(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
@ -897,7 +906,10 @@ func TestCRDB_Filter(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup initial data for query
|
// setup initial data for query
|
||||||
@ -987,7 +999,10 @@ func TestCRDB_LatestSequence(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup initial data for query
|
// setup initial data for query
|
||||||
@ -1131,7 +1146,10 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: testCRDBClient,
|
DB: &database.DB{
|
||||||
|
DB: testCRDBClient,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if err := db.Push(context.Background(), tt.args.events); err != nil {
|
if err := db.Push(context.Background(), tt.args.events); err != nil {
|
||||||
t.Errorf("CRDB.Push() error = %v", err)
|
t.Errorf("CRDB.Push() error = %v", err)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cockroachdb/cockroach-go/v2/testserver"
|
"github.com/cockroachdb/cockroach-go/v2/testserver"
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
@ -53,8 +54,8 @@ func initDB(db *sql.DB) error {
|
|||||||
|
|
||||||
err := initialise.Init(db,
|
err := initialise.Init(db,
|
||||||
initialise.VerifyUser(config.Username(), ""),
|
initialise.VerifyUser(config.Username(), ""),
|
||||||
initialise.VerifyDatabase(config.Database()),
|
initialise.VerifyDatabase(config.DatabaseName()),
|
||||||
initialise.VerifyGrant(config.Database(), config.Username()))
|
initialise.VerifyGrant(config.DatabaseName(), config.Username()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -66,3 +67,13 @@ func fillUniqueData(unique_type, field, instanceID string) error {
|
|||||||
_, err := testCRDBClient.Exec("INSERT INTO eventstore.unique_constraints (unique_type, unique_field, instance_id) VALUES ($1, $2, $3)", unique_type, field, instanceID)
|
_, err := testCRDBClient.Exec("INSERT INTO eventstore.unique_constraints (unique_type, unique_field, instance_id) VALUES ($1, $2, $3)", unique_type, field, instanceID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testDB struct{}
|
||||||
|
|
||||||
|
func (_ *testDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " }
|
||||||
|
|
||||||
|
func (*testDB) DatabaseName() string { return "db" }
|
||||||
|
|
||||||
|
func (*testDB) Username() string { return "user" }
|
||||||
|
|
||||||
|
func (*testDB) Type() string { return "type" }
|
||||||
|
@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
|
"github.com/zitadel/zitadel/internal/database/dialect"
|
||||||
z_errors "github.com/zitadel/zitadel/internal/errors"
|
z_errors "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
)
|
)
|
||||||
@ -24,6 +26,7 @@ type querier interface {
|
|||||||
instanceIDsQuery() string
|
instanceIDsQuery() string
|
||||||
db() *sql.DB
|
db() *sql.DB
|
||||||
orderByEventSequence(desc bool) string
|
orderByEventSequence(desc bool) string
|
||||||
|
dialect.Database
|
||||||
}
|
}
|
||||||
|
|
||||||
type scan func(dest ...interface{}) error
|
type scan func(dest ...interface{}) error
|
||||||
@ -34,6 +37,11 @@ func query(ctx context.Context, criteria querier, searchQuery *repository.Search
|
|||||||
if where == "" || query == "" {
|
if where == "" || query == "" {
|
||||||
return z_errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
return z_errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
||||||
}
|
}
|
||||||
|
if searchQuery.Tx == nil {
|
||||||
|
if travel := prepareTimeTravel(ctx, criteria, searchQuery.AllowTimeTravel); travel != "" {
|
||||||
|
query += travel
|
||||||
|
}
|
||||||
|
}
|
||||||
query += where
|
query += where
|
||||||
|
|
||||||
if searchQuery.Columns == repository.ColumnsEvent {
|
if searchQuery.Columns == repository.ColumnsEvent {
|
||||||
@ -85,6 +93,14 @@ func prepareColumns(criteria querier, columns repository.Columns) (string, func(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareTimeTravel(ctx context.Context, criteria querier, allow bool) string {
|
||||||
|
if !allow {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
took := call.Took(ctx)
|
||||||
|
return criteria.Timetravel(took)
|
||||||
|
}
|
||||||
|
|
||||||
func maxSequenceScanner(row scan, dest interface{}) (err error) {
|
func maxSequenceScanner(row scan, dest interface{}) (err error) {
|
||||||
sequence, ok := dest.(*Sequence)
|
sequence, ok := dest.(*Sequence)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/DATA-DOG/go-sqlmock"
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
)
|
)
|
||||||
@ -537,7 +538,10 @@ func Test_query_events_with_crdb(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
db := &CRDB{
|
db := &CRDB{
|
||||||
client: tt.fields.client,
|
DB: &database.DB{
|
||||||
|
DB: tt.fields.client,
|
||||||
|
Database: new(testDB),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup initial data for query
|
// setup initial data for query
|
||||||
@ -657,6 +661,36 @@ func Test_query_events_mocked(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "with limit and order by desc as of system time",
|
||||||
|
args: args{
|
||||||
|
dest: &[]*repository.Event{},
|
||||||
|
query: &repository.SearchQuery{
|
||||||
|
Columns: repository.ColumnsEvent,
|
||||||
|
Desc: true,
|
||||||
|
Limit: 5,
|
||||||
|
AllowTimeTravel: true,
|
||||||
|
Filters: [][]*repository.Filter{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Field: repository.FieldAggregateType,
|
||||||
|
Value: repository.AggregateType("user"),
|
||||||
|
Operation: repository.OperationEquals,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields{
|
||||||
|
mock: newMockClient(t).expectQuery(t,
|
||||||
|
`SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, previous_aggregate_type_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events AS OF SYSTEM TIME '-1 ms' WHERE \( aggregate_type = \$1 \) ORDER BY event_sequence DESC LIMIT \$2`,
|
||||||
|
[]driver.Value{repository.AggregateType("user"), uint64(5)},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "error sql conn closed",
|
name: "error sql conn closed",
|
||||||
args: args{
|
args: args{
|
||||||
@ -786,9 +820,11 @@ func Test_query_events_mocked(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
crdb := &CRDB{}
|
crdb := &CRDB{DB: &database.DB{
|
||||||
|
Database: new(testDB),
|
||||||
|
}}
|
||||||
if tt.fields.mock != nil {
|
if tt.fields.mock != nil {
|
||||||
crdb.client = tt.fields.mock.client
|
crdb.DB.DB = tt.fields.mock.client
|
||||||
}
|
}
|
||||||
|
|
||||||
err := query(context.Background(), crdb, tt.args.query, tt.args.dest)
|
err := query(context.Background(), crdb, tt.args.query, tt.args.dest)
|
||||||
|
@ -12,14 +12,15 @@ import (
|
|||||||
// SearchQueryBuilder represents the builder for your filter
|
// SearchQueryBuilder represents the builder for your filter
|
||||||
// if invalid data are set the filter will fail
|
// if invalid data are set the filter will fail
|
||||||
type SearchQueryBuilder struct {
|
type SearchQueryBuilder struct {
|
||||||
columns repository.Columns
|
columns repository.Columns
|
||||||
limit uint64
|
limit uint64
|
||||||
desc bool
|
desc bool
|
||||||
resourceOwner string
|
resourceOwner string
|
||||||
instanceID string
|
instanceID string
|
||||||
editorUser string
|
editorUser string
|
||||||
queries []*SearchQuery
|
queries []*SearchQuery
|
||||||
tx *sql.Tx
|
tx *sql.Tx
|
||||||
|
allowTimeTravel bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchQuery struct {
|
type SearchQuery struct {
|
||||||
@ -130,6 +131,13 @@ func (builder *SearchQueryBuilder) EditorUser(id string) *SearchQueryBuilder {
|
|||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowTimeTravel activates the time travel feature of the database if supported
|
||||||
|
// The queries will be made based on the call time
|
||||||
|
func (builder *SearchQueryBuilder) AllowTimeTravel() *SearchQueryBuilder {
|
||||||
|
builder.allowTimeTravel = true
|
||||||
|
return builder
|
||||||
|
}
|
||||||
|
|
||||||
// AddQuery creates a new sub query.
|
// AddQuery creates a new sub query.
|
||||||
// All fields in the sub query are AND-connected in the storage request.
|
// All fields in the sub query are AND-connected in the storage request.
|
||||||
// Multiple sub queries are OR-connected in the storage request.
|
// Multiple sub queries are OR-connected in the storage request.
|
||||||
@ -264,11 +272,12 @@ func (builder *SearchQueryBuilder) build(instanceID string) (*repository.SearchQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &repository.SearchQuery{
|
return &repository.SearchQuery{
|
||||||
Columns: builder.columns,
|
Columns: builder.columns,
|
||||||
Limit: builder.limit,
|
Limit: builder.limit,
|
||||||
Desc: builder.desc,
|
Desc: builder.desc,
|
||||||
Filters: filters,
|
Filters: filters,
|
||||||
Tx: builder.tx,
|
Tx: builder.tx,
|
||||||
|
AllowTimeTravel: builder.allowTimeTravel,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository"
|
||||||
z_sql "github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository/sql"
|
z_sql "github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository/sql"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
@ -22,7 +22,7 @@ type eventstore struct {
|
|||||||
repo repository.Repository
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(db *sql.DB) (Eventstore, error) {
|
func Start(db *database.DB) (Eventstore, error) {
|
||||||
return &eventstore{
|
return &eventstore{
|
||||||
repo: z_sql.Start(db),
|
repo: z_sql.Start(db),
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Start(client *sql.DB) *SQL {
|
func Start(client *database.DB) *SQL {
|
||||||
return &SQL{
|
return &SQL{
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
selectEscaped = `SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore\.events WHERE \( aggregate_type = \$1`
|
selectEscaped = `SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore\.events AS OF SYSTEM TIME '-1 ms' WHERE \( aggregate_type = \$1`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -172,14 +172,14 @@ func (db *dbMock) expectFilterEventsError(returnedErr error) *dbMock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *dbMock) expectLatestSequenceFilter(aggregateType string, sequence Sequence) *dbMock {
|
func (db *dbMock) expectLatestSequenceFilter(aggregateType string, sequence Sequence) *dbMock {
|
||||||
db.mock.ExpectQuery(`SELECT MAX\(event_sequence\) FROM eventstore\.events WHERE \( aggregate_type = \$1 \)`).
|
db.mock.ExpectQuery(`SELECT MAX\(event_sequence\) FROM eventstore\.events AS OF SYSTEM TIME '-1 ms' WHERE \( aggregate_type = \$1 \)`).
|
||||||
WithArgs(aggregateType).
|
WithArgs(aggregateType).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"max_sequence"}).AddRow(sequence))
|
WillReturnRows(sqlmock.NewRows([]string{"max_sequence"}).AddRow(sequence))
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *dbMock) expectLatestSequenceFilterError(aggregateType string, err error) *dbMock {
|
func (db *dbMock) expectLatestSequenceFilterError(aggregateType string, err error) *dbMock {
|
||||||
db.mock.ExpectQuery(`SELECT MAX\(event_sequence\) FROM eventstore\.events WHERE \( aggregate_type = \$1 \)`).
|
db.mock.ExpectQuery(`SELECT MAX\(event_sequence\) FROM eventstore\.events AS OF SYSTEM TIME '-1 ms' WHERE \( aggregate_type = \$1 \)`).
|
||||||
WithArgs(aggregateType).WillReturnError(err)
|
WithArgs(aggregateType).WillReturnError(err)
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
@ -16,16 +17,16 @@ type Querier interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) {
|
func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) {
|
||||||
return filter(db.client, searchQuery)
|
return filter(ctx, db.client, searchQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter(querier Querier, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) {
|
func filter(ctx context.Context, db *database.DB, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) {
|
||||||
query, limit, values, rowScanner := buildQuery(searchQuery)
|
query, limit, values, rowScanner := buildQuery(ctx, db, searchQuery)
|
||||||
if query == "" {
|
if query == "" {
|
||||||
return nil, errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
return nil, errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := querier.Query(query, values...)
|
rows, err := db.Query(query, values...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.New().WithError(err).Info("query failed")
|
logging.New().WithError(err).Info("query failed")
|
||||||
return nil, errors.ThrowInternal(err, "SQL-IJuyR", "unable to filter events")
|
return nil, errors.ThrowInternal(err, "SQL-IJuyR", "unable to filter events")
|
||||||
@ -48,7 +49,7 @@ func filter(querier Querier, searchQuery *es_models.SearchQueryFactory) (events
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *SQL) LatestSequence(ctx context.Context, queryFactory *es_models.SearchQueryFactory) (uint64, error) {
|
func (db *SQL) LatestSequence(ctx context.Context, queryFactory *es_models.SearchQueryFactory) (uint64, error) {
|
||||||
query, _, values, rowScanner := buildQuery(queryFactory)
|
query, _, values, rowScanner := buildQuery(ctx, db.client, queryFactory)
|
||||||
if query == "" {
|
if query == "" {
|
||||||
return 0, errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
return 0, errors.ThrowInvalidArgument(nil, "SQL-rWeBw", "invalid query factory")
|
||||||
}
|
}
|
||||||
@ -63,7 +64,7 @@ func (db *SQL) LatestSequence(ctx context.Context, queryFactory *es_models.Searc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *SQL) InstanceIDs(ctx context.Context, queryFactory *es_models.SearchQueryFactory) ([]string, error) {
|
func (db *SQL) InstanceIDs(ctx context.Context, queryFactory *es_models.SearchQueryFactory) ([]string, error) {
|
||||||
query, _, values, rowScanner := buildQuery(queryFactory)
|
query, _, values, rowScanner := buildQuery(ctx, db.client, queryFactory)
|
||||||
if query == "" {
|
if query == "" {
|
||||||
return nil, errors.ThrowInvalidArgument(nil, "SQL-Sfwg2", "invalid query factory")
|
return nil, errors.ThrowInvalidArgument(nil, "SQL-Sfwg2", "invalid query factory")
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
)
|
)
|
||||||
@ -122,7 +123,7 @@ func TestSQL_Filter(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
sql := &SQL{
|
sql := &SQL{
|
||||||
client: tt.fields.client.sqlClient,
|
client: &database.DB{DB: tt.fields.client.sqlClient, Database: new(testDB)},
|
||||||
}
|
}
|
||||||
events, err := sql.Filter(context.Background(), tt.args.searchQuery)
|
events, err := sql.Filter(context.Background(), tt.args.searchQuery)
|
||||||
if (err != nil) != tt.res.wantErr {
|
if (err != nil) != tt.res.wantErr {
|
||||||
@ -217,7 +218,7 @@ func TestSQL_LatestSequence(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
sql := &SQL{
|
sql := &SQL{
|
||||||
client: tt.fields.client.sqlClient,
|
client: &database.DB{DB: tt.fields.client.sqlClient, Database: new(testDB)},
|
||||||
}
|
}
|
||||||
sequence, err := sql.LatestSequence(context.Background(), tt.args.searchQuery)
|
sequence, err := sql.LatestSequence(context.Background(), tt.args.searchQuery)
|
||||||
if (err != nil) != tt.res.wantErr {
|
if (err != nil) != tt.res.wantErr {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -9,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
|
"github.com/zitadel/zitadel/internal/database/dialect"
|
||||||
z_errors "github.com/zitadel/zitadel/internal/errors"
|
z_errors "github.com/zitadel/zitadel/internal/errors"
|
||||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
)
|
)
|
||||||
@ -30,7 +33,7 @@ const (
|
|||||||
" FROM eventstore.events"
|
" FROM eventstore.events"
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildQuery(queryFactory *es_models.SearchQueryFactory) (query string, limit uint64, values []interface{}, rowScanner func(s scan, dest interface{}) error) {
|
func buildQuery(ctx context.Context, db dialect.Database, queryFactory *es_models.SearchQueryFactory) (query string, limit uint64, values []interface{}, rowScanner func(s scan, dest interface{}) error) {
|
||||||
searchQuery, err := queryFactory.Build()
|
searchQuery, err := queryFactory.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.New().WithError(err).Warn("search query factory invalid")
|
logging.New().WithError(err).Warn("search query factory invalid")
|
||||||
@ -41,6 +44,10 @@ func buildQuery(queryFactory *es_models.SearchQueryFactory) (query string, limit
|
|||||||
if where == "" || query == "" {
|
if where == "" || query == "" {
|
||||||
return "", 0, nil, nil
|
return "", 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if travel := db.Timetravel(call.Took(ctx)); travel != "" {
|
||||||
|
query += travel
|
||||||
|
}
|
||||||
query += where
|
query += where
|
||||||
|
|
||||||
if searchQuery.Columns == es_models.Columns_Event {
|
if searchQuery.Columns == es_models.Columns_Event {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
@ -435,7 +436,7 @@ func Test_buildQuery(t *testing.T) {
|
|||||||
queryFactory: es_models.NewSearchQueryFactory().OrderDesc().AddQuery().AggregateTypes("user").Factory(),
|
queryFactory: es_models.NewSearchQueryFactory().OrderDesc().AddQuery().AggregateTypes("user").Factory(),
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events WHERE ( aggregate_type = $1 ) ORDER BY event_sequence DESC",
|
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events AS OF SYSTEM TIME '-1 ms' WHERE ( aggregate_type = $1 ) ORDER BY event_sequence DESC",
|
||||||
rowScanner: true,
|
rowScanner: true,
|
||||||
values: []interface{}{es_models.AggregateType("user")},
|
values: []interface{}{es_models.AggregateType("user")},
|
||||||
},
|
},
|
||||||
@ -446,7 +447,7 @@ func Test_buildQuery(t *testing.T) {
|
|||||||
queryFactory: es_models.NewSearchQueryFactory().Limit(5).AddQuery().AggregateTypes("user").Factory(),
|
queryFactory: es_models.NewSearchQueryFactory().Limit(5).AddQuery().AggregateTypes("user").Factory(),
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events WHERE ( aggregate_type = $1 ) ORDER BY event_sequence LIMIT $2",
|
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events AS OF SYSTEM TIME '-1 ms' WHERE ( aggregate_type = $1 ) ORDER BY event_sequence LIMIT $2",
|
||||||
rowScanner: true,
|
rowScanner: true,
|
||||||
values: []interface{}{es_models.AggregateType("user"), uint64(5)},
|
values: []interface{}{es_models.AggregateType("user"), uint64(5)},
|
||||||
limit: 5,
|
limit: 5,
|
||||||
@ -458,7 +459,7 @@ func Test_buildQuery(t *testing.T) {
|
|||||||
queryFactory: es_models.NewSearchQueryFactory().Limit(5).OrderDesc().AddQuery().AggregateTypes("user").Factory(),
|
queryFactory: es_models.NewSearchQueryFactory().Limit(5).OrderDesc().AddQuery().AggregateTypes("user").Factory(),
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events WHERE ( aggregate_type = $1 ) ORDER BY event_sequence DESC LIMIT $2",
|
query: "SELECT creation_date, event_type, event_sequence, previous_aggregate_sequence, event_data, editor_service, editor_user, resource_owner, instance_id, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events AS OF SYSTEM TIME '-1 ms' WHERE ( aggregate_type = $1 ) ORDER BY event_sequence DESC LIMIT $2",
|
||||||
rowScanner: true,
|
rowScanner: true,
|
||||||
values: []interface{}{es_models.AggregateType("user"), uint64(5)},
|
values: []interface{}{es_models.AggregateType("user"), uint64(5)},
|
||||||
limit: 5,
|
limit: 5,
|
||||||
@ -466,8 +467,10 @@ func Test_buildQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
ctx := context.Background()
|
||||||
|
db := new(testDB)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
gotQuery, gotLimit, gotValues, gotRowScanner := buildQuery(tt.args.queryFactory)
|
gotQuery, gotLimit, gotValues, gotRowScanner := buildQuery(ctx, db, tt.args.queryFactory)
|
||||||
if gotQuery != tt.res.query {
|
if gotQuery != tt.res.query {
|
||||||
t.Errorf("buildQuery() gotQuery = %v, want %v", gotQuery, tt.res.query)
|
t.Errorf("buildQuery() gotQuery = %v, want %v", gotQuery, tt.res.query)
|
||||||
}
|
}
|
||||||
@ -489,3 +492,13 @@ func Test_buildQuery(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testDB struct{}
|
||||||
|
|
||||||
|
func (_ *testDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " }
|
||||||
|
|
||||||
|
func (*testDB) DatabaseName() string { return "db" }
|
||||||
|
|
||||||
|
func (*testDB) Username() string { return "user" }
|
||||||
|
|
||||||
|
func (*testDB) Type() string { return "type" }
|
||||||
|
@ -2,11 +2,12 @@ package sql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SQL struct {
|
type SQL struct {
|
||||||
client *sql.DB
|
client *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *SQL) Health(ctx context.Context) error {
|
func (db *SQL) Health(ctx context.Context) error {
|
||||||
|
@ -2,7 +2,6 @@ package access
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -12,7 +11,9 @@ import (
|
|||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
zitadel_http "github.com/zitadel/zitadel/internal/api/http"
|
zitadel_http "github.com/zitadel/zitadel/internal/api/http"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/logstore"
|
"github.com/zitadel/zitadel/internal/logstore"
|
||||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
"github.com/zitadel/zitadel/internal/repository/quota"
|
||||||
@ -36,10 +37,10 @@ var _ logstore.UsageQuerier = (*databaseLogStorage)(nil)
|
|||||||
var _ logstore.LogCleanupper = (*databaseLogStorage)(nil)
|
var _ logstore.LogCleanupper = (*databaseLogStorage)(nil)
|
||||||
|
|
||||||
type databaseLogStorage struct {
|
type databaseLogStorage struct {
|
||||||
dbClient *sql.DB
|
dbClient *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabaseLogStorage(dbClient *sql.DB) *databaseLogStorage {
|
func NewDatabaseLogStorage(dbClient *database.DB) *databaseLogStorage {
|
||||||
return &databaseLogStorage{dbClient: dbClient}
|
return &databaseLogStorage{dbClient: dbClient}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,12 +99,11 @@ func (l *databaseLogStorage) Emit(ctx context.Context, bulk []logstore.LogRecord
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: AS OF SYSTEM TIME
|
|
||||||
func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) {
|
func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) {
|
||||||
stmt, args, err := squirrel.Select(
|
stmt, args, err := squirrel.Select(
|
||||||
fmt.Sprintf("count(%s)", accessInstanceIdCol),
|
fmt.Sprintf("count(%s)", accessInstanceIdCol),
|
||||||
).
|
).
|
||||||
From(accessLogsTable).
|
From(accessLogsTable + l.dbClient.Timetravel(call.Took(ctx))).
|
||||||
Where(squirrel.And{
|
Where(squirrel.And{
|
||||||
squirrel.Eq{accessInstanceIdCol: instanceId},
|
squirrel.Eq{accessInstanceIdCol: instanceId},
|
||||||
squirrel.GtOrEq{accessTimestampCol: start},
|
squirrel.GtOrEq{accessTimestampCol: start},
|
||||||
|
@ -2,13 +2,14 @@ package execution
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Masterminds/squirrel"
|
"github.com/Masterminds/squirrel"
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
caos_errors "github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/logstore"
|
"github.com/zitadel/zitadel/internal/logstore"
|
||||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
"github.com/zitadel/zitadel/internal/repository/quota"
|
||||||
@ -29,10 +30,10 @@ var _ logstore.UsageQuerier = (*databaseLogStorage)(nil)
|
|||||||
var _ logstore.LogCleanupper = (*databaseLogStorage)(nil)
|
var _ logstore.LogCleanupper = (*databaseLogStorage)(nil)
|
||||||
|
|
||||||
type databaseLogStorage struct {
|
type databaseLogStorage struct {
|
||||||
dbClient *sql.DB
|
dbClient *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabaseLogStorage(dbClient *sql.DB) *databaseLogStorage {
|
func NewDatabaseLogStorage(dbClient *database.DB) *databaseLogStorage {
|
||||||
return &databaseLogStorage{dbClient: dbClient}
|
return &databaseLogStorage{dbClient: dbClient}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,12 +92,11 @@ func (l *databaseLogStorage) Emit(ctx context.Context, bulk []logstore.LogRecord
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: AS OF SYSTEM TIME
|
|
||||||
func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) {
|
func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) {
|
||||||
stmt, args, err := squirrel.Select(
|
stmt, args, err := squirrel.Select(
|
||||||
fmt.Sprintf("COALESCE(SUM(%s)::INT,0)", executionTookCol),
|
fmt.Sprintf("COALESCE(SUM(%s)::INT,0)", executionTookCol),
|
||||||
).
|
).
|
||||||
From(executionLogsTable).
|
From(executionLogsTable + l.dbClient.Timetravel(call.Took(ctx))).
|
||||||
Where(squirrel.And{
|
Where(squirrel.And{
|
||||||
squirrel.Eq{executionInstanceIdCol: instanceId},
|
squirrel.Eq{executionInstanceIdCol: instanceId},
|
||||||
squirrel.GtOrEq{executionTimestampCol: start},
|
squirrel.GtOrEq{executionTimestampCol: start},
|
||||||
|
@ -7,9 +7,12 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
"github.com/zitadel/zitadel/internal/repository/quota"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const handleThresholdTimeout = time.Minute
|
||||||
|
|
||||||
type QuotaQuerier interface {
|
type QuotaQuerier interface {
|
||||||
GetCurrentQuotaPeriod(ctx context.Context, instanceID string, unit quota.Unit) (config *quota.AddedEvent, periodStart time.Time, err error)
|
GetCurrentQuotaPeriod(ctx context.Context, instanceID string, unit quota.Unit) (config *quota.AddedEvent, periodStart time.Time, err error)
|
||||||
GetDueQuotaNotifications(ctx context.Context, config *quota.AddedEvent, periodStart time.Time, used uint64) ([]*quota.NotifiedEvent, error)
|
GetDueQuotaNotifications(ctx context.Context, config *quota.AddedEvent, periodStart time.Time, used uint64) ([]*quota.NotifiedEvent, error)
|
||||||
@ -94,17 +97,29 @@ func (s *Service) Limit(ctx context.Context, instanceID string) *uint64 {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go s.handleThresholds(ctx, quota, periodStart, usage)
|
||||||
|
|
||||||
var remaining *uint64
|
var remaining *uint64
|
||||||
if quota.Limit {
|
if quota.Limit {
|
||||||
r := uint64(math.Max(0, float64(quota.Amount)-float64(usage)))
|
r := uint64(math.Max(0, float64(quota.Amount)-float64(usage)))
|
||||||
remaining = &r
|
remaining = &r
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications, err := s.quotaQuerier.GetDueQuotaNotifications(ctx, quota, periodStart, usage)
|
|
||||||
if err != nil {
|
|
||||||
return remaining
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.usageReporter.Report(ctx, notifications)
|
|
||||||
return remaining
|
return remaining
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) handleThresholds(ctx context.Context, quota *quota.AddedEvent, periodStart time.Time, usage uint64) {
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
logging.OnError(err).Warn("handling quota thresholds failed")
|
||||||
|
}()
|
||||||
|
|
||||||
|
detatchedCtx, cancel := context.WithTimeout(authz.Detach(ctx), handleThresholdTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
notifications, err := s.quotaQuerier.GetDueQuotaNotifications(detatchedCtx, quota, periodStart, usage)
|
||||||
|
if err != nil || len(notifications) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.usageReporter.Report(detatchedCtx, notifications)
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -117,7 +118,7 @@ func (q *Queries) SearchActions(ctx context.Context, queries *ActionSearchQuerie
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareActionsQuery()
|
query, scan := prepareActionsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
ActionColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
ActionColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
}
|
}
|
||||||
@ -145,7 +146,7 @@ func (q *Queries) GetActionByID(ctx context.Context, id string, orgID string, wi
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareActionQuery()
|
stmt, scan := prepareActionQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
ActionColumnID.identifier(): id,
|
ActionColumnID.identifier(): id,
|
||||||
ActionColumnResourceOwner.identifier(): orgID,
|
ActionColumnResourceOwner.identifier(): orgID,
|
||||||
@ -179,7 +180,7 @@ func NewActionIDSearchQuery(id string) (SearchQuery, error) {
|
|||||||
return NewTextQuery(ActionColumnID, id, TextEquals)
|
return NewTextQuery(ActionColumnID, id, TextEquals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, error)) {
|
func prepareActionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
ActionColumnID.identifier(),
|
ActionColumnID.identifier(),
|
||||||
ActionColumnCreationDate.identifier(),
|
ActionColumnCreationDate.identifier(),
|
||||||
@ -192,7 +193,8 @@ func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, er
|
|||||||
ActionColumnTimeout.identifier(),
|
ActionColumnTimeout.identifier(),
|
||||||
ActionColumnAllowedToFail.identifier(),
|
ActionColumnAllowedToFail.identifier(),
|
||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(actionTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(actionTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*Actions, error) {
|
func(rows *sql.Rows) (*Actions, error) {
|
||||||
actions := make([]*Action, 0)
|
actions := make([]*Action, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
@ -230,7 +232,7 @@ func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareActionQuery() (sq.SelectBuilder, func(row *sql.Row) (*Action, error)) {
|
func prepareActionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) (*Action, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
ActionColumnID.identifier(),
|
ActionColumnID.identifier(),
|
||||||
ActionColumnCreationDate.identifier(),
|
ActionColumnCreationDate.identifier(),
|
||||||
@ -242,7 +244,8 @@ func prepareActionQuery() (sq.SelectBuilder, func(row *sql.Row) (*Action, error)
|
|||||||
ActionColumnScript.identifier(),
|
ActionColumnScript.identifier(),
|
||||||
ActionColumnTimeout.identifier(),
|
ActionColumnTimeout.identifier(),
|
||||||
ActionColumnAllowedToFail.identifier(),
|
ActionColumnAllowedToFail.identifier(),
|
||||||
).From(actionTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(actionTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*Action, error) {
|
func(row *sql.Row) (*Action, error) {
|
||||||
action := new(Action)
|
action := new(Action)
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -70,7 +71,7 @@ func (q *Queries) GetFlow(ctx context.Context, flowType domain.FlowType, orgID s
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareFlowQuery(flowType)
|
query, scan := prepareFlowQuery(ctx, q.client, flowType)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
FlowsTriggersColumnFlowType.identifier(): flowType,
|
FlowsTriggersColumnFlowType.identifier(): flowType,
|
||||||
FlowsTriggersColumnResourceOwner.identifier(): orgID,
|
FlowsTriggersColumnResourceOwner.identifier(): orgID,
|
||||||
@ -95,7 +96,7 @@ func (q *Queries) GetActiveActionsByFlowAndTriggerType(ctx context.Context, flow
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareTriggerActionsQuery()
|
stmt, scan := prepareTriggerActionsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
FlowsTriggersColumnFlowType.identifier(): flowType,
|
FlowsTriggersColumnFlowType.identifier(): flowType,
|
||||||
FlowsTriggersColumnTriggerType.identifier(): triggerType,
|
FlowsTriggersColumnTriggerType.identifier(): triggerType,
|
||||||
@ -122,7 +123,7 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareFlowTypesQuery()
|
stmt, scan := prepareFlowTypesQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
FlowsTriggersColumnActionID.identifier(): actionID,
|
FlowsTriggersColumnActionID.identifier(): actionID,
|
||||||
FlowsTriggersColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
FlowsTriggersColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -143,11 +144,11 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w
|
|||||||
return scan(rows)
|
return scan(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareFlowTypesQuery() (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowType, error)) {
|
func prepareFlowTypesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowType, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
FlowsTriggersColumnFlowType.identifier(),
|
FlowsTriggersColumnFlowType.identifier(),
|
||||||
).
|
).
|
||||||
From(flowsTriggersTable.identifier()).
|
From(flowsTriggersTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) ([]domain.FlowType, error) {
|
func(rows *sql.Rows) ([]domain.FlowType, error) {
|
||||||
types := []domain.FlowType{}
|
types := []domain.FlowType{}
|
||||||
@ -166,7 +167,7 @@ func prepareFlowTypesQuery() (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowTy
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action, error)) {
|
func prepareTriggerActionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]*Action, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
ActionColumnID.identifier(),
|
ActionColumnID.identifier(),
|
||||||
ActionColumnCreationDate.identifier(),
|
ActionColumnCreationDate.identifier(),
|
||||||
@ -180,7 +181,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
|
|||||||
ActionColumnTimeout.identifier(),
|
ActionColumnTimeout.identifier(),
|
||||||
).
|
).
|
||||||
From(flowsTriggersTable.name).
|
From(flowsTriggersTable.name).
|
||||||
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)).
|
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) ([]*Action, error) {
|
func(rows *sql.Rows) ([]*Action, error) {
|
||||||
actions := make([]*Action, 0)
|
actions := make([]*Action, 0)
|
||||||
@ -212,7 +213,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
func prepareFlowQuery(ctx context.Context, db prepareDatabase, flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
ActionColumnID.identifier(),
|
ActionColumnID.identifier(),
|
||||||
ActionColumnCreationDate.identifier(),
|
ActionColumnCreationDate.identifier(),
|
||||||
@ -232,7 +233,7 @@ func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Row
|
|||||||
FlowsTriggersColumnResourceOwner.identifier(),
|
FlowsTriggersColumnResourceOwner.identifier(),
|
||||||
).
|
).
|
||||||
From(flowsTriggersTable.name).
|
From(flowsTriggersTable.name).
|
||||||
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)).
|
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*Flow, error) {
|
func(rows *sql.Rows) (*Flow, error) {
|
||||||
flow := &Flow{
|
flow := &Flow{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package query
|
package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"errors"
|
"errors"
|
||||||
@ -14,6 +15,82 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareFlowStmt = `SELECT projections.actions3.id,` +
|
||||||
|
` projections.actions3.creation_date,` +
|
||||||
|
` projections.actions3.change_date,` +
|
||||||
|
` projections.actions3.resource_owner,` +
|
||||||
|
` projections.actions3.action_state,` +
|
||||||
|
` projections.actions3.sequence,` +
|
||||||
|
` projections.actions3.name,` +
|
||||||
|
` projections.actions3.script,` +
|
||||||
|
` projections.actions3.allowed_to_fail,` +
|
||||||
|
` projections.actions3.timeout,` +
|
||||||
|
` projections.flow_triggers2.trigger_type,` +
|
||||||
|
` projections.flow_triggers2.trigger_sequence,` +
|
||||||
|
` projections.flow_triggers2.flow_type,` +
|
||||||
|
` projections.flow_triggers2.change_date,` +
|
||||||
|
` projections.flow_triggers2.sequence,` +
|
||||||
|
` projections.flow_triggers2.resource_owner` +
|
||||||
|
` FROM projections.flow_triggers2` +
|
||||||
|
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id AND projections.flow_triggers2.instance_id = projections.actions3.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareFlowCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"state",
|
||||||
|
"sequence",
|
||||||
|
"name",
|
||||||
|
"script",
|
||||||
|
"allowed_to_fail",
|
||||||
|
"timeout",
|
||||||
|
// flow
|
||||||
|
"trigger_type",
|
||||||
|
"trigger_sequence",
|
||||||
|
"flow_type",
|
||||||
|
"change_date",
|
||||||
|
"sequence",
|
||||||
|
"resource_owner",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareTriggerActionStmt = `SELECT projections.actions3.id,` +
|
||||||
|
` projections.actions3.creation_date,` +
|
||||||
|
` projections.actions3.change_date,` +
|
||||||
|
` projections.actions3.resource_owner,` +
|
||||||
|
` projections.actions3.action_state,` +
|
||||||
|
` projections.actions3.sequence,` +
|
||||||
|
` projections.actions3.name,` +
|
||||||
|
` projections.actions3.script,` +
|
||||||
|
` projections.actions3.allowed_to_fail,` +
|
||||||
|
` projections.actions3.timeout` +
|
||||||
|
` FROM projections.flow_triggers2` +
|
||||||
|
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id AND projections.flow_triggers2.instance_id = projections.actions3.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
|
||||||
|
prepareTriggerActionCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"state",
|
||||||
|
"sequence",
|
||||||
|
"name",
|
||||||
|
"script",
|
||||||
|
"allowed_to_fail",
|
||||||
|
"timeout",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareFlowTypeStmt = `SELECT projections.flow_triggers2.flow_type` +
|
||||||
|
` FROM projections.flow_triggers2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
|
||||||
|
prepareFlowTypeCols = []string{
|
||||||
|
"flow_type",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_FlowPrepares(t *testing.T) {
|
func Test_FlowPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -27,29 +104,12 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "prepareFlowQuery no result",
|
name: "prepareFlowQuery no result",
|
||||||
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
|
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareFlowStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.flow_triggers2.trigger_type,`+
|
|
||||||
` projections.flow_triggers2.trigger_sequence,`+
|
|
||||||
` projections.flow_triggers2.flow_type,`+
|
|
||||||
` projections.flow_triggers2.change_date,`+
|
|
||||||
` projections.flow_triggers2.sequence,`+
|
|
||||||
` projections.flow_triggers2.resource_owner`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -61,48 +121,13 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prepareFlowQuery one action",
|
name: "prepareFlowQuery one action",
|
||||||
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
|
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareFlowStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareFlowCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.flow_triggers2.trigger_type,`+
|
|
||||||
` projections.flow_triggers2.trigger_sequence,`+
|
|
||||||
` projections.flow_triggers2.flow_type,`+
|
|
||||||
` projections.flow_triggers2.change_date,`+
|
|
||||||
` projections.flow_triggers2.sequence,`+
|
|
||||||
` projections.flow_triggers2.resource_owner`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"state",
|
|
||||||
"sequence",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"timeout",
|
|
||||||
//flow
|
|
||||||
"trigger_type",
|
|
||||||
"trigger_sequence",
|
|
||||||
"flow_type",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"resource_owner",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"action-id",
|
"action-id",
|
||||||
@ -150,48 +175,13 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prepareFlowQuery multiple actions",
|
name: "prepareFlowQuery multiple actions",
|
||||||
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
|
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareFlowStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareFlowCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.flow_triggers2.trigger_type,`+
|
|
||||||
` projections.flow_triggers2.trigger_sequence,`+
|
|
||||||
` projections.flow_triggers2.flow_type,`+
|
|
||||||
` projections.flow_triggers2.change_date,`+
|
|
||||||
` projections.flow_triggers2.sequence,`+
|
|
||||||
` projections.flow_triggers2.resource_owner`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"state",
|
|
||||||
"sequence",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"timeout",
|
|
||||||
//flow
|
|
||||||
"trigger_type",
|
|
||||||
"trigger_sequence",
|
|
||||||
"flow_type",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"resource_owner",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"action-id-pre",
|
"action-id-pre",
|
||||||
@ -271,48 +261,13 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prepareFlowQuery no action",
|
name: "prepareFlowQuery no action",
|
||||||
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
|
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareFlowStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareFlowCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.flow_triggers2.trigger_type,`+
|
|
||||||
` projections.flow_triggers2.trigger_sequence,`+
|
|
||||||
` projections.flow_triggers2.flow_type,`+
|
|
||||||
` projections.flow_triggers2.change_date,`+
|
|
||||||
` projections.flow_triggers2.sequence,`+
|
|
||||||
` projections.flow_triggers2.resource_owner`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"state",
|
|
||||||
"sequence",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"timeout",
|
|
||||||
//flow
|
|
||||||
"trigger_type",
|
|
||||||
"trigger_sequence",
|
|
||||||
"flow_type",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"resource_owner",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
nil,
|
nil,
|
||||||
@ -345,29 +300,12 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "prepareFlowQuery sql err",
|
name: "prepareFlowQuery sql err",
|
||||||
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
|
||||||
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
|
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareFlowStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.flow_triggers2.trigger_type,`+
|
|
||||||
` projections.flow_triggers2.trigger_sequence,`+
|
|
||||||
` projections.flow_triggers2.flow_type,`+
|
|
||||||
` projections.flow_triggers2.change_date,`+
|
|
||||||
` projections.flow_triggers2.sequence,`+
|
|
||||||
` projections.flow_triggers2.resource_owner`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -384,18 +322,7 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareTriggerActionsQuery,
|
prepare: prepareTriggerActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareTriggerActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -407,30 +334,8 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareTriggerActionsQuery,
|
prepare: prepareTriggerActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareTriggerActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareTriggerActionCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"state",
|
|
||||||
"sequence",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"timeout",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"action-id",
|
"action-id",
|
||||||
@ -467,30 +372,8 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareTriggerActionsQuery,
|
prepare: prepareTriggerActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareTriggerActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareTriggerActionCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"state",
|
|
||||||
"sequence",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"timeout",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"action-id-1",
|
"action-id-1",
|
||||||
@ -551,18 +434,7 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareTriggerActionsQuery,
|
prepare: prepareTriggerActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareTriggerActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` projections.actions3.timeout`+
|
|
||||||
` FROM projections.flow_triggers2`+
|
|
||||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -579,8 +451,7 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareFlowTypesQuery,
|
prepare: prepareFlowTypesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
|
regexp.QuoteMeta(prepareFlowTypeStmt),
|
||||||
` FROM projections.flow_triggers2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -592,11 +463,8 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareFlowTypesQuery,
|
prepare: prepareFlowTypesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
|
regexp.QuoteMeta(prepareFlowTypeStmt),
|
||||||
` FROM projections.flow_triggers2`),
|
prepareFlowTypeCols,
|
||||||
[]string{
|
|
||||||
"flow_type",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
domain.FlowTypeExternalAuthentication,
|
domain.FlowTypeExternalAuthentication,
|
||||||
@ -613,11 +481,8 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareFlowTypesQuery,
|
prepare: prepareFlowTypesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
|
regexp.QuoteMeta(prepareFlowTypeStmt),
|
||||||
` FROM projections.flow_triggers2`),
|
prepareFlowTypeCols,
|
||||||
[]string{
|
|
||||||
"flow_type",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
domain.FlowTypeExternalAuthentication,
|
domain.FlowTypeExternalAuthentication,
|
||||||
@ -638,8 +503,7 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
prepare: prepareFlowTypesQuery,
|
prepare: prepareFlowTypesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
|
regexp.QuoteMeta(prepareFlowTypeStmt),
|
||||||
` FROM projections.flow_triggers2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -654,7 +518,7 @@ func Test_FlowPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,60 @@ import (
|
|||||||
errs "github.com/zitadel/zitadel/internal/errors"
|
errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareActionsStmt = `SELECT projections.actions3.id,` +
|
||||||
|
` projections.actions3.creation_date,` +
|
||||||
|
` projections.actions3.change_date,` +
|
||||||
|
` projections.actions3.resource_owner,` +
|
||||||
|
` projections.actions3.sequence,` +
|
||||||
|
` projections.actions3.action_state,` +
|
||||||
|
` projections.actions3.name,` +
|
||||||
|
` projections.actions3.script,` +
|
||||||
|
` projections.actions3.timeout,` +
|
||||||
|
` projections.actions3.allowed_to_fail,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.actions3` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareActionsCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"sequence",
|
||||||
|
"action_state",
|
||||||
|
"name",
|
||||||
|
"script",
|
||||||
|
"timeout",
|
||||||
|
"allowed_to_fail",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareActionStmt = `SELECT projections.actions3.id,` +
|
||||||
|
` projections.actions3.creation_date,` +
|
||||||
|
` projections.actions3.change_date,` +
|
||||||
|
` projections.actions3.resource_owner,` +
|
||||||
|
` projections.actions3.sequence,` +
|
||||||
|
` projections.actions3.action_state,` +
|
||||||
|
` projections.actions3.name,` +
|
||||||
|
` projections.actions3.script,` +
|
||||||
|
` projections.actions3.timeout,` +
|
||||||
|
` projections.actions3.allowed_to_fail` +
|
||||||
|
` FROM projections.actions3` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareActionCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"sequence",
|
||||||
|
"action_state",
|
||||||
|
"name",
|
||||||
|
"script",
|
||||||
|
"timeout",
|
||||||
|
"allowed_to_fail",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_ActionPrepares(t *testing.T) {
|
func Test_ActionPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -29,18 +83,7 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionsQuery,
|
prepare: prepareActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionsStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -52,31 +95,8 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionsQuery,
|
prepare: prepareActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionsStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareActionsCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"action_state",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"timeout",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id",
|
"id",
|
||||||
@ -118,31 +138,8 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionsQuery,
|
prepare: prepareActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionsStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareActionsCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"action_state",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"timeout",
|
|
||||||
"allowed_to_fail",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id-1",
|
"id-1",
|
||||||
@ -208,18 +205,7 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionsQuery,
|
prepare: prepareActionsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionsStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -236,17 +222,7 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionQuery,
|
prepare: prepareActionQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -264,29 +240,8 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionQuery,
|
prepare: prepareActionQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQuery(
|
sqlExpectations: mockQuery(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
prepareActionCols,
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"action_state",
|
|
||||||
"name",
|
|
||||||
"script",
|
|
||||||
"timeout",
|
|
||||||
"allowed_to_fail",
|
|
||||||
},
|
|
||||||
[]driver.Value{
|
[]driver.Value{
|
||||||
"id",
|
"id",
|
||||||
testNow,
|
testNow,
|
||||||
@ -319,17 +274,7 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
prepare: prepareActionQuery,
|
prepare: prepareActionQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
|
regexp.QuoteMeta(prepareActionStmt),
|
||||||
` projections.actions3.creation_date,`+
|
|
||||||
` projections.actions3.change_date,`+
|
|
||||||
` projections.actions3.resource_owner,`+
|
|
||||||
` projections.actions3.sequence,`+
|
|
||||||
` projections.actions3.action_state,`+
|
|
||||||
` projections.actions3.name,`+
|
|
||||||
` projections.actions3.script,`+
|
|
||||||
` projections.actions3.timeout,`+
|
|
||||||
` projections.actions3.allowed_to_fail`+
|
|
||||||
` FROM projections.actions3`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -344,7 +289,7 @@ func Test_ActionPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/database"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
@ -250,7 +251,7 @@ func (q *Queries) AppByProjectAndAppID(ctx context.Context, shouldTriggerBulk bo
|
|||||||
projection.AppProjection.Trigger(ctx)
|
projection.AppProjection.Trigger(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, scan := prepareAppQuery()
|
stmt, scan := prepareAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppColumnID.identifier(): appID,
|
AppColumnID.identifier(): appID,
|
||||||
AppColumnProjectID.identifier(): projectID,
|
AppColumnProjectID.identifier(): projectID,
|
||||||
@ -272,7 +273,7 @@ func (q *Queries) AppByID(ctx context.Context, appID string, withOwnerRemoved bo
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAppQuery()
|
stmt, scan := prepareAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppColumnID.identifier(): appID,
|
AppColumnID.identifier(): appID,
|
||||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -293,7 +294,7 @@ func (q *Queries) AppBySAMLEntityID(ctx context.Context, entityID string, withOw
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAppQuery()
|
stmt, scan := prepareAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppSAMLConfigColumnEntityID.identifier(): entityID,
|
AppSAMLConfigColumnEntityID.identifier(): entityID,
|
||||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -314,7 +315,7 @@ func (q *Queries) ProjectByClientID(ctx context.Context, appID string, withOwner
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareProjectByAppQuery()
|
stmt, scan := prepareProjectByAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[ProjectColumnOwnerRemoved.identifier()] = false
|
eq[ProjectColumnOwnerRemoved.identifier()] = false
|
||||||
@ -339,7 +340,7 @@ func (q *Queries) ProjectIDFromOIDCClientID(ctx context.Context, appID string, w
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareProjectIDByAppQuery()
|
stmt, scan := prepareProjectIDByAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppOIDCConfigColumnClientID.identifier(): appID,
|
AppOIDCConfigColumnClientID.identifier(): appID,
|
||||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -360,7 +361,7 @@ func (q *Queries) ProjectIDFromClientID(ctx context.Context, appID string, withO
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareProjectIDByAppQuery()
|
stmt, scan := prepareProjectIDByAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[AppColumnOwnerRemoved.identifier()] = false
|
eq[AppColumnOwnerRemoved.identifier()] = false
|
||||||
@ -386,7 +387,7 @@ func (q *Queries) ProjectByOIDCClientID(ctx context.Context, id string, withOwne
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareProjectByAppQuery()
|
stmt, scan := prepareProjectByAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppOIDCConfigColumnClientID.identifier(): id,
|
AppOIDCConfigColumnClientID.identifier(): id,
|
||||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -407,7 +408,7 @@ func (q *Queries) AppByOIDCClientID(ctx context.Context, clientID string, withOw
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAppQuery()
|
stmt, scan := prepareAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AppOIDCConfigColumnClientID.identifier(): clientID,
|
AppOIDCConfigColumnClientID.identifier(): clientID,
|
||||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -428,7 +429,7 @@ func (q *Queries) AppByClientID(ctx context.Context, clientID string, withOwnerR
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAppQuery()
|
stmt, scan := prepareAppQuery(ctx, q.client)
|
||||||
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[AppColumnOwnerRemoved.identifier()] = false
|
eq[AppColumnOwnerRemoved.identifier()] = false
|
||||||
@ -452,7 +453,7 @@ func (q *Queries) SearchApps(ctx context.Context, queries *AppSearchQueries, wit
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareAppsQuery()
|
query, scan := prepareAppsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[AppColumnOwnerRemoved.identifier()] = false
|
eq[AppColumnOwnerRemoved.identifier()] = false
|
||||||
@ -478,7 +479,7 @@ func (q *Queries) SearchClientIDs(ctx context.Context, queries *AppSearchQueries
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareClientIDsQuery()
|
query, scan := prepareClientIDsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[AppColumnOwnerRemoved.identifier()] = false
|
eq[AppColumnOwnerRemoved.identifier()] = false
|
||||||
@ -503,7 +504,7 @@ func NewAppProjectIDSearchQuery(id string) (SearchQuery, error) {
|
|||||||
return NewTextQuery(AppColumnProjectID, id, TextEquals)
|
return NewTextQuery(AppColumnProjectID, id, TextEquals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
|
func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AppColumnID.identifier(),
|
AppColumnID.identifier(),
|
||||||
AppColumnName.identifier(),
|
AppColumnName.identifier(),
|
||||||
@ -542,7 +543,7 @@ func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
|
|||||||
).From(appsTable.identifier()).
|
).From(appsTable.identifier()).
|
||||||
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*App, error) {
|
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*App, error) {
|
||||||
app := new(App)
|
app := new(App)
|
||||||
|
|
||||||
@ -604,13 +605,13 @@ func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareProjectIDByAppQuery() (sq.SelectBuilder, func(*sql.Row) (projectID string, err error)) {
|
func prepareProjectIDByAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (projectID string, err error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AppColumnProjectID.identifier(),
|
AppColumnProjectID.identifier(),
|
||||||
).From(appsTable.identifier()).
|
).From(appsTable.identifier()).
|
||||||
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (projectID string, err error) {
|
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (projectID string, err error) {
|
||||||
err = row.Scan(
|
err = row.Scan(
|
||||||
&projectID,
|
&projectID,
|
||||||
@ -627,7 +628,7 @@ func prepareProjectIDByAppQuery() (sq.SelectBuilder, func(*sql.Row) (projectID s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
|
func prepareProjectByAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
ProjectColumnID.identifier(),
|
ProjectColumnID.identifier(),
|
||||||
ProjectColumnCreationDate.identifier(),
|
ProjectColumnCreationDate.identifier(),
|
||||||
@ -644,7 +645,7 @@ func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, err
|
|||||||
Join(join(AppColumnProjectID, ProjectColumnID)).
|
Join(join(AppColumnProjectID, ProjectColumnID)).
|
||||||
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*Project, error) {
|
func(row *sql.Row) (*Project, error) {
|
||||||
p := new(Project)
|
p := new(Project)
|
||||||
@ -671,7 +672,7 @@ func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
|
func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AppColumnID.identifier(),
|
AppColumnID.identifier(),
|
||||||
AppColumnName.identifier(),
|
AppColumnName.identifier(),
|
||||||
@ -711,7 +712,7 @@ func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
|
|||||||
).From(appsTable.identifier()).
|
).From(appsTable.identifier()).
|
||||||
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar), func(row *sql.Rows) (*Apps, error) {
|
PlaceholderFormat(sq.Dollar), func(row *sql.Rows) (*Apps, error) {
|
||||||
apps := &Apps{Apps: []*App{}}
|
apps := &Apps{Apps: []*App{}}
|
||||||
|
|
||||||
@ -777,13 +778,13 @@ func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareClientIDsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]string, error)) {
|
func prepareClientIDsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]string, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AppAPIConfigColumnClientID.identifier(),
|
AppAPIConfigColumnClientID.identifier(),
|
||||||
AppOIDCConfigColumnClientID.identifier(),
|
AppOIDCConfigColumnClientID.identifier(),
|
||||||
).From(appsTable.identifier()).
|
).From(appsTable.identifier()).
|
||||||
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
|
||||||
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]string, error) {
|
PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]string, error) {
|
||||||
ids := database.StringArray{}
|
ids := database.StringArray{}
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ var (
|
|||||||
` FROM projections.apps4` +
|
` FROM projections.apps4` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
|
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
|
||||||
` projections.apps4.name,` +
|
` projections.apps4.name,` +
|
||||||
` projections.apps4.project_id,` +
|
` projections.apps4.project_id,` +
|
||||||
@ -91,17 +92,20 @@ var (
|
|||||||
` FROM projections.apps4` +
|
` FROM projections.apps4` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
|
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps4_api_configs.client_id,` +
|
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps4_api_configs.client_id,` +
|
||||||
` projections.apps4_oidc_configs.client_id` +
|
` projections.apps4_oidc_configs.client_id` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps4` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id`)
|
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.project_id` +
|
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.project_id` +
|
||||||
` FROM projections.apps4` +
|
` FROM projections.apps4` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
|
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
|
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
|
||||||
` projections.projects3.creation_date,` +
|
` projections.projects3.creation_date,` +
|
||||||
` projections.projects3.change_date,` +
|
` projections.projects3.change_date,` +
|
||||||
@ -117,7 +121,8 @@ var (
|
|||||||
` JOIN projections.apps4 ON projections.projects3.id = projections.apps4.project_id AND projections.projects3.instance_id = projections.apps4.instance_id` +
|
` JOIN projections.apps4 ON projections.projects3.id = projections.apps4.project_id AND projections.projects3.instance_id = projections.apps4.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
|
||||||
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
|
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
|
|
||||||
appCols = database.StringArray{
|
appCols = database.StringArray{
|
||||||
"id",
|
"id",
|
||||||
@ -1009,7 +1014,7 @@ func Test_AppsPrepare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1628,7 +1633,7 @@ func Test_AppPrepare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1714,7 +1719,7 @@ func Test_AppIDsPrepare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1780,7 +1785,7 @@ func Test_ProjectIDByAppPrepare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1978,7 +1983,7 @@ func Test_ProjectByAppPrepare(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -129,7 +130,7 @@ func (q *Queries) SearchAuthNKeys(ctx context.Context, queries *AuthNKeySearchQu
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareAuthNKeysQuery()
|
query, scan := prepareAuthNKeysQuery(ctx, q.client)
|
||||||
query = queries.toQuery(query)
|
query = queries.toQuery(query)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AuthNKeyColumnEnabled.identifier(): true,
|
AuthNKeyColumnEnabled.identifier(): true,
|
||||||
@ -159,7 +160,7 @@ func (q *Queries) SearchAuthNKeysData(ctx context.Context, queries *AuthNKeySear
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareAuthNKeysDataQuery()
|
query, scan := prepareAuthNKeysDataQuery(ctx, q.client)
|
||||||
query = queries.toQuery(query)
|
query = queries.toQuery(query)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
AuthNKeyColumnEnabled.identifier(): true,
|
AuthNKeyColumnEnabled.identifier(): true,
|
||||||
@ -193,7 +194,7 @@ func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, i
|
|||||||
projection.AuthNKeyProjection.Trigger(ctx)
|
projection.AuthNKeyProjection.Trigger(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
query, scan := prepareAuthNKeyQuery()
|
query, scan := prepareAuthNKeyQuery(ctx, q.client)
|
||||||
for _, q := range queries {
|
for _, q := range queries {
|
||||||
query = q.toQuery(query)
|
query = q.toQuery(query)
|
||||||
}
|
}
|
||||||
@ -218,7 +219,7 @@ func (q *Queries) GetAuthNKeyPublicKeyByIDAndIdentifier(ctx context.Context, id
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAuthNKeyPublicKeyQuery()
|
stmt, scan := prepareAuthNKeyPublicKeyQuery(ctx, q.client)
|
||||||
eq := sq.And{
|
eq := sq.And{
|
||||||
sq.Eq{
|
sq.Eq{
|
||||||
AuthNKeyColumnID.identifier(): id,
|
AuthNKeyColumnID.identifier(): id,
|
||||||
@ -265,7 +266,7 @@ func NewAuthNKeyObjectIDQuery(id string) (SearchQuery, error) {
|
|||||||
return NewTextQuery(AuthNKeyColumnObjectID, id, TextEquals)
|
return NewTextQuery(AuthNKeyColumnObjectID, id, TextEquals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys, error)) {
|
func prepareAuthNKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AuthNKeyColumnID.identifier(),
|
AuthNKeyColumnID.identifier(),
|
||||||
AuthNKeyColumnCreationDate.identifier(),
|
AuthNKeyColumnCreationDate.identifier(),
|
||||||
@ -275,7 +276,8 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
|
|||||||
AuthNKeyColumnExpiration.identifier(),
|
AuthNKeyColumnExpiration.identifier(),
|
||||||
AuthNKeyColumnType.identifier(),
|
AuthNKeyColumnType.identifier(),
|
||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*AuthNKeys, error) {
|
func(rows *sql.Rows) (*AuthNKeys, error) {
|
||||||
authNKeys := make([]*AuthNKey, 0)
|
authNKeys := make([]*AuthNKey, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
@ -310,7 +312,7 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, error)) {
|
func prepareAuthNKeyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AuthNKeyColumnID.identifier(),
|
AuthNKeyColumnID.identifier(),
|
||||||
AuthNKeyColumnCreationDate.identifier(),
|
AuthNKeyColumnCreationDate.identifier(),
|
||||||
@ -319,7 +321,8 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er
|
|||||||
AuthNKeyColumnSequence.identifier(),
|
AuthNKeyColumnSequence.identifier(),
|
||||||
AuthNKeyColumnExpiration.identifier(),
|
AuthNKeyColumnExpiration.identifier(),
|
||||||
AuthNKeyColumnType.identifier(),
|
AuthNKeyColumnType.identifier(),
|
||||||
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*AuthNKey, error) {
|
func(row *sql.Row) (*AuthNKey, error) {
|
||||||
authNKey := new(AuthNKey)
|
authNKey := new(AuthNKey)
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
@ -341,10 +344,11 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]byte, error)) {
|
func prepareAuthNKeyPublicKeyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) ([]byte, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AuthNKeyColumnPublicKey.identifier(),
|
AuthNKeyColumnPublicKey.identifier(),
|
||||||
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) ([]byte, error) {
|
func(row *sql.Row) ([]byte, error) {
|
||||||
var publicKey []byte
|
var publicKey []byte
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
@ -360,7 +364,7 @@ func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]by
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
|
func prepareAuthNKeysDataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
AuthNKeyColumnID.identifier(),
|
AuthNKeyColumnID.identifier(),
|
||||||
AuthNKeyColumnCreationDate.identifier(),
|
AuthNKeyColumnCreationDate.identifier(),
|
||||||
@ -372,7 +376,8 @@ func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthN
|
|||||||
AuthNKeyColumnIdentifier.identifier(),
|
AuthNKeyColumnIdentifier.identifier(),
|
||||||
AuthNKeyColumnPublicKey.identifier(),
|
AuthNKeyColumnPublicKey.identifier(),
|
||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*AuthNKeysData, error) {
|
func(rows *sql.Rows) (*AuthNKeysData, error) {
|
||||||
authNKeys := make([]*AuthNKeyData, 0)
|
authNKeys := make([]*AuthNKeyData, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -12,6 +12,80 @@ import (
|
|||||||
errs "github.com/zitadel/zitadel/internal/errors"
|
errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareAuthNKeysStmt = `SELECT projections.authn_keys2.id,` +
|
||||||
|
` projections.authn_keys2.creation_date,` +
|
||||||
|
` projections.authn_keys2.change_date,` +
|
||||||
|
` projections.authn_keys2.resource_owner,` +
|
||||||
|
` projections.authn_keys2.sequence,` +
|
||||||
|
` projections.authn_keys2.expiration,` +
|
||||||
|
` projections.authn_keys2.type,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.authn_keys2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareAuthNKeysCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"sequence",
|
||||||
|
"expiration",
|
||||||
|
"type",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareAuthNKeysDataStmt = `SELECT projections.authn_keys2.id,` +
|
||||||
|
` projections.authn_keys2.creation_date,` +
|
||||||
|
` projections.authn_keys2.change_date,` +
|
||||||
|
` projections.authn_keys2.resource_owner,` +
|
||||||
|
` projections.authn_keys2.sequence,` +
|
||||||
|
` projections.authn_keys2.expiration,` +
|
||||||
|
` projections.authn_keys2.type,` +
|
||||||
|
` projections.authn_keys2.identifier,` +
|
||||||
|
` projections.authn_keys2.public_key,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.authn_keys2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareAuthNKeysDataCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"sequence",
|
||||||
|
"expiration",
|
||||||
|
"type",
|
||||||
|
"identifier",
|
||||||
|
"public_key",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareAuthNKeyStmt = `SELECT projections.authn_keys2.id,` +
|
||||||
|
` projections.authn_keys2.creation_date,` +
|
||||||
|
` projections.authn_keys2.change_date,` +
|
||||||
|
` projections.authn_keys2.resource_owner,` +
|
||||||
|
` projections.authn_keys2.sequence,` +
|
||||||
|
` projections.authn_keys2.expiration,` +
|
||||||
|
` projections.authn_keys2.type` +
|
||||||
|
` FROM projections.authn_keys2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareAuthNKeyCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"sequence",
|
||||||
|
"expiration",
|
||||||
|
"type",
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareAuthNKeyPublicKeyStmt = `SELECT projections.authn_keys2.public_key` +
|
||||||
|
` FROM projections.authn_keys2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareAuthNKeyPublicKeyCols = []string{
|
||||||
|
"public_key",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_AuthNKeyPrepares(t *testing.T) {
|
func Test_AuthNKeyPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -28,15 +102,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysQuery,
|
prepare: prepareAuthNKeysQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -48,25 +114,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysQuery,
|
prepare: prepareAuthNKeysQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
prepareAuthNKeysCols,
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"expiration",
|
|
||||||
"type",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id",
|
"id",
|
||||||
@ -102,25 +151,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysQuery,
|
prepare: prepareAuthNKeysQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
prepareAuthNKeysCols,
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"expiration",
|
|
||||||
"type",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id-1",
|
"id-1",
|
||||||
@ -174,15 +206,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysQuery,
|
prepare: prepareAuthNKeysQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -199,17 +223,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysDataQuery,
|
prepare: prepareAuthNKeysDataQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` projections.authn_keys2.identifier,`+
|
|
||||||
` projections.authn_keys2.public_key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -221,29 +235,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysDataQuery,
|
prepare: prepareAuthNKeysDataQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
prepareAuthNKeysDataCols,
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` projections.authn_keys2.identifier,`+
|
|
||||||
` projections.authn_keys2.public_key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"expiration",
|
|
||||||
"type",
|
|
||||||
"identifier",
|
|
||||||
"public_key",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id",
|
"id",
|
||||||
@ -283,29 +276,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysDataQuery,
|
prepare: prepareAuthNKeysDataQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
prepareAuthNKeysDataCols,
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` projections.authn_keys2.identifier,`+
|
|
||||||
` projections.authn_keys2.public_key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"expiration",
|
|
||||||
"type",
|
|
||||||
"identifier",
|
|
||||||
"public_key",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"id-1",
|
"id-1",
|
||||||
@ -367,17 +339,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeysDataQuery,
|
prepare: prepareAuthNKeysDataQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type,`+
|
|
||||||
` projections.authn_keys2.identifier,`+
|
|
||||||
` projections.authn_keys2.public_key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -394,14 +356,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyQuery,
|
prepare: prepareAuthNKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeyStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -419,23 +374,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyQuery,
|
prepare: prepareAuthNKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQuery(
|
sqlExpectations: mockQuery(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeyStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
prepareAuthNKeyCols,
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"sequence",
|
|
||||||
"expiration",
|
|
||||||
"type",
|
|
||||||
},
|
|
||||||
[]driver.Value{
|
[]driver.Value{
|
||||||
"id",
|
"id",
|
||||||
testNow,
|
testNow,
|
||||||
@ -462,14 +402,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyQuery,
|
prepare: prepareAuthNKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
|
regexp.QuoteMeta(prepareAuthNKeyStmt),
|
||||||
` projections.authn_keys2.creation_date,`+
|
|
||||||
` projections.authn_keys2.change_date,`+
|
|
||||||
` projections.authn_keys2.resource_owner,`+
|
|
||||||
` projections.authn_keys2.sequence,`+
|
|
||||||
` projections.authn_keys2.expiration,`+
|
|
||||||
` projections.authn_keys2.type`+
|
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -486,8 +419,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
|
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -505,11 +437,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQuery(
|
sqlExpectations: mockQuery(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
|
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||||
` FROM projections.authn_keys2`),
|
prepareAuthNKeyPublicKeyCols,
|
||||||
[]string{
|
|
||||||
"public_key",
|
|
||||||
},
|
|
||||||
[]driver.Value{
|
[]driver.Value{
|
||||||
[]byte("publicKey"),
|
[]byte("publicKey"),
|
||||||
},
|
},
|
||||||
@ -522,8 +451,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
|
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||||
` FROM projections.authn_keys2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -538,7 +466,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
@ -69,7 +70,7 @@ func (q *Queries) ActiveCertificates(ctx context.Context, t time.Time, usage dom
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareCertificateQuery()
|
query, scan := prepareCertificateQuery(ctx, q.client)
|
||||||
if t.IsZero() {
|
if t.IsZero() {
|
||||||
t = time.Now()
|
t = time.Now()
|
||||||
}
|
}
|
||||||
@ -102,7 +103,7 @@ func (q *Queries) ActiveCertificates(ctx context.Context, t time.Time, usage dom
|
|||||||
return keys, nil
|
return keys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareCertificateQuery() (sq.SelectBuilder, func(*sql.Rows) (*Certificates, error)) {
|
func prepareCertificateQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Certificates, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
KeyColID.identifier(),
|
KeyColID.identifier(),
|
||||||
KeyColCreationDate.identifier(),
|
KeyColCreationDate.identifier(),
|
||||||
@ -117,7 +118,7 @@ func prepareCertificateQuery() (sq.SelectBuilder, func(*sql.Rows) (*Certificates
|
|||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(keyTable.identifier()).
|
).From(keyTable.identifier()).
|
||||||
LeftJoin(join(CertificateColID, KeyColID)).
|
LeftJoin(join(CertificateColID, KeyColID)).
|
||||||
LeftJoin(join(KeyPrivateColID, KeyColID)).
|
LeftJoin(join(KeyPrivateColID, KeyColID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*Certificates, error) {
|
func(rows *sql.Rows) (*Certificates, error) {
|
||||||
certificates := make([]Certificate, 0)
|
certificates := make([]Certificate, 0)
|
||||||
|
@ -13,6 +13,37 @@ import (
|
|||||||
errs "github.com/zitadel/zitadel/internal/errors"
|
errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareCertificateStmt = `SELECT projections.keys4.id,` +
|
||||||
|
` projections.keys4.creation_date,` +
|
||||||
|
` projections.keys4.change_date,` +
|
||||||
|
` projections.keys4.sequence,` +
|
||||||
|
` projections.keys4.resource_owner,` +
|
||||||
|
` projections.keys4.algorithm,` +
|
||||||
|
` projections.keys4.use,` +
|
||||||
|
` projections.keys4_certificate.expiry,` +
|
||||||
|
` projections.keys4_certificate.certificate,` +
|
||||||
|
` projections.keys4_private.key,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.keys4` +
|
||||||
|
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id` +
|
||||||
|
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareCertificateCols = []string{
|
||||||
|
"id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"sequence",
|
||||||
|
"resource_owner",
|
||||||
|
"algorithm",
|
||||||
|
"use",
|
||||||
|
"expiry",
|
||||||
|
"certificate",
|
||||||
|
"key",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_CertificatePrepares(t *testing.T) {
|
func Test_CertificatePrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -29,20 +60,7 @@ func Test_CertificatePrepares(t *testing.T) {
|
|||||||
prepare: prepareCertificateQuery,
|
prepare: prepareCertificateQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
|
regexp.QuoteMeta(prepareCertificateStmt),
|
||||||
` projections.keys4.creation_date,`+
|
|
||||||
` projections.keys4.change_date,`+
|
|
||||||
` projections.keys4.sequence,`+
|
|
||||||
` projections.keys4.resource_owner,`+
|
|
||||||
` projections.keys4.algorithm,`+
|
|
||||||
` projections.keys4.use,`+
|
|
||||||
` projections.keys4_certificate.expiry,`+
|
|
||||||
` projections.keys4_certificate.certificate,`+
|
|
||||||
` projections.keys4_private.key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.keys4`+
|
|
||||||
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
|
|
||||||
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -60,33 +78,8 @@ func Test_CertificatePrepares(t *testing.T) {
|
|||||||
prepare: prepareCertificateQuery,
|
prepare: prepareCertificateQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
|
regexp.QuoteMeta(prepareCertificateStmt),
|
||||||
` projections.keys4.creation_date,`+
|
prepareCertificateCols,
|
||||||
` projections.keys4.change_date,`+
|
|
||||||
` projections.keys4.sequence,`+
|
|
||||||
` projections.keys4.resource_owner,`+
|
|
||||||
` projections.keys4.algorithm,`+
|
|
||||||
` projections.keys4.use,`+
|
|
||||||
` projections.keys4_certificate.expiry,`+
|
|
||||||
` projections.keys4_certificate.certificate,`+
|
|
||||||
` projections.keys4_private.key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.keys4`+
|
|
||||||
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
|
|
||||||
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"resource_owner",
|
|
||||||
"algorithm",
|
|
||||||
"use",
|
|
||||||
"expiry",
|
|
||||||
"certificate",
|
|
||||||
"key",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"key-id",
|
"key-id",
|
||||||
@ -135,20 +128,7 @@ func Test_CertificatePrepares(t *testing.T) {
|
|||||||
prepare: prepareCertificateQuery,
|
prepare: prepareCertificateQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
|
regexp.QuoteMeta(prepareCertificateStmt),
|
||||||
` projections.keys4.creation_date,`+
|
|
||||||
` projections.keys4.change_date,`+
|
|
||||||
` projections.keys4.sequence,`+
|
|
||||||
` projections.keys4.resource_owner,`+
|
|
||||||
` projections.keys4.algorithm,`+
|
|
||||||
` projections.keys4.use,`+
|
|
||||||
` projections.keys4_certificate.expiry,`+
|
|
||||||
` projections.keys4_certificate.certificate,`+
|
|
||||||
` projections.keys4_private.key,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.keys4`+
|
|
||||||
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
|
|
||||||
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -163,7 +143,7 @@ func Test_CertificatePrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ func (q *Queries) UserChanges(ctx context.Context, userID string, lastSequence u
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) changes(ctx context.Context, query func(query *eventstore.SearchQuery), lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) {
|
func (q *Queries) changes(ctx context.Context, query func(query *eventstore.SearchQuery), lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) {
|
||||||
builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit)
|
builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit).AllowTimeTravel()
|
||||||
if !sortAscending {
|
if !sortAscending {
|
||||||
builder.OrderDesc()
|
builder.OrderDesc()
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
@ -59,7 +60,7 @@ func (q *Queries) SearchCurrentSequences(ctx context.Context, queries *CurrentSe
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareCurrentSequencesQuery()
|
query, scan := prepareCurrentSequencesQuery(ctx, q.client)
|
||||||
stmt, args, err := queries.toQuery(query).ToSql()
|
stmt, args, err := queries.toQuery(query).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-MmFef", "Errors.Query.InvalidRequest")
|
return nil, errors.ThrowInvalidArgument(err, "QUERY-MmFef", "Errors.Query.InvalidRequest")
|
||||||
@ -76,7 +77,7 @@ func (q *Queries) latestSequence(ctx context.Context, projections ...table) (_ *
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareLatestSequence()
|
query, scan := prepareLatestSequence(ctx, q.client)
|
||||||
or := make(sq.Or, len(projections))
|
or := make(sq.Or, len(projections))
|
||||||
for i, projection := range projections {
|
for i, projection := range projections {
|
||||||
or[i] = sq.Eq{CurrentSequenceColProjectionName.identifier(): projection.name}
|
or[i] = sq.Eq{CurrentSequenceColProjectionName.identifier(): projection.name}
|
||||||
@ -201,11 +202,12 @@ func reset(tx *sql.Tx, tables []string, projectionName string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareLatestSequence() (sq.SelectBuilder, func(*sql.Row) (*LatestSequence, error)) {
|
func prepareLatestSequence(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LatestSequence, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
CurrentSequenceColCurrentSequence.identifier(),
|
CurrentSequenceColCurrentSequence.identifier(),
|
||||||
CurrentSequenceColTimestamp.identifier()).
|
CurrentSequenceColTimestamp.identifier()).
|
||||||
From(currentSequencesTable.identifier()).PlaceholderFormat(sq.Dollar),
|
From(currentSequencesTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*LatestSequence, error) {
|
func(row *sql.Row) (*LatestSequence, error) {
|
||||||
seq := new(LatestSequence)
|
seq := new(LatestSequence)
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
@ -219,13 +221,13 @@ func prepareLatestSequence() (sq.SelectBuilder, func(*sql.Row) (*LatestSequence,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareCurrentSequencesQuery() (sq.SelectBuilder, func(*sql.Rows) (*CurrentSequences, error)) {
|
func prepareCurrentSequencesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*CurrentSequences, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
"max("+CurrentSequenceColCurrentSequence.identifier()+") as "+CurrentSequenceColCurrentSequence.name,
|
"max("+CurrentSequenceColCurrentSequence.identifier()+") as "+CurrentSequenceColCurrentSequence.name,
|
||||||
"max("+CurrentSequenceColTimestamp.identifier()+") as "+CurrentSequenceColTimestamp.name,
|
"max("+CurrentSequenceColTimestamp.identifier()+") as "+CurrentSequenceColTimestamp.name,
|
||||||
CurrentSequenceColProjectionName.identifier(),
|
CurrentSequenceColProjectionName.identifier(),
|
||||||
countColumn.identifier()).
|
countColumn.identifier()).
|
||||||
From(currentSequencesTable.identifier()).
|
From(currentSequencesTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
GroupBy(CurrentSequenceColProjectionName.identifier()).
|
GroupBy(CurrentSequenceColProjectionName.identifier()).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*CurrentSequences, error) {
|
func(rows *sql.Rows) (*CurrentSequences, error) {
|
||||||
|
@ -9,6 +9,23 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
currentSequenceStmt = `SELECT max(projections.current_sequences.current_sequence) as current_sequence,` +
|
||||||
|
` max(projections.current_sequences.timestamp) as timestamp,` +
|
||||||
|
` projections.current_sequences.projection_name,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.current_sequences` +
|
||||||
|
" AS OF SYSTEM TIME '-1 ms' " +
|
||||||
|
` GROUP BY projections.current_sequences.projection_name`
|
||||||
|
|
||||||
|
currentSequenceCols = []string{
|
||||||
|
"current_sequence",
|
||||||
|
"timestamp",
|
||||||
|
"projection_name",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_CurrentSequencesPrepares(t *testing.T) {
|
func Test_CurrentSequencesPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -25,12 +42,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
|
|||||||
prepare: prepareCurrentSequencesQuery,
|
prepare: prepareCurrentSequencesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
|
regexp.QuoteMeta(currentSequenceStmt),
|
||||||
` max(projections.current_sequences.timestamp) as timestamp,`+
|
|
||||||
` projections.current_sequences.projection_name,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.current_sequences`+
|
|
||||||
` GROUP BY projections.current_sequences.projection_name`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -42,18 +54,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
|
|||||||
prepare: prepareCurrentSequencesQuery,
|
prepare: prepareCurrentSequencesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
|
regexp.QuoteMeta(currentSequenceStmt),
|
||||||
` max(projections.current_sequences.timestamp) as timestamp,`+
|
currentSequenceCols,
|
||||||
` projections.current_sequences.projection_name,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.current_sequences`+
|
|
||||||
` GROUP BY projections.current_sequences.projection_name`),
|
|
||||||
[]string{
|
|
||||||
"current_sequence",
|
|
||||||
"timestamp",
|
|
||||||
"projection_name",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
uint64(20211108),
|
uint64(20211108),
|
||||||
@ -81,18 +83,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
|
|||||||
prepare: prepareCurrentSequencesQuery,
|
prepare: prepareCurrentSequencesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
|
regexp.QuoteMeta(currentSequenceStmt),
|
||||||
` max(projections.current_sequences.timestamp) as timestamp,`+
|
currentSequenceCols,
|
||||||
` projections.current_sequences.projection_name,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.current_sequences`+
|
|
||||||
` GROUP BY projections.current_sequences.projection_name`),
|
|
||||||
[]string{
|
|
||||||
"current_sequence",
|
|
||||||
"timestamp",
|
|
||||||
"projection_name",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
uint64(20211108),
|
uint64(20211108),
|
||||||
@ -130,12 +122,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
|
|||||||
prepare: prepareCurrentSequencesQuery,
|
prepare: prepareCurrentSequencesQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
|
regexp.QuoteMeta(currentSequenceStmt),
|
||||||
` max(projections.current_sequences.timestamp) as timestamp,`+
|
|
||||||
` projections.current_sequences.projection_name,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.current_sequences`+
|
|
||||||
` GROUP BY projections.current_sequences.projection_name`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -150,7 +137,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
@ -88,7 +89,7 @@ func (q *Queries) CustomTextList(ctx context.Context, aggregateID, template, lan
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareCustomTextsQuery()
|
stmt, scan := prepareCustomTextsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
CustomTextColAggregateID.identifier(): aggregateID,
|
CustomTextColAggregateID.identifier(): aggregateID,
|
||||||
CustomTextColTemplate.identifier(): template,
|
CustomTextColTemplate.identifier(): template,
|
||||||
@ -119,7 +120,7 @@ func (q *Queries) CustomTextListByTemplate(ctx context.Context, aggregateID, tem
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareCustomTextsQuery()
|
stmt, scan := prepareCustomTextsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
CustomTextColAggregateID.identifier(): aggregateID,
|
CustomTextColAggregateID.identifier(): aggregateID,
|
||||||
CustomTextColTemplate.identifier(): template,
|
CustomTextColTemplate.identifier(): template,
|
||||||
@ -228,7 +229,7 @@ func (q *Queries) readLoginTranslationFile(ctx context.Context, lang string) ([]
|
|||||||
return contents, nil
|
return contents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareCustomTextsQuery() (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts, error)) {
|
func prepareCustomTextsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
CustomTextColAggregateID.identifier(),
|
CustomTextColAggregateID.identifier(),
|
||||||
CustomTextColSequence.identifier(),
|
CustomTextColSequence.identifier(),
|
||||||
@ -239,7 +240,8 @@ func prepareCustomTextsQuery() (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts,
|
|||||||
CustomTextColKey.identifier(),
|
CustomTextColKey.identifier(),
|
||||||
CustomTextColText.identifier(),
|
CustomTextColText.identifier(),
|
||||||
countColumn.identifier()).
|
countColumn.identifier()).
|
||||||
From(customTextTable.identifier()).PlaceholderFormat(sq.Dollar),
|
From(customTextTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*CustomTexts, error) {
|
func(rows *sql.Rows) (*CustomTexts, error) {
|
||||||
customTexts := make([]*CustomText, 0)
|
customTexts := make([]*CustomText, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -13,6 +13,31 @@ import (
|
|||||||
errs "github.com/zitadel/zitadel/internal/errors"
|
errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareCustomTextsStmt = `SELECT projections.custom_texts2.aggregate_id,` +
|
||||||
|
` projections.custom_texts2.sequence,` +
|
||||||
|
` projections.custom_texts2.creation_date,` +
|
||||||
|
` projections.custom_texts2.change_date,` +
|
||||||
|
` projections.custom_texts2.language,` +
|
||||||
|
` projections.custom_texts2.template,` +
|
||||||
|
` projections.custom_texts2.key,` +
|
||||||
|
` projections.custom_texts2.text,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.custom_texts2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareCustomTextsCols = []string{
|
||||||
|
"aggregate_id",
|
||||||
|
"sequence",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"language",
|
||||||
|
"template",
|
||||||
|
"key",
|
||||||
|
"text",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_CustomTextPrepares(t *testing.T) {
|
func Test_CustomTextPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -29,16 +54,7 @@ func Test_CustomTextPrepares(t *testing.T) {
|
|||||||
prepare: prepareCustomTextsQuery,
|
prepare: prepareCustomTextsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
|
regexp.QuoteMeta(prepareCustomTextsStmt),
|
||||||
` projections.custom_texts2.sequence,`+
|
|
||||||
` projections.custom_texts2.creation_date,`+
|
|
||||||
` projections.custom_texts2.change_date,`+
|
|
||||||
` projections.custom_texts2.language,`+
|
|
||||||
` projections.custom_texts2.template,`+
|
|
||||||
` projections.custom_texts2.key,`+
|
|
||||||
` projections.custom_texts2.text,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.custom_texts2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -56,27 +72,8 @@ func Test_CustomTextPrepares(t *testing.T) {
|
|||||||
prepare: prepareCustomTextsQuery,
|
prepare: prepareCustomTextsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
|
regexp.QuoteMeta(prepareCustomTextsStmt),
|
||||||
` projections.custom_texts2.sequence,`+
|
prepareCustomTextsCols,
|
||||||
` projections.custom_texts2.creation_date,`+
|
|
||||||
` projections.custom_texts2.change_date,`+
|
|
||||||
` projections.custom_texts2.language,`+
|
|
||||||
` projections.custom_texts2.template,`+
|
|
||||||
` projections.custom_texts2.key,`+
|
|
||||||
` projections.custom_texts2.text,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.custom_texts2`),
|
|
||||||
[]string{
|
|
||||||
"aggregate_id",
|
|
||||||
"sequence",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"language",
|
|
||||||
"template",
|
|
||||||
"key",
|
|
||||||
"text",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
@ -114,27 +111,8 @@ func Test_CustomTextPrepares(t *testing.T) {
|
|||||||
prepare: prepareCustomTextsQuery,
|
prepare: prepareCustomTextsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
|
regexp.QuoteMeta(prepareCustomTextsStmt),
|
||||||
` projections.custom_texts2.sequence,`+
|
prepareCustomTextsCols,
|
||||||
` projections.custom_texts2.creation_date,`+
|
|
||||||
` projections.custom_texts2.change_date,`+
|
|
||||||
` projections.custom_texts2.language,`+
|
|
||||||
` projections.custom_texts2.template,`+
|
|
||||||
` projections.custom_texts2.key,`+
|
|
||||||
` projections.custom_texts2.text,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.custom_texts2`),
|
|
||||||
[]string{
|
|
||||||
"aggregate_id",
|
|
||||||
"sequence",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"language",
|
|
||||||
"template",
|
|
||||||
"key",
|
|
||||||
"text",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
@ -192,16 +170,7 @@ func Test_CustomTextPrepares(t *testing.T) {
|
|||||||
prepare: prepareCustomTextsQuery,
|
prepare: prepareCustomTextsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
|
regexp.QuoteMeta(prepareCustomTextsStmt),
|
||||||
` projections.custom_texts2.sequence,`+
|
|
||||||
` projections.custom_texts2.creation_date,`+
|
|
||||||
` projections.custom_texts2.change_date,`+
|
|
||||||
` projections.custom_texts2.language,`+
|
|
||||||
` projections.custom_texts2.template,`+
|
|
||||||
` projections.custom_texts2.key,`+
|
|
||||||
` projections.custom_texts2.text,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.custom_texts2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -216,7 +185,7 @@ func Test_CustomTextPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -112,7 +113,7 @@ func (q *Queries) DomainPolicyByOrg(ctx context.Context, shouldTriggerBulk bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, scan := prepareDomainPolicyQuery()
|
stmt, scan := prepareDomainPolicyQuery(ctx, q.client)
|
||||||
query, args, err := stmt.Where(eq).OrderBy(DomainPolicyColIsDefault.identifier()).
|
query, args, err := stmt.Where(eq).OrderBy(DomainPolicyColIsDefault.identifier()).
|
||||||
Limit(1).ToSql()
|
Limit(1).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -127,7 +128,7 @@ func (q *Queries) DefaultDomainPolicy(ctx context.Context) (_ *DomainPolicy, err
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareDomainPolicyQuery()
|
stmt, scan := prepareDomainPolicyQuery(ctx, q.client)
|
||||||
query, args, err := stmt.Where(sq.Eq{
|
query, args, err := stmt.Where(sq.Eq{
|
||||||
DomainPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
DomainPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
DomainPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
DomainPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -142,7 +143,7 @@ func (q *Queries) DefaultDomainPolicy(ctx context.Context) (_ *DomainPolicy, err
|
|||||||
return scan(row)
|
return scan(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy, error)) {
|
func prepareDomainPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
DomainPolicyColID.identifier(),
|
DomainPolicyColID.identifier(),
|
||||||
DomainPolicyColSequence.identifier(),
|
DomainPolicyColSequence.identifier(),
|
||||||
@ -155,7 +156,8 @@ func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy
|
|||||||
DomainPolicyColIsDefault.identifier(),
|
DomainPolicyColIsDefault.identifier(),
|
||||||
DomainPolicyColState.identifier(),
|
DomainPolicyColState.identifier(),
|
||||||
).
|
).
|
||||||
From(domainPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
|
From(domainPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*DomainPolicy, error) {
|
func(row *sql.Row) (*DomainPolicy, error) {
|
||||||
policy := new(DomainPolicy)
|
policy := new(DomainPolicy)
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
@ -12,6 +12,33 @@ import (
|
|||||||
errs "github.com/zitadel/zitadel/internal/errors"
|
errs "github.com/zitadel/zitadel/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareDomainPolicyStmt = `SELECT projections.domain_policies2.id,` +
|
||||||
|
` projections.domain_policies2.sequence,` +
|
||||||
|
` projections.domain_policies2.creation_date,` +
|
||||||
|
` projections.domain_policies2.change_date,` +
|
||||||
|
` projections.domain_policies2.resource_owner,` +
|
||||||
|
` projections.domain_policies2.user_login_must_be_domain,` +
|
||||||
|
` projections.domain_policies2.validate_org_domains,` +
|
||||||
|
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,` +
|
||||||
|
` projections.domain_policies2.is_default,` +
|
||||||
|
` projections.domain_policies2.state` +
|
||||||
|
` FROM projections.domain_policies2` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareDomainPolicyCols = []string{
|
||||||
|
"id",
|
||||||
|
"sequence",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"resource_owner",
|
||||||
|
"user_login_must_be_domain",
|
||||||
|
"validate_org_domains",
|
||||||
|
"smtp_sender_address_matches_instance_domain",
|
||||||
|
"is_default",
|
||||||
|
"state",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_DomainPolicyPrepares(t *testing.T) {
|
func Test_DomainPolicyPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -28,17 +55,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
|
|||||||
prepare: prepareDomainPolicyQuery,
|
prepare: prepareDomainPolicyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
|
regexp.QuoteMeta(prepareDomainPolicyStmt),
|
||||||
` projections.domain_policies2.sequence,`+
|
|
||||||
` projections.domain_policies2.creation_date,`+
|
|
||||||
` projections.domain_policies2.change_date,`+
|
|
||||||
` projections.domain_policies2.resource_owner,`+
|
|
||||||
` projections.domain_policies2.user_login_must_be_domain,`+
|
|
||||||
` projections.domain_policies2.validate_org_domains,`+
|
|
||||||
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
|
|
||||||
` projections.domain_policies2.is_default,`+
|
|
||||||
` projections.domain_policies2.state`+
|
|
||||||
` FROM projections.domain_policies2`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -56,29 +73,8 @@ func Test_DomainPolicyPrepares(t *testing.T) {
|
|||||||
prepare: prepareDomainPolicyQuery,
|
prepare: prepareDomainPolicyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQuery(
|
sqlExpectations: mockQuery(
|
||||||
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
|
regexp.QuoteMeta(prepareDomainPolicyStmt),
|
||||||
` projections.domain_policies2.sequence,`+
|
prepareDomainPolicyCols,
|
||||||
` projections.domain_policies2.creation_date,`+
|
|
||||||
` projections.domain_policies2.change_date,`+
|
|
||||||
` projections.domain_policies2.resource_owner,`+
|
|
||||||
` projections.domain_policies2.user_login_must_be_domain,`+
|
|
||||||
` projections.domain_policies2.validate_org_domains,`+
|
|
||||||
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
|
|
||||||
` projections.domain_policies2.is_default,`+
|
|
||||||
` projections.domain_policies2.state`+
|
|
||||||
` FROM projections.domain_policies2`),
|
|
||||||
[]string{
|
|
||||||
"id",
|
|
||||||
"sequence",
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"resource_owner",
|
|
||||||
"user_login_must_be_domain",
|
|
||||||
"validate_org_domains",
|
|
||||||
"smtp_sender_address_matches_instance_domain",
|
|
||||||
"is_default",
|
|
||||||
"state",
|
|
||||||
},
|
|
||||||
[]driver.Value{
|
[]driver.Value{
|
||||||
"pol-id",
|
"pol-id",
|
||||||
uint64(20211109),
|
uint64(20211109),
|
||||||
@ -111,17 +107,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
|
|||||||
prepare: prepareDomainPolicyQuery,
|
prepare: prepareDomainPolicyQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
|
regexp.QuoteMeta(prepareDomainPolicyStmt),
|
||||||
` projections.domain_policies2.sequence,`+
|
|
||||||
` projections.domain_policies2.creation_date,`+
|
|
||||||
` projections.domain_policies2.change_date,`+
|
|
||||||
` projections.domain_policies2.resource_owner,`+
|
|
||||||
` projections.domain_policies2.user_login_must_be_domain,`+
|
|
||||||
` projections.domain_policies2.validate_org_domains,`+
|
|
||||||
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
|
|
||||||
` projections.domain_policies2.is_default,`+
|
|
||||||
` projections.domain_policies2.state`+
|
|
||||||
` FROM projections.domain_policies2`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -136,7 +122,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ type EventEditor struct {
|
|||||||
func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder) (_ []*Event, err error) {
|
func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder) (_ []*Event, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
events, err := q.eventstore.Filter(ctx, query)
|
events, err := q.eventstore.Filter(ctx, query.AllowTimeTravel())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
)
|
)
|
||||||
@ -70,7 +71,7 @@ type FailedEventSearchQueries struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SearchFailedEvents(ctx context.Context, queries *FailedEventSearchQueries) (failedEvents *FailedEvents, err error) {
|
func (q *Queries) SearchFailedEvents(ctx context.Context, queries *FailedEventSearchQueries) (failedEvents *FailedEvents, err error) {
|
||||||
query, scan := prepareFailedEventsQuery()
|
query, scan := prepareFailedEventsQuery(ctx, q.client)
|
||||||
stmt, args, err := queries.toQuery(query).ToSql()
|
stmt, args, err := queries.toQuery(query).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-n8rjJ", "Errors.Query.InvalidRequest")
|
return nil, errors.ThrowInvalidArgument(err, "QUERY-n8rjJ", "Errors.Query.InvalidRequest")
|
||||||
@ -123,7 +124,7 @@ func (q *FailedEventSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareFailedEventsQuery() (sq.SelectBuilder, func(*sql.Rows) (*FailedEvents, error)) {
|
func prepareFailedEventsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*FailedEvents, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
FailedEventsColumnProjectionName.identifier(),
|
FailedEventsColumnProjectionName.identifier(),
|
||||||
FailedEventsColumnFailedSequence.identifier(),
|
FailedEventsColumnFailedSequence.identifier(),
|
||||||
@ -131,7 +132,8 @@ func prepareFailedEventsQuery() (sq.SelectBuilder, func(*sql.Rows) (*FailedEvent
|
|||||||
FailedEventsColumnLastFailed.identifier(),
|
FailedEventsColumnLastFailed.identifier(),
|
||||||
FailedEventsColumnError.identifier(),
|
FailedEventsColumnError.identifier(),
|
||||||
countColumn.identifier()).
|
countColumn.identifier()).
|
||||||
From(failedEventsTable.identifier()).PlaceholderFormat(sq.Dollar),
|
From(failedEventsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*FailedEvents, error) {
|
func(rows *sql.Rows) (*FailedEvents, error) {
|
||||||
failedEvents := make([]*FailedEvent, 0)
|
failedEvents := make([]*FailedEvent, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -9,6 +9,26 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareFailedEventsStmt = `SELECT projections.failed_events.projection_name,` +
|
||||||
|
` projections.failed_events.failed_sequence,` +
|
||||||
|
` projections.failed_events.failure_count,` +
|
||||||
|
` projections.failed_events.last_failed,` +
|
||||||
|
` projections.failed_events.error,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.failed_events` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
|
||||||
|
prepareFailedEventsCols = []string{
|
||||||
|
"projection_name",
|
||||||
|
"failed_sequence",
|
||||||
|
"failure_count",
|
||||||
|
"last_failed",
|
||||||
|
"error",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_FailedEventsPrepares(t *testing.T) {
|
func Test_FailedEventsPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -25,13 +45,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
|
|||||||
prepare: prepareFailedEventsQuery,
|
prepare: prepareFailedEventsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
|
regexp.QuoteMeta(prepareFailedEventsStmt),
|
||||||
` projections.failed_events.failed_sequence,`+
|
|
||||||
` projections.failed_events.failure_count,`+
|
|
||||||
` projections.failed_events.last_failed,`+
|
|
||||||
` projections.failed_events.error,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.failed_events`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -43,21 +57,8 @@ func Test_FailedEventsPrepares(t *testing.T) {
|
|||||||
prepare: prepareFailedEventsQuery,
|
prepare: prepareFailedEventsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
|
regexp.QuoteMeta(prepareFailedEventsStmt),
|
||||||
` projections.failed_events.failed_sequence,`+
|
prepareFailedEventsCols,
|
||||||
` projections.failed_events.failure_count,`+
|
|
||||||
` projections.failed_events.last_failed,`+
|
|
||||||
` projections.failed_events.error,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.failed_events`),
|
|
||||||
[]string{
|
|
||||||
"projection_name",
|
|
||||||
"failed_sequence",
|
|
||||||
"failure_count",
|
|
||||||
"last_failed",
|
|
||||||
"error",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"projection-name",
|
"projection-name",
|
||||||
@ -89,21 +90,8 @@ func Test_FailedEventsPrepares(t *testing.T) {
|
|||||||
prepare: prepareFailedEventsQuery,
|
prepare: prepareFailedEventsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
|
regexp.QuoteMeta(prepareFailedEventsStmt),
|
||||||
` projections.failed_events.failed_sequence,`+
|
prepareFailedEventsCols,
|
||||||
` projections.failed_events.failure_count,`+
|
|
||||||
` projections.failed_events.last_failed,`+
|
|
||||||
` projections.failed_events.error,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.failed_events`),
|
|
||||||
[]string{
|
|
||||||
"projection_name",
|
|
||||||
"failed_sequence",
|
|
||||||
"failure_count",
|
|
||||||
"last_failed",
|
|
||||||
"error",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
"projection-name",
|
"projection-name",
|
||||||
@ -148,13 +136,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
|
|||||||
prepare: prepareFailedEventsQuery,
|
prepare: prepareFailedEventsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
|
regexp.QuoteMeta(prepareFailedEventsStmt),
|
||||||
` projections.failed_events.failed_sequence,`+
|
|
||||||
` projections.failed_events.failure_count,`+
|
|
||||||
` projections.failed_events.last_failed,`+
|
|
||||||
` projections.failed_events.error,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.failed_events`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -169,7 +151,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
@ -78,7 +79,7 @@ func (q *Queries) IAMMembers(ctx context.Context, queries *IAMMembersQuery, with
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareInstanceMembersQuery()
|
query, scan := prepareInstanceMembersQuery(ctx, q.client)
|
||||||
eq := sq.Eq{InstanceMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{InstanceMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
addIamMemberWithoutOwnerRemoved(eq)
|
addIamMemberWithoutOwnerRemoved(eq)
|
||||||
@ -106,7 +107,7 @@ func (q *Queries) IAMMembers(ctx context.Context, queries *IAMMembersQuery, with
|
|||||||
return members, err
|
return members, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
|
func prepareInstanceMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
InstanceMemberCreationDate.identifier(),
|
InstanceMemberCreationDate.identifier(),
|
||||||
InstanceMemberChangeDate.identifier(),
|
InstanceMemberChangeDate.identifier(),
|
||||||
@ -125,7 +126,7 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members,
|
|||||||
).From(instanceMemberTable.identifier()).
|
).From(instanceMemberTable.identifier()).
|
||||||
LeftJoin(join(HumanUserIDCol, InstanceMemberUserID)).
|
LeftJoin(join(HumanUserIDCol, InstanceMemberUserID)).
|
||||||
LeftJoin(join(MachineUserIDCol, InstanceMemberUserID)).
|
LeftJoin(join(MachineUserIDCol, InstanceMemberUserID)).
|
||||||
LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID)).
|
LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID) + db.Timetravel(call.Took(ctx))).
|
||||||
Where(
|
Where(
|
||||||
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
|
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
|
||||||
).PlaceholderFormat(sq.Dollar),
|
).PlaceholderFormat(sq.Dollar),
|
||||||
|
@ -34,6 +34,7 @@ var (
|
|||||||
"ON members.user_id = projections.users8_machines.user_id AND members.instance_id = projections.users8_machines.instance_id " +
|
"ON members.user_id = projections.users8_machines.user_id AND members.instance_id = projections.users8_machines.instance_id " +
|
||||||
"LEFT JOIN projections.login_names2 " +
|
"LEFT JOIN projections.login_names2 " +
|
||||||
"ON members.user_id = projections.login_names2.user_id AND members.instance_id = projections.login_names2.instance_id " +
|
"ON members.user_id = projections.login_names2.user_id AND members.instance_id = projections.login_names2.instance_id " +
|
||||||
|
"AS OF SYSTEM TIME '-1 ms' " +
|
||||||
"WHERE projections.login_names2.is_primary = $1")
|
"WHERE projections.login_names2.is_primary = $1")
|
||||||
instanceMembersColumns = []string{
|
instanceMembersColumns = []string{
|
||||||
"creation_date",
|
"creation_date",
|
||||||
@ -271,7 +272,7 @@ func Test_IAMMemberPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/database"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
@ -209,7 +210,7 @@ func (q *Queries) IDPByIDAndResourceOwner(ctx context.Context, shouldTriggerBulk
|
|||||||
sq.Eq{IDPResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
|
sq.Eq{IDPResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
stmt, scan := prepareIDPByIDQuery()
|
stmt, scan := prepareIDPByIDQuery(ctx, q.client)
|
||||||
query, args, err := stmt.Where(where).ToSql()
|
query, args, err := stmt.Where(where).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInternal(err, "QUERY-0gocI", "Errors.Query.SQLStatement")
|
return nil, errors.ThrowInternal(err, "QUERY-0gocI", "Errors.Query.SQLStatement")
|
||||||
@ -224,7 +225,7 @@ func (q *Queries) IDPs(ctx context.Context, queries *IDPSearchQueries, withOwner
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareIDPsQuery()
|
query, scan := prepareIDPsQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
IDPInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
IDPInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
}
|
}
|
||||||
@ -285,7 +286,7 @@ func (q *IDPSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
|
func prepareIDPByIDQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPIDCol.identifier(),
|
IDPIDCol.identifier(),
|
||||||
IDPResourceOwnerCol.identifier(),
|
IDPResourceOwnerCol.identifier(),
|
||||||
@ -313,7 +314,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
|
|||||||
JWTIDPColEndpoint.identifier(),
|
JWTIDPColEndpoint.identifier(),
|
||||||
).From(idpTable.identifier()).
|
).From(idpTable.identifier()).
|
||||||
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
|
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
|
||||||
LeftJoin(join(JWTIDPColIDPID, IDPIDCol)).
|
LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*IDP, error) {
|
func(row *sql.Row) (*IDP, error) {
|
||||||
idp := new(IDP)
|
idp := new(IDP)
|
||||||
@ -393,7 +394,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
|
func prepareIDPsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPIDCol.identifier(),
|
IDPIDCol.identifier(),
|
||||||
IDPResourceOwnerCol.identifier(),
|
IDPResourceOwnerCol.identifier(),
|
||||||
@ -422,7 +423,7 @@ func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
|
|||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(idpTable.identifier()).
|
).From(idpTable.identifier()).
|
||||||
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
|
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
|
||||||
LeftJoin(join(JWTIDPColIDPID, IDPIDCol)).
|
LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*IDPs, error) {
|
func(rows *sql.Rows) (*IDPs, error) {
|
||||||
idps := make([]*IDP, 0)
|
idps := make([]*IDP, 0)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -84,7 +85,7 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareIDPLoginPolicyLinksQuery()
|
query, scan := prepareIDPLoginPolicyLinksQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
IDPLoginPolicyLinkResourceOwnerCol.identifier(): resourceOwner,
|
IDPLoginPolicyLinkResourceOwnerCol.identifier(): resourceOwner,
|
||||||
IDPLoginPolicyLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
IDPLoginPolicyLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -109,14 +110,15 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
|
|||||||
return idps, err
|
return idps, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPLoginPolicyLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
|
func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPLoginPolicyLinkIDPIDCol.identifier(),
|
IDPLoginPolicyLinkIDPIDCol.identifier(),
|
||||||
IDPNameCol.identifier(),
|
IDPNameCol.identifier(),
|
||||||
IDPTypeCol.identifier(),
|
IDPTypeCol.identifier(),
|
||||||
countColumn.identifier()).
|
countColumn.identifier()).
|
||||||
From(idpLoginPolicyLinkTable.identifier()).
|
From(idpLoginPolicyLinkTable.identifier()).
|
||||||
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol)).PlaceholderFormat(sq.Dollar),
|
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*IDPLoginPolicyLinks, error) {
|
func(rows *sql.Rows) (*IDPLoginPolicyLinks, error) {
|
||||||
links := make([]*IDPLoginPolicyLink, 0)
|
links := make([]*IDPLoginPolicyLink, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -17,7 +17,8 @@ var (
|
|||||||
` projections.idps3.type,` +
|
` projections.idps3.type,` +
|
||||||
` COUNT(*) OVER ()` +
|
` COUNT(*) OVER ()` +
|
||||||
` FROM projections.idp_login_policy_links4` +
|
` FROM projections.idp_login_policy_links4` +
|
||||||
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id`)
|
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id AND projections.idp_login_policy_links4.instance_id = projections.idps3.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
loginPolicyIDPLinksCols = []string{
|
loginPolicyIDPLinksCols = []string{
|
||||||
"idp_id",
|
"idp_id",
|
||||||
"name",
|
"name",
|
||||||
@ -115,7 +116,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/database"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
@ -409,7 +410,7 @@ func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTri
|
|||||||
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
|
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
stmt, scan := prepareIDPTemplateByIDQuery()
|
stmt, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
|
||||||
query, args, err := stmt.Where(where).ToSql()
|
query, args, err := stmt.Where(where).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInternal(err, "QUERY-SFAew", "Errors.Query.SQLStatement")
|
return nil, errors.ThrowInternal(err, "QUERY-SFAew", "Errors.Query.SQLStatement")
|
||||||
@ -424,7 +425,7 @@ func (q *Queries) IDPTemplates(ctx context.Context, queries *IDPTemplateSearchQu
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareIDPTemplatesQuery()
|
query, scan := prepareIDPTemplatesQuery(ctx, q.client)
|
||||||
eq := sq.Eq{
|
eq := sq.Eq{
|
||||||
IDPTemplateInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
IDPTemplateInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
}
|
}
|
||||||
@ -485,7 +486,7 @@ func (q *IDPTemplateSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTemplate, error)) {
|
func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*IDPTemplate, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPTemplateIDCol.identifier(),
|
IDPTemplateIDCol.identifier(),
|
||||||
IDPTemplateResourceOwnerCol.identifier(),
|
IDPTemplateResourceOwnerCol.identifier(),
|
||||||
@ -553,7 +554,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
|||||||
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*IDPTemplate, error) {
|
func(row *sql.Row) (*IDPTemplate, error) {
|
||||||
idpTemplate := new(IDPTemplate)
|
idpTemplate := new(IDPTemplate)
|
||||||
@ -750,7 +751,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplates, error)) {
|
func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplates, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPTemplateIDCol.identifier(),
|
IDPTemplateIDCol.identifier(),
|
||||||
IDPTemplateResourceOwnerCol.identifier(),
|
IDPTemplateResourceOwnerCol.identifier(),
|
||||||
@ -819,7 +820,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
|
|||||||
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*IDPTemplates, error) {
|
func(rows *sql.Rows) (*IDPTemplates, error) {
|
||||||
templates := make([]*IDPTemplate, 0)
|
templates := make([]*IDPTemplate, 0)
|
||||||
|
@ -81,7 +81,8 @@ var (
|
|||||||
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
|
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
|
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
|
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id`
|
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
idpTemplateCols = []string{
|
idpTemplateCols = []string{
|
||||||
"id",
|
"id",
|
||||||
"resource_owner",
|
"resource_owner",
|
||||||
@ -212,7 +213,8 @@ var (
|
|||||||
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
|
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
|
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
|
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id`
|
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
idpTemplatesCols = []string{
|
idpTemplatesCols = []string{
|
||||||
"id",
|
"id",
|
||||||
"resource_owner",
|
"resource_owner",
|
||||||
@ -1628,7 +1630,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,7 +733,7 @@ func Test_IDPPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -92,7 +93,7 @@ func (q *Queries) IDPUserLinks(ctx context.Context, queries *IDPUserLinksSearchQ
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareIDPUserLinksQuery()
|
query, scan := prepareIDPUserLinksQuery(ctx, q.client)
|
||||||
eq := sq.Eq{IDPUserLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()}
|
eq := sq.Eq{IDPUserLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||||
if !withOwnerRemoved {
|
if !withOwnerRemoved {
|
||||||
eq[IDPUserLinkOwnerRemovedCol.identifier()] = false
|
eq[IDPUserLinkOwnerRemovedCol.identifier()] = false
|
||||||
@ -126,7 +127,7 @@ func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error)
|
|||||||
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
|
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
|
func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
IDPUserLinkIDPIDCol.identifier(),
|
IDPUserLinkIDPIDCol.identifier(),
|
||||||
IDPUserLinkUserIDCol.identifier(),
|
IDPUserLinkUserIDCol.identifier(),
|
||||||
@ -137,7 +138,8 @@ func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLink
|
|||||||
IDPUserLinkResourceOwnerCol.identifier(),
|
IDPUserLinkResourceOwnerCol.identifier(),
|
||||||
countColumn.identifier()).
|
countColumn.identifier()).
|
||||||
From(idpUserLinkTable.identifier()).
|
From(idpUserLinkTable.identifier()).
|
||||||
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol)).PlaceholderFormat(sq.Dollar),
|
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*IDPUserLinks, error) {
|
func(rows *sql.Rows) (*IDPUserLinks, error) {
|
||||||
idps := make([]*IDPUserLink, 0)
|
idps := make([]*IDPUserLink, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -21,7 +21,8 @@ var (
|
|||||||
` projections.idp_user_links3.resource_owner,` +
|
` projections.idp_user_links3.resource_owner,` +
|
||||||
` COUNT(*) OVER ()` +
|
` COUNT(*) OVER ()` +
|
||||||
` FROM projections.idp_user_links3` +
|
` FROM projections.idp_user_links3` +
|
||||||
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id`)
|
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id AND projections.idp_user_links3.instance_id = projections.idps3.instance_id` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
idpUserLinksCols = []string{
|
idpUserLinksCols = []string{
|
||||||
"idp_id",
|
"idp_id",
|
||||||
"user_id",
|
"user_id",
|
||||||
@ -139,7 +140,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/database"
|
"github.com/zitadel/zitadel/internal/database"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
@ -159,7 +160,7 @@ func (q *Queries) SearchInstances(ctx context.Context, queries *InstanceSearchQu
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
filter, query, scan := prepareInstancesQuery()
|
filter, query, scan := prepareInstancesQuery(ctx, q.client)
|
||||||
stmt, args, err := query(queries.toQuery(filter)).ToSql()
|
stmt, args, err := query(queries.toQuery(filter)).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-M9fow", "Errors.Query.SQLStatement")
|
return nil, errors.ThrowInvalidArgument(err, "QUERY-M9fow", "Errors.Query.SQLStatement")
|
||||||
@ -184,7 +185,7 @@ func (q *Queries) Instance(ctx context.Context, shouldTriggerBulk bool) (_ *Inst
|
|||||||
projection.InstanceProjection.Trigger(ctx)
|
projection.InstanceProjection.Trigger(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, scan := prepareInstanceDomainQuery(authz.GetInstance(ctx).RequestedDomain())
|
stmt, scan := prepareInstanceDomainQuery(ctx, q.client, authz.GetInstance(ctx).RequestedDomain())
|
||||||
query, args, err := stmt.Where(sq.Eq{
|
query, args, err := stmt.Where(sq.Eq{
|
||||||
InstanceColumnID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
InstanceColumnID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
}).ToSql()
|
}).ToSql()
|
||||||
@ -203,7 +204,7 @@ func (q *Queries) InstanceByHost(ctx context.Context, host string) (_ authz.Inst
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
stmt, scan := prepareAuthzInstanceQuery(host)
|
stmt, scan := prepareAuthzInstanceQuery(ctx, q.client, host)
|
||||||
host = strings.Split(host, ":")[0] //remove possible port
|
host = strings.Split(host, ":")[0] //remove possible port
|
||||||
query, args, err := stmt.Where(sq.Eq{
|
query, args, err := stmt.Where(sq.Eq{
|
||||||
InstanceDomainDomainCol.identifier(): host,
|
InstanceDomainDomainCol.identifier(): host,
|
||||||
@ -231,7 +232,7 @@ func (q *Queries) GetDefaultLanguage(ctx context.Context) language.Tag {
|
|||||||
return instance.DefaultLanguage()
|
return instance.DefaultLanguage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
|
func prepareInstanceQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
InstanceColumnID.identifier(),
|
InstanceColumnID.identifier(),
|
||||||
InstanceColumnCreationDate.identifier(),
|
InstanceColumnCreationDate.identifier(),
|
||||||
@ -243,7 +244,8 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta
|
|||||||
InstanceColumnConsoleAppID.identifier(),
|
InstanceColumnConsoleAppID.identifier(),
|
||||||
InstanceColumnDefaultLanguage.identifier(),
|
InstanceColumnDefaultLanguage.identifier(),
|
||||||
).
|
).
|
||||||
From(instanceTable.identifier()).PlaceholderFormat(sq.Dollar),
|
From(instanceTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(row *sql.Row) (*Instance, error) {
|
func(row *sql.Row) (*Instance, error) {
|
||||||
instance := &Instance{host: host}
|
instance := &Instance{host: host}
|
||||||
lang := ""
|
lang := ""
|
||||||
@ -269,7 +271,7 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
|
func prepareInstancesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(sq.SelectBuilder) sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
|
||||||
instanceFilterTable := instanceTable.setAlias(InstancesFilterTableAlias)
|
instanceFilterTable := instanceTable.setAlias(InstancesFilterTableAlias)
|
||||||
instanceFilterIDColumn := InstanceColumnID.setTable(instanceFilterTable)
|
instanceFilterIDColumn := InstanceColumnID.setTable(instanceFilterTable)
|
||||||
instanceFilterCountColumn := InstancesFilterTableAlias + ".count"
|
instanceFilterCountColumn := InstancesFilterTableAlias + ".count"
|
||||||
@ -298,7 +300,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.Select
|
|||||||
InstanceDomainSequenceCol.identifier(),
|
InstanceDomainSequenceCol.identifier(),
|
||||||
).FromSelect(builder, InstancesFilterTableAlias).
|
).FromSelect(builder, InstancesFilterTableAlias).
|
||||||
LeftJoin(join(InstanceColumnID, instanceFilterIDColumn)).
|
LeftJoin(join(InstanceColumnID, instanceFilterIDColumn)).
|
||||||
LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn)).
|
LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar)
|
PlaceholderFormat(sq.Dollar)
|
||||||
},
|
},
|
||||||
func(rows *sql.Rows) (*Instances, error) {
|
func(rows *sql.Rows) (*Instances, error) {
|
||||||
@ -373,7 +375,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.Select
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
|
func prepareInstanceDomainQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
InstanceColumnID.identifier(),
|
InstanceColumnID.identifier(),
|
||||||
InstanceColumnCreationDate.identifier(),
|
InstanceColumnCreationDate.identifier(),
|
||||||
@ -393,7 +395,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows)
|
|||||||
InstanceDomainSequenceCol.identifier(),
|
InstanceDomainSequenceCol.identifier(),
|
||||||
).
|
).
|
||||||
From(instanceTable.identifier()).
|
From(instanceTable.identifier()).
|
||||||
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)).
|
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*Instance, error) {
|
func(rows *sql.Rows) (*Instance, error) {
|
||||||
instance := &Instance{
|
instance := &Instance{
|
||||||
@ -455,7 +457,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAuthzInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
|
func prepareAuthzInstanceQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
InstanceColumnID.identifier(),
|
InstanceColumnID.identifier(),
|
||||||
InstanceColumnCreationDate.identifier(),
|
InstanceColumnCreationDate.identifier(),
|
||||||
@ -478,7 +480,7 @@ func prepareAuthzInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (
|
|||||||
).
|
).
|
||||||
From(instanceTable.identifier()).
|
From(instanceTable.identifier()).
|
||||||
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)).
|
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)).
|
||||||
LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID)).
|
LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID) + db.Timetravel(call.Took(ctx))).
|
||||||
PlaceholderFormat(sq.Dollar),
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*Instance, error) {
|
func(rows *sql.Rows) (*Instance, error) {
|
||||||
instance := &Instance{
|
instance := &Instance{
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/api/authz"
|
"github.com/zitadel/zitadel/internal/api/authz"
|
||||||
|
"github.com/zitadel/zitadel/internal/api/call"
|
||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/query/projection"
|
"github.com/zitadel/zitadel/internal/query/projection"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
@ -61,7 +62,7 @@ func (q *Queries) SearchInstanceDomains(ctx context.Context, queries *InstanceDo
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareInstanceDomainsQuery()
|
query, scan := prepareInstanceDomainsQuery(ctx, q.client)
|
||||||
stmt, args, err := queries.toQuery(query).
|
stmt, args, err := queries.toQuery(query).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
InstanceDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
InstanceDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||||
@ -77,7 +78,7 @@ func (q *Queries) SearchInstanceDomainsGlobal(ctx context.Context, queries *Inst
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
query, scan := prepareInstanceDomainsQuery()
|
query, scan := prepareInstanceDomainsQuery(ctx, q.client)
|
||||||
stmt, args, err := queries.toQuery(query).ToSql()
|
stmt, args, err := queries.toQuery(query).ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInvalidArgument(err, "QUERY-IHhLR", "Errors.Query.SQLStatement")
|
return nil, errors.ThrowInvalidArgument(err, "QUERY-IHhLR", "Errors.Query.SQLStatement")
|
||||||
@ -99,7 +100,7 @@ func (q *Queries) queryInstanceDomains(ctx context.Context, stmt string, scan fu
|
|||||||
return domains, err
|
return domains, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareInstanceDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*InstanceDomains, error)) {
|
func prepareInstanceDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*InstanceDomains, error)) {
|
||||||
return sq.Select(
|
return sq.Select(
|
||||||
InstanceDomainCreationDateCol.identifier(),
|
InstanceDomainCreationDateCol.identifier(),
|
||||||
InstanceDomainChangeDateCol.identifier(),
|
InstanceDomainChangeDateCol.identifier(),
|
||||||
@ -109,7 +110,8 @@ func prepareInstanceDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instance
|
|||||||
InstanceDomainIsGeneratedCol.identifier(),
|
InstanceDomainIsGeneratedCol.identifier(),
|
||||||
InstanceDomainIsPrimaryCol.identifier(),
|
InstanceDomainIsPrimaryCol.identifier(),
|
||||||
countColumn.identifier(),
|
countColumn.identifier(),
|
||||||
).From(instanceDomainsTable.identifier()).PlaceholderFormat(sq.Dollar),
|
).From(instanceDomainsTable.identifier() + db.Timetravel(call.Took(ctx))).
|
||||||
|
PlaceholderFormat(sq.Dollar),
|
||||||
func(rows *sql.Rows) (*InstanceDomains, error) {
|
func(rows *sql.Rows) (*InstanceDomains, error) {
|
||||||
domains := make([]*InstanceDomain, 0)
|
domains := make([]*InstanceDomain, 0)
|
||||||
var count uint64
|
var count uint64
|
||||||
|
@ -9,6 +9,29 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
prepareInstanceDomainsStmt = `SELECT projections.instance_domains.creation_date,` +
|
||||||
|
` projections.instance_domains.change_date,` +
|
||||||
|
` projections.instance_domains.sequence,` +
|
||||||
|
` projections.instance_domains.domain,` +
|
||||||
|
` projections.instance_domains.instance_id,` +
|
||||||
|
` projections.instance_domains.is_generated,` +
|
||||||
|
` projections.instance_domains.is_primary,` +
|
||||||
|
` COUNT(*) OVER ()` +
|
||||||
|
` FROM projections.instance_domains` +
|
||||||
|
` AS OF SYSTEM TIME '-1 ms'`
|
||||||
|
prepareInstanceDomainsCols = []string{
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"sequence",
|
||||||
|
"domain",
|
||||||
|
"instance_id",
|
||||||
|
"is_generated",
|
||||||
|
"is_primary",
|
||||||
|
"count",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_InstanceDomainPrepares(t *testing.T) {
|
func Test_InstanceDomainPrepares(t *testing.T) {
|
||||||
type want struct {
|
type want struct {
|
||||||
sqlExpectations sqlExpectation
|
sqlExpectations sqlExpectation
|
||||||
@ -25,15 +48,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
|
|||||||
prepare: prepareInstanceDomainsQuery,
|
prepare: prepareInstanceDomainsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
|
regexp.QuoteMeta(prepareInstanceDomainsStmt),
|
||||||
` projections.instance_domains.change_date,`+
|
|
||||||
` projections.instance_domains.sequence,`+
|
|
||||||
` projections.instance_domains.domain,`+
|
|
||||||
` projections.instance_domains.instance_id,`+
|
|
||||||
` projections.instance_domains.is_generated,`+
|
|
||||||
` projections.instance_domains.is_primary,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.instance_domains`),
|
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
@ -45,25 +60,8 @@ func Test_InstanceDomainPrepares(t *testing.T) {
|
|||||||
prepare: prepareInstanceDomainsQuery,
|
prepare: prepareInstanceDomainsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
|
regexp.QuoteMeta(prepareInstanceDomainsStmt),
|
||||||
` projections.instance_domains.change_date,`+
|
prepareInstanceDomainsCols,
|
||||||
` projections.instance_domains.sequence,`+
|
|
||||||
` projections.instance_domains.domain,`+
|
|
||||||
` projections.instance_domains.instance_id,`+
|
|
||||||
` projections.instance_domains.is_generated,`+
|
|
||||||
` projections.instance_domains.is_primary,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.instance_domains`),
|
|
||||||
[]string{
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"domain",
|
|
||||||
"instance_id",
|
|
||||||
"is_generated",
|
|
||||||
"is_primary",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
testNow,
|
testNow,
|
||||||
@ -99,25 +97,8 @@ func Test_InstanceDomainPrepares(t *testing.T) {
|
|||||||
prepare: prepareInstanceDomainsQuery,
|
prepare: prepareInstanceDomainsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueries(
|
sqlExpectations: mockQueries(
|
||||||
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
|
regexp.QuoteMeta(prepareInstanceDomainsStmt),
|
||||||
` projections.instance_domains.change_date,`+
|
prepareInstanceDomainsCols,
|
||||||
` projections.instance_domains.sequence,`+
|
|
||||||
` projections.instance_domains.domain,`+
|
|
||||||
` projections.instance_domains.instance_id,`+
|
|
||||||
` projections.instance_domains.is_generated,`+
|
|
||||||
` projections.instance_domains.is_primary,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.instance_domains`),
|
|
||||||
[]string{
|
|
||||||
"creation_date",
|
|
||||||
"change_date",
|
|
||||||
"sequence",
|
|
||||||
"domain",
|
|
||||||
"instance_id",
|
|
||||||
"is_generated",
|
|
||||||
"is_primary",
|
|
||||||
"count",
|
|
||||||
},
|
|
||||||
[][]driver.Value{
|
[][]driver.Value{
|
||||||
{
|
{
|
||||||
testNow,
|
testNow,
|
||||||
@ -171,15 +152,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
|
|||||||
prepare: prepareInstanceDomainsQuery,
|
prepare: prepareInstanceDomainsQuery,
|
||||||
want: want{
|
want: want{
|
||||||
sqlExpectations: mockQueryErr(
|
sqlExpectations: mockQueryErr(
|
||||||
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
|
regexp.QuoteMeta(prepareInstanceDomainsStmt),
|
||||||
` projections.instance_domains.change_date,`+
|
|
||||||
` projections.instance_domains.sequence,`+
|
|
||||||
` projections.instance_domains.domain,`+
|
|
||||||
` projections.instance_domains.instance_id,`+
|
|
||||||
` projections.instance_domains.is_generated,`+
|
|
||||||
` projections.instance_domains.is_primary,`+
|
|
||||||
` COUNT(*) OVER ()`+
|
|
||||||
` FROM projections.instance_domains`),
|
|
||||||
sql.ErrConnDone,
|
sql.ErrConnDone,
|
||||||
),
|
),
|
||||||
err: func(err error) (error, bool) {
|
err: func(err error) (error, bool) {
|
||||||
@ -194,7 +167,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user