diff --git a/build/zitadel/generate-grpc.sh b/build/zitadel/generate-grpc.sh index d115db55aa..93053eedb5 100755 --- a/build/zitadel/generate-grpc.sh +++ b/build/zitadel/generate-grpc.sh @@ -93,102 +93,4 @@ protoc \ mv ${ZITADEL_PATH}/pkg/grpc/auth/zitadel/* ${ZITADEL_PATH}/pkg/grpc/auth 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" diff --git a/cmd/initialise/init.go b/cmd/initialise/init.go index 4afd85b473..78baf6c204 100644 --- a/cmd/initialise/init.go +++ b/cmd/initialise/init.go @@ -59,8 +59,8 @@ The user provided by flags needs privileges to func InitAll(config *Config) { err := initialise(config.Database, VerifyUser(config.Database.Username(), config.Database.Password()), - VerifyDatabase(config.Database.Database()), - VerifyGrant(config.Database.Database(), config.Database.Username()), + VerifyDatabase(config.Database.DatabaseName()), + VerifyGrant(config.Database.DatabaseName(), config.Database.Username()), ) 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() - return Init(db, steps...) + return Init(db.DB, steps...) } func Init(db *sql.DB, steps ...func(*sql.DB) error) error { diff --git a/cmd/initialise/verify_database.go b/cmd/initialise/verify_database.go index e9f46687f9..5bdb8a1421 100644 --- a/cmd/initialise/verify_database.go +++ b/cmd/initialise/verify_database.go @@ -27,7 +27,7 @@ The user provided by flags needs priviledge to Run: func(cmd *cobra.Command, args []string) { 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") }, } diff --git a/cmd/initialise/verify_grant.go b/cmd/initialise/verify_grant.go index bbe2b639ee..5b89e9b727 100644 --- a/cmd/initialise/verify_grant.go +++ b/cmd/initialise/verify_grant.go @@ -22,7 +22,7 @@ Prereqesits: Run: func(cmd *cobra.Command, args []string) { 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") }, } diff --git a/cmd/initialise/verify_zitadel.go b/cmd/initialise/verify_zitadel.go index cc8db65435..74fe2a2467 100644 --- a/cmd/initialise/verify_zitadel.go +++ b/cmd/initialise/verify_zitadel.go @@ -66,14 +66,14 @@ func VerifyZitadel(db *sql.DB, 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) if err != nil { return err } - if err := VerifyZitadel(db, config); err != nil { + if err := VerifyZitadel(db.DB, config); err != nil { return err } diff --git a/cmd/key/key.go b/cmd/key/key.go index 02fa272a8a..1ccde775ed 100644 --- a/cmd/key/key.go +++ b/cmd/key/key.go @@ -128,5 +128,5 @@ func keyStorage(config database.Config, masterKey string) (crypto.KeyStorage, er if err != nil { return nil, err } - return cryptoDB.NewKeyStorage(db, masterKey) + return cryptoDB.NewKeyStorage(db.DB, masterKey) } diff --git a/cmd/setup/setup.go b/cmd/setup/setup.go index 8bae6b3df3..ab8e3f769c 100644 --- a/cmd/setup/setup.go +++ b/cmd/setup/setup.go @@ -66,14 +66,14 @@ func Setup(config *Config, steps *Steps, masterKey string) { logging.OnError(err).Fatal("unable to start eventstore") migration.RegisterMappers(eventstoreClient) - steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient} - steps.s2AssetsTable = &AssetTable{dbClient: dbClient} + steps.s1ProjectionTable = &ProjectionTable{dbClient: dbClient.DB} + steps.s2AssetsTable = &AssetTable{dbClient: dbClient.DB} steps.FirstInstance.instanceSetup = config.DefaultInstance steps.FirstInstance.userEncryptionKey = config.EncryptionKeys.User steps.FirstInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP steps.FirstInstance.masterKey = masterKey - steps.FirstInstance.db = dbClient + steps.FirstInstance.db = dbClient.DB steps.FirstInstance.es = eventstoreClient steps.FirstInstance.defaults = config.SystemDefaults 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.externalPort = config.ExternalPort - steps.s4EventstoreIndexes = &EventstoreIndexes{dbClient: dbClient, dbType: config.Database.Type()} - steps.s5LastFailed = &LastFailed{dbClient: dbClient} - steps.s6OwnerRemoveColumns = &OwnerRemoveColumns{dbClient: dbClient} - steps.s7LogstoreTables = &LogstoreTables{dbClient: dbClient, username: config.Database.Username(), dbType: config.Database.Type()} - steps.s8AuthTokens = &AuthTokenIndexes{dbClient: dbClient} + steps.s4EventstoreIndexes = &EventstoreIndexes{dbClient: dbClient.DB, dbType: config.Database.Type()} + steps.s5LastFailed = &LastFailed{dbClient: dbClient.DB} + steps.s6OwnerRemoveColumns = &OwnerRemoveColumns{dbClient: dbClient.DB} + steps.s7LogstoreTables = &LogstoreTables{dbClient: dbClient.DB, username: config.Database.Username(), dbType: config.Database.Type()} + steps.s8AuthTokens = &AuthTokenIndexes{dbClient: dbClient.DB} err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil) logging.OnError(err).Fatal("unable to start projections") diff --git a/cmd/start/start.go b/cmd/start/start.go index 2653e43887..1cb6bab94f 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -3,7 +3,6 @@ package start import ( "context" "crypto/tls" - "database/sql" _ "embed" "fmt" "net" @@ -95,7 +94,7 @@ func startZitadel(config *Config, masterKey string) error { 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 { 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) } - storage, err := config.AssetStorage.NewStorage(dbClient) + storage, err := config.AssetStorage.NewStorage(dbClient.DB) if err != nil { 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) - actionsLogstoreSvc := logstore.New(commands, usageReporter, actionsExecutionDBEmitter, actionsExecutionStdoutEmitter) + actionsLogstoreSvc := logstore.New(queries, usageReporter, actionsExecutionDBEmitter, actionsExecutionStdoutEmitter) if actionsLogstoreSvc.Enabled() { logging.Warn("execution logs are currently in beta") } @@ -175,7 +174,7 @@ func startZitadel(config *Config, masterKey string) error { if err != nil { 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 { return err } @@ -189,7 +188,7 @@ func startAPIs( commands *command.Commands, queries *query.Queries, eventstore *eventstore.Eventstore, - dbClient *sql.DB, + dbClient *database.DB, config *Config, store static.Storage, authZRepo authz_repo.Repository, @@ -233,10 +232,10 @@ func startAPIs( if err != nil { 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 } - 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 } 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...) 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) if err != nil { @@ -272,7 +271,7 @@ func startAPIs( } 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 { return fmt.Errorf("unable to start console: %w", err) } diff --git a/go.mod b/go.mod index 2dc5f6ceeb..8ad5accb8f 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,22 @@ module github.com/zitadel/zitadel go 1.19 require ( - cloud.google.com/go/storage v1.28.1 - github.com/BurntSushi/toml v0.4.1 + cloud.google.com/go/storage v1.29.0 + github.com/BurntSushi/toml v1.2.1 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/squirrel v1.5.2 - github.com/VictoriaMetrics/fastcache v1.8.0 + github.com/Masterminds/squirrel v1.5.3 + github.com/VictoriaMetrics/fastcache v1.12.1 github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b 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/cockroachdb/cockroach-go/v2 v2.2.18 - github.com/dop251/goja v0.0.0-20220815083517-0c74f9139fd6 - github.com/dop251/goja_nodejs v0.0.0-20220905124449-678b33ca5009 + github.com/cockroachdb/cockroach-go/v2 v2.2.20 + github.com/dop251/goja v0.0.0-20230216180835-5937a312edda + github.com/dop251/goja_nodejs v0.0.0-20230207183254-2229640ea097 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/go-ldap/ldap/v3 v3.4.4 github.com/golang/glog v1.0.0 @@ -33,26 +33,26 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1 github.com/h2non/gock v1.2.0 github.com/improbable-eng/grpc-web v0.15.0 - github.com/jackc/pgconn v1.12.1 - github.com/jackc/pgtype v1.11.0 - github.com/jackc/pgx/v4 v4.16.1 + github.com/jackc/pgconn v1.14.0 + github.com/jackc/pgtype v1.14.0 + github.com/jackc/pgx/v4 v4.18.0 github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52 github.com/jinzhu/gorm v1.9.16 - github.com/k3a/html2text v1.0.8 - github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 - github.com/lib/pq v1.10.6 + github.com/k3a/html2text v1.1.0 + github.com/kevinburke/twilio-go v0.0.0-20221122012537-65f3dd7539e2 + github.com/lib/pq v1.10.7 github.com/lucasb-eyer/go-colorful v1.2.0 - github.com/minio/minio-go/v7 v7.0.20 - github.com/mitchellh/mapstructure v1.4.3 - github.com/muesli/gamut v0.2.0 - github.com/nicksnyder/go-i18n/v2 v2.1.2 + github.com/minio/minio-go/v7 v7.0.49 + github.com/mitchellh/mapstructure v1.5.0 + github.com/muesli/gamut v0.3.1 + github.com/nicksnyder/go-i18n/v2 v2.2.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/rs/cors v1.8.3 - github.com/sony/sonyflake v1.0.0 - github.com/spf13/cobra v1.3.0 - github.com/spf13/viper v1.10.1 + github.com/sony/sonyflake v1.1.0 + github.com/spf13/cobra v1.6.1 + github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.8.1 github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203 github.com/ttacon/libphonenumber v1.2.1 @@ -61,21 +61,21 @@ require ( 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/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/prometheus v0.25.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.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/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/net v0.7.0 golang.org/x/oauth2 v0.5.0 golang.org/x/sync v0.1.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/genproto v0.0.0-20230221151758-ace64dc21148 google.golang.org/grpc v1.53.0 @@ -85,119 +85,120 @@ 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/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.11.0 // indirect - cloud.google.com/go/trace v1.4.0 // indirect + cloud.google.com/go/iam v0.12.0 // indirect + cloud.google.com/go/trace v1.8.0 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/amdonov/xmlsig v0.1.0 // indirect github.com/beevik/etree v1.1.0 // 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/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dsoprea/go-exif v0.0.0-20210131231135-d154f10435cc // indirect - github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4 // indirect - github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb // indirect - github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210128210355-86b1014917f2 // indirect - github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d // indirect - github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c // indirect - github.com/dsoprea/go-png-image-structure v0.0.0-20200807080309-a98d4e94ac82 // indirect - github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/fxamacker/cbor/v2 v2.2.0 // indirect + github.com/dlclark/regexp2 v1.8.1 // indirect + github.com/dsoprea/go-exif v0.0.0-20221012082141-d21ac8e2de85 // indirect + github.com/dsoprea/go-exif/v2 v2.0.0-20221012082141-d21ac8e2de85 // indirect + github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 // indirect + github.com/dsoprea/go-jpeg-image-structure v0.0.0-20221012074422-4f3f7e934102 // indirect + github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect + github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect + github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d // indirect + github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/ghodss/yaml v1.0.0 // 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-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/uuid v4.0.0+incompatible // indirect - github.com/golang-jwt/jwt/v4 v4.1.0 // indirect - github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/golang/geo v0.0.0-20200319012246-673a6f80352d // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 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/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/websocket v1.4.2 // indirect - github.com/h2non/filetype v1.1.1 // indirect + github.com/h2non/filetype v1.1.3 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // 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/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect - github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect - github.com/klauspost/compress v1.14.2 // indirect - github.com/klauspost/cpuid v1.3.1 // indirect + github.com/kevinburke/rest v0.0.0-20230118171807-ac09c3f0ec45 // indirect + github.com/klauspost/compress v1.15.15 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // 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/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/minio/md5-simd v1.1.0 // indirect - github.com/minio/sha256-simd v0.1.1 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/minio/md5-simd v1.1.2 // indirect + github.com/minio/sha256-simd v1.0.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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 // indirect - github.com/muesli/kmeans v0.2.1 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect + github.com/muesli/kmeans v0.3.1 // 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/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/rs/xid v1.2.1 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rs/xid v1.4.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/spf13/afero v1.9.2 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // 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/wcharczuk/go-chart/v2 v2.1.0 // 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.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect go.opentelemetry.io/otel/internal/metric v0.25.0 // indirect - go.opentelemetry.io/proto/otlp v0.10.0 // indirect - golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 // indirect - golang.org/x/mod v0.7.0 // indirect + go.opentelemetry.io/proto/otlp v0.15.0 // indirect + golang.org/x/mod v0.8.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // 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.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.7 // indirect ) replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.4 - diff --git a/go.sum b/go.sum index d7639d4258..a4f28ec522 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ +bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= +bitbucket.org/liamstask/goose v0.0.0-20150115234039-8488cc47d90c/go.mod h1:hSVuE3qU7grINVSwrmzHfpg9k87ALBk+XaualNyUzI4= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -20,18 +24,8 @@ cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPT cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.108.0 h1:xntQwnfn8oHGX0crLVinvHM+AhXvi3QHQIEcX/2hiWk= -cloud.google.com/go v0.108.0/go.mod h1:lNUfQqusBJp0bgAg6qrHgYFYbTB+dOiob1itwnlD33Q= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -45,62 +39,88 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/iam v0.11.0 h1:kwCWfKwB6ePZoZnGLwrd3B6Ru/agoHANTUBWpVNIdnM= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/logging v1.6.1 h1:ZBsZK+JG+oCDT+vaxwqF2egKNRjz8soXiS6Xv79benI= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/monitoring v1.8.0 h1:c9riaGSPQ4dUKWB+M1Fl0N+iLxstMbCktdEwYSPGDvA= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/spanner v1.17.0/go.mod h1:+17t2ixFwRG4lWRwE+5kipDR9Ef07Jkmc8z0IbMDKUs= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/trace v1.4.0 h1:qO9eLn2esajC9sxpqp1YKX37nXC3L4BfGnPS0Cx9dYo= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/trace v1.8.0 h1:GFPLxbp5/FzdgTzor3nlNYNxMd6hLmzkE7sA9F0qQcA= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= +contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= +contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= +contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= +contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= +contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= +contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= +github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= +github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0 h1:38fNtfhHY6bs22b/D6+hDzO6JR0rDzpGPD36dY2uPL4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0/go.mod h1:jE23wM1jvwSKgdGcoOkj5j9n1VWtncW36pL2bK1JU+0= +github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.11.2 h1:Z5/bjyZhqXd7dNI76Z/KnyxtqavKF1UgGhInFSAIa8s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.11.2/go.mod h1:mHbBqn8wTt1/+bTA55xe2mLX5b+RKz2dVcGz8sH2HsY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.35.2 h1:xXo67CnDmiDMhgD3zAiuejKKMQ9nNkAQZZ4RS5U5jJY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.35.2 h1:uH5W8NML+jD8iFiBbNUh5X7Nt0FVDK44Hel+Ux0ZEqU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.35.2/go.mod h1:H785fvlgotVZqht+1rHhXSs8EJ8uPVmpBYkTYO3ccpc= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= -github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VictoriaMetrics/fastcache v1.8.0 h1:ybZqS7kRy8YVzYsI09GLzQhs7iqS6cOEH2avtknD1SU= -github.com/VictoriaMetrics/fastcache v1.8.0/go.mod h1:n7Sl+ioh/HlWeYHLSIBIE8TcZFHg/+xgvomWSS5xuEE= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -112,37 +132,60 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc github.com/amdonov/xmlsig v0.1.0 h1:i0iQ3neKLmUhcfIRgiiR3eRPKgXZj+n5lAfqnfKoeXI= github.com/amdonov/xmlsig v0.1.0/go.mod h1:jTR/jO0E8fSl/cLvMesP+RjxyV4Ux4WL1Ip64ZnQpA0= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/apache/beam v2.28.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ= +github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= +github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= +github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= -github.com/benbjohnson/clock v1.2.0 h1:9Re3G2TWxkE06LdMWMpcY6KV81GLXMGiYpPYUPkFAws= github.com/benbjohnson/clock v1.2.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= +github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -151,88 +194,117 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1CUzYdAZXijuvLuRMirgiXdf3zsM2Ig= -github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= +github.com/cloudflare/backoff v0.0.0-20161212185259-647f3cdfc87a/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY= +github.com/cloudflare/cfssl v1.6.3 h1:hDhRaGQN55nh0510/7A5QBN3xLoDz/M7nQX80icXvzs= +github.com/cloudflare/cfssl v1.6.3/go.mod h1:Kq0iHKY8sm2klDeQ2Ci/FI+6QdBGuyPWodgTJFLrXIw= +github.com/cloudflare/redoctober v0.0.0-20201013214028-99c99a8e7544/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210322005330-6414d713912e/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/cockroach-go/v2 v2.2.18 h1:bRNZWqzRSZesVYFjDAl1jgFb1jhIFIEreWIC2kPbcdY= -github.com/cockroachdb/cockroach-go/v2 v2.2.18/go.mod h1:mzlIDDBALQfEjv/7DU12fb2AfQ/MUYTlychcMpWp9QI= +github.com/cockroachdb/cockroach-go/v2 v2.2.20 h1:TLSzwdTdIwgsbdApHzaxunhSMrmbGf5YY6oxtaP2kvw= +github.com/cockroachdb/cockroach-go/v2 v2.2.20/go.mod h1:73vQi5H/H7kE8SgOt+XA6729Tubvj5hxKIEgbQQhp4c= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= -github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0= +github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20220815083517-0c74f9139fd6 h1:xHdUVG+c8SWJnct16Z3QJOVlaYo3OwoJyamo6kR6OL0= -github.com/dop251/goja v0.0.0-20220815083517-0c74f9139fd6/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= +github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= +github.com/dop251/goja v0.0.0-20230216180835-5937a312edda h1:yWEvdMtib3RbPysHDTNf/c3gerF5r+iMcmhlAeE6hEk= +github.com/dop251/goja v0.0.0-20230216180835-5937a312edda/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/dop251/goja_nodejs v0.0.0-20220905124449-678b33ca5009 h1:HIFRhi3kCQY7NMLX8WaoO0WNBLOKWrkWiQpxtvVwbS4= -github.com/dop251/goja_nodejs v0.0.0-20220905124449-678b33ca5009/go.mod h1:+CJy9V5cGycP5qwp6RM5jLg+TFEMyGtD7A9xUbU/BOQ= +github.com/dop251/goja_nodejs v0.0.0-20230207183254-2229640ea097 h1:WsLyDk8yHsVT1puf/32883ZxEb6Pgqd19AlQH9mxVK0= +github.com/dop251/goja_nodejs v0.0.0-20230207183254-2229640ea097/go.mod h1:0tlktQL7yHfYEtjcRGi/eiOkbDR5XF7gyFFvbC5//E0= github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= -github.com/dsoprea/go-exif v0.0.0-20210131231135-d154f10435cc h1:AuzYp98IFVOi0NU/WcZyGDQ6vAh/zkCjxGD3kt8aLzA= github.com/dsoprea/go-exif v0.0.0-20210131231135-d154f10435cc/go.mod h1:lOaOt7+UEppOgyvRy749v3do836U/hw0YVJNjoyPaEs= +github.com/dsoprea/go-exif v0.0.0-20221012082141-d21ac8e2de85 h1:+wKSjK8wh5Ybb63Fx1QvTSIfWU/n1nmqEzZy+82pqbQ= +github.com/dsoprea/go-exif v0.0.0-20221012082141-d21ac8e2de85/go.mod h1:lOaOt7+UEppOgyvRy749v3do836U/hw0YVJNjoyPaEs= github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= -github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4 h1:Mg7pY7kxDQD2Bkvr1N+XW4BESSIQ7tTTR7Vv+Gi2CsM= github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0= -github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb h1:gwjJjUr6FY7zAWVEueFPrcRHhd9+IK81TcItbqw2du4= +github.com/dsoprea/go-exif/v2 v2.0.0-20221012082141-d21ac8e2de85 h1:sgMOHQHMiddteUitH9QYgaRTwAcqqr5X9z5j4yNXDuY= +github.com/dsoprea/go-exif/v2 v2.0.0-20221012082141-d21ac8e2de85/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc= +github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8= +github.com/dsoprea/go-exif/v3 v3.0.0-20210512043655-120bcdb2a55e/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk= github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM= -github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210128210355-86b1014917f2 h1:ULCSN6v0WISNbALxomGPXh4dSjRKPW+7+seYoMz8UTc= +github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 h1:YDRiMEm32T60Kpm35YzOK9ZHgjsS1Qrid+XskNcsdp8= +github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM= github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210128210355-86b1014917f2/go.mod h1:ZoOP3yUG0HD1T4IUjIFsz/2OAB2yB4YX6NSm4K+uJRg= +github.com/dsoprea/go-jpeg-image-structure v0.0.0-20221012074422-4f3f7e934102 h1:P1dsxzctGkmG6Zf7gH2xrZhNXWP5/FuLDI7xbCGsWTo= +github.com/dsoprea/go-jpeg-image-structure v0.0.0-20221012074422-4f3f7e934102/go.mod h1:6+tQXZ+I62x13UZ+hemLVoZIuq/usVzvau7bqwUo9P0= github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA= -github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d h1:F/7L5wr/fP/SKeO5HuMlNEX9Ipyx2MbH2rV9G4zJRpk= github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= -github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c h1:7j5aWACOzROpr+dvMtu8GnI97g9ShLWD72XIELMgn+c= +github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg= +github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c/go.mod h1:pqKB+ijp27cEcrHxhXVgUUMlSDRuGJJp1E+20Lj5H0E= -github.com/dsoprea/go-png-image-structure v0.0.0-20200807080309-a98d4e94ac82 h1:RdwKOEEe2ND/JmoKh6I/EQlR9idKJTDOMffPFK6vN2M= +github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d h1:dg6UMHa50VI01WuPWXPbNJpO8QSyvIF5T5n2IZiqX3A= +github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d/go.mod h1:pqKB+ijp27cEcrHxhXVgUUMlSDRuGJJp1E+20Lj5H0E= github.com/dsoprea/go-png-image-structure v0.0.0-20200807080309-a98d4e94ac82/go.mod h1:aDYQkL/5gfRNZkoxiLTSWU4Y8/gV/4MVsy/MU9uwTak= -github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176 h1:CfXezFYb2STGOd1+n1HshvE191zVx+QX3A1nML5xxME= +github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d h1:8+qI8ant/vZkNSsbwSjIR6XJfWcDVTg/qx/3pRUUZNA= +github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d/go.mod h1:yTR3tKgyk20phAFg6IE9ulMA5NjEDD2wyx+okRFLVtw= github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8= -github.com/duo-labs/webauthn v0.0.0-20211216225436-9a12cd078b8a h1:mKoV2b/J8sVVvc6jCl7SxdOrED5cHKdQaHUxjoO5W74= -github.com/duo-labs/webauthn v0.0.0-20211216225436-9a12cd078b8a/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ= +github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8= +github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 h1:/py11NlxDaOxkT9OKN+gXgT+QOH5xj1ZRoyusfRIlo4= +github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349/go.mod h1:KVK+/Hul09ujXAGq+42UBgCTnXkiJZRnLYdURGjQUwo= +github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU= +github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec h1:darQ1FPPrwlzwmuN3fRMVCrsaCpuDqkKHADYzcMa73M= +github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec/go.mod h1:V3q8IgNpNqFio+56G0vy/QZIi7iho65UFrDwdF5OtZA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -242,49 +314,70 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ= github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= -github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o= +github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw= +github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= +github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= +github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs= github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -292,44 +385,53 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= +github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= -github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= +github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= +github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -364,13 +466,16 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= +github.com/google/certificate-transparency-go v1.1.2-0.20210511102531-373a877eec92/go.mod h1:kXWPsHVPSKVuxPPG69BRtumCbAW537FydV/GH89oBhM= +github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= +github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -386,15 +491,20 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= +github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= +github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= +github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -407,28 +517,32 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= +github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/trillian v1.3.14-0.20210409160123-c5ea3abd4a41/go.mod h1:1dPv0CUjNQVFEDuAUFhZql16pw/VlPgaX8qj+g5pVzQ= +github.com/google/trillian v1.3.14-0.20210428093031-b4ddea2e86b1/go.mod h1:FdIJX+NoDk/dIN2ZxTyz5nAJWgf+NSSSriPAMThChTY= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3 h1:eHv/jVY/JNop1xg2J9cBb4EzyMpWZoNCP1BslSAIkOI= -github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3/go.mod h1:h/KNeRx7oYU4SpA4SoY7W2/NxDKEEVuwA6j9A27L4OI= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ= +github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/csrf v1.7.1 h1:Ir3o2c1/Uzj6FBxMlAUB6SivgVMy1ONXwYgXn+/aHPE= github.com/gorilla/csrf v1.7.1/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= @@ -443,43 +557,45 @@ github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlI github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1 h1:I6ITHEanAwjB0FvaxmGm8pKqmCLR7QIe05ZmO4QAXMw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1/go.mod h1:gYC+WX4YJFarA2ie73G2epzt7TBWpo9pzcBnK1g0MSw= -github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= +github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -488,32 +604,32 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -526,8 +642,9 @@ github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfG github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.12.0/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= -github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8= github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -543,30 +660,39 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y= github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs= github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI= -github.com/jackc/pgx/v4 v4.16.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y= github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ= +github.com/jackc/pgx/v4 v4.18.0 h1:Ltaa1ePvc7msFGALnCrqKJVEByu/qYh5jJBYcDtAno4= +github.com/jackc/pgx/v4 v4.18.0/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52 h1:jny9eqYPwkG8IVy7foUoRjQmFLcArCSz+uPsL6KS0HQ= github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52/go.mod h1:RDZ+4PR3mDOtTpVbI0qBE+rdhmtIrtbssiNn38/1OWA= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jhump/protoreflect v1.8.2/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -574,11 +700,17 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= +github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg= +github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -592,33 +724,38 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k3a/html2text v1.0.8 h1:rVanLhKilpnJUJs/CNKWzMC4YaQINGxK0rSG8ssmnV0= -github.com/k3a/html2text v1.0.8/go.mod h1:ieEXykM67iT8lTvEWBh6fhpH4B23kB9OMKPdIBmgUqA= +github.com/k3a/html2text v1.1.0 h1:ks4hKSTdiTRsLr0DM771mI5TvsoG6zH7m1Ulv7eJRHw= +github.com/k3a/html2text v1.1.0/go.mod h1:ieEXykM67iT8lTvEWBh6fhpH4B23kB9OMKPdIBmgUqA= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 h1:K8qael4LemsmJCGt+ccI8b0fCNFDttmEu3qtpFt3G0M= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw= -github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c h1:hnbwWED5rIu+UaMkLR3JtnscMVGqp35lfzQwLuZAAUY= -github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= -github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 h1:PSsFm2SRpq9LnaRHLz4u9ZZ3liWjgXM6OMxXE4/qlgY= -github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk= +github.com/kevinburke/rest v0.0.0-20230118171807-ac09c3f0ec45 h1:WMM9MCVDgEtKsp7eQe0DCCkMaqykkNwdx38wn86NlVk= +github.com/kevinburke/rest v0.0.0-20230118171807-ac09c3f0ec45/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/twilio-go v0.0.0-20221122012537-65f3dd7539e2 h1:k+lYMvS9cAl7e4Ea78qodfa6QZfXNa4QlFS/0GYpanI= +github.com/kevinburke/twilio-go v0.0.0-20221122012537-65f3dd7539e2/go.mod h1:PDdDH7RSKjjy9iFyoMzfeChOSmXpXuMEUqmAJSihxx4= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= +github.com/kisom/goutils v1.4.3/go.mod h1:Lp5qrquG7yhYnWzZCI/68Pa/GpFynw//od6EkGnWpac= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= -github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= -github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -627,76 +764,87 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/go-gypsy v1.0.0/go.mod h1:chkXM0zjdpXOiqkCW1XcCHDfjfk14PH2KKkQWxfJUcU= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= -github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= -github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio-go/v7 v7.0.20 h1:0+Xt1SkCKDgcx5cmo3UxXcJ37u5Gy+/2i/+eQYqmYJw= -github.com/minio/minio-go/v7 v7.0.20/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2DAn1ou4+Do= -github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.49 h1:dE5DfOtnXMXCjr/HWI6zN9vCrY6Sv666qhhiwUMvGV4= +github.com/minio/minio-go/v7 v7.0.49/go.mod h1:UI34MvQEiob3Cf/gGExGMmzugkM/tNgbFypNDy5LMVc= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -706,16 +854,20 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/muesli/clusters v0.0.0-20180605185049-a07a36e67d36/go.mod h1:mw5KDqUj0eLj/6DUNINLVJNoPTFkEuGMHtJsXLviLkY= github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 h1:p4A2Jx7Lm3NV98VRMKlyWd3nqf8obft8NfXlAUmqd3I= github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762/go.mod h1:mw5KDqUj0eLj/6DUNINLVJNoPTFkEuGMHtJsXLviLkY= -github.com/muesli/gamut v0.2.0 h1:IZbl/hQzChTXtqDSXL8CDtjdRt58LivY03bGCm1yDyU= -github.com/muesli/gamut v0.2.0/go.mod h1:kz1+UJqI1thNtocJlowyqG2o0FNsN0W534VoMVsR9/Y= -github.com/muesli/kmeans v0.2.1 h1:ja5AnwfyDCVBCANrAfXr2pOh292FQnSeu1lySACDJU0= -github.com/muesli/kmeans v0.2.1/go.mod h1:eNyybq0tX9/iBEP6EMU4Y7dpmGK0uEhODdZpnG1a/iQ= +github.com/muesli/gamut v0.3.1 h1:8hozovcrDBWLLAwuOXC+UDyO0/uNroIdXAmY/lQOMHo= +github.com/muesli/gamut v0.3.1/go.mod h1:BED0DN21PXU1YaYNwaTmX9700SRHPcWWd6Llj0zsz5k= +github.com/muesli/kmeans v0.3.1 h1:KshLQ8wAETfLWOJKMuDCVYHnafddSa1kwGh/IypGIzY= +github.com/muesli/kmeans v0.3.1/go.mod h1:8/OvJW7cHc1BpRf8URb43m+vR105DDe+Kj1WcFXYDqc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= @@ -726,15 +878,22 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/nicksnyder/go-i18n/v2 v2.1.2 h1:QHYxcUJnGHBaq7XbvgunmZ2Pn0focXFqTD61CkH146c= -github.com/nicksnyder/go-i18n/v2 v2.1.2/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs= +github.com/nicksnyder/go-i18n/v2 v2.2.1 h1:aOzRCdwsJuoExfZhoiXHy4bjruwCMdt5otbYojM/PaA= +github.com/nicksnyder/go-i18n/v2 v2.2.1/go.mod h1:fF2++lPHlo+/kPaj3nB0uxtPwzlPm+BlgwGX7MkeGj0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -744,12 +903,18 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -761,20 +926,24 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= -github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= +github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -782,26 +951,42 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.24.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/pseudomuto/protoc-gen-doc v1.4.1/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -810,26 +995,31 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg= github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -837,32 +1027,48 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= +github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5-0.20210205191134-5ec6847320e5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM= -github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4= +github.com/sony/sonyflake v1.1.0 h1:wnrEcL3aOkWmPlhScLEGAXKkLAIslnBteNUq4Bw6MM4= +github.com/sony/sonyflake v1.1.0/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= -github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= -github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= -github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -871,6 +1077,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -882,29 +1089,48 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203 h1:1SWXcTphBQjYGWRRxLFIAR1LVtQEj4eR7xPtyeOVM/c= github.com/superseriousbusiness/exifremove v0.0.0-20210330092427-6acd27eac203/go.mod h1:0Xw5cYMOYpgaWs+OOSx41ugycl2qvKTi9tlMMcZhFyY= +github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= +github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= +github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA= +github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= +github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b h1:tnWgqoOBmInkt5pbLjagwNVjjT4RdJhFHzL1ebCSRh8= -github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -918,11 +1144,26 @@ github.com/zitadel/oidc/v2 v2.0.0-dynamic-issuer.8 h1:e6sRhY3Lijku8XBzazLoWpJcjO github.com/zitadel/oidc/v2 v2.0.0-dynamic-issuer.8/go.mod h1:2jHMP6o/WK0EmcNJkz+FSpjeqcCuQG9YqqqzKZkfgIE= github.com/zitadel/saml v0.0.10 h1:cyKd78Vat9vz55S74lggJrXMSqbAPsnJDrPFTPScNYY= github.com/zitadel/saml v0.0.10/go.mod h1:Hze1/zRN9j1uh7U+89vweP/OwLNO8BLHg3zU1Jtycdg= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= +github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= +github.com/zmap/zcrypto v0.0.0-20210123152837-9cf5beac6d91/go.mod h1:R/deQh6+tSWlgI9tb4jNmXxn8nSCabl5ZQsBX9//I/E= +github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc/go.mod h1:FM4U1E3NzlNMRnSUTU3P1UdukWhYGifqEsjk9fn7BCk= +github.com/zmap/zlint/v3 v3.1.0/go.mod h1:L7t8s3sEKkb0A2BxGy1IWrxt1ZATa1R4QfJZaQOD3zU= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw= +go.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU= +go.etcd.io/etcd/client/v3 v3.5.0-alpha.0/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8= +go.etcd.io/etcd/etcdctl/v3 v3.5.0-alpha.0/go.mod h1:YPwSaBciV5G6Gpt435AasAG3ROetZsKNUzibRa/++oo= +go.etcd.io/etcd/pkg/v3 v3.5.0-alpha.0/go.mod h1:tV31atvwzcybuqejDoY3oaNRTtlD2l/Ot78Pc9w7DMY= +go.etcd.io/etcd/raft/v3 v3.5.0-alpha.0/go.mod h1:FAwse6Zlm5v4tEWZaTjmNhe17Int4Oxbu7+2r0DiD3w= +go.etcd.io/etcd/server/v3 v3.5.0-alpha.0/go.mod h1:tsKetYpt980ZTpzl/gb+UOJj9RkIyCb1u4wjzMg90BQ= +go.etcd.io/etcd/tests/v3 v3.5.0-alpha.0/go.mod h1:HnrHxjyCuZ8YDt8PYVyQQ5d1ZQfzJVEtQWllr5Vp/30= +go.etcd.io/etcd/v3 v3.5.0-alpha.0/go.mod h1:JZ79d3LV6NUfPjUxXrpiFAYcjhT+06qqw+i28snx8To= +go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -936,14 +1177,11 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0 h1:TON1iU3Y5oIytGQHIejDYLam5uoSMsmA0UV9Yupb5gQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0/go.mod h1:T/zQwBldOpoAEpE3HMbLnI8ydESZVz4ggw6Is4FF9LI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0/go.mod h1:7W3JSDYTtH3qKKHrS1fMiwLtK7iZFLPq1+7htfspX/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0 h1:0BgiNWjN7rUWO9HdjF4L12r8OW86QkVQcYmCjnayJLo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0/go.mod h1:bdvm3YpMxWAgEfQhtTBaVR8ceXPRuRBSQrvOBnIlHxc= -go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ= -go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= +go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0= +go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 h1:xzbcGykysUh776gzD1LUPsNNHKWN0kQWDnJhn1ddUuk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0/go.mod h1:14T5gr+Y6s2AgHPqBMgnGwp04csUjQmYXFWPeiBoq5s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0 h1:VsgsSCDwOSuO8eMVh63Cd4nACMqgjpmAeJSIvVNneD0= @@ -952,63 +1190,72 @@ go.opentelemetry.io/otel/exporters/prometheus v0.25.0 h1:8f9PiHQ2yqRRWktEJ/u2cIP go.opentelemetry.io/otel/exporters/prometheus v0.25.0/go.mod h1:TmEyKmTplB/cdILsJBqD9/JDK9ssGXWjsrpmMHodFLw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0 h1:OiYdrCq1Ctwnovp6EofSPwlp5aGy4LgKNbkg7PtEUw8= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0/go.mod h1:DUFCmFkXr0VtAHl5Zq2JRx24G6ze5CAq8YfdD36RdX8= -go.opentelemetry.io/otel/internal/metric v0.23.0/go.mod h1:z+RPiDJe30YnCrOhFGivwBS+DU1JU/PiLKkk4re2DNY= go.opentelemetry.io/otel/internal/metric v0.25.0 h1:w/7RXe16WdPylaIXDgcYM6t/q0K5lXgSdZOEbIEyliE= go.opentelemetry.io/otel/internal/metric v0.25.0/go.mod h1:Nhuw26QSX7d6n4duoqAFi5KOQR4AuzyMcl5eXOgwxtc= -go.opentelemetry.io/otel/metric v0.23.0/go.mod h1:G/Nn9InyNnIv7J6YVkQfpc0JCfKBNJaERBGw08nqmVQ= go.opentelemetry.io/otel/metric v0.25.0 h1:7cXOnCADUsR3+EOqxPaSKwhEuNu0gz/56dRN1hpIdKw= go.opentelemetry.io/otel/metric v0.25.0/go.mod h1:E884FSpQfnJOMMUaq+05IWlJ4rjZpk2s/F1Ju+TEEm8= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= +go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= +go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU= go.opentelemetry.io/otel/sdk/export/metric v0.25.0 h1:6UjAFmVB5Fza3K5qUJpYWGrk8QMPIqlSnya5FI46VBY= go.opentelemetry.io/otel/sdk/export/metric v0.25.0/go.mod h1:Ej7NOa+WpN49EIcr1HMUYRvxXXCCnQCg2+ovdt2z8Pk= go.opentelemetry.io/otel/sdk/metric v0.25.0 h1:J+Ta+4IAA5W9AdWhGQLfciEpavBqqSkBzTDeYvJLFNU= go.opentelemetry.io/otel/sdk/metric v0.25.0/go.mod h1:G4xzj4LvC6xDDSsVXpvRVclQCbofGGg4ZU2VKKtDRfg= -go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo= -go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= -go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= +go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0= +go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= +go.opentelemetry.io/proto/otlp v0.15.0 h1:h0bKrvdrT/9sBwEJ6iWUqT/N/xPcS66bL4u3isneJ6w= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1024,7 +1271,6 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1049,15 +1295,15 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1068,13 +1314,17 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1088,32 +1338,34 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1123,12 +1375,11 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= @@ -1136,6 +1387,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1154,7 +1406,9 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1163,15 +1417,14 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190620070143-6f217b454f45/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1179,7 +1432,6 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1196,43 +1448,36 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1240,6 +1485,7 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1249,6 +1495,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -1256,15 +1503,19 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1272,15 +1523,18 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191118222007-07fc4c7f2b98/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1298,16 +1552,19 @@ golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200701151220-7cb253f4c4f8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201014170642-d1624618ad65/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1316,13 +1573,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1333,9 +1586,12 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3j golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1353,34 +1609,30 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1403,7 +1655,6 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200605102947-12044bf5ea91/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1420,34 +1671,14 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210331142528-b7513248f0ba/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148 h1:muK+gVBJBfFb4SejshDBlN2/UgxCCOKH9Y34ljqEGOc= google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1474,12 +1705,7 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= @@ -1495,6 +1721,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -1509,16 +1736,20 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= -gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -1534,6 +1765,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.3.5/go.mod h1:EGCWefLFQSVFrHGy4J8EtiHCWX5Q8t0yz2Jt9aKkGzU= @@ -1548,13 +1780,16 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +honnef.co/go/tools v0.1.4/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/internal/admin/repository/eventsourcing/repository.go b/internal/admin/repository/eventsourcing/repository.go index 63bcb6b15f..d7c03c1fc9 100644 --- a/internal/admin/repository/eventsourcing/repository.go +++ b/internal/admin/repository/eventsourcing/repository.go @@ -2,11 +2,11 @@ package eventsourcing import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/eventstore" "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/spooler" admin_view "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view" + "github.com/zitadel/zitadel/internal/database" eventstore2 "github.com/zitadel/zitadel/internal/eventstore" v1 "github.com/zitadel/zitadel/internal/eventstore/v1" es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler" @@ -23,7 +23,7 @@ type EsRepository struct { 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) if err != nil { return nil, err diff --git a/internal/admin/repository/eventsourcing/spooler/spooler.go b/internal/admin/repository/eventsourcing/spooler/spooler.go index 98542b309f..8b9fa592dd 100644 --- a/internal/admin/repository/eventsourcing/spooler/spooler.go +++ b/internal/admin/repository/eventsourcing/spooler/spooler.go @@ -2,10 +2,10 @@ package spooler import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/handler" "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing/view" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" v1 "github.com/zitadel/zitadel/internal/eventstore/v1" "github.com/zitadel/zitadel/internal/eventstore/v1/spooler" @@ -20,11 +20,11 @@ type SpoolerConfig struct { 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{ Eventstore: es, EventstoreV2: esV2, - Locker: &locker{dbClient: sql}, + Locker: &locker{dbClient: sql.DB}, ConcurrentWorkers: c.ConcurrentWorkers, ConcurrentInstances: c.ConcurrentInstances, ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, static), diff --git a/internal/admin/repository/eventsourcing/view/view.go b/internal/admin/repository/eventsourcing/view/view.go index 4b8c52392d..8f27706985 100644 --- a/internal/admin/repository/eventsourcing/view/view.go +++ b/internal/admin/repository/eventsourcing/view/view.go @@ -1,16 +1,15 @@ package view import ( - "database/sql" - "github.com/jinzhu/gorm" + "github.com/zitadel/zitadel/internal/database" ) type View struct { Db *gorm.DB } -func StartView(sqlClient *sql.DB) (*View, error) { +func StartView(sqlClient *database.DB) (*View, error) { gorm, err := gorm.Open("postgres", sqlClient) if err != nil { return nil, err diff --git a/internal/api/assets/asset.go b/internal/api/assets/asset.go index 815d1a17c7..f570b7dd9d 100644 --- a/internal/api/assets/asset.go +++ b/internal/api/assets/asset.go @@ -82,7 +82,7 @@ func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, 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{ commands: commands, errorHandler: DefaultErrorHandler, @@ -94,7 +94,7 @@ func NewHandler(commands *command.Commands, verifier *authz.TokenVerifier, authC verifier.RegisterServer("Assets-API", "assets", AssetsService_AuthMethods) router := mux.NewRouter() - router.Use(instanceInterceptor, assetCacheInterceptor, accessInterceptor) + router.Use(callDurationInterceptor, instanceInterceptor, assetCacheInterceptor, accessInterceptor) RegisterRoutes(router, h) router.PathPrefix("/{owner}").Methods("GET").HandlerFunc(DownloadHandleFunc(h, h.GetFile())) return http_util.CopyHeadersToContext(http_mw.CORSInterceptor(router)) diff --git a/internal/api/authz/detach.go b/internal/api/authz/detach.go new file mode 100644 index 0000000000..acdf255e68 --- /dev/null +++ b/internal/api/authz/detach.go @@ -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) } diff --git a/internal/api/call/duration.go b/internal/api/call/duration.go new file mode 100644 index 0000000000..24573aa367 --- /dev/null +++ b/internal/api/call/duration.go @@ -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) +} diff --git a/internal/api/call/duration_test.go b/internal/api/call/duration_test.go new file mode 100644 index 0000000000..4556460652 --- /dev/null +++ b/internal/api/call/duration_test.go @@ -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) + } + }) + } +} diff --git a/internal/api/grpc/admin/import.go b/internal/api/grpc/admin/import.go index c82ae90eb9..4380393377 100644 --- a/internal/api/grpc/admin/import.go +++ b/internal/api/grpc/admin/import.go @@ -88,17 +88,6 @@ func (c *count) getProgress() string { "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) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() @@ -169,7 +158,7 @@ func (s *Server) ImportData(ctx context.Context, req *admin_pb.ImportDataRequest if err != nil { return nil, err } - dctx := Detach(ctx) + dctx := authz.Detach(ctx) go func() { ch := make(chan importResponse, 1) ctxTimeout, cancel := context.WithTimeout(dctx, timeoutDuration) diff --git a/internal/api/grpc/server/gateway.go b/internal/api/grpc/server/gateway.go index c0e32685fe..6c3b2fbdea 100644 --- a/internal/api/grpc/server/gateway.go +++ b/internal/api/grpc/server/gateway.go @@ -71,6 +71,7 @@ func CreateGateway(ctx context.Context, g Gateway, port uint16, http1HostName st } func addInterceptors(handler http.Handler, http1HostName string) http.Handler { + handler = http_mw.CallDurationHandler(handler) handler = http1Host(handler, http1HostName) handler = http_mw.CORSInterceptor(handler) handler = http_mw.DefaultTelemetryHandler(handler) diff --git a/internal/api/grpc/server/middleware/call_interceptor.go b/internal/api/grpc/server/middleware/call_interceptor.go new file mode 100644 index 0000000000..69a89cd2f0 --- /dev/null +++ b/internal/api/grpc/server/middleware/call_interceptor.go @@ -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) + } +} diff --git a/internal/api/grpc/server/server.go b/internal/api/grpc/server/server.go index b81d77d6cf..86fb625928 100644 --- a/internal/api/grpc/server/server.go +++ b/internal/api/grpc/server/server.go @@ -35,6 +35,7 @@ func CreateServer( serverOptions := []grpc.ServerOption{ grpc.UnaryInterceptor( grpc_middleware.ChainUnaryServer( + middleware.CallDurationHandler(), middleware.DefaultTracingServer(), middleware.MetricsHandler(metricTypes, grpc_api.Probes...), middleware.NoCacheInterceptor(), diff --git a/internal/api/http/middleware/call_interceptor.go b/internal/api/http/middleware/call_interceptor.go new file mode 100644 index 0000000000..9159f6c100 --- /dev/null +++ b/internal/api/http/middleware/call_interceptor.go @@ -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()))) + }) +} diff --git a/internal/api/oidc/key.go b/internal/api/oidc/key.go index a587a949df..3b4f73c83f 100644 --- a/internal/api/oidc/key.go +++ b/internal/api/oidc/key.go @@ -187,6 +187,7 @@ func (o *OPStorage) getMaxKeySequence(ctx context.Context) (uint64, error) { return o.eventstore.LatestSequence(ctx, eventstore.NewSearchQueryBuilder(eventstore.ColumnsMaxSequence). ResourceOwner(authz.GetInstance(ctx).InstanceID()). + AllowTimeTravel(). AddQuery(). AggregateTypes(keypair.AggregateType, instance.AggregateType). Builder(), diff --git a/internal/api/oidc/op.go b/internal/api/oidc/op.go index 2ef3b29320..a5c4d0da38 100644 --- a/internal/api/oidc/op.go +++ b/internal/api/oidc/op.go @@ -2,7 +2,6 @@ package oidc import ( "context" - "database/sql" "fmt" "net/http" "time" @@ -18,6 +17,7 @@ import ( "github.com/zitadel/zitadel/internal/auth/repository" "github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" caos_errs "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/handler/crdb" @@ -73,7 +73,7 @@ type OPStorage struct { 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) if err != nil { 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 } -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{ repo: repo, command: command, @@ -182,7 +182,7 @@ func newStorage(config Config, command *command.Commands, query *query.Queries, defaultRefreshTokenIdleExpiration: config.DefaultRefreshTokenIdleExpiration, defaultRefreshTokenExpiration: config.DefaultRefreshTokenExpiration, encAlg: encAlg, - locker: crdb.NewLocker(projections, locksTable, signingKey), + locker: crdb.NewLocker(db.DB, locksTable, signingKey), assetAPIPrefix: assets.AssetAPI(externalSecure), } } diff --git a/internal/api/saml/provider.go b/internal/api/saml/provider.go index eaab04d683..8158846214 100644 --- a/internal/api/saml/provider.go +++ b/internal/api/saml/provider.go @@ -2,7 +2,6 @@ package saml import ( "context" - "database/sql" "fmt" "net/http" @@ -14,6 +13,7 @@ import ( "github.com/zitadel/zitadel/internal/auth/repository" "github.com/zitadel/zitadel/internal/command" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/handler/crdb" "github.com/zitadel/zitadel/internal/query" @@ -38,7 +38,7 @@ func NewProvider( encAlg crypto.EncryptionAlgorithm, certEncAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, - projections *sql.DB, + projections *database.DB, instanceHandler, userAgentCookie, accessHandler func(http.Handler) http.Handler, @@ -89,12 +89,12 @@ func newStorage( encAlg crypto.EncryptionAlgorithm, certEncAlg crypto.EncryptionAlgorithm, es *eventstore.Eventstore, - projections *sql.DB, + db *database.DB, ) (*Storage, error) { return &Storage{ encAlg: encAlg, certEncAlg: certEncAlg, - locker: crdb.NewLocker(projections, locksTable, signingKey), + locker: crdb.NewLocker(db.DB, locksTable, signingKey), eventstore: es, repo: repo, command: command, diff --git a/internal/api/ui/console/console.go b/internal/api/ui/console/console.go index 87b68532d7..ac11fcf706 100644 --- a/internal/api/ui/console/console.go +++ b/internal/api/ui/console/console.go @@ -88,7 +88,7 @@ func (f *file) Stat() (_ fs.FileInfo, err error) { 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") if err != nil { return nil, err @@ -103,7 +103,7 @@ func Start(config Config, externalSecure bool, issuer op.IssuerFromRequest, inst 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) { url := http_util.BuildOrigin(r.Host, externalSecure) environmentJSON, err := createEnvironmentJSON(url, issuer(r), authz.GetInstance(r.Context()).ConsoleClientID(), customerPortal) diff --git a/internal/api/ui/login/login.go b/internal/api/ui/login/login.go index 85e9380a67..de42f7e68d 100644 --- a/internal/api/ui/login/login.go +++ b/internal/api/ui/login/login.go @@ -67,8 +67,8 @@ func CreateLogin(config Config, userAgentCookie, issuerInterceptor, oidcInstanceHandler, - samlInstanceHandler mux.MiddlewareFunc, - assetCache mux.MiddlewareFunc, + samlInstanceHandler, + assetCache, accessHandler mux.MiddlewareFunc, userCodeAlg crypto.EncryptionAlgorithm, idpConfigAlg crypto.EncryptionAlgorithm, diff --git a/internal/auth/repository/eventsourcing/repository.go b/internal/auth/repository/eventsourcing/repository.go index 531c03248d..bc19fdab6c 100644 --- a/internal/auth/repository/eventsourcing/repository.go +++ b/internal/auth/repository/eventsourcing/repository.go @@ -2,7 +2,6 @@ package eventsourcing import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/eventstore" "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/spooler" @@ -11,6 +10,7 @@ import ( "github.com/zitadel/zitadel/internal/command" sd "github.com/zitadel/zitadel/internal/config/systemdefaults" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" eventstore2 "github.com/zitadel/zitadel/internal/eventstore" v1 "github.com/zitadel/zitadel/internal/eventstore/v1" es_spol "github.com/zitadel/zitadel/internal/eventstore/v1/spooler" @@ -34,7 +34,7 @@ type EsRepository struct { 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) if err != nil { return nil, err diff --git a/internal/auth/repository/eventsourcing/spooler/spooler.go b/internal/auth/repository/eventsourcing/spooler/spooler.go index 63185e2b0d..4da8340154 100644 --- a/internal/auth/repository/eventsourcing/spooler/spooler.go +++ b/internal/auth/repository/eventsourcing/spooler/spooler.go @@ -2,11 +2,11 @@ package spooler import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/handler" "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view" sd "github.com/zitadel/zitadel/internal/config/systemdefaults" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" v1 "github.com/zitadel/zitadel/internal/eventstore/v1" "github.com/zitadel/zitadel/internal/eventstore/v1/spooler" @@ -21,11 +21,11 @@ type SpoolerConfig struct { 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{ Eventstore: es, EventstoreV2: esV2, - Locker: &locker{dbClient: client}, + Locker: &locker{dbClient: client.DB}, ConcurrentWorkers: c.ConcurrentWorkers, ConcurrentInstances: c.ConcurrentInstances, ViewHandlers: handler.Register(ctx, c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults, queries), diff --git a/internal/auth/repository/eventsourcing/view/user.go b/internal/auth/repository/eventsourcing/view/user.go index ab24f5fd2d..51cd52f007 100644 --- a/internal/auth/repository/eventsourcing/view/user.go +++ b/internal/auth/repository/eventsourcing/view/user.go @@ -21,15 +21,6 @@ func (v *View) UserByID(userID, instanceID string) (*model.UserView, error) { 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) { loginNameQuery, err := query.NewUserLoginNamesSearchQuery(loginName) if err != nil { diff --git a/internal/auth/repository/eventsourcing/view/view.go b/internal/auth/repository/eventsourcing/view/view.go index 54c57e99f7..80f683bc80 100644 --- a/internal/auth/repository/eventsourcing/view/view.go +++ b/internal/auth/repository/eventsourcing/view/view.go @@ -1,11 +1,10 @@ package view import ( - "database/sql" - "github.com/jinzhu/gorm" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" eventstore "github.com/zitadel/zitadel/internal/eventstore/v1" "github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/query" @@ -19,7 +18,7 @@ type View struct { 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) if err != nil { return nil, err diff --git a/internal/auth_request/repository/cache/cache.go b/internal/auth_request/repository/cache/cache.go index dd68b05ff8..37bdb2276f 100644 --- a/internal/auth_request/repository/cache/cache.go +++ b/internal/auth_request/repository/cache/cache.go @@ -9,15 +9,16 @@ import ( "time" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" caos_errs "github.com/zitadel/zitadel/internal/errors" ) type AuthRequestCache struct { - client *sql.DB + client *database.DB } -func Start(dbClient *sql.DB) *AuthRequestCache { +func Start(dbClient *database.DB) *AuthRequestCache { return &AuthRequestCache{ client: dbClient, } diff --git a/internal/authz/authz.go b/internal/authz/authz.go index 268ea3aec1..f8f21e4125 100644 --- a/internal/authz/authz.go +++ b/internal/authz/authz.go @@ -1,14 +1,13 @@ package authz import ( - "database/sql" - "github.com/zitadel/zitadel/internal/authz/repository" "github.com/zitadel/zitadel/internal/authz/repository/eventsourcing" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "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) } diff --git a/internal/authz/repository/eventsourcing/repository.go b/internal/authz/repository/eventsourcing/repository.go index 3e8f8200f3..c3f212d96c 100644 --- a/internal/authz/repository/eventsourcing/repository.go +++ b/internal/authz/repository/eventsourcing/repository.go @@ -2,12 +2,12 @@ package eventsourcing import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/authz/repository" "github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/eventstore" authz_view "github.com/zitadel/zitadel/internal/authz/repository/eventsourcing/view" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" v1 "github.com/zitadel/zitadel/internal/eventstore/v1" "github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/query" @@ -18,7 +18,7 @@ type EsRepository struct { 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) if err != nil { return nil, err diff --git a/internal/authz/repository/eventsourcing/view/view.go b/internal/authz/repository/eventsourcing/view/view.go index eed184979b..a55dec7699 100644 --- a/internal/authz/repository/eventsourcing/view/view.go +++ b/internal/authz/repository/eventsourcing/view/view.go @@ -1,8 +1,7 @@ package view import ( - "database/sql" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/query" @@ -15,7 +14,7 @@ type View struct { 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) if err != nil { return nil, err diff --git a/internal/command/quota_model.go b/internal/command/quota_model.go index 123bd35550..3da2598934 100644 --- a/internal/command/quota_model.go +++ b/internal/command/quota_model.go @@ -9,7 +9,6 @@ type quotaWriteModel struct { eventstore.WriteModel unit quota.Unit active bool - config *quota.AddedEvent } // newQuotaWriteModel aggregateId is filled by reducing unit matching events @@ -43,11 +42,9 @@ func (wm *quotaWriteModel) Reduce() error { case *quota.AddedEvent: wm.AggregateID = e.Aggregate().ID wm.active = true - wm.config = e case *quota.RemovedEvent: wm.AggregateID = e.Aggregate().ID wm.active = false - wm.config = nil } } return wm.WriteModel.Reduce() diff --git a/internal/command/quota_notifications_model.go b/internal/command/quota_notifications_model.go deleted file mode 100644 index 41382e5bca..0000000000 --- a/internal/command/quota_notifications_model.go +++ /dev/null @@ -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() -} diff --git a/internal/command/quota_period.go b/internal/command/quota_period.go deleted file mode 100644 index c82d1707e3..0000000000 --- a/internal/command/quota_period.go +++ /dev/null @@ -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) -} diff --git a/internal/database/cockroach/config.go b/internal/database/cockroach/config.go index ab13575c3b..841787b9fd 100644 --- a/internal/database/cockroach/config.go +++ b/internal/database/cockroach/config.go @@ -2,6 +2,7 @@ package cockroach import ( "database/sql" + "fmt" "strconv" "strings" "time" @@ -89,6 +90,15 @@ func (c *Config) Type() string { 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 { Username string Password string diff --git a/internal/database/cockroach/config_test.go b/internal/database/cockroach/config_test.go new file mode 100644 index 0000000000..ca16f98f7c --- /dev/null +++ b/internal/database/cockroach/config_test.go @@ -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) + } + }) + } +} diff --git a/internal/database/database.go b/internal/database/database.go index 6f216b332b..c7507f1e68 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -19,7 +19,12 @@ func (c *Config) SetConnector(connector dialect.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) if err != nil { 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 client, nil + return &DB{ + DB: client, + Database: config.connector, + }, nil } 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 } -func (c Config) Database() string { +func (c Config) DatabaseName() string { return c.connector.DatabaseName() } diff --git a/internal/database/dialect/config.go b/internal/database/dialect/config.go index b043c9f370..9e3680710b 100644 --- a/internal/database/dialect/config.go +++ b/internal/database/dialect/config.go @@ -3,6 +3,7 @@ package dialect import ( "database/sql" "sync" + "time" ) type Config struct { @@ -29,10 +30,15 @@ type Matcher interface { type Connector interface { Connect(useAdmin bool) (*sql.DB, error) + Password() string + Database +} + +type Database interface { DatabaseName() string Username() string - Password() string Type() string + Timetravel(time.Duration) string } func Register(matcher Matcher, config Connector, isDefault bool) { diff --git a/internal/database/postgres/config.go b/internal/database/postgres/config.go index ab8dbb3ff5..a276015619 100644 --- a/internal/database/postgres/config.go +++ b/internal/database/postgres/config.go @@ -89,6 +89,10 @@ func (c *Config) Type() string { return "postgres" } +func (c *Config) Timetravel(time.Duration) string { + return "" +} + type User struct { Username string Password string diff --git a/internal/eventstore/config.go b/internal/eventstore/config.go index bd401e27df..c9d00da267 100644 --- a/internal/eventstore/config.go +++ b/internal/eventstore/config.go @@ -1,16 +1,16 @@ package eventstore import ( - "database/sql" "time" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore/repository" z_sql "github.com/zitadel/zitadel/internal/eventstore/repository/sql" ) type Config struct { PushTimeout time.Duration - Client *sql.DB + Client *database.DB repo repository.Repository } diff --git a/internal/eventstore/handler/crdb/handler_stmt.go b/internal/eventstore/handler/crdb/handler_stmt.go index 83d844a966..65eb99426a 100644 --- a/internal/eventstore/handler/crdb/handler_stmt.go +++ b/internal/eventstore/handler/crdb/handler_stmt.go @@ -7,6 +7,7 @@ import ( "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/handler" @@ -19,7 +20,7 @@ var ( type StatementHandlerConfig struct { handler.ProjectionHandlerConfig - Client *sql.DB + Client *database.DB SequenceTable string LockTable string FailedEventsTable string @@ -34,7 +35,7 @@ type StatementHandler struct { *handler.ProjectionHandler Locker - client *sql.DB + client *database.DB sequenceTable string currentSequenceStmt string updateSequencesBaseStmt string @@ -74,7 +75,7 @@ func NewStatementHandler( aggregates: aggregateTypes, reduces: reduces, bulkLimit: config.BulkLimit, - Locker: NewLocker(config.Client, config.LockTable, config.ProjectionName), + Locker: NewLocker(config.Client.DB, config.LockTable, config.ProjectionName), initCheck: config.InitCheck, initialized: make(chan bool), } @@ -96,7 +97,7 @@ func (h *StatementHandler) SearchQuery(ctx context.Context, instanceIDs []string 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 _, instanceID := range instanceIDs { diff --git a/internal/eventstore/handler/crdb/handler_stmt_test.go b/internal/eventstore/handler/crdb/handler_stmt_test.go index 401d86ec09..8c0d1537f4 100644 --- a/internal/eventstore/handler/crdb/handler_stmt_test.go +++ b/internal/eventstore/handler/crdb/handler_stmt_test.go @@ -12,6 +12,7 @@ import ( "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/handler" "github.com/zitadel/zitadel/internal/eventstore/repository" @@ -114,6 +115,7 @@ func TestProjectionHandler_SearchQuery(t *testing.T) { }, SearchQueryBuilder: eventstore. NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). AddQuery(). AggregateTypes("testAgg"). SequenceGreater(5). @@ -143,6 +145,7 @@ func TestProjectionHandler_SearchQuery(t *testing.T) { }, SearchQueryBuilder: eventstore. NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). AddQuery(). AggregateTypes("testAgg"). SequenceGreater(5). @@ -171,7 +174,9 @@ func TestProjectionHandler_SearchQuery(t *testing.T) { }, SequenceTable: tt.fields.sequenceTable, BulkLimit: tt.fields.bulkLimit, - Client: client, + Client: &database.DB{ + DB: client, + }, }) h.aggregates = tt.fields.aggregates @@ -549,7 +554,9 @@ func TestStatementHandler_Update(t *testing.T) { sequenceTable: "my_sequences", currentSequenceStmt: fmt.Sprintf(currentSequenceStmtFormat, "my_sequences"), updateSequencesBaseStmt: fmt.Sprintf(updateCurrentSequencesStmtFormat, "my_sequences"), - client: client, + client: &database.DB{ + DB: client, + }, } h.aggregates = tt.fields.aggregates @@ -1121,7 +1128,9 @@ func TestStatementHandler_executeStmts(t *testing.T) { ProjectionName: tt.fields.projectionName, RequeueEvery: 0, }, - Client: client, + Client: &database.DB{ + DB: client, + }, FailedEventsTable: tt.fields.failedEventsTable, MaxFailureCount: tt.fields.maxFailureCount, }, diff --git a/internal/eventstore/handler/handler_projection.go b/internal/eventstore/handler/handler_projection.go index c8c8dda7a5..b86067c27d 100644 --- a/internal/eventstore/handler/handler_projection.go +++ b/internal/eventstore/handler/handler_projection.go @@ -194,7 +194,7 @@ func (h *ProjectionHandler) schedule(ctx context.Context) { var succeededOnce bool var err error // 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 { if !succeededOnce { // (re)check if it has succeeded in the meantime diff --git a/internal/eventstore/local_crdb_test.go b/internal/eventstore/local_crdb_test.go index 1ac0e6779e..85dc78aea8 100644 --- a/internal/eventstore/local_crdb_test.go +++ b/internal/eventstore/local_crdb_test.go @@ -4,6 +4,7 @@ import ( "database/sql" "os" "testing" + "time" "github.com/cockroachdb/cockroach-go/v2/testserver" "github.com/zitadel/logging" @@ -14,7 +15,7 @@ import ( ) var ( - testCRDBClient *sql.DB + testCRDBClient *database.DB ) func TestMain(m *testing.M) { @@ -23,7 +24,11 @@ func TestMain(m *testing.M) { 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 { logging.WithFields("error", err).Fatal("unable to connect to db") } @@ -39,7 +44,7 @@ func TestMain(m *testing.M) { ts.Stop() }() - if err = initDB(testCRDBClient); err != nil { + if err = initDB(testCRDBClient.DB); err != nil { logging.WithFields("error", err).Fatal("migrations failed") } @@ -57,10 +62,20 @@ func initDB(db *sql.DB) error { }) err := initialise.Init(db, initialise.VerifyUser(config.Username(), ""), - initialise.VerifyDatabase(config.Database()), - initialise.VerifyGrant(config.Database(), config.Username())) + initialise.VerifyDatabase(config.DatabaseName()), + initialise.VerifyGrant(config.DatabaseName(), config.Username())) if err != nil { return err } 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" } diff --git a/internal/eventstore/read_model.go b/internal/eventstore/read_model.go index 066e119fef..3e07743fac 100644 --- a/internal/eventstore/read_model.go +++ b/internal/eventstore/read_model.go @@ -2,7 +2,7 @@ package eventstore 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 might be saved in a database or in memory type ReadModel struct { @@ -15,14 +15,13 @@ type ReadModel struct { 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 -func (rm *ReadModel) AppendEvents(events ...Event) *ReadModel { +func (rm *ReadModel) AppendEvents(events ...Event) { 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 func (rm *ReadModel) Reduce() error { if len(rm.Events) == 0 { diff --git a/internal/eventstore/repository/search_query.go b/internal/eventstore/repository/search_query.go index 6270fdc62b..2b315289ca 100644 --- a/internal/eventstore/repository/search_query.go +++ b/internal/eventstore/repository/search_query.go @@ -8,11 +8,12 @@ import ( // SearchQuery defines the which and how data are queried type SearchQuery struct { - Columns Columns - Limit uint64 - Desc bool - Filters [][]*Filter - Tx *sql.Tx + Columns Columns + Limit uint64 + Desc bool + Filters [][]*Filter + Tx *sql.Tx + AllowTimeTravel bool } // Columns defines which fields of the event are needed for the query diff --git a/internal/eventstore/repository/sql/crdb.go b/internal/eventstore/repository/sql/crdb.go index d78311aaa4..91b5cd06ef 100644 --- a/internal/eventstore/repository/sql/crdb.go +++ b/internal/eventstore/repository/sql/crdb.go @@ -13,6 +13,7 @@ import ( "github.com/lib/pq" "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" caos_errs "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore/repository" ) @@ -97,19 +98,19 @@ const ( ) type CRDB struct { - client *sql.DB + *database.DB } -func NewCRDB(client *sql.DB) *CRDB { +func NewCRDB(client *database.DB) *CRDB { 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. // 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 { - 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 ( 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`) 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 { 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") } - 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") } @@ -249,7 +250,7 @@ func (db *CRDB) InstanceIDs(ctx context.Context, searchQuery *repository.SearchQ } func (db *CRDB) db() *sql.DB { - return db.client + return db.DB.DB } func (db *CRDB) orderByEventSequence(desc bool) string { diff --git a/internal/eventstore/repository/sql/crdb_test.go b/internal/eventstore/repository/sql/crdb_test.go index 5bae721be7..17deaa0cea 100644 --- a/internal/eventstore/repository/sql/crdb_test.go +++ b/internal/eventstore/repository/sql/crdb_test.go @@ -437,7 +437,10 @@ func TestCRDB_Push_OneAggregate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{ + DB: testCRDBClient, + Database: new(testDB), + }, } if tt.args.uniqueDataType != "" && tt.args.uniqueDataField != "" { 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 { t.Run(tt.name, func(t *testing.T) { 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 { 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 { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{DB: testCRDBClient}, } 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 { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{ + DB: testCRDBClient, + Database: new(testDB), + }, } wg := sync.WaitGroup{} @@ -897,7 +906,10 @@ func TestCRDB_Filter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{ + DB: testCRDBClient, + Database: new(testDB), + }, } // setup initial data for query @@ -987,7 +999,10 @@ func TestCRDB_LatestSequence(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{ + DB: testCRDBClient, + Database: new(testDB), + }, } // setup initial data for query @@ -1131,7 +1146,10 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: testCRDBClient, + DB: &database.DB{ + DB: testCRDBClient, + Database: new(testDB), + }, } if err := db.Push(context.Background(), tt.args.events); err != nil { t.Errorf("CRDB.Push() error = %v", err) diff --git a/internal/eventstore/repository/sql/local_crdb_test.go b/internal/eventstore/repository/sql/local_crdb_test.go index 4e63bbee6c..50c3465b10 100644 --- a/internal/eventstore/repository/sql/local_crdb_test.go +++ b/internal/eventstore/repository/sql/local_crdb_test.go @@ -4,6 +4,7 @@ import ( "database/sql" "os" "testing" + "time" "github.com/cockroachdb/cockroach-go/v2/testserver" "github.com/zitadel/logging" @@ -53,8 +54,8 @@ func initDB(db *sql.DB) error { err := initialise.Init(db, initialise.VerifyUser(config.Username(), ""), - initialise.VerifyDatabase(config.Database()), - initialise.VerifyGrant(config.Database(), config.Username())) + initialise.VerifyDatabase(config.DatabaseName()), + initialise.VerifyGrant(config.DatabaseName(), config.Username())) if err != nil { 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) 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" } diff --git a/internal/eventstore/repository/sql/query.go b/internal/eventstore/repository/sql/query.go index 9b97014658..2457a0638b 100644 --- a/internal/eventstore/repository/sql/query.go +++ b/internal/eventstore/repository/sql/query.go @@ -10,6 +10,8 @@ import ( "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" "github.com/zitadel/zitadel/internal/eventstore/repository" ) @@ -24,6 +26,7 @@ type querier interface { instanceIDsQuery() string db() *sql.DB orderByEventSequence(desc bool) string + dialect.Database } type scan func(dest ...interface{}) error @@ -34,6 +37,11 @@ func query(ctx context.Context, criteria querier, searchQuery *repository.Search if where == "" || query == "" { 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 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) { sequence, ok := dest.(*Sequence) if !ok { diff --git a/internal/eventstore/repository/sql/query_test.go b/internal/eventstore/repository/sql/query_test.go index a1b6abc95d..396de93349 100644 --- a/internal/eventstore/repository/sql/query_test.go +++ b/internal/eventstore/repository/sql/query_test.go @@ -10,6 +10,7 @@ import ( "github.com/DATA-DOG/go-sqlmock" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore/repository" ) @@ -537,7 +538,10 @@ func Test_query_events_with_crdb(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := &CRDB{ - client: tt.fields.client, + DB: &database.DB{ + DB: tt.fields.client, + Database: new(testDB), + }, } // setup initial data for query @@ -657,6 +661,36 @@ func Test_query_events_mocked(t *testing.T) { 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", args: args{ @@ -786,9 +820,11 @@ func Test_query_events_mocked(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - crdb := &CRDB{} + crdb := &CRDB{DB: &database.DB{ + Database: new(testDB), + }} 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) diff --git a/internal/eventstore/search_query.go b/internal/eventstore/search_query.go index 08f65ce989..9acf33ea4e 100644 --- a/internal/eventstore/search_query.go +++ b/internal/eventstore/search_query.go @@ -12,14 +12,15 @@ import ( // SearchQueryBuilder represents the builder for your filter // if invalid data are set the filter will fail type SearchQueryBuilder struct { - columns repository.Columns - limit uint64 - desc bool - resourceOwner string - instanceID string - editorUser string - queries []*SearchQuery - tx *sql.Tx + columns repository.Columns + limit uint64 + desc bool + resourceOwner string + instanceID string + editorUser string + queries []*SearchQuery + tx *sql.Tx + allowTimeTravel bool } type SearchQuery struct { @@ -130,6 +131,13 @@ func (builder *SearchQueryBuilder) EditorUser(id string) *SearchQueryBuilder { 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. // All fields in the sub query are AND-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{ - Columns: builder.columns, - Limit: builder.limit, - Desc: builder.desc, - Filters: filters, - Tx: builder.tx, + Columns: builder.columns, + Limit: builder.limit, + Desc: builder.desc, + Filters: filters, + Tx: builder.tx, + AllowTimeTravel: builder.allowTimeTravel, }, nil } diff --git a/internal/eventstore/v1/eventstore.go b/internal/eventstore/v1/eventstore.go index 53d3a5a8a8..0fc311f2e4 100644 --- a/internal/eventstore/v1/eventstore.go +++ b/internal/eventstore/v1/eventstore.go @@ -2,8 +2,8 @@ package v1 import ( "context" - "database/sql" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository" z_sql "github.com/zitadel/zitadel/internal/eventstore/v1/internal/repository/sql" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -22,7 +22,7 @@ type eventstore struct { repo repository.Repository } -func Start(db *sql.DB) (Eventstore, error) { +func Start(db *database.DB) (Eventstore, error) { return &eventstore{ repo: z_sql.Start(db), }, nil diff --git a/internal/eventstore/v1/internal/repository/sql/config.go b/internal/eventstore/v1/internal/repository/sql/config.go index 08bea22d98..bef2df0de2 100644 --- a/internal/eventstore/v1/internal/repository/sql/config.go +++ b/internal/eventstore/v1/internal/repository/sql/config.go @@ -1,10 +1,10 @@ package sql import ( - "database/sql" + "github.com/zitadel/zitadel/internal/database" ) -func Start(client *sql.DB) *SQL { +func Start(client *database.DB) *SQL { return &SQL{ client: client, } diff --git a/internal/eventstore/v1/internal/repository/sql/db_mock_test.go b/internal/eventstore/v1/internal/repository/sql/db_mock_test.go index 643fd9eb4c..6c271a572e 100644 --- a/internal/eventstore/v1/internal/repository/sql/db_mock_test.go +++ b/internal/eventstore/v1/internal/repository/sql/db_mock_test.go @@ -12,7 +12,7 @@ import ( ) 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 ( @@ -172,14 +172,14 @@ func (db *dbMock) expectFilterEventsError(returnedErr error) *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). WillReturnRows(sqlmock.NewRows([]string{"max_sequence"}).AddRow(sequence)) return db } 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) return db } diff --git a/internal/eventstore/v1/internal/repository/sql/filter.go b/internal/eventstore/v1/internal/repository/sql/filter.go index ab339e00b6..0ae8bb3ae1 100644 --- a/internal/eventstore/v1/internal/repository/sql/filter.go +++ b/internal/eventstore/v1/internal/repository/sql/filter.go @@ -6,6 +6,7 @@ import ( "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" "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) { - 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) { - query, limit, values, rowScanner := buildQuery(searchQuery) +func filter(ctx context.Context, db *database.DB, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) { + query, limit, values, rowScanner := buildQuery(ctx, db, searchQuery) if query == "" { 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 { logging.New().WithError(err).Info("query failed") 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) { - query, _, values, rowScanner := buildQuery(queryFactory) + query, _, values, rowScanner := buildQuery(ctx, db.client, queryFactory) if query == "" { 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) { - query, _, values, rowScanner := buildQuery(queryFactory) + query, _, values, rowScanner := buildQuery(ctx, db.client, queryFactory) if query == "" { return nil, errors.ThrowInvalidArgument(nil, "SQL-Sfwg2", "invalid query factory") } diff --git a/internal/eventstore/v1/internal/repository/sql/filter_test.go b/internal/eventstore/v1/internal/repository/sql/filter_test.go index f5353dcc22..df352a236a 100644 --- a/internal/eventstore/v1/internal/repository/sql/filter_test.go +++ b/internal/eventstore/v1/internal/repository/sql/filter_test.go @@ -6,6 +6,7 @@ import ( "math" "testing" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" ) @@ -122,7 +123,7 @@ func TestSQL_Filter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { 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) if (err != nil) != tt.res.wantErr { @@ -217,7 +218,7 @@ func TestSQL_LatestSequence(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { 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) if (err != nil) != tt.res.wantErr { diff --git a/internal/eventstore/v1/internal/repository/sql/query.go b/internal/eventstore/v1/internal/repository/sql/query.go index 2fa6d1ff55..798cbdd417 100644 --- a/internal/eventstore/v1/internal/repository/sql/query.go +++ b/internal/eventstore/v1/internal/repository/sql/query.go @@ -1,6 +1,7 @@ package sql import ( + "context" "database/sql" "errors" "fmt" @@ -9,6 +10,8 @@ import ( "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" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" ) @@ -30,7 +33,7 @@ const ( " 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() if err != nil { 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 == "" { return "", 0, nil, nil } + + if travel := db.Timetravel(call.Took(ctx)); travel != "" { + query += travel + } query += where if searchQuery.Columns == es_models.Columns_Event { diff --git a/internal/eventstore/v1/internal/repository/sql/query_test.go b/internal/eventstore/v1/internal/repository/sql/query_test.go index e6ee3afda2..8197893b9c 100644 --- a/internal/eventstore/v1/internal/repository/sql/query_test.go +++ b/internal/eventstore/v1/internal/repository/sql/query_test.go @@ -1,6 +1,7 @@ package sql import ( + "context" "database/sql" "reflect" "testing" @@ -435,7 +436,7 @@ func Test_buildQuery(t *testing.T) { queryFactory: es_models.NewSearchQueryFactory().OrderDesc().AddQuery().AggregateTypes("user").Factory(), }, 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, 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(), }, 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, values: []interface{}{es_models.AggregateType("user"), uint64(5)}, limit: 5, @@ -458,7 +459,7 @@ func Test_buildQuery(t *testing.T) { queryFactory: es_models.NewSearchQueryFactory().Limit(5).OrderDesc().AddQuery().AggregateTypes("user").Factory(), }, 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, values: []interface{}{es_models.AggregateType("user"), uint64(5)}, limit: 5, @@ -466,8 +467,10 @@ func Test_buildQuery(t *testing.T) { }, } for _, tt := range tests { + ctx := context.Background() + db := new(testDB) 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 { 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" } diff --git a/internal/eventstore/v1/internal/repository/sql/sql.go b/internal/eventstore/v1/internal/repository/sql/sql.go index 6afa768919..3f5ecc431e 100644 --- a/internal/eventstore/v1/internal/repository/sql/sql.go +++ b/internal/eventstore/v1/internal/repository/sql/sql.go @@ -2,11 +2,12 @@ package sql import ( "context" - "database/sql" + + "github.com/zitadel/zitadel/internal/database" ) type SQL struct { - client *sql.DB + client *database.DB } func (db *SQL) Health(ctx context.Context) error { diff --git a/internal/logstore/emitters/access/database.go b/internal/logstore/emitters/access/database.go index 96d60f596d..494789cdb1 100644 --- a/internal/logstore/emitters/access/database.go +++ b/internal/logstore/emitters/access/database.go @@ -2,7 +2,6 @@ package access import ( "context" - "database/sql" "fmt" "net/http" "strings" @@ -12,7 +11,9 @@ import ( "github.com/zitadel/logging" "google.golang.org/grpc/codes" + "github.com/zitadel/zitadel/internal/api/call" zitadel_http "github.com/zitadel/zitadel/internal/api/http" + "github.com/zitadel/zitadel/internal/database" caos_errors "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/logstore" "github.com/zitadel/zitadel/internal/repository/quota" @@ -36,10 +37,10 @@ var _ logstore.UsageQuerier = (*databaseLogStorage)(nil) var _ logstore.LogCleanupper = (*databaseLogStorage)(nil) 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} } @@ -98,12 +99,11 @@ func (l *databaseLogStorage) Emit(ctx context.Context, bulk []logstore.LogRecord return nil } -// TODO: AS OF SYSTEM TIME func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) { stmt, args, err := squirrel.Select( fmt.Sprintf("count(%s)", accessInstanceIdCol), ). - From(accessLogsTable). + From(accessLogsTable + l.dbClient.Timetravel(call.Took(ctx))). Where(squirrel.And{ squirrel.Eq{accessInstanceIdCol: instanceId}, squirrel.GtOrEq{accessTimestampCol: start}, diff --git a/internal/logstore/emitters/execution/database.go b/internal/logstore/emitters/execution/database.go index 1c64829eb7..499fedd931 100644 --- a/internal/logstore/emitters/execution/database.go +++ b/internal/logstore/emitters/execution/database.go @@ -2,13 +2,14 @@ package execution import ( "context" - "database/sql" "fmt" "time" "github.com/Masterminds/squirrel" "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" "github.com/zitadel/zitadel/internal/logstore" "github.com/zitadel/zitadel/internal/repository/quota" @@ -29,10 +30,10 @@ var _ logstore.UsageQuerier = (*databaseLogStorage)(nil) var _ logstore.LogCleanupper = (*databaseLogStorage)(nil) 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} } @@ -91,12 +92,11 @@ func (l *databaseLogStorage) Emit(ctx context.Context, bulk []logstore.LogRecord return nil } -// TODO: AS OF SYSTEM TIME func (l *databaseLogStorage) QueryUsage(ctx context.Context, instanceId string, start time.Time) (uint64, error) { stmt, args, err := squirrel.Select( fmt.Sprintf("COALESCE(SUM(%s)::INT,0)", executionTookCol), ). - From(executionLogsTable). + From(executionLogsTable + l.dbClient.Timetravel(call.Took(ctx))). Where(squirrel.And{ squirrel.Eq{executionInstanceIdCol: instanceId}, squirrel.GtOrEq{executionTimestampCol: start}, diff --git a/internal/logstore/service.go b/internal/logstore/service.go index a24a7fea06..80c459dc9d 100644 --- a/internal/logstore/service.go +++ b/internal/logstore/service.go @@ -7,9 +7,12 @@ import ( "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/repository/quota" ) +const handleThresholdTimeout = time.Minute + type QuotaQuerier interface { 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) @@ -94,17 +97,29 @@ func (s *Service) Limit(ctx context.Context, instanceID string) *uint64 { return nil } + go s.handleThresholds(ctx, quota, periodStart, usage) + var remaining *uint64 if quota.Limit { r := uint64(math.Max(0, float64(quota.Amount)-float64(usage))) remaining = &r } - - notifications, err := s.quotaQuerier.GetDueQuotaNotifications(ctx, quota, periodStart, usage) - if err != nil { - return remaining - } - - err = s.usageReporter.Report(ctx, notifications) 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) +} diff --git a/internal/query/action.go b/internal/query/action.go index 9e4246ca29..5c5a786bbb 100644 --- a/internal/query/action.go +++ b/internal/query/action.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareActionsQuery() + query, scan := prepareActionsQuery(ctx, q.client) eq := sq.Eq{ 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareActionQuery() + stmt, scan := prepareActionQuery(ctx, q.client) eq := sq.Eq{ ActionColumnID.identifier(): id, ActionColumnResourceOwner.identifier(): orgID, @@ -179,7 +180,7 @@ func NewActionIDSearchQuery(id string) (SearchQuery, error) { 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( ActionColumnID.identifier(), ActionColumnCreationDate.identifier(), @@ -192,7 +193,8 @@ func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, er ActionColumnTimeout.identifier(), ActionColumnAllowedToFail.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) { actions := make([]*Action, 0) 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( ActionColumnID.identifier(), ActionColumnCreationDate.identifier(), @@ -242,7 +244,8 @@ func prepareActionQuery() (sq.SelectBuilder, func(row *sql.Row) (*Action, error) ActionColumnScript.identifier(), ActionColumnTimeout.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) { action := new(Action) err := row.Scan( diff --git a/internal/query/action_flow.go b/internal/query/action_flow.go index 56a3771d3c..ca6c999233 100644 --- a/internal/query/action_flow.go +++ b/internal/query/action_flow.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareFlowQuery(flowType) + query, scan := prepareFlowQuery(ctx, q.client, flowType) eq := sq.Eq{ FlowsTriggersColumnFlowType.identifier(): flowType, FlowsTriggersColumnResourceOwner.identifier(): orgID, @@ -95,7 +96,7 @@ func (q *Queries) GetActiveActionsByFlowAndTriggerType(ctx context.Context, flow ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareTriggerActionsQuery() + stmt, scan := prepareTriggerActionsQuery(ctx, q.client) eq := sq.Eq{ FlowsTriggersColumnFlowType.identifier(): flowType, FlowsTriggersColumnTriggerType.identifier(): triggerType, @@ -122,7 +123,7 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareFlowTypesQuery() + stmt, scan := prepareFlowTypesQuery(ctx, q.client) eq := sq.Eq{ FlowsTriggersColumnActionID.identifier(): actionID, FlowsTriggersColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -143,11 +144,11 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w 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( FlowsTriggersColumnFlowType.identifier(), ). - From(flowsTriggersTable.identifier()). + From(flowsTriggersTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]domain.FlowType, error) { 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( ActionColumnID.identifier(), ActionColumnCreationDate.identifier(), @@ -180,7 +181,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action, ActionColumnTimeout.identifier(), ). From(flowsTriggersTable.name). - LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)). + LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]*Action, error) { 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( ActionColumnID.identifier(), ActionColumnCreationDate.identifier(), @@ -232,7 +233,7 @@ func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Row FlowsTriggersColumnResourceOwner.identifier(), ). From(flowsTriggersTable.name). - LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)). + LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Flow, error) { flow := &Flow{ diff --git a/internal/query/action_flow_test.go b/internal/query/action_flow_test.go index 4f1caf8b9e..a4a9131d89 100644 --- a/internal/query/action_flow_test.go +++ b/internal/query/action_flow_test.go @@ -1,6 +1,7 @@ package query import ( + "context" "database/sql" "database/sql/driver" "errors" @@ -14,6 +15,82 @@ import ( "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) { type want struct { sqlExpectations sqlExpectation @@ -27,29 +104,12 @@ func Test_FlowPrepares(t *testing.T) { }{ { name: "prepareFlowQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { - return prepareFlowQuery(domain.FlowTypeExternalAuthentication) + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { + return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication) }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareFlowStmt), nil, nil, ), @@ -61,48 +121,13 @@ func Test_FlowPrepares(t *testing.T) { }, { name: "prepareFlowQuery one action", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { - return prepareFlowQuery(domain.FlowTypeExternalAuthentication) + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { + return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication) }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []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", - }, + regexp.QuoteMeta(prepareFlowStmt), + prepareFlowCols, [][]driver.Value{ { "action-id", @@ -150,48 +175,13 @@ func Test_FlowPrepares(t *testing.T) { }, { name: "prepareFlowQuery multiple actions", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { - return prepareFlowQuery(domain.FlowTypeExternalAuthentication) + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { + return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication) }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []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", - }, + regexp.QuoteMeta(prepareFlowStmt), + prepareFlowCols, [][]driver.Value{ { "action-id-pre", @@ -271,48 +261,13 @@ func Test_FlowPrepares(t *testing.T) { }, { name: "prepareFlowQuery no action", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { - return prepareFlowQuery(domain.FlowTypeExternalAuthentication) + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { + return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication) }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []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", - }, + regexp.QuoteMeta(prepareFlowStmt), + prepareFlowCols, [][]driver.Value{ { nil, @@ -345,29 +300,12 @@ func Test_FlowPrepares(t *testing.T) { }, { name: "prepareFlowQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { - return prepareFlowQuery(domain.FlowTypeExternalAuthentication) + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) { + return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication) }, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareFlowStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -384,18 +322,7 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareTriggerActionStmt), nil, nil, ), @@ -407,30 +334,8 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "state", - "sequence", - "name", - "script", - "allowed_to_fail", - "timeout", - }, + regexp.QuoteMeta(prepareTriggerActionStmt), + prepareTriggerActionCols, [][]driver.Value{ { "action-id", @@ -467,30 +372,8 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "state", - "sequence", - "name", - "script", - "allowed_to_fail", - "timeout", - }, + regexp.QuoteMeta(prepareTriggerActionStmt), + prepareTriggerActionCols, [][]driver.Value{ { "action-id-1", @@ -551,18 +434,7 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareTriggerActionStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -579,8 +451,7 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareFlowTypesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+ - ` FROM projections.flow_triggers2`), + regexp.QuoteMeta(prepareFlowTypeStmt), nil, nil, ), @@ -592,11 +463,8 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareFlowTypesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+ - ` FROM projections.flow_triggers2`), - []string{ - "flow_type", - }, + regexp.QuoteMeta(prepareFlowTypeStmt), + prepareFlowTypeCols, [][]driver.Value{ { domain.FlowTypeExternalAuthentication, @@ -613,11 +481,8 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareFlowTypesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+ - ` FROM projections.flow_triggers2`), - []string{ - "flow_type", - }, + regexp.QuoteMeta(prepareFlowTypeStmt), + prepareFlowTypeCols, [][]driver.Value{ { domain.FlowTypeExternalAuthentication, @@ -638,8 +503,7 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareFlowTypesQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+ - ` FROM projections.flow_triggers2`), + regexp.QuoteMeta(prepareFlowTypeStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -654,7 +518,7 @@ func Test_FlowPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/action_test.go b/internal/query/action_test.go index c75c5311b3..2dfe6e8e32 100644 --- a/internal/query/action_test.go +++ b/internal/query/action_test.go @@ -13,6 +13,60 @@ import ( 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) { type want struct { sqlExpectations sqlExpectation @@ -29,18 +83,7 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareActionsStmt), nil, nil, ), @@ -52,31 +95,8 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "action_state", - "name", - "script", - "timeout", - "allowed_to_fail", - "count", - }, + regexp.QuoteMeta(prepareActionsStmt), + prepareActionsCols, [][]driver.Value{ { "id", @@ -118,31 +138,8 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "action_state", - "name", - "script", - "timeout", - "allowed_to_fail", - "count", - }, + regexp.QuoteMeta(prepareActionsStmt), + prepareActionsCols, [][]driver.Value{ { "id-1", @@ -208,18 +205,7 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareActionsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -236,17 +222,7 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareActionStmt), nil, nil, ), @@ -264,29 +240,8 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "action_state", - "name", - "script", - "timeout", - "allowed_to_fail", - }, + regexp.QuoteMeta(prepareActionStmt), + prepareActionCols, []driver.Value{ "id", testNow, @@ -319,17 +274,7 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareActionStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -344,7 +289,7 @@ func Test_ActionPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/app.go b/internal/query/app.go index 6d1f393406..e08d25e096 100644 --- a/internal/query/app.go +++ b/internal/query/app.go @@ -10,6 +10,7 @@ import ( "github.com/zitadel/logging" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -250,7 +251,7 @@ func (q *Queries) AppByProjectAndAppID(ctx context.Context, shouldTriggerBulk bo projection.AppProjection.Trigger(ctx) } - stmt, scan := prepareAppQuery() + stmt, scan := prepareAppQuery(ctx, q.client) eq := sq.Eq{ AppColumnID.identifier(): appID, AppColumnProjectID.identifier(): projectID, @@ -272,7 +273,7 @@ func (q *Queries) AppByID(ctx context.Context, appID string, withOwnerRemoved bo ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAppQuery() + stmt, scan := prepareAppQuery(ctx, q.client) eq := sq.Eq{ AppColumnID.identifier(): appID, 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAppQuery() + stmt, scan := prepareAppQuery(ctx, q.client) eq := sq.Eq{ AppSAMLConfigColumnEntityID.identifier(): entityID, 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareProjectByAppQuery() + stmt, scan := prepareProjectByAppQuery(ctx, q.client) eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[ProjectColumnOwnerRemoved.identifier()] = false @@ -339,7 +340,7 @@ func (q *Queries) ProjectIDFromOIDCClientID(ctx context.Context, appID string, w ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareProjectIDByAppQuery() + stmt, scan := prepareProjectIDByAppQuery(ctx, q.client) eq := sq.Eq{ AppOIDCConfigColumnClientID.identifier(): appID, 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareProjectIDByAppQuery() + stmt, scan := prepareProjectIDByAppQuery(ctx, q.client) eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[AppColumnOwnerRemoved.identifier()] = false @@ -386,7 +387,7 @@ func (q *Queries) ProjectByOIDCClientID(ctx context.Context, id string, withOwne ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareProjectByAppQuery() + stmt, scan := prepareProjectByAppQuery(ctx, q.client) eq := sq.Eq{ AppOIDCConfigColumnClientID.identifier(): id, 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAppQuery() + stmt, scan := prepareAppQuery(ctx, q.client) eq := sq.Eq{ AppOIDCConfigColumnClientID.identifier(): clientID, 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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAppQuery() + stmt, scan := prepareAppQuery(ctx, q.client) eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[AppColumnOwnerRemoved.identifier()] = false @@ -452,7 +453,7 @@ func (q *Queries) SearchApps(ctx context.Context, queries *AppSearchQueries, wit ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareAppsQuery() + query, scan := prepareAppsQuery(ctx, q.client) eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[AppColumnOwnerRemoved.identifier()] = false @@ -478,7 +479,7 @@ func (q *Queries) SearchClientIDs(ctx context.Context, queries *AppSearchQueries ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareClientIDsQuery() + query, scan := prepareClientIDsQuery(ctx, q.client) eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[AppColumnOwnerRemoved.identifier()] = false @@ -503,7 +504,7 @@ func NewAppProjectIDSearchQuery(id string) (SearchQuery, error) { 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( AppColumnID.identifier(), AppColumnName.identifier(), @@ -542,7 +543,7 @@ func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) { ).From(appsTable.identifier()). LeftJoin(join(AppAPIConfigColumnAppID, 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) { 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( AppColumnProjectID.identifier(), ).From(appsTable.identifier()). LeftJoin(join(AppAPIConfigColumnAppID, 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) { err = row.Scan( &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( ProjectColumnID.identifier(), ProjectColumnCreationDate.identifier(), @@ -644,7 +645,7 @@ func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, err Join(join(AppColumnProjectID, ProjectColumnID)). LeftJoin(join(AppAPIConfigColumnAppID, 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) (*Project, error) { 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( AppColumnID.identifier(), AppColumnName.identifier(), @@ -711,7 +712,7 @@ func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) { ).From(appsTable.identifier()). LeftJoin(join(AppAPIConfigColumnAppID, 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) { 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( AppAPIConfigColumnClientID.identifier(), AppOIDCConfigColumnClientID.identifier(), ).From(appsTable.identifier()). 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) { ids := database.StringArray{} diff --git a/internal/query/app_test.go b/internal/query/app_test.go index f69ca48875..3076a6ed0c 100644 --- a/internal/query/app_test.go +++ b/internal/query/app_test.go @@ -52,7 +52,8 @@ var ( ` 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_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,` + ` projections.apps4.name,` + ` projections.apps4.project_id,` + @@ -91,17 +92,20 @@ var ( ` 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_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,` + ` projections.apps4_oidc_configs.client_id` + ` 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_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` + ` 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_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,` + ` projections.projects3.creation_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` + ` 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_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{ "id", @@ -1009,7 +1014,7 @@ func Test_AppsPrepare(t *testing.T) { } for _, tt := range tests { 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 { 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 { 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 { 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 { 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...) }) } } diff --git a/internal/query/authn_key.go b/internal/query/authn_key.go index 455a96db81..3d9341c947 100644 --- a/internal/query/authn_key.go +++ b/internal/query/authn_key.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareAuthNKeysQuery() + query, scan := prepareAuthNKeysQuery(ctx, q.client) query = queries.toQuery(query) eq := sq.Eq{ AuthNKeyColumnEnabled.identifier(): true, @@ -159,7 +160,7 @@ func (q *Queries) SearchAuthNKeysData(ctx context.Context, queries *AuthNKeySear ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareAuthNKeysDataQuery() + query, scan := prepareAuthNKeysDataQuery(ctx, q.client) query = queries.toQuery(query) eq := sq.Eq{ AuthNKeyColumnEnabled.identifier(): true, @@ -193,7 +194,7 @@ func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, i projection.AuthNKeyProjection.Trigger(ctx) } - query, scan := prepareAuthNKeyQuery() + query, scan := prepareAuthNKeyQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -218,7 +219,7 @@ func (q *Queries) GetAuthNKeyPublicKeyByIDAndIdentifier(ctx context.Context, id ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAuthNKeyPublicKeyQuery() + stmt, scan := prepareAuthNKeyPublicKeyQuery(ctx, q.client) eq := sq.And{ sq.Eq{ AuthNKeyColumnID.identifier(): id, @@ -265,7 +266,7 @@ func NewAuthNKeyObjectIDQuery(id string) (SearchQuery, error) { 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( AuthNKeyColumnID.identifier(), AuthNKeyColumnCreationDate.identifier(), @@ -275,7 +276,8 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys AuthNKeyColumnExpiration.identifier(), AuthNKeyColumnType.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) { authNKeys := make([]*AuthNKey, 0) 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( AuthNKeyColumnID.identifier(), AuthNKeyColumnCreationDate.identifier(), @@ -319,7 +321,8 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er AuthNKeyColumnSequence.identifier(), AuthNKeyColumnExpiration.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) { authNKey := new(AuthNKey) 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( 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) { var publicKey []byte 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( AuthNKeyColumnID.identifier(), AuthNKeyColumnCreationDate.identifier(), @@ -372,7 +376,8 @@ func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthN AuthNKeyColumnIdentifier.identifier(), AuthNKeyColumnPublicKey.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) { authNKeys := make([]*AuthNKeyData, 0) var count uint64 diff --git a/internal/query/authn_key_test.go b/internal/query/authn_key_test.go index 947f46aaf6..9deb9bfa4c 100644 --- a/internal/query/authn_key_test.go +++ b/internal/query/authn_key_test.go @@ -12,6 +12,80 @@ import ( 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) { type want struct { sqlExpectations sqlExpectation @@ -28,15 +102,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeysStmt), nil, nil, ), @@ -48,25 +114,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "expiration", - "type", - "count", - }, + regexp.QuoteMeta(prepareAuthNKeysStmt), + prepareAuthNKeysCols, [][]driver.Value{ { "id", @@ -102,25 +151,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "expiration", - "type", - "count", - }, + regexp.QuoteMeta(prepareAuthNKeysStmt), + prepareAuthNKeysCols, [][]driver.Value{ { "id-1", @@ -174,15 +206,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeysStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -199,17 +223,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysDataQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeysDataStmt), nil, nil, ), @@ -221,29 +235,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysDataQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "expiration", - "type", - "identifier", - "public_key", - "count", - }, + regexp.QuoteMeta(prepareAuthNKeysDataStmt), + prepareAuthNKeysDataCols, [][]driver.Value{ { "id", @@ -283,29 +276,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysDataQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "expiration", - "type", - "identifier", - "public_key", - "count", - }, + regexp.QuoteMeta(prepareAuthNKeysDataStmt), + prepareAuthNKeysDataCols, [][]driver.Value{ { "id-1", @@ -367,17 +339,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeysDataQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeysDataStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -394,14 +356,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeyStmt), nil, nil, ), @@ -419,23 +374,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "expiration", - "type", - }, + regexp.QuoteMeta(prepareAuthNKeyStmt), + prepareAuthNKeyCols, []driver.Value{ "id", testNow, @@ -462,14 +402,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareAuthNKeyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -486,8 +419,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyPublicKeyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+ - ` FROM projections.authn_keys2`), + regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt), nil, nil, ), @@ -505,11 +437,8 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyPublicKeyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+ - ` FROM projections.authn_keys2`), - []string{ - "public_key", - }, + regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt), + prepareAuthNKeyPublicKeyCols, []driver.Value{ []byte("publicKey"), }, @@ -522,8 +451,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { prepare: prepareAuthNKeyPublicKeyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+ - ` FROM projections.authn_keys2`), + regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -538,7 +466,7 @@ func Test_AuthNKeyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/certificate.go b/internal/query/certificate.go index 79a995959f..2856138804 100644 --- a/internal/query/certificate.go +++ b/internal/query/certificate.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareCertificateQuery() + query, scan := prepareCertificateQuery(ctx, q.client) if t.IsZero() { t = time.Now() } @@ -102,7 +103,7 @@ func (q *Queries) ActiveCertificates(ctx context.Context, t time.Time, usage dom 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( KeyColID.identifier(), KeyColCreationDate.identifier(), @@ -117,7 +118,7 @@ func prepareCertificateQuery() (sq.SelectBuilder, func(*sql.Rows) (*Certificates countColumn.identifier(), ).From(keyTable.identifier()). LeftJoin(join(CertificateColID, KeyColID)). - LeftJoin(join(KeyPrivateColID, KeyColID)). + LeftJoin(join(KeyPrivateColID, KeyColID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Certificates, error) { certificates := make([]Certificate, 0) diff --git a/internal/query/certificate_test.go b/internal/query/certificate_test.go index 99cc9cb742..4bd1de2be7 100644 --- a/internal/query/certificate_test.go +++ b/internal/query/certificate_test.go @@ -13,6 +13,37 @@ import ( 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) { type want struct { sqlExpectations sqlExpectation @@ -29,20 +60,7 @@ func Test_CertificatePrepares(t *testing.T) { prepare: prepareCertificateQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareCertificateStmt), nil, nil, ), @@ -60,33 +78,8 @@ func Test_CertificatePrepares(t *testing.T) { prepare: prepareCertificateQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "id", - "creation_date", - "change_date", - "sequence", - "resource_owner", - "algorithm", - "use", - "expiry", - "certificate", - "key", - "count", - }, + regexp.QuoteMeta(prepareCertificateStmt), + prepareCertificateCols, [][]driver.Value{ { "key-id", @@ -135,20 +128,7 @@ func Test_CertificatePrepares(t *testing.T) { prepare: prepareCertificateQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareCertificateStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -163,7 +143,7 @@ func Test_CertificatePrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/changes.go b/internal/query/changes.go index 77e23cfc87..43669f3d32 100644 --- a/internal/query/changes.go +++ b/internal/query/changes.go @@ -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) { - builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit) + builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit).AllowTimeTravel() if !sortAscending { builder.OrderDesc() } diff --git a/internal/query/current_sequence.go b/internal/query/current_sequence.go index ba784c6aba..ba7f278713 100644 --- a/internal/query/current_sequence.go +++ b/internal/query/current_sequence.go @@ -10,6 +10,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareCurrentSequencesQuery() + query, scan := prepareCurrentSequencesQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).ToSql() if err != nil { 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) defer func() { span.EndWithError(err) }() - query, scan := prepareLatestSequence() + query, scan := prepareLatestSequence(ctx, q.client) or := make(sq.Or, len(projections)) for i, projection := range projections { or[i] = sq.Eq{CurrentSequenceColProjectionName.identifier(): projection.name} @@ -201,11 +202,12 @@ func reset(tx *sql.Tx, tables []string, projectionName string) error { 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( CurrentSequenceColCurrentSequence.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) { seq := new(LatestSequence) 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( "max("+CurrentSequenceColCurrentSequence.identifier()+") as "+CurrentSequenceColCurrentSequence.name, "max("+CurrentSequenceColTimestamp.identifier()+") as "+CurrentSequenceColTimestamp.name, CurrentSequenceColProjectionName.identifier(), countColumn.identifier()). - From(currentSequencesTable.identifier()). + From(currentSequencesTable.identifier() + db.Timetravel(call.Took(ctx))). GroupBy(CurrentSequenceColProjectionName.identifier()). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*CurrentSequences, error) { diff --git a/internal/query/current_sequence_test.go b/internal/query/current_sequence_test.go index 204bba2803..cdd78a43c2 100644 --- a/internal/query/current_sequence_test.go +++ b/internal/query/current_sequence_test.go @@ -9,6 +9,23 @@ import ( "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) { type want struct { sqlExpectations sqlExpectation @@ -25,12 +42,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) { prepare: prepareCurrentSequencesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`+ - ` GROUP BY projections.current_sequences.projection_name`), + regexp.QuoteMeta(currentSequenceStmt), nil, nil, ), @@ -42,18 +54,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) { prepare: prepareCurrentSequencesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`+ - ` GROUP BY projections.current_sequences.projection_name`), - []string{ - "current_sequence", - "timestamp", - "projection_name", - "count", - }, + regexp.QuoteMeta(currentSequenceStmt), + currentSequenceCols, [][]driver.Value{ { uint64(20211108), @@ -81,18 +83,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) { prepare: prepareCurrentSequencesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`+ - ` GROUP BY projections.current_sequences.projection_name`), - []string{ - "current_sequence", - "timestamp", - "projection_name", - "count", - }, + regexp.QuoteMeta(currentSequenceStmt), + currentSequenceCols, [][]driver.Value{ { uint64(20211108), @@ -130,12 +122,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) { prepare: prepareCurrentSequencesQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`+ - ` GROUP BY projections.current_sequences.projection_name`), + regexp.QuoteMeta(currentSequenceStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -150,7 +137,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/custom_text.go b/internal/query/custom_text.go index 45ed7edd05..dcf9628d2b 100644 --- a/internal/query/custom_text.go +++ b/internal/query/custom_text.go @@ -13,6 +13,7 @@ import ( "sigs.k8s.io/yaml" "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/errors" "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) defer func() { span.EndWithError(err) }() - stmt, scan := prepareCustomTextsQuery() + stmt, scan := prepareCustomTextsQuery(ctx, q.client) eq := sq.Eq{ CustomTextColAggregateID.identifier(): aggregateID, CustomTextColTemplate.identifier(): template, @@ -119,7 +120,7 @@ func (q *Queries) CustomTextListByTemplate(ctx context.Context, aggregateID, tem ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareCustomTextsQuery() + stmt, scan := prepareCustomTextsQuery(ctx, q.client) eq := sq.Eq{ CustomTextColAggregateID.identifier(): aggregateID, CustomTextColTemplate.identifier(): template, @@ -228,7 +229,7 @@ func (q *Queries) readLoginTranslationFile(ctx context.Context, lang string) ([] 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( CustomTextColAggregateID.identifier(), CustomTextColSequence.identifier(), @@ -239,7 +240,8 @@ func prepareCustomTextsQuery() (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts, CustomTextColKey.identifier(), CustomTextColText.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) { customTexts := make([]*CustomText, 0) var count uint64 diff --git a/internal/query/custom_text_test.go b/internal/query/custom_text_test.go index c37f06f2c0..93a9508ba4 100644 --- a/internal/query/custom_text_test.go +++ b/internal/query/custom_text_test.go @@ -13,6 +13,31 @@ import ( 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) { type want struct { sqlExpectations sqlExpectation @@ -29,16 +54,7 @@ func Test_CustomTextPrepares(t *testing.T) { prepare: prepareCustomTextsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareCustomTextsStmt), nil, nil, ), @@ -56,27 +72,8 @@ func Test_CustomTextPrepares(t *testing.T) { prepare: prepareCustomTextsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "aggregate_id", - "sequence", - "creation_date", - "change_date", - "language", - "template", - "key", - "text", - "count", - }, + regexp.QuoteMeta(prepareCustomTextsStmt), + prepareCustomTextsCols, [][]driver.Value{ { "agg-id", @@ -114,27 +111,8 @@ func Test_CustomTextPrepares(t *testing.T) { prepare: prepareCustomTextsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "aggregate_id", - "sequence", - "creation_date", - "change_date", - "language", - "template", - "key", - "text", - "count", - }, + regexp.QuoteMeta(prepareCustomTextsStmt), + prepareCustomTextsCols, [][]driver.Value{ { "agg-id", @@ -192,16 +170,7 @@ func Test_CustomTextPrepares(t *testing.T) { prepare: prepareCustomTextsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareCustomTextsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -216,7 +185,7 @@ func Test_CustomTextPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/domain_policy.go b/internal/query/domain_policy.go index a5579ebffe..f9f5f94b75 100644 --- a/internal/query/domain_policy.go +++ b/internal/query/domain_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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()). Limit(1).ToSql() if err != nil { @@ -127,7 +128,7 @@ func (q *Queries) DefaultDomainPolicy(ctx context.Context) (_ *DomainPolicy, err ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareDomainPolicyQuery() + stmt, scan := prepareDomainPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ DomainPolicyColID.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) } -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( DomainPolicyColID.identifier(), DomainPolicyColSequence.identifier(), @@ -155,7 +156,8 @@ func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy DomainPolicyColIsDefault.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) { policy := new(DomainPolicy) err := row.Scan( diff --git a/internal/query/domain_policy_test.go b/internal/query/domain_policy_test.go index d41fb40257..5940555b28 100644 --- a/internal/query/domain_policy_test.go +++ b/internal/query/domain_policy_test.go @@ -12,6 +12,33 @@ import ( 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) { type want struct { sqlExpectations sqlExpectation @@ -28,17 +55,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { prepare: prepareDomainPolicyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareDomainPolicyStmt), nil, nil, ), @@ -56,29 +73,8 @@ func Test_DomainPolicyPrepares(t *testing.T) { prepare: prepareDomainPolicyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`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`), - []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", - }, + regexp.QuoteMeta(prepareDomainPolicyStmt), + prepareDomainPolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -111,17 +107,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { prepare: prepareDomainPolicyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareDomainPolicyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -136,7 +122,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/event.go b/internal/query/event.go index 1b5d3a6ab1..d5c4462a63 100644 --- a/internal/query/event.go +++ b/internal/query/event.go @@ -26,7 +26,7 @@ type EventEditor struct { func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder) (_ []*Event, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - events, err := q.eventstore.Filter(ctx, query) + events, err := q.eventstore.Filter(ctx, query.AllowTimeTravel()) if err != nil { return nil, err } diff --git a/internal/query/failed_events.go b/internal/query/failed_events.go index 203380e0bb..2afd28d5e4 100644 --- a/internal/query/failed_events.go +++ b/internal/query/failed_events.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" + "github.com/zitadel/zitadel/internal/api/call" "github.com/zitadel/zitadel/internal/errors" "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) { - query, scan := prepareFailedEventsQuery() + query, scan := prepareFailedEventsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).ToSql() if err != nil { 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 } -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( FailedEventsColumnProjectionName.identifier(), FailedEventsColumnFailedSequence.identifier(), @@ -131,7 +132,8 @@ func prepareFailedEventsQuery() (sq.SelectBuilder, func(*sql.Rows) (*FailedEvent FailedEventsColumnLastFailed.identifier(), FailedEventsColumnError.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) { failedEvents := make([]*FailedEvent, 0) var count uint64 diff --git a/internal/query/failed_events_test.go b/internal/query/failed_events_test.go index 495a66716f..ede972c27c 100644 --- a/internal/query/failed_events_test.go +++ b/internal/query/failed_events_test.go @@ -9,6 +9,26 @@ import ( "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) { type want struct { sqlExpectations sqlExpectation @@ -25,13 +45,7 @@ func Test_FailedEventsPrepares(t *testing.T) { prepare: prepareFailedEventsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareFailedEventsStmt), nil, nil, ), @@ -43,21 +57,8 @@ func Test_FailedEventsPrepares(t *testing.T) { prepare: prepareFailedEventsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "projection_name", - "failed_sequence", - "failure_count", - "last_failed", - "error", - "count", - }, + regexp.QuoteMeta(prepareFailedEventsStmt), + prepareFailedEventsCols, [][]driver.Value{ { "projection-name", @@ -89,21 +90,8 @@ func Test_FailedEventsPrepares(t *testing.T) { prepare: prepareFailedEventsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "projection_name", - "failed_sequence", - "failure_count", - "last_failed", - "error", - "count", - }, + regexp.QuoteMeta(prepareFailedEventsStmt), + prepareFailedEventsCols, [][]driver.Value{ { "projection-name", @@ -148,13 +136,7 @@ func Test_FailedEventsPrepares(t *testing.T) { prepare: prepareFailedEventsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareFailedEventsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -169,7 +151,7 @@ func Test_FailedEventsPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/iam_member.go b/internal/query/iam_member.go index 43905c7830..38bbe13fc5 100644 --- a/internal/query/iam_member.go +++ b/internal/query/iam_member.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareInstanceMembersQuery() + query, scan := prepareInstanceMembersQuery(ctx, q.client) eq := sq.Eq{InstanceMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addIamMemberWithoutOwnerRemoved(eq) @@ -106,7 +107,7 @@ func (q *Queries) IAMMembers(ctx context.Context, queries *IAMMembersQuery, with 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( InstanceMemberCreationDate.identifier(), InstanceMemberChangeDate.identifier(), @@ -125,7 +126,7 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, ).From(instanceMemberTable.identifier()). LeftJoin(join(HumanUserIDCol, InstanceMemberUserID)). LeftJoin(join(MachineUserIDCol, InstanceMemberUserID)). - LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID)). + LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), diff --git a/internal/query/iam_member_test.go b/internal/query/iam_member_test.go index b8942c886c..15fd2c16ad 100644 --- a/internal/query/iam_member_test.go +++ b/internal/query/iam_member_test.go @@ -34,6 +34,7 @@ var ( "ON members.user_id = projections.users8_machines.user_id AND members.instance_id = projections.users8_machines.instance_id " + "LEFT JOIN projections.login_names2 " + "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") instanceMembersColumns = []string{ "creation_date", @@ -271,7 +272,7 @@ func Test_IAMMemberPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/idp.go b/internal/query/idp.go index f0996888c3..e483755c81 100644 --- a/internal/query/idp.go +++ b/internal/query/idp.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/database" "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()}, }, } - stmt, scan := prepareIDPByIDQuery() + stmt, scan := prepareIDPByIDQuery(ctx, q.client) query, args, err := stmt.Where(where).ToSql() if err != nil { 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) defer func() { span.EndWithError(err) }() - query, scan := prepareIDPsQuery() + query, scan := prepareIDPsQuery(ctx, q.client) eq := sq.Eq{ IDPInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(), } @@ -285,7 +286,7 @@ func (q *IDPSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder { 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( IDPIDCol.identifier(), IDPResourceOwnerCol.identifier(), @@ -313,7 +314,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) { JWTIDPColEndpoint.identifier(), ).From(idpTable.identifier()). LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)). - LeftJoin(join(JWTIDPColIDPID, IDPIDCol)). + LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*IDP, error) { 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( IDPIDCol.identifier(), IDPResourceOwnerCol.identifier(), @@ -422,7 +423,7 @@ func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) { countColumn.identifier(), ).From(idpTable.identifier()). LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)). - LeftJoin(join(JWTIDPColIDPID, IDPIDCol)). + LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*IDPs, error) { idps := make([]*IDP, 0) diff --git a/internal/query/idp_login_policy_link.go b/internal/query/idp_login_policy_link.go index f6640cf3e6..d0077e7d4b 100644 --- a/internal/query/idp_login_policy_link.go +++ b/internal/query/idp_login_policy_link.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareIDPLoginPolicyLinksQuery() + query, scan := prepareIDPLoginPolicyLinksQuery(ctx, q.client) eq := sq.Eq{ IDPLoginPolicyLinkResourceOwnerCol.identifier(): resourceOwner, IDPLoginPolicyLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -109,14 +110,15 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string, 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( IDPLoginPolicyLinkIDPIDCol.identifier(), IDPNameCol.identifier(), IDPTypeCol.identifier(), countColumn.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) { links := make([]*IDPLoginPolicyLink, 0) var count uint64 diff --git a/internal/query/idp_login_policy_link_test.go b/internal/query/idp_login_policy_link_test.go index 2dfb2965a9..44d6e8d6c3 100644 --- a/internal/query/idp_login_policy_link_test.go +++ b/internal/query/idp_login_policy_link_test.go @@ -17,7 +17,8 @@ var ( ` projections.idps3.type,` + ` COUNT(*) OVER ()` + ` 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{ "idp_id", "name", @@ -115,7 +116,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/idp_template.go b/internal/query/idp_template.go index 2ca0ffe390..ef781eb0a0 100644 --- a/internal/query/idp_template.go +++ b/internal/query/idp_template.go @@ -10,6 +10,7 @@ import ( "github.com/zitadel/logging" "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/database" "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()}, }, } - stmt, scan := prepareIDPTemplateByIDQuery() + stmt, scan := prepareIDPTemplateByIDQuery(ctx, q.client) query, args, err := stmt.Where(where).ToSql() if err != nil { 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) defer func() { span.EndWithError(err) }() - query, scan := prepareIDPTemplatesQuery() + query, scan := prepareIDPTemplatesQuery(ctx, q.client) eq := sq.Eq{ IDPTemplateInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(), } @@ -485,7 +486,7 @@ func (q *IDPTemplateSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil 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( IDPTemplateIDCol.identifier(), IDPTemplateResourceOwnerCol.identifier(), @@ -553,7 +554,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)). LeftJoin(join(JWTIDCol, IDPTemplateIDCol)). LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)). - LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)). + LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*IDPTemplate, error) { 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( IDPTemplateIDCol.identifier(), IDPTemplateResourceOwnerCol.identifier(), @@ -819,7 +820,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)). LeftJoin(join(JWTIDCol, IDPTemplateIDCol)). LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)). - LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)). + LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*IDPTemplates, error) { templates := make([]*IDPTemplate, 0) diff --git a/internal/query/idp_template_test.go b/internal/query/idp_template_test.go index a70aa7ef54..b07c1841c0 100644 --- a/internal/query/idp_template_test.go +++ b/internal/query/idp_template_test.go @@ -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_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_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{ "id", "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_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_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{ "id", "resource_owner", @@ -1628,7 +1630,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/idp_test.go b/internal/query/idp_test.go index b29306c9e3..6a692ed164 100644 --- a/internal/query/idp_test.go +++ b/internal/query/idp_test.go @@ -733,7 +733,7 @@ func Test_IDPPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/idp_user_link.go b/internal/query/idp_user_link.go index bd2f3eab80..465a6a3968 100644 --- a/internal/query/idp_user_link.go +++ b/internal/query/idp_user_link.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareIDPUserLinksQuery() + query, scan := prepareIDPUserLinksQuery(ctx, q.client) eq := sq.Eq{IDPUserLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[IDPUserLinkOwnerRemovedCol.identifier()] = false @@ -126,7 +127,7 @@ func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error) 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( IDPUserLinkIDPIDCol.identifier(), IDPUserLinkUserIDCol.identifier(), @@ -137,7 +138,8 @@ func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLink IDPUserLinkResourceOwnerCol.identifier(), countColumn.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) { idps := make([]*IDPUserLink, 0) var count uint64 diff --git a/internal/query/idp_user_link_test.go b/internal/query/idp_user_link_test.go index aa7387b970..859c164cb8 100644 --- a/internal/query/idp_user_link_test.go +++ b/internal/query/idp_user_link_test.go @@ -21,7 +21,8 @@ var ( ` projections.idp_user_links3.resource_owner,` + ` COUNT(*) OVER ()` + ` 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{ "idp_id", "user_id", @@ -139,7 +140,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/instance.go b/internal/query/instance.go index 9e5ef8673e..2b4cfb1850 100644 --- a/internal/query/instance.go +++ b/internal/query/instance.go @@ -11,6 +11,7 @@ import ( "golang.org/x/text/language" "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/errors" "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) defer func() { span.EndWithError(err) }() - filter, query, scan := prepareInstancesQuery() + filter, query, scan := prepareInstancesQuery(ctx, q.client) stmt, args, err := query(queries.toQuery(filter)).ToSql() if err != nil { 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) } - stmt, scan := prepareInstanceDomainQuery(authz.GetInstance(ctx).RequestedDomain()) + stmt, scan := prepareInstanceDomainQuery(ctx, q.client, authz.GetInstance(ctx).RequestedDomain()) query, args, err := stmt.Where(sq.Eq{ InstanceColumnID.identifier(): authz.GetInstance(ctx).InstanceID(), }).ToSql() @@ -203,7 +204,7 @@ func (q *Queries) InstanceByHost(ctx context.Context, host string) (_ authz.Inst ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareAuthzInstanceQuery(host) + stmt, scan := prepareAuthzInstanceQuery(ctx, q.client, host) host = strings.Split(host, ":")[0] //remove possible port query, args, err := stmt.Where(sq.Eq{ InstanceDomainDomainCol.identifier(): host, @@ -231,7 +232,7 @@ func (q *Queries) GetDefaultLanguage(ctx context.Context) language.Tag { 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( InstanceColumnID.identifier(), InstanceColumnCreationDate.identifier(), @@ -243,7 +244,8 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta InstanceColumnConsoleAppID.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) { instance := &Instance{host: host} 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) instanceFilterIDColumn := InstanceColumnID.setTable(instanceFilterTable) instanceFilterCountColumn := InstancesFilterTableAlias + ".count" @@ -298,7 +300,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.Select InstanceDomainSequenceCol.identifier(), ).FromSelect(builder, InstancesFilterTableAlias). LeftJoin(join(InstanceColumnID, instanceFilterIDColumn)). - LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn)). + LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar) }, 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( InstanceColumnID.identifier(), InstanceColumnCreationDate.identifier(), @@ -393,7 +395,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) InstanceDomainSequenceCol.identifier(), ). From(instanceTable.identifier()). - LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)). + LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Instance, error) { 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( InstanceColumnID.identifier(), InstanceColumnCreationDate.identifier(), @@ -478,7 +480,7 @@ func prepareAuthzInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Rows) ( ). From(instanceTable.identifier()). LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)). - LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID)). + LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Instance, error) { instance := &Instance{ diff --git a/internal/query/instance_domain.go b/internal/query/instance_domain.go index ab7e217e07..6eedd3f06f 100644 --- a/internal/query/instance_domain.go +++ b/internal/query/instance_domain.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "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) defer func() { span.EndWithError(err) }() - query, scan := prepareInstanceDomainsQuery() + query, scan := prepareInstanceDomainsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query). Where(sq.Eq{ InstanceDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -77,7 +78,7 @@ func (q *Queries) SearchInstanceDomainsGlobal(ctx context.Context, queries *Inst ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareInstanceDomainsQuery() + query, scan := prepareInstanceDomainsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).ToSql() if err != nil { 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 } -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( InstanceDomainCreationDateCol.identifier(), InstanceDomainChangeDateCol.identifier(), @@ -109,7 +110,8 @@ func prepareInstanceDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instance InstanceDomainIsGeneratedCol.identifier(), InstanceDomainIsPrimaryCol.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) { domains := make([]*InstanceDomain, 0) var count uint64 diff --git a/internal/query/instance_domain_test.go b/internal/query/instance_domain_test.go index fd2acd6f10..06d8e8dc04 100644 --- a/internal/query/instance_domain_test.go +++ b/internal/query/instance_domain_test.go @@ -9,6 +9,29 @@ import ( "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) { type want struct { sqlExpectations sqlExpectation @@ -25,15 +48,7 @@ func Test_InstanceDomainPrepares(t *testing.T) { prepare: prepareInstanceDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareInstanceDomainsStmt), nil, nil, ), @@ -45,25 +60,8 @@ func Test_InstanceDomainPrepares(t *testing.T) { prepare: prepareInstanceDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "creation_date", - "change_date", - "sequence", - "domain", - "instance_id", - "is_generated", - "is_primary", - "count", - }, + regexp.QuoteMeta(prepareInstanceDomainsStmt), + prepareInstanceDomainsCols, [][]driver.Value{ { testNow, @@ -99,25 +97,8 @@ func Test_InstanceDomainPrepares(t *testing.T) { prepare: prepareInstanceDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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`), - []string{ - "creation_date", - "change_date", - "sequence", - "domain", - "instance_id", - "is_generated", - "is_primary", - "count", - }, + regexp.QuoteMeta(prepareInstanceDomainsStmt), + prepareInstanceDomainsCols, [][]driver.Value{ { testNow, @@ -171,15 +152,7 @@ func Test_InstanceDomainPrepares(t *testing.T) { prepare: prepareInstanceDomainsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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`), + regexp.QuoteMeta(prepareInstanceDomainsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -194,7 +167,7 @@ func Test_InstanceDomainPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/instance_test.go b/internal/query/instance_test.go index 552b558a47..0320631283 100644 --- a/internal/query/instance_test.go +++ b/internal/query/instance_test.go @@ -1,10 +1,12 @@ package query import ( + "context" "database/sql" "database/sql/driver" "errors" "fmt" + "reflect" "regexp" "testing" @@ -24,7 +26,8 @@ var ( ` projections.instances.console_client_id,` + ` projections.instances.console_app_id,` + ` projections.instances.default_language` + - ` FROM projections.instances` + ` FROM projections.instances` + + ` AS OF SYSTEM TIME '-1 ms'` instanceCols = []string{ "id", "creation_date", @@ -54,7 +57,8 @@ var ( ` projections.instance_domains.sequence` + ` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f` + ` LEFT JOIN projections.instances ON f.id = projections.instances.id` + - ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id` + ` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` instancesCols = []string{ "count", "id", @@ -82,16 +86,16 @@ func Test_InstancePrepares(t *testing.T) { err checkErr } tests := []struct { - name string - prepare interface{} - want want - object interface{} + name string + prepare interface{} + additionalArgs []reflect.Value + want want + object interface{} }{ { - name: "prepareInstanceQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) { - return prepareInstanceQuery("") - }, + name: "prepareInstanceQuery no result", + additionalArgs: []reflect.Value{reflect.ValueOf("")}, + prepare: prepareInstanceQuery, want: want{ sqlExpectations: mockQueries( regexp.QuoteMeta(instanceQuery), @@ -108,10 +112,9 @@ func Test_InstancePrepares(t *testing.T) { object: (*Instance)(nil), }, { - name: "prepareInstanceQuery found", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) { - return prepareInstanceQuery("") - }, + name: "prepareInstanceQuery found", + additionalArgs: []reflect.Value{reflect.ValueOf("")}, + prepare: prepareInstanceQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(instanceQuery), @@ -142,10 +145,9 @@ func Test_InstancePrepares(t *testing.T) { }, }, { - name: "prepareInstanceQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) { - return prepareInstanceQuery("") - }, + name: "prepareInstanceQuery sql err", + additionalArgs: []reflect.Value{reflect.ValueOf("")}, + prepare: prepareInstanceQuery, want: want{ sqlExpectations: mockQueryErr( regexp.QuoteMeta(instanceQuery), @@ -162,8 +164,8 @@ func Test_InstancePrepares(t *testing.T) { }, { name: "prepareInstancesQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { - filter, query, scan := prepareInstancesQuery() + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery(ctx, db) return query(filter), scan }, want: want{ @@ -177,8 +179,8 @@ func Test_InstancePrepares(t *testing.T) { }, { name: "prepareInstancesQuery one result", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { - filter, query, scan := prepareInstancesQuery() + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery(ctx, db) return query(filter), scan }, want: want{ @@ -241,8 +243,8 @@ func Test_InstancePrepares(t *testing.T) { }, { name: "prepareInstancesQuery multiple results", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { - filter, query, scan := prepareInstancesQuery() + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery(ctx, db) return query(filter), scan }, want: want{ @@ -374,8 +376,8 @@ func Test_InstancePrepares(t *testing.T) { }, { name: "prepareInstancesQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { - filter, query, scan := prepareInstancesQuery() + prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) { + filter, query, scan := prepareInstancesQuery(ctx, db) return query(filter), scan }, want: want{ @@ -395,7 +397,7 @@ func Test_InstancePrepares(t *testing.T) { } for _, tt := range tests { 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, append(defaultPrepareArgs, tt.additionalArgs...)...) }) } } diff --git a/internal/query/key.go b/internal/query/key.go index 103183e977..1c9891383c 100644 --- a/internal/query/key.go +++ b/internal/query/key.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -180,7 +181,7 @@ func (q *Queries) ActivePublicKeys(ctx context.Context, t time.Time) (_ *PublicK ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := preparePublicKeysQuery() + query, scan := preparePublicKeysQuery(ctx, q.client) if t.IsZero() { t = time.Now() } @@ -212,7 +213,7 @@ func (q *Queries) ActivePrivateSigningKey(ctx context.Context, t time.Time) (_ * ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := preparePrivateKeysQuery() + stmt, scan := preparePrivateKeysQuery(ctx, q.client) if t.IsZero() { t = time.Now() } @@ -243,7 +244,7 @@ func (q *Queries) ActivePrivateSigningKey(ctx context.Context, t time.Time) (_ * return keys, nil } -func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, error)) { +func preparePublicKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, error)) { return sq.Select( KeyColID.identifier(), KeyColCreationDate.identifier(), @@ -256,7 +257,7 @@ func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, e KeyPublicColKey.identifier(), countColumn.identifier(), ).From(keyTable.identifier()). - LeftJoin(join(KeyPublicColID, KeyColID)). + LeftJoin(join(KeyPublicColID, KeyColID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*PublicKeys, error) { keys := make([]PublicKey, 0) @@ -299,7 +300,7 @@ func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, e } } -func preparePrivateKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys, error)) { +func preparePrivateKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys, error)) { return sq.Select( KeyColID.identifier(), KeyColCreationDate.identifier(), @@ -312,7 +313,7 @@ func preparePrivateKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys, KeyPrivateColKey.identifier(), countColumn.identifier(), ).From(keyTable.identifier()). - LeftJoin(join(KeyPrivateColID, KeyColID)). + LeftJoin(join(KeyPrivateColID, KeyColID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*PrivateKeys, error) { keys := make([]PrivateKey, 0) diff --git a/internal/query/key_test.go b/internal/query/key_test.go index fee2ea552f..26ab889719 100644 --- a/internal/query/key_test.go +++ b/internal/query/key_test.go @@ -15,6 +15,48 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + preparePublicKeysStmt = `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_public.expiry,` + + ` projections.keys4_public.key,` + + ` COUNT(*) OVER ()` + + ` FROM projections.keys4` + + ` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id AND projections.keys4.instance_id = projections.keys4_public.instance_id` + + ` AS OF SYSTEM TIME '-1 ms' ` + preparePublicKeysCols = []string{ + "id", + "creation_date", + "change_date", + "sequence", + "resource_owner", + "algorithm", + "use", + "expiry", + "key", + "count", + } + + preparePrivateKeysStmt = `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_private.expiry,` + + ` projections.keys4_private.key,` + + ` COUNT(*) OVER ()` + + ` FROM projections.keys4` + + ` 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' ` +) + func Test_KeyPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -31,18 +73,7 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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_public.expiry,`+ - ` projections.keys4_public.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`), + regexp.QuoteMeta(preparePublicKeysStmt), nil, nil, ), @@ -60,30 +91,8 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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_public.expiry,`+ - ` projections.keys4_public.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`), - []string{ - "id", - "creation_date", - "change_date", - "sequence", - "resource_owner", - "algorithm", - "use", - "expiry", - "key", - "count", - }, + regexp.QuoteMeta(preparePublicKeysStmt), + preparePublicKeysCols, [][]driver.Value{ { "key-id", @@ -128,18 +137,7 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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_public.expiry,`+ - ` projections.keys4_public.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`), + regexp.QuoteMeta(preparePublicKeysStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -156,18 +154,7 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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_private.expiry,`+ - ` projections.keys4_private.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`), + regexp.QuoteMeta(preparePrivateKeysStmt), nil, nil, ), @@ -185,30 +172,8 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`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_private.expiry,`+ - ` projections.keys4_private.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`), - []string{ - "id", - "creation_date", - "change_date", - "sequence", - "resource_owner", - "algorithm", - "use", - "expiry", - "key", - "count", - }, + regexp.QuoteMeta(preparePrivateKeysStmt), + preparePublicKeysCols, [][]driver.Value{ { "key-id", @@ -255,18 +220,7 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`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_private.expiry,`+ - ` projections.keys4_private.key,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.keys4`+ - ` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`), + regexp.QuoteMeta(preparePrivateKeysStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -281,7 +235,7 @@ func Test_KeyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/label_policy.go b/internal/query/label_policy.go index 6c0293358a..731dbba2e0 100644 --- a/internal/query/label_policy.go +++ b/internal/query/label_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -45,7 +46,7 @@ func (q *Queries) ActiveLabelPolicyByOrg(ctx context.Context, orgID string, with ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareLabelPolicyQuery() + stmt, scan := prepareLabelPolicyQuery(ctx, q.client) eq := sq.Eq{ LabelPolicyColState.identifier(): domain.LabelPolicyStateActive, LabelPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -75,7 +76,7 @@ func (q *Queries) PreviewLabelPolicyByOrg(ctx context.Context, orgID string) (_ ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareLabelPolicyQuery() + stmt, scan := prepareLabelPolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ sq.Or{ @@ -105,7 +106,7 @@ func (q *Queries) DefaultActiveLabelPolicy(ctx context.Context) (_ *LabelPolicy, ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareLabelPolicyQuery() + stmt, scan := prepareLabelPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ LabelPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(), LabelPolicyColState.identifier(): domain.LabelPolicyStateActive, @@ -125,7 +126,7 @@ func (q *Queries) DefaultPreviewLabelPolicy(ctx context.Context) (_ *LabelPolicy ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareLabelPolicyQuery() + stmt, scan := prepareLabelPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ LabelPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(), LabelPolicyColState.identifier(): domain.LabelPolicyStatePreview, @@ -223,7 +224,7 @@ var ( } ) -func prepareLabelPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, error)) { +func prepareLabelPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, error)) { return sq.Select( LabelPolicyColCreationDate.identifier(), LabelPolicyColChangeDate.identifier(), @@ -252,7 +253,8 @@ func prepareLabelPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, LabelPolicyColDarkLogoURL.identifier(), LabelPolicyColDarkIconURL.identifier(), ). - From(labelPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), + From(labelPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*LabelPolicy, error) { policy := new(LabelPolicy) diff --git a/internal/query/lockout_policy.go b/internal/query/lockout_policy.go index babda3bbb8..84b0e27eed 100644 --- a/internal/query/lockout_policy.go +++ b/internal/query/lockout_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -94,7 +95,7 @@ func (q *Queries) LockoutPolicyByOrg(ctx context.Context, shouldTriggerBulk bool eq[LockoutPolicyOwnerRemoved.identifier()] = false } - stmt, scan := prepareLockoutPolicyQuery() + stmt, scan := prepareLockoutPolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ eq, @@ -117,7 +118,7 @@ func (q *Queries) DefaultLockoutPolicy(ctx context.Context) (_ *LockoutPolicy, e ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareLockoutPolicyQuery() + stmt, scan := prepareLockoutPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ LockoutColID.identifier(): authz.GetInstance(ctx).InstanceID(), LockoutColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -132,7 +133,7 @@ func (q *Queries) DefaultLockoutPolicy(ctx context.Context) (_ *LockoutPolicy, e return scan(row) } -func prepareLockoutPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LockoutPolicy, error)) { +func prepareLockoutPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LockoutPolicy, error)) { return sq.Select( LockoutColID.identifier(), LockoutColSequence.identifier(), @@ -144,7 +145,8 @@ func prepareLockoutPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LockoutPoli LockoutColIsDefault.identifier(), LockoutColState.identifier(), ). - From(lockoutTable.identifier()).PlaceholderFormat(sq.Dollar), + From(lockoutTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*LockoutPolicy, error) { policy := new(LockoutPolicy) err := row.Scan( diff --git a/internal/query/lockout_policy_test.go b/internal/query/lockout_policy_test.go index f8ebb70e25..5c1833182b 100644 --- a/internal/query/lockout_policy_test.go +++ b/internal/query/lockout_policy_test.go @@ -12,6 +12,32 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareLockoutPolicyStmt = `SELECT projections.lockout_policies2.id,` + + ` projections.lockout_policies2.sequence,` + + ` projections.lockout_policies2.creation_date,` + + ` projections.lockout_policies2.change_date,` + + ` projections.lockout_policies2.resource_owner,` + + ` projections.lockout_policies2.show_failure,` + + ` projections.lockout_policies2.max_password_attempts,` + + ` projections.lockout_policies2.is_default,` + + ` projections.lockout_policies2.state` + + ` FROM projections.lockout_policies2` + + ` AS OF SYSTEM TIME '-1 ms'` + + prepareLockoutPolicyCols = []string{ + "id", + "sequence", + "creation_date", + "change_date", + "resource_owner", + "show_failure", + "max_password_attempts", + "is_default", + "state", + } +) + func Test_LockoutPolicyPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,16 +54,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) { prepare: prepareLockoutPolicyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+ - ` projections.lockout_policies2.sequence,`+ - ` projections.lockout_policies2.creation_date,`+ - ` projections.lockout_policies2.change_date,`+ - ` projections.lockout_policies2.resource_owner,`+ - ` projections.lockout_policies2.show_failure,`+ - ` projections.lockout_policies2.max_password_attempts,`+ - ` projections.lockout_policies2.is_default,`+ - ` projections.lockout_policies2.state`+ - ` FROM projections.lockout_policies2`), + regexp.QuoteMeta(prepareLockoutPolicyStmt), nil, nil, ), @@ -55,27 +72,8 @@ func Test_LockoutPolicyPrepares(t *testing.T) { prepare: prepareLockoutPolicyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+ - ` projections.lockout_policies2.sequence,`+ - ` projections.lockout_policies2.creation_date,`+ - ` projections.lockout_policies2.change_date,`+ - ` projections.lockout_policies2.resource_owner,`+ - ` projections.lockout_policies2.show_failure,`+ - ` projections.lockout_policies2.max_password_attempts,`+ - ` projections.lockout_policies2.is_default,`+ - ` projections.lockout_policies2.state`+ - ` FROM projections.lockout_policies2`), - []string{ - "id", - "sequence", - "creation_date", - "change_date", - "resource_owner", - "show_failure", - "max_password_attempts", - "is_default", - "state", - }, + regexp.QuoteMeta(prepareLockoutPolicyStmt), + prepareLockoutPolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -106,16 +104,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) { prepare: prepareLockoutPolicyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+ - ` projections.lockout_policies2.sequence,`+ - ` projections.lockout_policies2.creation_date,`+ - ` projections.lockout_policies2.change_date,`+ - ` projections.lockout_policies2.resource_owner,`+ - ` projections.lockout_policies2.show_failure,`+ - ` projections.lockout_policies2.max_password_attempts,`+ - ` projections.lockout_policies2.is_default,`+ - ` projections.lockout_policies2.state`+ - ` FROM projections.lockout_policies2`), + regexp.QuoteMeta(prepareLockoutPolicyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -130,7 +119,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/login_policy.go b/internal/query/login_policy.go index d8c34067b7..d575a26d33 100644 --- a/internal/query/login_policy.go +++ b/internal/query/login_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -172,7 +173,7 @@ func (q *Queries) LoginPolicyByID(ctx context.Context, shouldTriggerBulk bool, o eq[LoginPolicyColumnOwnerRemoved.identifier()] = false } - query, scan := prepareLoginPolicyQuery() + query, scan := prepareLoginPolicyQuery(ctx, q.client) stmt, args, err := query.Where( sq.And{ eq, @@ -212,7 +213,7 @@ func (q *Queries) DefaultLoginPolicy(ctx context.Context) (_ *LoginPolicy, err e ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareLoginPolicyQuery() + query, scan := prepareLoginPolicyQuery(ctx, q.client) stmt, args, err := query.Where(sq.Eq{ LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(), LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -232,7 +233,7 @@ func (q *Queries) SecondFactorsByOrg(ctx context.Context, orgID string) (_ *Seco ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareLoginPolicy2FAsQuery() + query, scan := prepareLoginPolicy2FAsQuery(ctx, q.client) stmt, args, err := query.Where( sq.And{ sq.Eq{ @@ -266,7 +267,7 @@ func (q *Queries) DefaultSecondFactors(ctx context.Context) (_ *SecondFactors, e ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareLoginPolicy2FAsQuery() + query, scan := prepareLoginPolicy2FAsQuery(ctx, q.client) stmt, args, err := query.Where(sq.Eq{ LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(), LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -288,7 +289,7 @@ func (q *Queries) MultiFactorsByOrg(ctx context.Context, orgID string) (_ *Multi ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareLoginPolicyMFAsQuery() + query, scan := prepareLoginPolicyMFAsQuery(ctx, q.client) stmt, args, err := query.Where( sq.And{ sq.Eq{ @@ -322,7 +323,7 @@ func (q *Queries) DefaultMultiFactors(ctx context.Context) (_ *MultiFactors, err ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareLoginPolicyMFAsQuery() + query, scan := prepareLoginPolicyMFAsQuery(ctx, q.client) stmt, args, err := query.Where(sq.Eq{ LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(), LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -340,7 +341,7 @@ func (q *Queries) DefaultMultiFactors(ctx context.Context) (_ *MultiFactors, err return factors, err } -func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, error)) { +func prepareLoginPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, error)) { return sq.Select( LoginPolicyColumnOrgID.identifier(), LoginPolicyColumnCreationDate.identifier(), @@ -365,7 +366,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, LoginPolicyColumnMFAInitSkipLifetime.identifier(), LoginPolicyColumnSecondFactorCheckLifetime.identifier(), LoginPolicyColumnMultiFactorCheckLifetime.identifier(), - ).From(loginPolicyTable.identifier()). + ).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*LoginPolicy, error) { p := new(LoginPolicy) @@ -408,10 +409,11 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, } } -func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFactors, error)) { +func prepareLoginPolicy2FAsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecondFactors, error)) { return sq.Select( LoginPolicyColumnSecondFactors.identifier(), - ).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), + ).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SecondFactors, error) { p := new(SecondFactors) err := row.Scan( @@ -429,10 +431,11 @@ func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFac } } -func prepareLoginPolicyMFAsQuery() (sq.SelectBuilder, func(*sql.Row) (*MultiFactors, error)) { +func prepareLoginPolicyMFAsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MultiFactors, error)) { return sq.Select( LoginPolicyColumnMultiFactors.identifier(), - ).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), + ).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*MultiFactors, error) { p := new(MultiFactors) err := row.Scan( diff --git a/internal/query/login_policy_test.go b/internal/query/login_policy_test.go index fdf2230908..144545633f 100644 --- a/internal/query/login_policy_test.go +++ b/internal/query/login_policy_test.go @@ -38,7 +38,8 @@ var ( ` projections.login_policies4.mfa_init_skip_lifetime,` + ` projections.login_policies4.second_factor_check_lifetime,` + ` projections.login_policies4.multi_factor_check_lifetime` + - ` FROM projections.login_policies4` + ` FROM projections.login_policies4` + + ` AS OF SYSTEM TIME '-1 ms'` loginPolicyCols = []string{ "aggregate_id", "creation_date", @@ -64,6 +65,20 @@ var ( "second_factor_check_lifetime", "multi_factor_check_lifetime", } + + prepareLoginPolicy2FAsStmt = `SELECT projections.login_policies4.second_factors` + + ` FROM projections.login_policies4` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareLoginPolicy2FAsCols = []string{ + "second_factors", + } + + prepareLoginPolicyMFAsStmt = `SELECT projections.login_policies4.multi_factors` + + ` FROM projections.login_policies4` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareLoginPolicyMFAsCols = []string{ + "multi_factors", + } ) func Test_LoginPolicyPrepares(t *testing.T) { @@ -177,11 +192,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicy2FAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+ - ` FROM projections.login_policies4`), - []string{ - "second_factors", - }, + regexp.QuoteMeta(prepareLoginPolicy2FAsStmt), + prepareLoginPolicy2FAsCols, nil, ), err: func(err error) (error, bool) { @@ -198,11 +210,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicy2FAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+ - ` FROM projections.login_policies4`), - []string{ - "second_factors", - }, + regexp.QuoteMeta(prepareLoginPolicy2FAsStmt), + prepareLoginPolicy2FAsCols, []driver.Value{ database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, }, @@ -220,11 +229,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicy2FAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+ - ` FROM projections.login_policies4`), - []string{ - "second_factors", - }, + regexp.QuoteMeta(prepareLoginPolicy2FAsStmt), + prepareLoginPolicy2FAsCols, []driver.Value{ database.EnumArray[domain.SecondFactorType]{}, }, @@ -237,8 +243,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicy2FAsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+ - ` FROM projections.login_policies4`), + regexp.QuoteMeta(prepareLoginPolicy2FAsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -255,11 +260,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicyMFAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+ - ` FROM projections.login_policies4`), - []string{ - "multi_factors", - }, + regexp.QuoteMeta(prepareLoginPolicyMFAsStmt), + prepareLoginPolicyMFAsCols, nil, ), err: func(err error) (error, bool) { @@ -276,11 +278,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicyMFAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+ - ` FROM projections.login_policies4`), - []string{ - "multi_factors", - }, + regexp.QuoteMeta(prepareLoginPolicyMFAsStmt), + prepareLoginPolicyMFAsCols, []driver.Value{ database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, }, @@ -298,11 +297,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicyMFAsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+ - ` FROM projections.login_policies4`), - []string{ - "multi_factors", - }, + regexp.QuoteMeta(prepareLoginPolicyMFAsStmt), + prepareLoginPolicyMFAsCols, []driver.Value{ database.EnumArray[domain.MultiFactorType]{}, }, @@ -315,8 +311,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { prepare: prepareLoginPolicyMFAsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+ - ` FROM projections.login_policies4`), + regexp.QuoteMeta(prepareLoginPolicyMFAsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -331,7 +326,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/mail_template.go b/internal/query/mail_template.go index 0cabf46c09..13459a4a9a 100644 --- a/internal/query/mail_template.go +++ b/internal/query/mail_template.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -73,7 +74,7 @@ func (q *Queries) MailTemplateByOrg(ctx context.Context, orgID string, withOwner ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareMailTemplateQuery() + stmt, scan := prepareMailTemplateQuery(ctx, q.client) eq := sq.Eq{MailTemplateColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[MailTemplateColOwnerRemoved.identifier()] = false @@ -100,7 +101,7 @@ func (q *Queries) DefaultMailTemplate(ctx context.Context) (_ *MailTemplate, err ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareMailTemplateQuery() + stmt, scan := prepareMailTemplateQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ MailTemplateColAggregateID.identifier(): authz.GetInstance(ctx).InstanceID(), MailTemplateColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -115,7 +116,7 @@ func (q *Queries) DefaultMailTemplate(ctx context.Context) (_ *MailTemplate, err return scan(row) } -func prepareMailTemplateQuery() (sq.SelectBuilder, func(*sql.Row) (*MailTemplate, error)) { +func prepareMailTemplateQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MailTemplate, error)) { return sq.Select( MailTemplateColAggregateID.identifier(), MailTemplateColSequence.identifier(), @@ -125,7 +126,8 @@ func prepareMailTemplateQuery() (sq.SelectBuilder, func(*sql.Row) (*MailTemplate MailTemplateColIsDefault.identifier(), MailTemplateColState.identifier(), ). - From(mailTemplateTable.identifier()).PlaceholderFormat(sq.Dollar), + From(mailTemplateTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*MailTemplate, error) { policy := new(MailTemplate) err := row.Scan( diff --git a/internal/query/message_text.go b/internal/query/message_text.go index 0312e9e3d9..f4d3eee837 100644 --- a/internal/query/message_text.go +++ b/internal/query/message_text.go @@ -16,6 +16,7 @@ import ( "sigs.k8s.io/yaml" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -127,7 +128,7 @@ func (q *Queries) DefaultMessageText(ctx context.Context) (_ *MessageText, err e ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareMessageTextQuery() + stmt, scan := prepareMessageTextQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ MessageTextColAggregateID.identifier(): authz.GetInstance(ctx).InstanceID(), MessageTextColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -160,7 +161,7 @@ func (q *Queries) CustomMessageTextByTypeAndLanguage(ctx context.Context, aggreg ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareMessageTextQuery() + stmt, scan := prepareMessageTextQuery(ctx, q.client) eq := sq.Eq{ MessageTextColLanguage.identifier(): language, MessageTextColType.identifier(): messageType, @@ -240,7 +241,7 @@ func (q *Queries) readNotificationTextMessages(ctx context.Context, language str return contents, nil } -func prepareMessageTextQuery() (sq.SelectBuilder, func(*sql.Row) (*MessageText, error)) { +func prepareMessageTextQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MessageText, error)) { return sq.Select( MessageTextColAggregateID.identifier(), MessageTextColSequence.identifier(), @@ -257,7 +258,8 @@ func prepareMessageTextQuery() (sq.SelectBuilder, func(*sql.Row) (*MessageText, MessageTextColButtonText.identifier(), MessageTextColFooter.identifier(), ). - From(messageTextTable.identifier()).PlaceholderFormat(sq.Dollar), + From(messageTextTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*MessageText, error) { msg := new(MessageText) lang := "" diff --git a/internal/query/message_text_test.go b/internal/query/message_text_test.go index af54f6ac7d..d371a2f171 100644 --- a/internal/query/message_text_test.go +++ b/internal/query/message_text_test.go @@ -14,6 +14,41 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareMessageTextStmt = `SELECT projections.message_texts2.aggregate_id,` + + ` projections.message_texts2.sequence,` + + ` projections.message_texts2.creation_date,` + + ` projections.message_texts2.change_date,` + + ` projections.message_texts2.state,` + + ` projections.message_texts2.type,` + + ` projections.message_texts2.language,` + + ` projections.message_texts2.title,` + + ` projections.message_texts2.pre_header,` + + ` projections.message_texts2.subject,` + + ` projections.message_texts2.greeting,` + + ` projections.message_texts2.text,` + + ` projections.message_texts2.button_text,` + + ` projections.message_texts2.footer_text` + + ` FROM projections.message_texts2` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareMessgeTextCols = []string{ + "aggregate_id", + "sequence", + "creation_date", + "change_date", + "state", + "type", + "language", + "title", + "pre_header", + "subject", + "greeting", + "text", + "button_text", + "footer_text", + } +) + func Test_MessageTextPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -30,21 +65,7 @@ func Test_MessageTextPrepares(t *testing.T) { prepare: prepareMessageTextQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+ - ` projections.message_texts2.sequence,`+ - ` projections.message_texts2.creation_date,`+ - ` projections.message_texts2.change_date,`+ - ` projections.message_texts2.state,`+ - ` projections.message_texts2.type,`+ - ` projections.message_texts2.language,`+ - ` projections.message_texts2.title,`+ - ` projections.message_texts2.pre_header,`+ - ` projections.message_texts2.subject,`+ - ` projections.message_texts2.greeting,`+ - ` projections.message_texts2.text,`+ - ` projections.message_texts2.button_text,`+ - ` projections.message_texts2.footer_text`+ - ` FROM projections.message_texts2`), + regexp.QuoteMeta(prepareMessageTextStmt), nil, nil, ), @@ -62,37 +83,8 @@ func Test_MessageTextPrepares(t *testing.T) { prepare: prepareMessageTextQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+ - ` projections.message_texts2.sequence,`+ - ` projections.message_texts2.creation_date,`+ - ` projections.message_texts2.change_date,`+ - ` projections.message_texts2.state,`+ - ` projections.message_texts2.type,`+ - ` projections.message_texts2.language,`+ - ` projections.message_texts2.title,`+ - ` projections.message_texts2.pre_header,`+ - ` projections.message_texts2.subject,`+ - ` projections.message_texts2.greeting,`+ - ` projections.message_texts2.text,`+ - ` projections.message_texts2.button_text,`+ - ` projections.message_texts2.footer_text`+ - ` FROM projections.message_texts2`), - []string{ - "aggregate_id", - "sequence", - "creation_date", - "change_date", - "state", - "type", - "language", - "title", - "pre_header", - "subject", - "greeting", - "text", - "button_text", - "footer_text", - }, + regexp.QuoteMeta(prepareMessageTextStmt), + prepareMessgeTextCols, []driver.Value{ "agg-id", uint64(20211109), @@ -133,21 +125,7 @@ func Test_MessageTextPrepares(t *testing.T) { prepare: prepareMessageTextQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+ - ` projections.message_texts2.sequence,`+ - ` projections.message_texts2.creation_date,`+ - ` projections.message_texts2.change_date,`+ - ` projections.message_texts2.state,`+ - ` projections.message_texts2.type,`+ - ` projections.message_texts2.language,`+ - ` projections.message_texts2.title,`+ - ` projections.message_texts2.pre_header,`+ - ` projections.message_texts2.subject,`+ - ` projections.message_texts2.greeting,`+ - ` projections.message_texts2.text,`+ - ` projections.message_texts2.button_text,`+ - ` projections.message_texts2.footer_text`+ - ` FROM projections.message_texts2`), + regexp.QuoteMeta(prepareMessageTextStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -162,7 +140,7 @@ func Test_MessageTextPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/notification_policy.go b/internal/query/notification_policy.go index 1ae61e8fa8..e15e7c84f7 100644 --- a/internal/query/notification_policy.go +++ b/internal/query/notification_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -88,7 +89,7 @@ func (q *Queries) NotificationPolicyByOrg(ctx context.Context, shouldTriggerBulk if !withOwnerRemoved { eq[NotificationPolicyColOwnerRemoved.identifier()] = false } - stmt, scan := prepareNotificationPolicyQuery() + stmt, scan := prepareNotificationPolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ eq, @@ -116,7 +117,7 @@ func (q *Queries) DefaultNotificationPolicy(ctx context.Context, shouldTriggerBu } } - stmt, scan := prepareNotificationPolicyQuery() + stmt, scan := prepareNotificationPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ NotificationPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(), NotificationPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -131,7 +132,7 @@ func (q *Queries) DefaultNotificationPolicy(ctx context.Context, shouldTriggerBu return scan(row) } -func prepareNotificationPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*NotificationPolicy, error)) { +func prepareNotificationPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*NotificationPolicy, error)) { return sq.Select( NotificationPolicyColID.identifier(), NotificationPolicyColSequence.identifier(), @@ -142,7 +143,8 @@ func prepareNotificationPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*Notifi NotificationPolicyColIsDefault.identifier(), NotificationPolicyColState.identifier(), ). - From(notificationPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), + From(notificationPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*NotificationPolicy, error) { policy := new(NotificationPolicy) err := row.Scan( diff --git a/internal/query/notification_policy_test.go b/internal/query/notification_policy_test.go index b46b597c9a..b318531fb5 100644 --- a/internal/query/notification_policy_test.go +++ b/internal/query/notification_policy_test.go @@ -12,15 +12,28 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) -var notificationPolicyStmt = regexp.QuoteMeta(`SELECT projections.notification_policies.id,` + - ` projections.notification_policies.sequence,` + - ` projections.notification_policies.creation_date,` + - ` projections.notification_policies.change_date,` + - ` projections.notification_policies.resource_owner,` + - ` projections.notification_policies.password_change,` + - ` projections.notification_policies.is_default,` + - ` projections.notification_policies.state` + - ` FROM projections.notification_policies`) +var ( + notificationPolicyStmt = regexp.QuoteMeta(`SELECT projections.notification_policies.id,` + + ` projections.notification_policies.sequence,` + + ` projections.notification_policies.creation_date,` + + ` projections.notification_policies.change_date,` + + ` projections.notification_policies.resource_owner,` + + ` projections.notification_policies.password_change,` + + ` projections.notification_policies.is_default,` + + ` projections.notification_policies.state` + + ` FROM projections.notification_policies` + + ` AS OF SYSTEM TIME '-1 ms'`) + notificationPolicyCols = []string{ + "id", + "sequence", + "creation_date", + "change_date", + "resource_owner", + "password_change", + "is_default", + "state", + } +) func Test_NotificationPolicyPrepares(t *testing.T) { type want struct { @@ -57,16 +70,7 @@ func Test_NotificationPolicyPrepares(t *testing.T) { want: want{ sqlExpectations: mockQuery( notificationPolicyStmt, - []string{ - "id", - "sequence", - "creation_date", - "change_date", - "resource_owner", - "password_change", - "is_default", - "state", - }, + notificationPolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -110,7 +114,7 @@ func Test_NotificationPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/notification_provider.go b/internal/query/notification_provider.go index 2179629c25..bbc0c50a08 100644 --- a/internal/query/notification_provider.go +++ b/internal/query/notification_provider.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -73,7 +74,7 @@ func (q *Queries) NotificationProviderByIDAndType(ctx context.Context, aggID str ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareDebugNotificationProviderQuery() + query, scan := prepareDebugNotificationProviderQuery(ctx, q.client) stmt, args, err := query.Where( sq.And{ sq.Eq{NotificationProviderColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}, @@ -93,7 +94,7 @@ func (q *Queries) NotificationProviderByIDAndType(ctx context.Context, aggID str return scan(row) } -func prepareDebugNotificationProviderQuery() (sq.SelectBuilder, func(*sql.Row) (*DebugNotificationProvider, error)) { +func prepareDebugNotificationProviderQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*DebugNotificationProvider, error)) { return sq.Select( NotificationProviderColumnAggID.identifier(), NotificationProviderColumnCreationDate.identifier(), @@ -103,7 +104,8 @@ func prepareDebugNotificationProviderQuery() (sq.SelectBuilder, func(*sql.Row) ( NotificationProviderColumnState.identifier(), NotificationProviderColumnType.identifier(), NotificationProviderColumnCompact.identifier(), - ).From(notificationProviderTable.identifier()).PlaceholderFormat(sq.Dollar), + ).From(notificationProviderTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*DebugNotificationProvider, error) { p := new(DebugNotificationProvider) err := row.Scan( diff --git a/internal/query/notification_provider_test.go b/internal/query/notification_provider_test.go index a2ff0d3a61..2fafe45ea1 100644 --- a/internal/query/notification_provider_test.go +++ b/internal/query/notification_provider_test.go @@ -12,6 +12,29 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareNotificationProviderStmt = `SELECT projections.notification_providers.aggregate_id,` + + ` projections.notification_providers.creation_date,` + + ` projections.notification_providers.change_date,` + + ` projections.notification_providers.sequence,` + + ` projections.notification_providers.resource_owner,` + + ` projections.notification_providers.state,` + + ` projections.notification_providers.provider_type,` + + ` projections.notification_providers.compact` + + ` FROM projections.notification_providers` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareNotificationProviderCols = []string{ + "aggregate_id", + "creation_date", + "change_date", + "sequence", + "resource_owner", + "state", + "provider_type", + "compact", + } +) + func Test_NotificationProviderPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,15 +51,7 @@ func Test_NotificationProviderPrepares(t *testing.T) { prepare: prepareDebugNotificationProviderQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+ - ` projections.notification_providers.creation_date,`+ - ` projections.notification_providers.change_date,`+ - ` projections.notification_providers.sequence,`+ - ` projections.notification_providers.resource_owner,`+ - ` projections.notification_providers.state,`+ - ` projections.notification_providers.provider_type,`+ - ` projections.notification_providers.compact`+ - ` FROM projections.notification_providers`), + regexp.QuoteMeta(prepareNotificationProviderStmt), nil, nil, ), @@ -54,25 +69,8 @@ func Test_NotificationProviderPrepares(t *testing.T) { prepare: prepareDebugNotificationProviderQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+ - ` projections.notification_providers.creation_date,`+ - ` projections.notification_providers.change_date,`+ - ` projections.notification_providers.sequence,`+ - ` projections.notification_providers.resource_owner,`+ - ` projections.notification_providers.state,`+ - ` projections.notification_providers.provider_type,`+ - ` projections.notification_providers.compact`+ - ` FROM projections.notification_providers`), - []string{ - "aggregate_id", - "creation_date", - "change_date", - "sequence", - "resource_owner", - "state", - "provider_type", - "compact", - }, + regexp.QuoteMeta(prepareNotificationProviderStmt), + prepareNotificationProviderCols, []driver.Value{ "agg-id", testNow, @@ -101,15 +99,7 @@ func Test_NotificationProviderPrepares(t *testing.T) { prepare: prepareDebugNotificationProviderQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+ - ` projections.notification_providers.creation_date,`+ - ` projections.notification_providers.change_date,`+ - ` projections.notification_providers.sequence,`+ - ` projections.notification_providers.resource_owner,`+ - ` projections.notification_providers.state,`+ - ` projections.notification_providers.provider_type,`+ - ` projections.notification_providers.compact`+ - ` FROM projections.notification_providers`), + regexp.QuoteMeta(prepareNotificationProviderStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -124,7 +114,7 @@ func Test_NotificationProviderPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/oidc_settings.go b/internal/query/oidc_settings.go index aaab9b1a58..af26406cc4 100644 --- a/internal/query/oidc_settings.go +++ b/internal/query/oidc_settings.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -78,7 +79,7 @@ func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) ( ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareOIDCSettingsQuery() + stmt, scan := prepareOIDCSettingsQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ OIDCSettingsColumnAggregateID.identifier(): aggregateID, OIDCSettingsColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -91,7 +92,7 @@ func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) ( return scan(row) } -func prepareOIDCSettingsQuery() (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings, error)) { +func prepareOIDCSettingsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings, error)) { return sq.Select( OIDCSettingsColumnAggregateID.identifier(), OIDCSettingsColumnCreationDate.identifier(), @@ -102,7 +103,8 @@ func prepareOIDCSettingsQuery() (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings OIDCSettingsColumnIdTokenLifetime.identifier(), OIDCSettingsColumnRefreshTokenIdleExpiration.identifier(), OIDCSettingsColumnRefreshTokenExpiration.identifier()). - From(oidcSettingsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(oidcSettingsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*OIDCSettings, error) { oidcSettings := new(OIDCSettings) err := row.Scan( diff --git a/internal/query/oidc_settings_test.go b/internal/query/oidc_settings_test.go index 1831156081..40f544795b 100644 --- a/internal/query/oidc_settings_test.go +++ b/internal/query/oidc_settings_test.go @@ -12,6 +12,31 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareOIDCSettingsStmt = `SELECT projections.oidc_settings2.aggregate_id,` + + ` projections.oidc_settings2.creation_date,` + + ` projections.oidc_settings2.change_date,` + + ` projections.oidc_settings2.resource_owner,` + + ` projections.oidc_settings2.sequence,` + + ` projections.oidc_settings2.access_token_lifetime,` + + ` projections.oidc_settings2.id_token_lifetime,` + + ` projections.oidc_settings2.refresh_token_idle_expiration,` + + ` projections.oidc_settings2.refresh_token_expiration` + + ` FROM projections.oidc_settings2` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareOIDCSettingsCols = []string{ + "aggregate_id", + "creation_date", + "change_date", + "resource_owner", + "sequence", + "access_token_lifetime", + "id_token_lifetime", + "refresh_token_idle_expiration", + "refresh_token_expiration", + } +) + func Test_OIDCConfigsPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,16 +53,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) { prepare: prepareOIDCSettingsQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.oidc_settings2.aggregate_id,`+ - ` projections.oidc_settings2.creation_date,`+ - ` projections.oidc_settings2.change_date,`+ - ` projections.oidc_settings2.resource_owner,`+ - ` projections.oidc_settings2.sequence,`+ - ` projections.oidc_settings2.access_token_lifetime,`+ - ` projections.oidc_settings2.id_token_lifetime,`+ - ` projections.oidc_settings2.refresh_token_idle_expiration,`+ - ` projections.oidc_settings2.refresh_token_expiration`+ - ` FROM projections.oidc_settings`, + prepareOIDCSettingsStmt, nil, nil, ), @@ -55,27 +71,8 @@ func Test_OIDCConfigsPrepares(t *testing.T) { prepare: prepareOIDCSettingsQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.oidc_settings2.aggregate_id,`+ - ` projections.oidc_settings2.creation_date,`+ - ` projections.oidc_settings2.change_date,`+ - ` projections.oidc_settings2.resource_owner,`+ - ` projections.oidc_settings2.sequence,`+ - ` projections.oidc_settings2.access_token_lifetime,`+ - ` projections.oidc_settings2.id_token_lifetime,`+ - ` projections.oidc_settings2.refresh_token_idle_expiration,`+ - ` projections.oidc_settings2.refresh_token_expiration`+ - ` FROM projections.oidc_settings`), - []string{ - "aggregate_id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "access_token_lifetime", - "id_token_lifetime", - "refresh_token_idle_expiration", - "refresh_token_expiration", - }, + regexp.QuoteMeta(prepareOIDCSettingsStmt), + prepareOIDCSettingsCols, []driver.Value{ "agg-id", testNow, @@ -106,16 +103,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) { prepare: prepareOIDCSettingsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.oidc_settings2.aggregate_id,`+ - ` projections.oidc_settings2.creation_date,`+ - ` projections.oidc_settings2.change_date,`+ - ` projections.oidc_settings2.resource_owner,`+ - ` projections.oidc_settings2.sequence,`+ - ` projections.oidc_settings2.access_token_lifetime,`+ - ` projections.oidc_settings2.id_token_lifetime,`+ - ` projections.oidc_settings2.refresh_token_idle_expiration,`+ - ` projections.oidc_settings2.refresh_token_expiration`+ - ` FROM projections.oidc_settings`), + regexp.QuoteMeta(prepareOIDCSettingsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -130,7 +118,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/org.go b/internal/query/org.go index 5b91c4cf68..08931a8f8f 100644 --- a/internal/query/org.go +++ b/internal/query/org.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/api/call" domain_pkg "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -96,7 +97,7 @@ func (q *Queries) OrgByID(ctx context.Context, shouldTriggerBulk bool, id string projection.OrgProjection.Trigger(ctx) } - stmt, scan := prepareOrgQuery() + stmt, scan := prepareOrgQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ OrgColumnID.identifier(): id, OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -113,7 +114,7 @@ func (q *Queries) OrgByPrimaryDomain(ctx context.Context, domain string) (_ *Org ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareOrgQuery() + stmt, scan := prepareOrgQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ OrgColumnDomain.identifier(): domain, OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -130,7 +131,7 @@ func (q *Queries) OrgByVerifiedDomain(ctx context.Context, domain string) (_ *Or ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareOrgWithDomainsQuery() + stmt, scan := prepareOrgWithDomainsQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ OrgDomainDomainCol.identifier(): domain, OrgDomainIsVerifiedCol.identifier(): true, @@ -151,7 +152,7 @@ func (q *Queries) IsOrgUnique(ctx context.Context, name, domain string) (isUniqu if name == "" && domain == "" { return false, errors.ThrowInvalidArgument(nil, "QUERY-DGqfd", "Errors.Query.InvalidRequest") } - query, scan := prepareOrgUniqueQuery() + query, scan := prepareOrgUniqueQuery(ctx, q.client) stmt, args, err := query.Where( sq.And{ sq.Eq{ @@ -190,7 +191,7 @@ func (q *Queries) SearchOrgs(ctx context.Context, queries *OrgSearchQueries) (or ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareOrgsQuery() + query, scan := prepareOrgsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query). Where(sq.Eq{ OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -231,7 +232,7 @@ func NewOrgIDsSearchQuery(ids ...string) (SearchQuery, error) { return NewListQuery(OrgColumnID, list, ListIn) } -func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) { +func prepareOrgsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) { return sq.Select( OrgColumnID.identifier(), OrgColumnCreationDate.identifier(), @@ -242,7 +243,8 @@ func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) { OrgColumnName.identifier(), OrgColumnDomain.identifier(), countColumn.identifier()). - From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(orgsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Orgs, error) { orgs := make([]*Org, 0) var count uint64 @@ -278,7 +280,7 @@ func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) { } } -func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) { +func prepareOrgQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Org, error)) { return sq.Select( OrgColumnID.identifier(), OrgColumnCreationDate.identifier(), @@ -289,42 +291,7 @@ func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) { OrgColumnName.identifier(), OrgColumnDomain.identifier(), ). - From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar), - func(row *sql.Row) (*Org, error) { - o := new(Org) - err := row.Scan( - &o.ID, - &o.CreationDate, - &o.ChangeDate, - &o.ResourceOwner, - &o.State, - &o.Sequence, - &o.Name, - &o.Domain, - ) - if err != nil { - if errs.Is(err, sql.ErrNoRows) { - return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound") - } - return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal") - } - return o, nil - } -} - -func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) { - return sq.Select( - OrgColumnID.identifier(), - OrgColumnCreationDate.identifier(), - OrgColumnChangeDate.identifier(), - OrgColumnResourceOwner.identifier(), - OrgColumnState.identifier(), - OrgColumnSequence.identifier(), - OrgColumnName.identifier(), - OrgColumnDomain.identifier(), - ). - From(orgsTable.identifier()). - LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)). + From(orgsTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*Org, error) { o := new(Org) @@ -348,10 +315,46 @@ func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error } } -func prepareOrgUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { +func prepareOrgWithDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Org, error)) { + return sq.Select( + OrgColumnID.identifier(), + OrgColumnCreationDate.identifier(), + OrgColumnChangeDate.identifier(), + OrgColumnResourceOwner.identifier(), + OrgColumnState.identifier(), + OrgColumnSequence.identifier(), + OrgColumnName.identifier(), + OrgColumnDomain.identifier(), + ). + From(orgsTable.identifier()). + LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID) + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), + func(row *sql.Row) (*Org, error) { + o := new(Org) + err := row.Scan( + &o.ID, + &o.CreationDate, + &o.ChangeDate, + &o.ResourceOwner, + &o.State, + &o.Sequence, + &o.Name, + &o.Domain, + ) + if err != nil { + if errs.Is(err, sql.ErrNoRows) { + return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound") + } + return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal") + } + return o, nil + } +} + +func prepareOrgUniqueQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (bool, error)) { return sq.Select(uniqueColumn.identifier()). From(orgsTable.identifier()). - LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)). + LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (isUnique bool, err error) { err = row.Scan(&isUnique) diff --git a/internal/query/org_domain.go b/internal/query/org_domain.go index e9ca4edaa5..a901e2d4c6 100644 --- a/internal/query/org_domain.go +++ b/internal/query/org_domain.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -59,7 +60,7 @@ func (q *Queries) SearchOrgDomains(ctx context.Context, queries *OrgDomainSearch ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareDomainsQuery() + query, scan := prepareDomainsQuery(ctx, q.client) eq := sq.Eq{OrgDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[OrgDomainOwnerRemovedCol.identifier()] = false @@ -81,7 +82,7 @@ func (q *Queries) SearchOrgDomains(ctx context.Context, queries *OrgDomainSearch return domains, err } -func prepareDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Domains, error)) { +func prepareDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Domains, error)) { return sq.Select( OrgDomainCreationDateCol.identifier(), OrgDomainChangeDateCol.identifier(), @@ -92,7 +93,8 @@ func prepareDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Domains, error)) OrgDomainIsPrimaryCol.identifier(), OrgDomainValidationTypeCol.identifier(), countColumn.identifier(), - ).From(orgDomainsTable.identifier()).PlaceholderFormat(sq.Dollar), + ).From(orgDomainsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Domains, error) { domains := make([]*Domain, 0) var count uint64 diff --git a/internal/query/org_domain_test.go b/internal/query/org_domain_test.go index 3a4395a081..18bd817046 100644 --- a/internal/query/org_domain_test.go +++ b/internal/query/org_domain_test.go @@ -11,6 +11,31 @@ import ( "github.com/zitadel/zitadel/internal/domain" ) +var ( + prepareOrgDomainsStmt = `SELECT projections.org_domains2.creation_date,` + + ` projections.org_domains2.change_date,` + + ` projections.org_domains2.sequence,` + + ` projections.org_domains2.domain,` + + ` projections.org_domains2.org_id,` + + ` projections.org_domains2.is_verified,` + + ` projections.org_domains2.is_primary,` + + ` projections.org_domains2.validation_type,` + + ` COUNT(*) OVER ()` + + ` FROM projections.org_domains2` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareOrgDomainsCols = []string{ + "id", + "creation_date", + "change_date", + "resource_owner", + "org_state", + "sequence", + "name", + "primary_domain", + "count", + } +) + func Test_OrgDomainPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -27,16 +52,7 @@ func Test_OrgDomainPrepares(t *testing.T) { prepare: prepareDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+ - ` projections.org_domains2.change_date,`+ - ` projections.org_domains2.sequence,`+ - ` projections.org_domains2.domain,`+ - ` projections.org_domains2.org_id,`+ - ` projections.org_domains2.is_verified,`+ - ` projections.org_domains2.is_primary,`+ - ` projections.org_domains2.validation_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.org_domains2`), + regexp.QuoteMeta(prepareOrgDomainsStmt), nil, nil, ), @@ -48,27 +64,8 @@ func Test_OrgDomainPrepares(t *testing.T) { prepare: prepareDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+ - ` projections.org_domains2.change_date,`+ - ` projections.org_domains2.sequence,`+ - ` projections.org_domains2.domain,`+ - ` projections.org_domains2.org_id,`+ - ` projections.org_domains2.is_verified,`+ - ` projections.org_domains2.is_primary,`+ - ` projections.org_domains2.validation_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.org_domains2`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "org_state", - "sequence", - "name", - "primary_domain", - "count", - }, + regexp.QuoteMeta(prepareOrgDomainsStmt), + prepareOrgDomainsCols, [][]driver.Value{ { testNow, @@ -106,27 +103,8 @@ func Test_OrgDomainPrepares(t *testing.T) { prepare: prepareDomainsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+ - ` projections.org_domains2.change_date,`+ - ` projections.org_domains2.sequence,`+ - ` projections.org_domains2.domain,`+ - ` projections.org_domains2.org_id,`+ - ` projections.org_domains2.is_verified,`+ - ` projections.org_domains2.is_primary,`+ - ` projections.org_domains2.validation_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.org_domains2`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "org_state", - "sequence", - "name", - "primary_domain", - "count", - }, + regexp.QuoteMeta(prepareOrgDomainsStmt), + prepareOrgDomainsCols, [][]driver.Value{ { testNow, @@ -184,16 +162,7 @@ func Test_OrgDomainPrepares(t *testing.T) { prepare: prepareDomainsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+ - ` projections.org_domains2.change_date,`+ - ` projections.org_domains2.sequence,`+ - ` projections.org_domains2.domain,`+ - ` projections.org_domains2.org_id,`+ - ` projections.org_domains2.is_verified,`+ - ` projections.org_domains2.is_primary,`+ - ` projections.org_domains2.validation_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.org_domains2`), + regexp.QuoteMeta(prepareOrgDomainsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -208,7 +177,7 @@ func Test_OrgDomainPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/org_member.go b/internal/query/org_member.go index c203f540c9..859bbc0988 100644 --- a/internal/query/org_member.go +++ b/internal/query/org_member.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -80,7 +81,7 @@ func (q *Queries) OrgMembers(ctx context.Context, queries *OrgMembersQuery, with ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareOrgMembersQuery() + query, scan := prepareOrgMembersQuery(ctx, q.client) eq := sq.Eq{OrgMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addOrgMemberWithoutOwnerRemoved(eq) @@ -108,7 +109,7 @@ func (q *Queries) OrgMembers(ctx context.Context, queries *OrgMembersQuery, with return members, err } -func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { +func prepareOrgMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { return sq.Select( OrgMemberCreationDate.identifier(), OrgMemberChangeDate.identifier(), @@ -127,7 +128,7 @@ func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, erro ).From(orgMemberTable.identifier()). LeftJoin(join(HumanUserIDCol, OrgMemberUserID)). LeftJoin(join(MachineUserIDCol, OrgMemberUserID)). - LeftJoin(join(LoginNameUserIDCol, OrgMemberUserID)). + LeftJoin(join(LoginNameUserIDCol, OrgMemberUserID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), diff --git a/internal/query/org_member_test.go b/internal/query/org_member_test.go index 89b947fc80..c8cfd7e3e4 100644 --- a/internal/query/org_member_test.go +++ b/internal/query/org_member_test.go @@ -37,6 +37,7 @@ var ( "LEFT JOIN projections.login_names2 " + "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") orgMembersColumns = []string{ "creation_date", @@ -274,7 +275,7 @@ func Test_OrgMemberPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/org_metadata.go b/internal/query/org_metadata.go index 77bb9e5739..c22bd6a71b 100644 --- a/internal/query/org_metadata.go +++ b/internal/query/org_metadata.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -84,7 +85,7 @@ func (q *Queries) GetOrgMetadataByKey(ctx context.Context, shouldTriggerBulk boo projection.OrgMetadataProjection.Trigger(ctx) } - query, scan := prepareOrgMetadataQuery() + query, scan := prepareOrgMetadataQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -119,7 +120,7 @@ func (q *Queries) SearchOrgMetadata(ctx context.Context, shouldTriggerBulk bool, if !withOwnerRemoved { eq[OrgMetadataOwnerRemovedCol.identifier()] = false } - query, scan := prepareOrgMetadataListQuery() + query, scan := prepareOrgMetadataListQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).Where(eq).ToSql() if err != nil { return nil, errors.ThrowInternal(err, "QUERY-Egbld", "Errors.Query.SQLStatment") @@ -162,7 +163,7 @@ func NewOrgMetadataKeySearchQuery(value string, comparison TextComparison) (Sear return NewTextQuery(OrgMetadataKeyCol, value, comparison) } -func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, error)) { +func prepareOrgMetadataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, error)) { return sq.Select( OrgMetadataCreationDateCol.identifier(), OrgMetadataChangeDateCol.identifier(), @@ -171,7 +172,7 @@ func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, OrgMetadataKeyCol.identifier(), OrgMetadataValueCol.identifier(), ). - From(orgMetadataTable.identifier()). + From(orgMetadataTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*OrgMetadata, error) { m := new(OrgMetadata) @@ -194,7 +195,7 @@ func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, } } -func prepareOrgMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*OrgMetadataList, error)) { +func prepareOrgMetadataListQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*OrgMetadataList, error)) { return sq.Select( OrgMetadataCreationDateCol.identifier(), OrgMetadataChangeDateCol.identifier(), @@ -203,7 +204,7 @@ func prepareOrgMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*OrgMetad OrgMetadataKeyCol.identifier(), OrgMetadataValueCol.identifier(), countColumn.identifier()). - From(orgMetadataTable.identifier()). + From(orgMetadataTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*OrgMetadataList, error) { metadata := make([]*OrgMetadata, 0) diff --git a/internal/query/org_metadata_test.go b/internal/query/org_metadata_test.go index 78bb48a176..4bfee48412 100644 --- a/internal/query/org_metadata_test.go +++ b/internal/query/org_metadata_test.go @@ -18,7 +18,8 @@ var ( ` projections.org_metadata2.sequence,` + ` projections.org_metadata2.key,` + ` projections.org_metadata2.value` + - ` FROM projections.org_metadata2` + ` FROM projections.org_metadata2` + + ` AS OF SYSTEM TIME '-1 ms'` orgMetadataCols = []string{ "creation_date", "change_date", @@ -34,7 +35,8 @@ var ( ` projections.org_metadata2.key,` + ` projections.org_metadata2.value,` + ` COUNT(*) OVER ()` + - ` FROM projections.org_metadata2` + ` FROM projections.org_metadata2` + + ` AS OF SYSTEM TIME '-1 ms'` orgMetadataListCols = []string{ "creation_date", "change_date", @@ -242,7 +244,7 @@ func Test_OrgMetadataPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/org_test.go b/internal/query/org_test.go index 93acdc1555..194c7bd13e 100644 --- a/internal/query/org_test.go +++ b/internal/query/org_test.go @@ -11,13 +11,66 @@ import ( "github.com/DATA-DOG/go-sqlmock" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" ) var ( - orgUniqueQuery = "SELECT COUNT(*) = 0 FROM projections.orgs LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id WHERE (projections.org_domains2.is_verified = $1 AND projections.orgs.instance_id = $2 AND (projections.org_domains2.domain ILIKE $3 OR projections.orgs.name ILIKE $4) AND projections.orgs.org_state <> $5)" + orgUniqueQuery = "SELECT COUNT(*) = 0 FROM projections.orgs LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id AS OF SYSTEM TIME '-1 ms' WHERE (projections.org_domains2.is_verified = $1 AND projections.orgs.instance_id = $2 AND (projections.org_domains2.domain ILIKE $3 OR projections.orgs.name ILIKE $4) AND projections.orgs.org_state <> $5)" orgUniqueCols = []string{"is_unique"} + + prepareOrgsQueryStmt = `SELECT projections.orgs.id,` + + ` projections.orgs.creation_date,` + + ` projections.orgs.change_date,` + + ` projections.orgs.resource_owner,` + + ` projections.orgs.org_state,` + + ` projections.orgs.sequence,` + + ` projections.orgs.name,` + + ` projections.orgs.primary_domain,` + + ` COUNT(*) OVER ()` + + ` FROM projections.orgs` + + ` AS OF SYSTEM TIME '-1 ms' ` + prepareOrgsQueryCols = []string{ + "id", + "creation_date", + "change_date", + "resource_owner", + "org_state", + "sequence", + "name", + "primary_domain", + "count", + } + + prepareOrgQueryStmt = `SELECT projections.orgs.id,` + + ` projections.orgs.creation_date,` + + ` projections.orgs.change_date,` + + ` projections.orgs.resource_owner,` + + ` projections.orgs.org_state,` + + ` projections.orgs.sequence,` + + ` projections.orgs.name,` + + ` projections.orgs.primary_domain` + + ` FROM projections.orgs` + + ` AS OF SYSTEM TIME '-1 ms' ` + prepareOrgQueryCols = []string{ + "id", + "creation_date", + "change_date", + "resource_owner", + "org_state", + "sequence", + "name", + "primary_domain", + } + + prepareOrgUniqueStmt = `SELECT COUNT(*) = 0` + + ` FROM projections.orgs` + + ` LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id` + + ` AS OF SYSTEM TIME '-1 ms' ` + prepareOrgUniqueCols = []string{ + "count", + } ) func Test_OrgPrepares(t *testing.T) { @@ -36,16 +89,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgsQueryStmt), nil, nil, ), @@ -57,27 +101,8 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.orgs`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "org_state", - "sequence", - "name", - "primary_domain", - "count", - }, + regexp.QuoteMeta(prepareOrgsQueryStmt), + prepareOrgsQueryCols, [][]driver.Value{ { "id", @@ -115,27 +140,8 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.orgs`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "org_state", - "sequence", - "name", - "primary_domain", - "count", - }, + regexp.QuoteMeta(prepareOrgsQueryStmt), + prepareOrgsQueryCols, [][]driver.Value{ { "id-1", @@ -193,16 +199,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgsQueryStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -219,15 +216,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgQueryStmt), nil, nil, ), @@ -245,25 +234,8 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain`+ - ` FROM projections.orgs`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "org_state", - "sequence", - "name", - "primary_domain", - }, + regexp.QuoteMeta(prepareOrgQueryStmt), + prepareOrgQueryCols, []driver.Value{ "id", testNow, @@ -292,15 +264,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.orgs.id,`+ - ` projections.orgs.creation_date,`+ - ` projections.orgs.change_date,`+ - ` projections.orgs.resource_owner,`+ - ` projections.orgs.org_state,`+ - ` projections.orgs.sequence,`+ - ` projections.orgs.name,`+ - ` projections.orgs.primary_domain`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgQueryStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -317,8 +281,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgUniqueQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT COUNT(*) = 0`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgUniqueStmt), nil, nil, ), @@ -336,11 +299,8 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgUniqueQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT COUNT(*) = 0`+ - ` FROM projections.orgs`), - []string{ - "count", - }, + regexp.QuoteMeta(prepareOrgUniqueStmt), + prepareOrgUniqueCols, []driver.Value{ 1, }, @@ -353,8 +313,7 @@ func Test_OrgPrepares(t *testing.T) { prepare: prepareOrgUniqueQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT COUNT(*) = 0`+ - ` FROM projections.orgs`), + regexp.QuoteMeta(prepareOrgUniqueStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -369,7 +328,7 @@ func Test_OrgPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } @@ -456,7 +415,10 @@ func TestQueries_IsOrgUnique(t *testing.T) { t.Run(tt.name, func(t *testing.T) { q := &Queries{ - client: client, + client: &database.DB{ + DB: client, + Database: new(prepareDB), + }, } gotIsUnique, err := q.IsOrgUnique(context.Background(), tt.args.name, tt.args.domain) diff --git a/internal/query/password_age_policy.go b/internal/query/password_age_policy.go index 522d761507..2de71235af 100644 --- a/internal/query/password_age_policy.go +++ b/internal/query/password_age_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -91,7 +92,7 @@ func (q *Queries) PasswordAgePolicyByOrg(ctx context.Context, shouldTriggerBulk if !withOwnerRemoved { eq[PasswordAgeColOwnerRemoved.identifier()] = false } - stmt, scan := preparePasswordAgePolicyQuery() + stmt, scan := preparePasswordAgePolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ eq, @@ -118,7 +119,7 @@ func (q *Queries) DefaultPasswordAgePolicy(ctx context.Context, shouldTriggerBul projection.PasswordAgeProjection.Trigger(ctx) } - stmt, scan := preparePasswordAgePolicyQuery() + stmt, scan := preparePasswordAgePolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ PasswordAgeColID.identifier(): authz.GetInstance(ctx).InstanceID(), }). @@ -132,7 +133,7 @@ func (q *Queries) DefaultPasswordAgePolicy(ctx context.Context, shouldTriggerBul return scan(row) } -func preparePasswordAgePolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PasswordAgePolicy, error)) { +func preparePasswordAgePolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PasswordAgePolicy, error)) { return sq.Select( PasswordAgeColID.identifier(), PasswordAgeColSequence.identifier(), @@ -144,7 +145,8 @@ func preparePasswordAgePolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*Passwor PasswordAgeColIsDefault.identifier(), PasswordAgeColState.identifier(), ). - From(passwordAgeTable.identifier()).PlaceholderFormat(sq.Dollar), + From(passwordAgeTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*PasswordAgePolicy, error) { policy := new(PasswordAgePolicy) err := row.Scan( diff --git a/internal/query/password_age_policy_test.go b/internal/query/password_age_policy_test.go index f11a78f4b1..15fbfe5935 100644 --- a/internal/query/password_age_policy_test.go +++ b/internal/query/password_age_policy_test.go @@ -12,6 +12,31 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + preparePasswordAgePolicyStmt = `SELECT projections.password_age_policies2.id,` + + ` projections.password_age_policies2.sequence,` + + ` projections.password_age_policies2.creation_date,` + + ` projections.password_age_policies2.change_date,` + + ` projections.password_age_policies2.resource_owner,` + + ` projections.password_age_policies2.expire_warn_days,` + + ` projections.password_age_policies2.max_age_days,` + + ` projections.password_age_policies2.is_default,` + + ` projections.password_age_policies2.state` + + ` FROM projections.password_age_policies2` + + ` AS OF SYSTEM TIME '-1 ms'` + preparePasswordAgePolicyCols = []string{ + "id", + "sequence", + "creation_date", + "change_date", + "resource_owner", + "expire_warn_days", + "max_age_days", + "is_default", + "state", + } +) + func Test_PasswordAgePolicyPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,16 +53,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) { prepare: preparePasswordAgePolicyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+ - ` projections.password_age_policies2.sequence,`+ - ` projections.password_age_policies2.creation_date,`+ - ` projections.password_age_policies2.change_date,`+ - ` projections.password_age_policies2.resource_owner,`+ - ` projections.password_age_policies2.expire_warn_days,`+ - ` projections.password_age_policies2.max_age_days,`+ - ` projections.password_age_policies2.is_default,`+ - ` projections.password_age_policies2.state`+ - ` FROM projections.password_age_policies2`), + regexp.QuoteMeta(preparePasswordAgePolicyStmt), nil, nil, ), @@ -55,27 +71,8 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) { prepare: preparePasswordAgePolicyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+ - ` projections.password_age_policies2.sequence,`+ - ` projections.password_age_policies2.creation_date,`+ - ` projections.password_age_policies2.change_date,`+ - ` projections.password_age_policies2.resource_owner,`+ - ` projections.password_age_policies2.expire_warn_days,`+ - ` projections.password_age_policies2.max_age_days,`+ - ` projections.password_age_policies2.is_default,`+ - ` projections.password_age_policies2.state`+ - ` FROM projections.password_age_policies2`), - []string{ - "id", - "sequence", - "creation_date", - "change_date", - "resource_owner", - "expire_warn_days", - "max_age_days", - "is_default", - "state", - }, + regexp.QuoteMeta(preparePasswordAgePolicyStmt), + preparePasswordAgePolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -106,16 +103,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) { prepare: preparePasswordAgePolicyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+ - ` projections.password_age_policies2.sequence,`+ - ` projections.password_age_policies2.creation_date,`+ - ` projections.password_age_policies2.change_date,`+ - ` projections.password_age_policies2.resource_owner,`+ - ` projections.password_age_policies2.expire_warn_days,`+ - ` projections.password_age_policies2.max_age_days,`+ - ` projections.password_age_policies2.is_default,`+ - ` projections.password_age_policies2.state`+ - ` FROM projections.password_age_policies2`), + regexp.QuoteMeta(preparePasswordAgePolicyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -130,7 +118,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/password_complexity_policy.go b/internal/query/password_complexity_policy.go index e952332c08..4877f0159c 100644 --- a/internal/query/password_complexity_policy.go +++ b/internal/query/password_complexity_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -43,7 +44,7 @@ func (q *Queries) PasswordComplexityPolicyByOrg(ctx context.Context, shouldTrigg if !withOwnerRemoved { eq[PasswordComplexityColOwnerRemoved.identifier()] = false } - stmt, scan := preparePasswordComplexityPolicyQuery() + stmt, scan := preparePasswordComplexityPolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ eq, @@ -70,7 +71,7 @@ func (q *Queries) DefaultPasswordComplexityPolicy(ctx context.Context, shouldTri projection.PasswordComplexityProjection.Trigger(ctx) } - stmt, scan := preparePasswordComplexityPolicyQuery() + stmt, scan := preparePasswordComplexityPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ PasswordComplexityColID.identifier(): authz.GetInstance(ctx).InstanceID(), PasswordComplexityColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -148,7 +149,7 @@ var ( } ) -func preparePasswordComplexityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PasswordComplexityPolicy, error)) { +func preparePasswordComplexityPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PasswordComplexityPolicy, error)) { return sq.Select( PasswordComplexityColID.identifier(), PasswordComplexityColSequence.identifier(), @@ -163,7 +164,8 @@ func preparePasswordComplexityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (* PasswordComplexityColIsDefault.identifier(), PasswordComplexityColState.identifier(), ). - From(passwordComplexityTable.identifier()).PlaceholderFormat(sq.Dollar), + From(passwordComplexityTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*PasswordComplexityPolicy, error) { policy := new(PasswordComplexityPolicy) err := row.Scan( diff --git a/internal/query/password_complexity_policy_test.go b/internal/query/password_complexity_policy_test.go index 6071d6617b..7629940fc1 100644 --- a/internal/query/password_complexity_policy_test.go +++ b/internal/query/password_complexity_policy_test.go @@ -12,6 +12,37 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + preparePasswordComplexityPolicyStmt = `SELECT projections.password_complexity_policies2.id,` + + ` projections.password_complexity_policies2.sequence,` + + ` projections.password_complexity_policies2.creation_date,` + + ` projections.password_complexity_policies2.change_date,` + + ` projections.password_complexity_policies2.resource_owner,` + + ` projections.password_complexity_policies2.min_length,` + + ` projections.password_complexity_policies2.has_lowercase,` + + ` projections.password_complexity_policies2.has_uppercase,` + + ` projections.password_complexity_policies2.has_number,` + + ` projections.password_complexity_policies2.has_symbol,` + + ` projections.password_complexity_policies2.is_default,` + + ` projections.password_complexity_policies2.state` + + ` FROM projections.password_complexity_policies2` + + ` AS OF SYSTEM TIME '-1 ms'` + preparePasswordComplexityPolicyCols = []string{ + "id", + "sequence", + "creation_date", + "change_date", + "resource_owner", + "min_length", + "has_lowercase", + "has_uppercase", + "has_number", + "has_symbol", + "is_default", + "state", + } +) + func Test_PasswordComplexityPolicyPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,19 +59,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) { prepare: preparePasswordComplexityPolicyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+ - ` projections.password_complexity_policies2.sequence,`+ - ` projections.password_complexity_policies2.creation_date,`+ - ` projections.password_complexity_policies2.change_date,`+ - ` projections.password_complexity_policies2.resource_owner,`+ - ` projections.password_complexity_policies2.min_length,`+ - ` projections.password_complexity_policies2.has_lowercase,`+ - ` projections.password_complexity_policies2.has_uppercase,`+ - ` projections.password_complexity_policies2.has_number,`+ - ` projections.password_complexity_policies2.has_symbol,`+ - ` projections.password_complexity_policies2.is_default,`+ - ` projections.password_complexity_policies2.state`+ - ` FROM projections.password_complexity_policies2`), + regexp.QuoteMeta(preparePasswordComplexityPolicyStmt), nil, nil, ), @@ -58,33 +77,8 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) { prepare: preparePasswordComplexityPolicyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+ - ` projections.password_complexity_policies2.sequence,`+ - ` projections.password_complexity_policies2.creation_date,`+ - ` projections.password_complexity_policies2.change_date,`+ - ` projections.password_complexity_policies2.resource_owner,`+ - ` projections.password_complexity_policies2.min_length,`+ - ` projections.password_complexity_policies2.has_lowercase,`+ - ` projections.password_complexity_policies2.has_uppercase,`+ - ` projections.password_complexity_policies2.has_number,`+ - ` projections.password_complexity_policies2.has_symbol,`+ - ` projections.password_complexity_policies2.is_default,`+ - ` projections.password_complexity_policies2.state`+ - ` FROM projections.password_complexity_policies2`), - []string{ - "id", - "sequence", - "creation_date", - "change_date", - "resource_owner", - "min_length", - "has_lowercase", - "has_uppercase", - "has_number", - "has_symbol", - "is_default", - "state", - }, + regexp.QuoteMeta(preparePasswordComplexityPolicyStmt), + preparePasswordComplexityPolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -121,19 +115,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) { prepare: preparePasswordComplexityPolicyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+ - ` projections.password_complexity_policies2.sequence,`+ - ` projections.password_complexity_policies2.creation_date,`+ - ` projections.password_complexity_policies2.change_date,`+ - ` projections.password_complexity_policies2.resource_owner,`+ - ` projections.password_complexity_policies2.min_length,`+ - ` projections.password_complexity_policies2.has_lowercase,`+ - ` projections.password_complexity_policies2.has_uppercase,`+ - ` projections.password_complexity_policies2.has_number,`+ - ` projections.password_complexity_policies2.has_symbol,`+ - ` projections.password_complexity_policies2.is_default,`+ - ` projections.password_complexity_policies2.state`+ - ` FROM projections.password_complexity_policies2`), + regexp.QuoteMeta(preparePasswordComplexityPolicyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -148,7 +130,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/prepare_test.go b/internal/query/prepare_test.go index 439712662c..db309805ca 100644 --- a/internal/query/prepare_test.go +++ b/internal/query/prepare_test.go @@ -1,6 +1,7 @@ package query import ( + "context" "database/sql" "database/sql/driver" "errors" @@ -19,14 +20,14 @@ var ( testNow = time.Now() ) -//assertPrepare checks if the prepare func executes the correct sql query and returns the correct object -//prepareFunc must be of type +// assertPrepare checks if the prepare func executes the correct sql query and returns the correct object +// prepareFunc must be of type // func() (sq.SelectBuilder, func(*sql.Rows) (*struct, error)) // or // func() (sq.SelectBuilder, func(*sql.Row) (*struct, error)) -//expectedObject represents the return value of scan -//sqlExpectation represents the query executed on the database -func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr) bool { +// expectedObject represents the return value of scan +// sqlExpectation represents the query executed on the database +func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr, prepareArgs ...reflect.Value) bool { t.Helper() client, mock, err := sqlmock.New() @@ -36,7 +37,7 @@ func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExp mock = sqlExpectation(mock) - builder, scan, err := execPrepare(prepareFunc) + builder, scan, err := execPrepare(prepareFunc, prepareArgs) if err != nil { t.Error(err) return false @@ -177,12 +178,12 @@ func validateScan(scanType reflect.Type) error { return nil } -func execPrepare(prepare interface{}) (builder sq.SelectBuilder, scan interface{}, err error) { +func execPrepare(prepare interface{}, args []reflect.Value) (builder sq.SelectBuilder, scan interface{}, err error) { prepareVal := reflect.ValueOf(prepare) if err := validatePrepare(prepareVal.Type()); err != nil { return sq.SelectBuilder{}, nil, err } - res := prepareVal.Call([]reflect.Value{}) + res := prepareVal.Call(args) return res[0].Interface().(sq.SelectBuilder), res[1].Interface(), nil } @@ -191,7 +192,7 @@ func validatePrepare(prepareType reflect.Type) error { if prepareType.Kind() != reflect.Func { return errors.New("prepare is not a function") } - if prepareType.NumIn() != 0 { + if prepareType.NumIn() < 2 { return fmt.Errorf("prepare: invalid number of inputs: want: 0 got %d", prepareType.NumIn()) } if prepareType.NumOut() != 2 { @@ -297,7 +298,7 @@ func TestValidatePrepare(t *testing.T) { }, { name: "correct", - t: reflect.TypeOf(func() (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) { + t: reflect.TypeOf(func(context.Context, prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) { log.Fatal("should not be executed") return sq.SelectBuilder{}, nil }), @@ -313,3 +314,15 @@ func TestValidatePrepare(t *testing.T) { }) } } + +type prepareDB struct{} + +func (_ *prepareDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " } + +var defaultPrepareArgs = []reflect.Value{reflect.ValueOf(context.Background()), reflect.ValueOf(new(prepareDB))} + +func (*prepareDB) DatabaseName() string { return "db" } + +func (*prepareDB) Username() string { return "user" } + +func (*prepareDB) Type() string { return "type" } diff --git a/internal/query/privacy_policy.go b/internal/query/privacy_policy.go index 83be590f15..0cbfe9f287 100644 --- a/internal/query/privacy_policy.go +++ b/internal/query/privacy_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -96,7 +97,7 @@ func (q *Queries) PrivacyPolicyByOrg(ctx context.Context, shouldTriggerBulk bool if !withOwnerRemoved { eq[PrivacyColOwnerRemoved.identifier()] = false } - stmt, scan := preparePrivacyPolicyQuery() + stmt, scan := preparePrivacyPolicyQuery(ctx, q.client) query, args, err := stmt.Where( sq.And{ eq, @@ -122,7 +123,7 @@ func (q *Queries) DefaultPrivacyPolicy(ctx context.Context, shouldTriggerBulk bo projection.PrivacyPolicyProjection.Trigger(ctx) } - stmt, scan := preparePrivacyPolicyQuery() + stmt, scan := preparePrivacyPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ PrivacyColID.identifier(): authz.GetInstance(ctx).InstanceID(), PrivacyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -137,7 +138,7 @@ func (q *Queries) DefaultPrivacyPolicy(ctx context.Context, shouldTriggerBulk bo return scan(row) } -func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPolicy, error)) { +func preparePrivacyPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PrivacyPolicy, error)) { return sq.Select( PrivacyColID.identifier(), PrivacyColSequence.identifier(), @@ -150,7 +151,8 @@ func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPoli PrivacyColIsDefault.identifier(), PrivacyColState.identifier(), ). - From(privacyTable.identifier()).PlaceholderFormat(sq.Dollar), + From(privacyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*PrivacyPolicy, error) { policy := new(PrivacyPolicy) err := row.Scan( diff --git a/internal/query/privacy_policy_test.go b/internal/query/privacy_policy_test.go index 9aa801c854..b9966c2b7d 100644 --- a/internal/query/privacy_policy_test.go +++ b/internal/query/privacy_policy_test.go @@ -12,6 +12,33 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + preparePrivacyPolicyStmt = `SELECT projections.privacy_policies2.id,` + + ` projections.privacy_policies2.sequence,` + + ` projections.privacy_policies2.creation_date,` + + ` projections.privacy_policies2.change_date,` + + ` projections.privacy_policies2.resource_owner,` + + ` projections.privacy_policies2.privacy_link,` + + ` projections.privacy_policies2.tos_link,` + + ` projections.privacy_policies2.help_link,` + + ` projections.privacy_policies2.is_default,` + + ` projections.privacy_policies2.state` + + ` FROM projections.privacy_policies2` + + ` AS OF SYSTEM TIME '-1 ms'` + preparePrivacyPolicyCols = []string{ + "id", + "sequence", + "creation_date", + "change_date", + "resource_owner", + "privacy_link", + "tos_link", + "help_link", + "is_default", + "state", + } +) + func Test_PrivacyPolicyPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,17 +55,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) { prepare: preparePrivacyPolicyQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+ - ` projections.privacy_policies2.sequence,`+ - ` projections.privacy_policies2.creation_date,`+ - ` projections.privacy_policies2.change_date,`+ - ` projections.privacy_policies2.resource_owner,`+ - ` projections.privacy_policies2.privacy_link,`+ - ` projections.privacy_policies2.tos_link,`+ - ` projections.privacy_policies2.help_link,`+ - ` projections.privacy_policies2.is_default,`+ - ` projections.privacy_policies2.state`+ - ` FROM projections.privacy_policies2`), + regexp.QuoteMeta(preparePrivacyPolicyStmt), nil, nil, ), @@ -56,29 +73,8 @@ func Test_PrivacyPolicyPrepares(t *testing.T) { prepare: preparePrivacyPolicyQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+ - ` projections.privacy_policies2.sequence,`+ - ` projections.privacy_policies2.creation_date,`+ - ` projections.privacy_policies2.change_date,`+ - ` projections.privacy_policies2.resource_owner,`+ - ` projections.privacy_policies2.privacy_link,`+ - ` projections.privacy_policies2.tos_link,`+ - ` projections.privacy_policies2.help_link,`+ - ` projections.privacy_policies2.is_default,`+ - ` projections.privacy_policies2.state`+ - ` FROM projections.privacy_policies2`), - []string{ - "id", - "sequence", - "creation_date", - "change_date", - "resource_owner", - "privacy_link", - "tos_link", - "help_link", - "is_default", - "state", - }, + regexp.QuoteMeta(preparePrivacyPolicyStmt), + preparePrivacyPolicyCols, []driver.Value{ "pol-id", uint64(20211109), @@ -111,17 +107,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) { prepare: preparePrivacyPolicyQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+ - ` projections.privacy_policies2.sequence,`+ - ` projections.privacy_policies2.creation_date,`+ - ` projections.privacy_policies2.change_date,`+ - ` projections.privacy_policies2.resource_owner,`+ - ` projections.privacy_policies2.privacy_link,`+ - ` projections.privacy_policies2.tos_link,`+ - ` projections.privacy_policies2.help_link,`+ - ` projections.privacy_policies2.is_default,`+ - ` projections.privacy_policies2.state`+ - ` FROM projections.privacy_policies2`), + regexp.QuoteMeta(preparePrivacyPolicyStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -136,7 +122,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/project.go b/internal/query/project.go index b1a2749869..e7df58cf54 100644 --- a/internal/query/project.go +++ b/internal/query/project.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -107,7 +108,7 @@ func (q *Queries) ProjectByID(ctx context.Context, shouldTriggerBulk bool, id st projection.ProjectProjection.Trigger(ctx) } - stmt, scan := prepareProjectQuery() + stmt, scan := prepareProjectQuery(ctx, q.client) eq := sq.Eq{ ProjectColumnID.identifier(): id, ProjectColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -128,7 +129,7 @@ func (q *Queries) SearchProjects(ctx context.Context, queries *ProjectSearchQuer ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareProjectsQuery() + query, scan := prepareProjectsQuery(ctx, q.client) eq := sq.Eq{ProjectColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[ProjectColumnOwnerRemoved.identifier()] = false @@ -195,7 +196,7 @@ func (q *ProjectSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder return query } -func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) { +func prepareProjectQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Project, error)) { return sq.Select( ProjectColumnID.identifier(), ProjectColumnCreationDate.identifier(), @@ -208,7 +209,8 @@ func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) ProjectColumnProjectRoleCheck.identifier(), ProjectColumnHasProjectCheck.identifier(), ProjectColumnPrivateLabelingSetting.identifier()). - From(projectsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(projectsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*Project, error) { p := new(Project) err := row.Scan( @@ -234,7 +236,7 @@ func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) } } -func prepareProjectsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Projects, error)) { +func prepareProjectsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Projects, error)) { return sq.Select( ProjectColumnID.identifier(), ProjectColumnCreationDate.identifier(), @@ -248,7 +250,8 @@ func prepareProjectsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Projects, error ProjectColumnHasProjectCheck.identifier(), ProjectColumnPrivateLabelingSetting.identifier(), countColumn.identifier()). - From(projectsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(projectsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Projects, error) { projects := make([]*Project, 0) var count uint64 diff --git a/internal/query/project_grant.go b/internal/query/project_grant.go index 441b27b923..bbf2657360 100644 --- a/internal/query/project_grant.go +++ b/internal/query/project_grant.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -118,7 +119,7 @@ func (q *Queries) ProjectGrantByID(ctx context.Context, shouldTriggerBulk bool, projection.ProjectGrantProjection.Trigger(ctx) } - stmt, scan := prepareProjectGrantQuery() + stmt, scan := prepareProjectGrantQuery(ctx, q.client) eq := sq.Eq{ ProjectGrantColumnGrantID.identifier(): id, ProjectGrantColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -140,7 +141,7 @@ func (q *Queries) ProjectGrantByIDAndGrantedOrg(ctx context.Context, id, granted ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareProjectGrantQuery() + stmt, scan := prepareProjectGrantQuery(ctx, q.client) eq := sq.Eq{ ProjectGrantColumnGrantID.identifier(): id, ProjectGrantColumnGrantedOrgID.identifier(): grantedOrg, @@ -163,7 +164,7 @@ func (q *Queries) SearchProjectGrants(ctx context.Context, queries *ProjectGrant ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareProjectGrantsQuery() + query, scan := prepareProjectGrantsQuery(ctx, q.client) eq := sq.Eq{ ProjectGrantColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), } @@ -272,7 +273,7 @@ func (q *ProjectGrantSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBui return query } -func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant, error)) { +func prepareProjectGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant, error)) { resourceOwnerOrgTable := orgsTable.setAlias(ProjectGrantResourceOwnerTableAlias) resourceOwnerIDColumn := OrgColumnID.setTable(resourceOwnerOrgTable) grantedOrgTable := orgsTable.setAlias(ProjectGrantGrantedOrgTableAlias) @@ -290,10 +291,11 @@ func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant ProjectGrantColumnGrantedOrgName.identifier(), ProjectGrantColumnGrantedRoleKeys.identifier(), ProjectGrantColumnResourceOwnerName.identifier()). - From(projectGrantsTable.identifier()).PlaceholderFormat(sq.Dollar). + From(projectGrantsTable.identifier()). + PlaceholderFormat(sq.Dollar). LeftJoin(join(ProjectColumnID, ProjectGrantColumnProjectID)). LeftJoin(join(resourceOwnerIDColumn, ProjectGrantColumnResourceOwner)). - LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID)), + LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID) + db.Timetravel(call.Took(ctx))), func(row *sql.Row) (*ProjectGrant, error) { grant := new(ProjectGrant) var ( @@ -330,7 +332,7 @@ func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant } } -func prepareProjectGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectGrants, error)) { +func prepareProjectGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*ProjectGrants, error)) { resourceOwnerOrgTable := orgsTable.setAlias(ProjectGrantResourceOwnerTableAlias) resourceOwnerIDColumn := OrgColumnID.setTable(resourceOwnerOrgTable) grantedOrgTable := orgsTable.setAlias(ProjectGrantGrantedOrgTableAlias) @@ -349,10 +351,11 @@ func prepareProjectGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectGra ProjectGrantColumnGrantedRoleKeys.identifier(), ProjectGrantColumnResourceOwnerName.identifier(), countColumn.identifier()). - From(projectGrantsTable.identifier()).PlaceholderFormat(sq.Dollar). + From(projectGrantsTable.identifier()). + PlaceholderFormat(sq.Dollar). LeftJoin(join(ProjectColumnID, ProjectGrantColumnProjectID)). LeftJoin(join(resourceOwnerIDColumn, ProjectGrantColumnResourceOwner)). - LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID)), + LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID) + db.Timetravel(call.Took(ctx))), func(rows *sql.Rows) (*ProjectGrants, error) { projects := make([]*ProjectGrant, 0) var ( diff --git a/internal/query/project_grant_member.go b/internal/query/project_grant_member.go index 0397b045e3..5e0176207b 100644 --- a/internal/query/project_grant_member.go +++ b/internal/query/project_grant_member.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" ) @@ -94,7 +95,7 @@ func addProjectGrantMemberWithoutOwnerRemoved(eq map[string]interface{}) { } func (q *Queries) ProjectGrantMembers(ctx context.Context, queries *ProjectGrantMembersQuery, withOwnerRemoved bool) (*Members, error) { - query, scan := prepareProjectGrantMembersQuery() + query, scan := prepareProjectGrantMembersQuery(ctx, q.client) eq := sq.Eq{ProjectGrantMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addProjectGrantMemberWithoutOwnerRemoved(eq) @@ -122,7 +123,7 @@ func (q *Queries) ProjectGrantMembers(ctx context.Context, queries *ProjectGrant return members, err } -func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { +func prepareProjectGrantMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { return sq.Select( ProjectGrantMemberCreationDate.identifier(), ProjectGrantMemberChangeDate.identifier(), @@ -142,7 +143,7 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb LeftJoin(join(HumanUserIDCol, ProjectGrantMemberUserID)). LeftJoin(join(MachineUserIDCol, ProjectGrantMemberUserID)). LeftJoin(join(LoginNameUserIDCol, ProjectGrantMemberUserID)). - LeftJoin(join(ProjectGrantColumnGrantID, ProjectGrantMemberGrantID)). + LeftJoin(join(ProjectGrantColumnGrantID, ProjectGrantMemberGrantID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), diff --git a/internal/query/project_grant_member_test.go b/internal/query/project_grant_member_test.go index 1c1bb51486..8a50d09337 100644 --- a/internal/query/project_grant_member_test.go +++ b/internal/query/project_grant_member_test.go @@ -40,6 +40,7 @@ var ( "LEFT JOIN projections.project_grants3 " + "ON members.grant_id = projections.project_grants3.grant_id " + "AND members.instance_id = projections.project_grants3.instance_id " + + `AS OF SYSTEM TIME '-1 ms' ` + "WHERE projections.login_names2.is_primary = $1") projectGrantMembersColumns = []string{ "creation_date", @@ -277,7 +278,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/project_grant_test.go b/internal/query/project_grant_test.go index 89de79f65b..65de48a66c 100644 --- a/internal/query/project_grant_test.go +++ b/internal/query/project_grant_test.go @@ -30,7 +30,8 @@ var ( ` FROM projections.project_grants3 ` + ` LEFT JOIN projections.projects3 ON projections.project_grants3.project_id = projections.projects3.id AND projections.project_grants3.instance_id = projections.projects3.instance_id ` + ` LEFT JOIN projections.orgs AS r ON projections.project_grants3.resource_owner = r.id AND projections.project_grants3.instance_id = r.instance_id` + - ` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` + ` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` projectGrantsCols = []string{ "project_id", "grant_id", @@ -61,7 +62,8 @@ var ( ` FROM projections.project_grants3 ` + ` LEFT JOIN projections.projects3 ON projections.project_grants3.project_id = projections.projects3.id AND projections.project_grants3.instance_id = projections.projects3.instance_id ` + ` LEFT JOIN projections.orgs AS r ON projections.project_grants3.resource_owner = r.id AND projections.project_grants3.instance_id = r.instance_id` + - ` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` + ` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` projectGrantCols = []string{ "project_id", "grant_id", @@ -571,7 +573,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/project_member.go b/internal/query/project_member.go index 4b80d9b594..09c8f9e479 100644 --- a/internal/query/project_member.go +++ b/internal/query/project_member.go @@ -7,6 +7,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -80,7 +81,7 @@ func (q *Queries) ProjectMembers(ctx context.Context, queries *ProjectMembersQue ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareProjectMembersQuery() + query, scan := prepareProjectMembersQuery(ctx, q.client) eq := sq.Eq{ProjectMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addProjectMemberWithoutOwnerRemoved(eq) @@ -108,7 +109,7 @@ func (q *Queries) ProjectMembers(ctx context.Context, queries *ProjectMembersQue return members, err } -func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { +func prepareProjectMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) { return sq.Select( ProjectMemberCreationDate.identifier(), ProjectMemberChangeDate.identifier(), @@ -127,7 +128,7 @@ func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, ).From(projectMemberTable.identifier()). LeftJoin(join(HumanUserIDCol, ProjectMemberUserID)). LeftJoin(join(MachineUserIDCol, ProjectMemberUserID)). - LeftJoin(join(LoginNameUserIDCol, ProjectMemberUserID)). + LeftJoin(join(LoginNameUserIDCol, ProjectMemberUserID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), diff --git a/internal/query/project_member_test.go b/internal/query/project_member_test.go index d62688454b..960a3c1ce5 100644 --- a/internal/query/project_member_test.go +++ b/internal/query/project_member_test.go @@ -37,6 +37,7 @@ var ( "LEFT JOIN projections.login_names2 " + "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") projectMembersColumns = []string{ "creation_date", @@ -274,7 +275,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/project_role.go b/internal/query/project_role.go index 4fe83a39c7..03ebbf60bd 100644 --- a/internal/query/project_role.go +++ b/internal/query/project_role.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -95,7 +96,7 @@ func (q *Queries) SearchProjectRoles(ctx context.Context, shouldTriggerBulk bool eq[ProjectRoleColumnOwnerRemoved.identifier()] = false } - query, scan := prepareProjectRolesQuery() + query, scan := prepareProjectRolesQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).Where(eq).ToSql() if err != nil { return nil, errors.ThrowInvalidArgument(err, "QUERY-3N9ff", "Errors.Query.InvalidRequest") @@ -131,7 +132,7 @@ func (q *Queries) SearchGrantedProjectRoles(ctx context.Context, grantID, grante eq[ProjectRoleColumnOwnerRemoved.identifier()] = false } - query, scan := prepareProjectRolesQuery() + query, scan := prepareProjectRolesQuery(ctx, q.client) stmt, args, err := queries.toQuery(query).Where(eq).ToSql() if err != nil { return nil, errors.ThrowInvalidArgument(err, "QUERY-3N9ff", "Errors.Query.InvalidRequest") @@ -212,7 +213,7 @@ func (q *ProjectRoleSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil return query } -func prepareProjectRolesQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectRoles, error)) { +func prepareProjectRolesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*ProjectRoles, error)) { return sq.Select( ProjectRoleColumnProjectID.identifier(), ProjectRoleColumnCreationDate.identifier(), @@ -223,7 +224,8 @@ func prepareProjectRolesQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectRole ProjectRoleColumnDisplayName.identifier(), ProjectRoleColumnGroupName.identifier(), countColumn.identifier()). - From(projectRolesTable.identifier()).PlaceholderFormat(sq.Dollar), + From(projectRolesTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*ProjectRoles, error) { projects := make([]*ProjectRole, 0) var count uint64 diff --git a/internal/query/project_role_test.go b/internal/query/project_role_test.go index c76a8bd591..9324cf2929 100644 --- a/internal/query/project_role_test.go +++ b/internal/query/project_role_test.go @@ -9,6 +9,31 @@ import ( "testing" ) +var ( + prepareProjectRolesStmt = `SELECT projections.project_roles3.project_id,` + + ` projections.project_roles3.creation_date,` + + ` projections.project_roles3.change_date,` + + ` projections.project_roles3.resource_owner,` + + ` projections.project_roles3.sequence,` + + ` projections.project_roles3.role_key,` + + ` projections.project_roles3.display_name,` + + ` projections.project_roles3.group_name,` + + ` COUNT(*) OVER ()` + + ` FROM projections.project_roles3` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareProjectRolesCols = []string{ + "project_id", + "creation_date", + "change_date", + "resource_owner", + "sequence", + "role_key", + "display_name", + "group_name", + "count", + } +) + func Test_ProjectRolePrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -25,16 +50,7 @@ func Test_ProjectRolePrepares(t *testing.T) { prepare: prepareProjectRolesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+ - ` projections.project_roles3.creation_date,`+ - ` projections.project_roles3.change_date,`+ - ` projections.project_roles3.resource_owner,`+ - ` projections.project_roles3.sequence,`+ - ` projections.project_roles3.role_key,`+ - ` projections.project_roles3.display_name,`+ - ` projections.project_roles3.group_name,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.project_roles3`), + regexp.QuoteMeta(prepareProjectRolesStmt), nil, nil, ), @@ -46,27 +62,8 @@ func Test_ProjectRolePrepares(t *testing.T) { prepare: prepareProjectRolesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+ - ` projections.project_roles3.creation_date,`+ - ` projections.project_roles3.change_date,`+ - ` projections.project_roles3.resource_owner,`+ - ` projections.project_roles3.sequence,`+ - ` projections.project_roles3.role_key,`+ - ` projections.project_roles3.display_name,`+ - ` projections.project_roles3.group_name,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.project_roles3`), - []string{ - "project_id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "role_key", - "display_name", - "group_name", - "count", - }, + regexp.QuoteMeta(prepareProjectRolesStmt), + prepareProjectRolesCols, [][]driver.Value{ { "project-id", @@ -104,27 +101,8 @@ func Test_ProjectRolePrepares(t *testing.T) { prepare: prepareProjectRolesQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+ - ` projections.project_roles3.creation_date,`+ - ` projections.project_roles3.change_date,`+ - ` projections.project_roles3.resource_owner,`+ - ` projections.project_roles3.sequence,`+ - ` projections.project_roles3.role_key,`+ - ` projections.project_roles3.display_name,`+ - ` projections.project_roles3.group_name,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.project_roles3`), - []string{ - "project_id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "role_key", - "display_name", - "group_name", - "count", - }, + regexp.QuoteMeta(prepareProjectRolesStmt), + prepareProjectRolesCols, [][]driver.Value{ { "project-id", @@ -182,16 +160,7 @@ func Test_ProjectRolePrepares(t *testing.T) { prepare: prepareProjectRolesQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+ - ` projections.project_roles3.creation_date,`+ - ` projections.project_roles3.change_date,`+ - ` projections.project_roles3.resource_owner,`+ - ` projections.project_roles3.sequence,`+ - ` projections.project_roles3.role_key,`+ - ` projections.project_roles3.display_name,`+ - ` projections.project_roles3.group_name,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.project_roles3`), + regexp.QuoteMeta(prepareProjectRolesStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -206,7 +175,7 @@ func Test_ProjectRolePrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/project_test.go b/internal/query/project_test.go index 1e9884fdcc..ea96f62c4f 100644 --- a/internal/query/project_test.go +++ b/internal/query/project_test.go @@ -26,6 +26,62 @@ var ( "has_project_check", "private_labeling_setting", } + + prepareProjectsStmt = `SELECT projections.projects3.id,` + + ` projections.projects3.creation_date,` + + ` projections.projects3.change_date,` + + ` projections.projects3.resource_owner,` + + ` projections.projects3.state,` + + ` projections.projects3.sequence,` + + ` projections.projects3.name,` + + ` projections.projects3.project_role_assertion,` + + ` projections.projects3.project_role_check,` + + ` projections.projects3.has_project_check,` + + ` projections.projects3.private_labeling_setting,` + + ` COUNT(*) OVER ()` + + ` FROM projections.projects3` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareProjectsCols = []string{ + "id", + "creation_date", + "change_date", + "resource_owner", + "state", + "sequence", + "name", + "project_role_assertion", + "project_role_check", + "has_project_check", + "private_labeling_setting", + "count", + } + + prepareProjectStmt = `SELECT projections.projects3.id,` + + ` projections.projects3.creation_date,` + + ` projections.projects3.change_date,` + + ` projections.projects3.resource_owner,` + + ` projections.projects3.state,` + + ` projections.projects3.sequence,` + + ` projections.projects3.name,` + + ` projections.projects3.project_role_assertion,` + + ` projections.projects3.project_role_check,` + + ` projections.projects3.has_project_check,` + + ` projections.projects3.private_labeling_setting` + + ` FROM projections.projects3` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareProjectCols = []string{ + "id", + "creation_date", + "change_date", + "resource_owner", + "state", + "sequence", + "name", + "project_role_assertion", + "project_role_check", + "has_project_check", + "private_labeling_setting", + } ) func Test_ProjectPrepares(t *testing.T) { @@ -44,19 +100,7 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.projects3`), + regexp.QuoteMeta(prepareProjectsStmt), nil, nil, ), @@ -68,33 +112,8 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.projects3`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "state", - "sequence", - "name", - "project_role_assertion", - "project_role_check", - "has_project_check", - "private_labeling_setting", - "count", - }, + regexp.QuoteMeta(prepareProjectsStmt), + prepareProjectsCols, [][]driver.Value{ { "id", @@ -138,33 +157,8 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.projects3`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "state", - "sequence", - "name", - "project_role_assertion", - "project_role_check", - "has_project_check", - "private_labeling_setting", - "count", - }, + regexp.QuoteMeta(prepareProjectsStmt), + prepareProjectsCols, [][]driver.Value{ { "id-1", @@ -234,19 +228,7 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.projects3`), + regexp.QuoteMeta(prepareProjectsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -263,18 +245,7 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting`+ - ` FROM projections.projects3`, + prepareProjectStmt, nil, nil, ), @@ -292,31 +263,8 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting`+ - ` FROM projections.projects3`), - []string{ - "id", - "creation_date", - "change_date", - "resource_owner", - "state", - "sequence", - "name", - "project_role_assertion", - "project_role_check", - "has_project_check", - "private_labeling_setting", - }, + regexp.QuoteMeta(prepareProjectStmt), + prepareProjectCols, []driver.Value{ "id", testNow, @@ -351,18 +299,7 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.projects3.id,`+ - ` projections.projects3.creation_date,`+ - ` projections.projects3.change_date,`+ - ` projections.projects3.resource_owner,`+ - ` projections.projects3.state,`+ - ` projections.projects3.sequence,`+ - ` projections.projects3.name,`+ - ` projections.projects3.project_role_assertion,`+ - ` projections.projects3.project_role_check,`+ - ` projections.projects3.has_project_check,`+ - ` projections.projects3.private_labeling_setting`+ - ` FROM projections.projects3`), + regexp.QuoteMeta(prepareProjectStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -377,7 +314,7 @@ func Test_ProjectPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/projection/projection.go b/internal/query/projection/projection.go index fd59ebfd49..f6245ad4ed 100644 --- a/internal/query/projection/projection.go +++ b/internal/query/projection/projection.go @@ -2,9 +2,9 @@ package projection import ( "context" - "database/sql" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/handler" "github.com/zitadel/zitadel/internal/eventstore/handler/crdb" @@ -74,7 +74,7 @@ var ( projections []projection ) -func Create(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, config Config, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm) error { +func Create(ctx context.Context, sqlClient *database.DB, es *eventstore.Eventstore, config Config, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm) error { projectionConfig = crdb.StatementHandlerConfig{ ProjectionHandlerConfig: handler.ProjectionHandlerConfig{ HandlerConfig: handler.HandlerConfig{ diff --git a/internal/query/query.go b/internal/query/query.go index 65907bd808..0fc324f843 100644 --- a/internal/query/query.go +++ b/internal/query/query.go @@ -2,10 +2,10 @@ package query import ( "context" - "database/sql" "fmt" "net/http" "sync" + "time" "github.com/rakyll/statik/fs" "golang.org/x/text/language" @@ -13,6 +13,7 @@ import ( "github.com/zitadel/zitadel/internal/api/authz" sd "github.com/zitadel/zitadel/internal/config/systemdefaults" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/query/projection" @@ -27,7 +28,7 @@ import ( type Queries struct { eventstore *eventstore.Eventstore - client *sql.DB + client *database.DB idpConfigEncryption crypto.EncryptionAlgorithm @@ -42,7 +43,7 @@ type Queries struct { multifactors domain.MultifactorConfigs } -func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *sql.DB, projections projection.Config, defaults sd.SystemDefaults, idpConfigEncryption, otpEncryption, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm, zitadelRoles []authz.RoleMapping) (repo *Queries, err error) { +func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *database.DB, projections projection.Config, defaults sd.SystemDefaults, idpConfigEncryption, otpEncryption, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm, zitadelRoles []authz.RoleMapping) (repo *Queries, err error) { statikLoginFS, err := fs.NewWithNamespace("login") if err != nil { return nil, fmt.Errorf("unable to start login statik dir") @@ -91,3 +92,7 @@ func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *sql func (q *Queries) Health(ctx context.Context) error { return q.client.Ping() } + +type prepareDatabase interface { + Timetravel(d time.Duration) string +} diff --git a/internal/query/quota_model.go b/internal/query/quota_model.go new file mode 100644 index 0000000000..322ea67aac --- /dev/null +++ b/internal/query/quota_model.go @@ -0,0 +1,55 @@ +package query + +import ( + "github.com/zitadel/zitadel/internal/eventstore" + "github.com/zitadel/zitadel/internal/repository/quota" +) + +type quotaReadModel struct { + eventstore.ReadModel + unit quota.Unit + active bool + config *quota.AddedEvent +} + +// newQuotaReadModel aggregateId is filled by reducing unit matching events +func newQuotaReadModel(instanceId, resourceOwner string, unit quota.Unit) *quotaReadModel { + return "aReadModel{ + ReadModel: eventstore.ReadModel{ + InstanceID: instanceId, + ResourceOwner: resourceOwner, + }, + unit: unit, + } +} + +func (rm *quotaReadModel) Query() *eventstore.SearchQueryBuilder { + query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + ResourceOwner(rm.ResourceOwner). + AllowTimeTravel(). + AddQuery(). + InstanceID(rm.InstanceID). + AggregateTypes(quota.AggregateType). + EventTypes( + quota.AddedEventType, + quota.RemovedEventType, + ).EventData(map[string]interface{}{"unit": rm.unit}) + + return query.Builder() +} + +func (rm *quotaReadModel) Reduce() error { + for _, event := range rm.Events { + switch e := event.(type) { + case *quota.AddedEvent: + rm.AggregateID = e.Aggregate().ID + rm.active = true + rm.config = e + case *quota.RemovedEvent: + rm.AggregateID = e.Aggregate().ID + rm.active = false + rm.config = nil + } + } + return rm.ReadModel.Reduce() +} diff --git a/internal/command/quota_notifications.go b/internal/query/quota_notifications.go similarity index 63% rename from internal/command/quota_notifications.go rename to internal/query/quota_notifications.go index 15f1695df7..f5ac6f2522 100644 --- a/internal/command/quota_notifications.go +++ b/internal/query/quota_notifications.go @@ -1,4 +1,4 @@ -package command +package query import ( "context" @@ -9,13 +9,13 @@ import ( "github.com/zitadel/zitadel/internal/repository/quota" ) -func (c *Commands) GetDueQuotaNotifications(ctx context.Context, config *quota.AddedEvent, periodStart time.Time, usedAbs uint64) ([]*quota.NotifiedEvent, error) { +func (q *Queries) GetDueQuotaNotifications(ctx context.Context, config *quota.AddedEvent, periodStart time.Time, usedAbs uint64) ([]*quota.NotifiedEvent, error) { if len(config.Notifications) == 0 { return nil, nil } aggregate := config.Aggregate() - wm, err := c.getQuotaNotificationsWriteModel(ctx, aggregate, periodStart) + wm, err := q.getQuotaNotificationsReadModel(ctx, aggregate, periodStart) if err != nil { return nil, err } @@ -53,7 +53,7 @@ func (c *Commands) GetDueQuotaNotifications(ctx context.Context, config *quota.A return dueNotifications, nil } -func (c *Commands) getQuotaNotificationsWriteModel(ctx context.Context, aggregate eventstore.Aggregate, periodStart time.Time) (*quotaNotificationsWriteModel, error) { - wm := newQuotaNotificationsWriteModel(aggregate.ID, aggregate.InstanceID, aggregate.ResourceOwner, periodStart) - return wm, c.eventstore.FilterToQueryReducer(ctx, wm) +func (q *Queries) getQuotaNotificationsReadModel(ctx context.Context, aggregate eventstore.Aggregate, periodStart time.Time) (*quotaNotificationsReadModel, error) { + wm := newQuotaNotificationsReadModel(aggregate.ID, aggregate.InstanceID, aggregate.ResourceOwner, periodStart) + return wm, q.eventstore.FilterToQueryReducer(ctx, wm) } diff --git a/internal/query/quota_notifications_model.go b/internal/query/quota_notifications_model.go new file mode 100644 index 0000000000..a64aa05b06 --- /dev/null +++ b/internal/query/quota_notifications_model.go @@ -0,0 +1,46 @@ +package query + +import ( + "time" + + "github.com/zitadel/zitadel/internal/eventstore" + "github.com/zitadel/zitadel/internal/repository/quota" +) + +type quotaNotificationsReadModel struct { + eventstore.ReadModel + periodStart time.Time + latestNotifiedThresholds map[string]uint16 +} + +func newQuotaNotificationsReadModel(aggregateId, instanceId, resourceOwner string, periodStart time.Time) *quotaNotificationsReadModel { + return "aNotificationsReadModel{ + ReadModel: eventstore.ReadModel{ + AggregateID: aggregateId, + InstanceID: instanceId, + ResourceOwner: resourceOwner, + }, + periodStart: periodStart, + latestNotifiedThresholds: make(map[string]uint16), + } +} + +func (rm *quotaNotificationsReadModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + ResourceOwner(rm.ResourceOwner). + AllowTimeTravel(). + AddQuery(). + InstanceID(rm.InstanceID). + AggregateTypes(quota.AggregateType). + AggregateIDs(rm.AggregateID). + CreationDateAfter(rm.periodStart). + EventTypes(quota.NotifiedEventType).Builder() +} + +func (rm *quotaNotificationsReadModel) Reduce() error { + for _, event := range rm.Events { + e := event.(*quota.NotifiedEvent) + rm.latestNotifiedThresholds[e.ID] = e.Threshold + } + return rm.ReadModel.Reduce() +} diff --git a/internal/query/quota_period.go b/internal/query/quota_period.go new file mode 100644 index 0000000000..b18a5f0427 --- /dev/null +++ b/internal/query/quota_period.go @@ -0,0 +1,30 @@ +package query + +import ( + "context" + "time" + + "github.com/zitadel/zitadel/internal/repository/quota" +) + +func (q *Queries) GetCurrentQuotaPeriod(ctx context.Context, instanceID string, unit quota.Unit) (*quota.AddedEvent, time.Time, error) { + rm, err := q.getQuotaReadModel(ctx, instanceID, instanceID, unit) + if err != nil || !rm.active { + return nil, time.Time{}, err + } + + return rm.config, pushPeriodStart(rm.config.From, rm.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) +} + +func (q *Queries) getQuotaReadModel(ctx context.Context, instanceId, resourceOwner string, unit quota.Unit) (*quotaReadModel, error) { + rm := newQuotaReadModel(instanceId, resourceOwner, unit) + return rm, q.eventstore.FilterToQueryReducer(ctx, rm) +} diff --git a/internal/query/secret_generator_test.go b/internal/query/secret_generator_test.go index 82d8269344..2d84c9b1c7 100644 --- a/internal/query/secret_generator_test.go +++ b/internal/query/secret_generator_test.go @@ -13,6 +13,67 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareSecretGeneratorStmt = `SELECT projections.secret_generators2.aggregate_id,` + + ` projections.secret_generators2.generator_type,` + + ` projections.secret_generators2.creation_date,` + + ` projections.secret_generators2.change_date,` + + ` projections.secret_generators2.resource_owner,` + + ` projections.secret_generators2.sequence,` + + ` projections.secret_generators2.length,` + + ` projections.secret_generators2.expiry,` + + ` projections.secret_generators2.include_lower_letters,` + + ` projections.secret_generators2.include_upper_letters,` + + ` projections.secret_generators2.include_digits,` + + ` projections.secret_generators2.include_symbols` + + ` FROM projections.secret_generators2` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareSecretGeneratorCols = []string{ + "aggregate_id", + "generator_type", + "creation_date", + "change_date", + "resource_owner", + "sequence", + "length", + "expiry", + "include_lower_letters", + "include_upper_letters", + "include_digits", + "include_symbols", + } + prepareSecretGeneratorsStmt = `SELECT projections.secret_generators2.aggregate_id,` + + ` projections.secret_generators2.generator_type,` + + ` projections.secret_generators2.creation_date,` + + ` projections.secret_generators2.change_date,` + + ` projections.secret_generators2.resource_owner,` + + ` projections.secret_generators2.sequence,` + + ` projections.secret_generators2.length,` + + ` projections.secret_generators2.expiry,` + + ` projections.secret_generators2.include_lower_letters,` + + ` projections.secret_generators2.include_upper_letters,` + + ` projections.secret_generators2.include_digits,` + + ` projections.secret_generators2.include_symbols,` + + ` COUNT(*) OVER ()` + + ` FROM projections.secret_generators2` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareSecretGeneratorsCols = []string{ + "aggregate_id", + "generator_type", + "creation_date", + "change_date", + "resource_owner", + "sequence", + "length", + "expiry", + "include_lower_letters", + "include_upper_letters", + "include_digits", + "include_symbols", + "count", + } +) + func Test_SecretGeneratorsPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -29,20 +90,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.secret_generators2`), + regexp.QuoteMeta(prepareSecretGeneratorsStmt), nil, nil, ), @@ -54,35 +102,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.secret_generators2`), - []string{ - "aggregate_id", - "generator_type", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "length", - "expiry", - "include_lower_letters", - "include_upper_letters", - "include_digits", - "include_symbols", - "count", - }, + regexp.QuoteMeta(prepareSecretGeneratorsStmt), + prepareSecretGeneratorsCols, [][]driver.Value{ { "agg-id", @@ -128,35 +149,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.secret_generators2`), - []string{ - "aggregate_id", - "generator_type", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "length", - "expiry", - "include_lower_letters", - "include_upper_letters", - "include_digits", - "include_symbols", - "count", - }, + regexp.QuoteMeta(prepareSecretGeneratorsStmt), + prepareSecretGeneratorsCols, [][]driver.Value{ { "agg-id", @@ -230,20 +224,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.secret_generators2`), + regexp.QuoteMeta(prepareSecretGeneratorsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -260,19 +241,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols`+ - ` FROM projections.secret_generators2`, + prepareSecretGeneratorStmt, nil, nil, ), @@ -290,33 +259,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols`+ - ` FROM projections.secret_generators2`), - []string{ - "aggregate_id", - "generator_type", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "length", - "expiry", - "include_lower_letters", - "include_upper_letters", - "include_digits", - "include_symbols", - }, + regexp.QuoteMeta(prepareSecretGeneratorStmt), + prepareSecretGeneratorCols, []driver.Value{ "agg-id", domain.SecretGeneratorTypeInitCode, @@ -353,19 +297,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+ - ` projections.secret_generators2.generator_type,`+ - ` projections.secret_generators2.creation_date,`+ - ` projections.secret_generators2.change_date,`+ - ` projections.secret_generators2.resource_owner,`+ - ` projections.secret_generators2.sequence,`+ - ` projections.secret_generators2.length,`+ - ` projections.secret_generators2.expiry,`+ - ` projections.secret_generators2.include_lower_letters,`+ - ` projections.secret_generators2.include_upper_letters,`+ - ` projections.secret_generators2.include_digits,`+ - ` projections.secret_generators2.include_symbols`+ - ` FROM projections.secret_generators2`), + regexp.QuoteMeta(prepareSecretGeneratorStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -380,7 +312,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/secret_generators.go b/internal/query/secret_generators.go index e5dc1b5378..a4859279f6 100644 --- a/internal/query/secret_generators.go +++ b/internal/query/secret_generators.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -137,7 +138,7 @@ func (q *Queries) SecretGeneratorByType(ctx context.Context, generatorType domai ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareSecretGeneratorQuery() + stmt, scan := prepareSecretGeneratorQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ SecretGeneratorColumnGeneratorType.identifier(): generatorType, SecretGeneratorColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -154,7 +155,7 @@ func (q *Queries) SearchSecretGenerators(ctx context.Context, queries *SecretGen ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareSecretGeneratorsQuery() + query, scan := prepareSecretGeneratorsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query). Where(sq.Eq{ SecretGeneratorColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -187,7 +188,7 @@ func NewSecretGeneratorTypeSearchQuery(value int32) (SearchQuery, error) { return NewNumberQuery(SecretGeneratorColumnGeneratorType, value, NumberEquals) } -func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGenerator, error)) { +func prepareSecretGeneratorQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecretGenerator, error)) { return sq.Select( SecretGeneratorColumnAggregateID.identifier(), SecretGeneratorColumnGeneratorType.identifier(), @@ -201,7 +202,8 @@ func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGen SecretGeneratorColumnIncludeUpperLetters.identifier(), SecretGeneratorColumnIncludeDigits.identifier(), SecretGeneratorColumnIncludeSymbols.identifier()). - From(secretGeneratorsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(secretGeneratorsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SecretGenerator, error) { secretGenerator := new(SecretGenerator) err := row.Scan( @@ -228,7 +230,7 @@ func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGen } } -func prepareSecretGeneratorsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SecretGenerators, error)) { +func prepareSecretGeneratorsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*SecretGenerators, error)) { return sq.Select( SecretGeneratorColumnAggregateID.identifier(), SecretGeneratorColumnGeneratorType.identifier(), @@ -243,7 +245,8 @@ func prepareSecretGeneratorsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SecretG SecretGeneratorColumnIncludeDigits.identifier(), SecretGeneratorColumnIncludeSymbols.identifier(), countColumn.identifier()). - From(secretGeneratorsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(secretGeneratorsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*SecretGenerators, error) { secretGenerators := make([]*SecretGenerator, 0) var count uint64 diff --git a/internal/query/security_policy.go b/internal/query/security_policy.go index 69df792015..29e15de21b 100644 --- a/internal/query/security_policy.go +++ b/internal/query/security_policy.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -57,7 +58,7 @@ type SecurityPolicy struct { } func (q *Queries) SecurityPolicy(ctx context.Context) (*SecurityPolicy, error) { - stmt, scan := prepareSecurityPolicyQuery() + stmt, scan := prepareSecurityPolicyQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ SecurityPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), }).ToSql() @@ -69,7 +70,7 @@ func (q *Queries) SecurityPolicy(ctx context.Context) (*SecurityPolicy, error) { return scan(row) } -func prepareSecurityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*SecurityPolicy, error)) { +func prepareSecurityPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecurityPolicy, error)) { return sq.Select( SecurityPolicyColumnInstanceID.identifier(), SecurityPolicyColumnCreationDate.identifier(), @@ -78,7 +79,8 @@ func prepareSecurityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*SecurityPo SecurityPolicyColumnSequence.identifier(), SecurityPolicyColumnEnabled.identifier(), SecurityPolicyColumnAllowedOrigins.identifier()). - From(securityPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), + From(securityPolicyTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SecurityPolicy, error) { securityPolicy := new(SecurityPolicy) err := row.Scan( diff --git a/internal/query/sms.go b/internal/query/sms.go index 40eb75576e..6b0273ed26 100644 --- a/internal/query/sms.go +++ b/internal/query/sms.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -118,7 +119,7 @@ func (q *Queries) SMSProviderConfigByID(ctx context.Context, id string) (_ *SMSC ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareSMSConfigQuery() + query, scan := prepareSMSConfigQuery(ctx, q.client) stmt, args, err := query.Where( sq.Eq{ SMSConfigColumnID.identifier(): id, @@ -137,7 +138,7 @@ func (q *Queries) SMSProviderConfig(ctx context.Context, queries ...SearchQuery) ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareSMSConfigQuery() + query, scan := prepareSMSConfigQuery(ctx, q.client) for _, searchQuery := range queries { query = searchQuery.toQuery(query) } @@ -158,7 +159,7 @@ func (q *Queries) SearchSMSConfigs(ctx context.Context, queries *SMSConfigsSearc ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareSMSConfigsQuery() + query, scan := prepareSMSConfigsQuery(ctx, q.client) stmt, args, err := queries.toQuery(query). Where(sq.Eq{ SMSConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -183,7 +184,7 @@ func NewSMSProviderStateQuery(state domain.SMSConfigState) (SearchQuery, error) return NewNumberQuery(SMSConfigColumnState, state, NumberEquals) } -func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, error)) { +func prepareSMSConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, error)) { return sq.Select( SMSConfigColumnID.identifier(), SMSConfigColumnAggregateID.identifier(), @@ -198,7 +199,7 @@ func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, erro SMSTwilioConfigColumnToken.identifier(), SMSTwilioConfigColumnSenderNumber.identifier(), ).From(smsConfigsTable.identifier()). - LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID)). + LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SMSConfig, error) { config := new(SMSConfig) @@ -234,7 +235,7 @@ func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, erro } } -func prepareSMSConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, error)) { +func prepareSMSConfigsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, error)) { return sq.Select( SMSConfigColumnID.identifier(), SMSConfigColumnAggregateID.identifier(), @@ -250,7 +251,7 @@ func prepareSMSConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, e SMSTwilioConfigColumnSenderNumber.identifier(), countColumn.identifier(), ).From(smsConfigsTable.identifier()). - LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID)). + LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Rows) (*SMSConfigs, error) { configs := &SMSConfigs{Configs: []*SMSConfig{}} diff --git a/internal/query/sms_test.go b/internal/query/sms_test.go index 2964cfe574..88b0516de0 100644 --- a/internal/query/sms_test.go +++ b/internal/query/sms_test.go @@ -28,7 +28,8 @@ var ( ` projections.sms_configs2_twilio.token,` + ` projections.sms_configs2_twilio.sender_number` + ` FROM projections.sms_configs2` + - ` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id`) + ` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'`) expectedSMSConfigsQuery = regexp.QuoteMeta(`SELECT projections.sms_configs2.id,` + ` projections.sms_configs2.aggregate_id,` + ` projections.sms_configs2.creation_date,` + @@ -44,7 +45,8 @@ var ( ` projections.sms_configs2_twilio.sender_number,` + ` COUNT(*) OVER ()` + ` FROM projections.sms_configs2` + - ` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id`) + ` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'`) smsConfigCols = []string{ "id", @@ -228,7 +230,7 @@ func Test_SMSConfigssPrepare(t *testing.T) { } for _, tt := range tests { 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...) }) } } @@ -320,7 +322,7 @@ func Test_SMSConfigPrepare(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/smtp.go b/internal/query/smtp.go index f8614e8b86..4b0f0a019d 100644 --- a/internal/query/smtp.go +++ b/internal/query/smtp.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -94,7 +95,7 @@ func (q *Queries) SMTPConfigByAggregateID(ctx context.Context, aggregateID strin ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - stmt, scan := prepareSMTPConfigQuery() + stmt, scan := prepareSMTPConfigQuery(ctx, q.client) query, args, err := stmt.Where(sq.Eq{ SMTPConfigColumnAggregateID.identifier(): aggregateID, SMTPConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -107,7 +108,7 @@ func (q *Queries) SMTPConfigByAggregateID(ctx context.Context, aggregateID strin return scan(row) } -func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, error)) { +func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, error)) { password := new(crypto.CryptoValue) return sq.Select( @@ -122,7 +123,8 @@ func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, er SMTPConfigColumnSMTPHost.identifier(), SMTPConfigColumnSMTPUser.identifier(), SMTPConfigColumnSMTPPassword.identifier()). - From(smtpConfigsTable.identifier()).PlaceholderFormat(sq.Dollar), + From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SMTPConfig, error) { config := new(SMTPConfig) err := row.Scan( diff --git a/internal/query/smtp_test.go b/internal/query/smtp_test.go index 37ae71620c..77ef763ed0 100644 --- a/internal/query/smtp_test.go +++ b/internal/query/smtp_test.go @@ -12,6 +12,35 @@ import ( errs "github.com/zitadel/zitadel/internal/errors" ) +var ( + prepareSMTPConfigStmt = `SELECT projections.smtp_configs.aggregate_id,` + + ` projections.smtp_configs.creation_date,` + + ` projections.smtp_configs.change_date,` + + ` projections.smtp_configs.resource_owner,` + + ` projections.smtp_configs.sequence,` + + ` projections.smtp_configs.tls,` + + ` projections.smtp_configs.sender_address,` + + ` projections.smtp_configs.sender_name,` + + ` projections.smtp_configs.host,` + + ` projections.smtp_configs.username,` + + ` projections.smtp_configs.password` + + ` FROM projections.smtp_configs` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareSMTPConfigCols = []string{ + "aggregate_id", + "creation_date", + "change_date", + "resource_owner", + "sequence", + "tls", + "sender_address", + "sender_name", + "smtp_host", + "smtp_user", + "smtp_password", + } +) + func Test_SMTPConfigsPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -28,18 +57,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) { prepare: prepareSMTPConfigQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.smtp_configs.aggregate_id,`+ - ` projections.smtp_configs.creation_date,`+ - ` projections.smtp_configs.change_date,`+ - ` projections.smtp_configs.resource_owner,`+ - ` projections.smtp_configs.sequence,`+ - ` projections.smtp_configs.tls,`+ - ` projections.smtp_configs.sender_address,`+ - ` projections.smtp_configs.sender_name,`+ - ` projections.smtp_configs.host,`+ - ` projections.smtp_configs.username,`+ - ` projections.smtp_configs.password`+ - ` FROM projections.smtp_configs`, + prepareSMTPConfigStmt, nil, nil, ), @@ -57,31 +75,8 @@ func Test_SMTPConfigsPrepares(t *testing.T) { prepare: prepareSMTPConfigQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.smtp_configs.aggregate_id,`+ - ` projections.smtp_configs.creation_date,`+ - ` projections.smtp_configs.change_date,`+ - ` projections.smtp_configs.resource_owner,`+ - ` projections.smtp_configs.sequence,`+ - ` projections.smtp_configs.tls,`+ - ` projections.smtp_configs.sender_address,`+ - ` projections.smtp_configs.sender_name,`+ - ` projections.smtp_configs.host,`+ - ` projections.smtp_configs.username,`+ - ` projections.smtp_configs.password`+ - ` FROM projections.smtp_configs`), - []string{ - "aggregate_id", - "creation_date", - "change_date", - "resource_owner", - "sequence", - "tls", - "sender_address", - "sender_name", - "smtp_host", - "smtp_user", - "smtp_password", - }, + regexp.QuoteMeta(prepareSMTPConfigStmt), + prepareSMTPConfigCols, []driver.Value{ "agg-id", testNow, @@ -116,18 +111,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) { prepare: prepareSMTPConfigQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.smtp_configs.aggregate_id,`+ - ` projections.smtp_configs.creation_date,`+ - ` projections.smtp_configs.change_date,`+ - ` projections.smtp_configs.resource_owner,`+ - ` projections.smtp_configs.sequence,`+ - ` projections.smtp_configs.tls,`+ - ` projections.smtp_configs.sender_address,`+ - ` projections.smtp_configs.sender_name,`+ - ` projections.smtp_configs.host,`+ - ` projections.smtp_configs.username,`+ - ` projections.smtp_configs.password`+ - ` FROM projections.smtp_configs`), + regexp.QuoteMeta(prepareSMTPConfigStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -142,7 +126,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/user.go b/internal/query/user.go index cfe86314e1..7790ce9b8d 100644 --- a/internal/query/user.go +++ b/internal/query/user.go @@ -11,6 +11,7 @@ import ( "golang.org/x/text/language" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -341,7 +342,7 @@ func (q *Queries) GetUserByID(ctx context.Context, shouldTriggerBulk bool, userI projection.LoginNameProjection.Trigger(ctx) } - query, scan := prepareUserQuery() + query, scan := prepareUserQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -370,7 +371,7 @@ func (q *Queries) GetUser(ctx context.Context, shouldTriggerBulk bool, withOwner projection.LoginNameProjection.Trigger(ctx) } - query, scan := prepareUserQuery() + query, scan := prepareUserQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -393,7 +394,7 @@ func (q *Queries) GetHumanProfile(ctx context.Context, userID string, withOwnerR ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareProfileQuery() + query, scan := prepareProfileQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -417,7 +418,7 @@ func (q *Queries) GetHumanEmail(ctx context.Context, userID string, withOwnerRem ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareEmailQuery() + query, scan := prepareEmailQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -441,7 +442,7 @@ func (q *Queries) GetHumanPhone(ctx context.Context, userID string, withOwnerRem ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := preparePhoneQuery() + query, scan := preparePhoneQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -470,7 +471,7 @@ func (q *Queries) GetNotifyUserByID(ctx context.Context, shouldTriggered bool, u projection.LoginNameProjection.Trigger(ctx) } - query, scan := prepareNotifyUserQuery() + query, scan := prepareNotifyUserQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -499,7 +500,7 @@ func (q *Queries) GetNotifyUser(ctx context.Context, shouldTriggered bool, withO projection.LoginNameProjection.Trigger(ctx) } - query, scan := prepareNotifyUserQuery() + query, scan := prepareNotifyUserQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -522,7 +523,7 @@ func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, w ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareUsersQuery() + query, scan := prepareUsersQuery(ctx, q.client) eq := sq.Eq{UserInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addUserWithoutOwnerRemoved(eq) @@ -549,7 +550,7 @@ func (q *Queries) IsUserUnique(ctx context.Context, username, email, resourceOwn ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareUserUniqueQuery() + query, scan := prepareUserUniqueQuery(ctx, q.client) queries := make([]SearchQuery, 0, 3) if username != "" { usernameQuery, err := NewUserUsernameSearchQuery(username, TextEquals) @@ -722,7 +723,7 @@ func preparePreferredLoginNamesQuery() (string, []interface{}, error) { ).ToSql() } -func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { +func prepareUserQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*User, error)) { loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery() if err != nil { return sq.SelectBuilder{}, nil @@ -770,7 +771,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { loginNamesArgs...). LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+ userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+ - userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(), + userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*User, error) { @@ -863,7 +864,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { } } -func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) { +func prepareProfileQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) { return sq.Select( UserIDCol.identifier(), UserCreationDateCol.identifier(), @@ -879,7 +880,7 @@ func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) HumanGenderCol.identifier(), HumanAvatarURLCol.identifier()). From(userTable.identifier()). - LeftJoin(join(HumanUserIDCol, UserIDCol)). + LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*Profile, error) { p := new(Profile) @@ -929,7 +930,7 @@ func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) } } -func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) { +func prepareEmailQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Email, error)) { return sq.Select( UserIDCol.identifier(), UserCreationDateCol.identifier(), @@ -940,7 +941,7 @@ func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) { HumanEmailCol.identifier(), HumanIsEmailVerifiedCol.identifier()). From(userTable.identifier()). - LeftJoin(join(HumanUserIDCol, UserIDCol)). + LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*Email, error) { e := new(Email) @@ -976,7 +977,7 @@ func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) { } } -func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) { +func preparePhoneQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) { return sq.Select( UserIDCol.identifier(), UserCreationDateCol.identifier(), @@ -987,7 +988,7 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) { HumanPhoneCol.identifier(), HumanIsPhoneVerifiedCol.identifier()). From(userTable.identifier()). - LeftJoin(join(HumanUserIDCol, UserIDCol)). + LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*Phone, error) { e := new(Phone) @@ -1023,7 +1024,7 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) { } } -func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { +func prepareNotifyUserQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery() if err != nil { return sq.SelectBuilder{}, nil @@ -1068,7 +1069,7 @@ func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, er loginNamesArgs...). LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+ userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+ - userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(), + userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*NotifyUser, error) { @@ -1155,7 +1156,7 @@ func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, er } } -func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { +func prepareUserUniqueQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (bool, error)) { return sq.Select( UserIDCol.identifier(), UserStateCol.identifier(), @@ -1164,7 +1165,7 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { HumanEmailCol.identifier(), HumanIsEmailVerifiedCol.identifier()). From(userTable.identifier()). - LeftJoin(join(HumanUserIDCol, UserIDCol)). + LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (bool, error) { userID := sql.NullString{} @@ -1192,7 +1193,7 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { } } -func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { +func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery() if err != nil { return sq.SelectBuilder{}, nil @@ -1239,7 +1240,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { loginNamesArgs...). LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+ userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+ - userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(), + userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Users, error) { diff --git a/internal/query/user_auth_method.go b/internal/query/user_auth_method.go index 3fca2a43e3..0321a87501 100644 --- a/internal/query/user_auth_method.go +++ b/internal/query/user_auth_method.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -91,7 +92,7 @@ func (q *Queries) SearchUserAuthMethods(ctx context.Context, queries *UserAuthMe ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareUserAuthMethodsQuery() + query, scan := prepareUserAuthMethodsQuery(ctx, q.client) eq := sq.Eq{UserAuthMethodColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { eq[UserAuthMethodColumnOwnerRemoved.identifier()] = false @@ -203,7 +204,7 @@ func (q *UserAuthMethodSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectB return query } -func prepareUserAuthMethodsQuery() (sq.SelectBuilder, func(*sql.Rows) (*AuthMethods, error)) { +func prepareUserAuthMethodsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*AuthMethods, error)) { return sq.Select( UserAuthMethodColumnTokenID.identifier(), UserAuthMethodColumnCreationDate.identifier(), @@ -215,7 +216,8 @@ func prepareUserAuthMethodsQuery() (sq.SelectBuilder, func(*sql.Rows) (*AuthMeth UserAuthMethodColumnState.identifier(), UserAuthMethodColumnMethodType.identifier(), countColumn.identifier()). - From(userAuthMethodTable.identifier()).PlaceholderFormat(sq.Dollar), + From(userAuthMethodTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*AuthMethods, error) { userAuthMethods := make([]*AuthMethod, 0) var count uint64 diff --git a/internal/query/user_auth_method_test.go b/internal/query/user_auth_method_test.go index 8c77f546c1..b09d6c9e79 100644 --- a/internal/query/user_auth_method_test.go +++ b/internal/query/user_auth_method_test.go @@ -11,6 +11,33 @@ import ( "github.com/zitadel/zitadel/internal/domain" ) +var ( + prepareUserAuthMethodsStmt = `SELECT projections.user_auth_methods4.token_id,` + + ` projections.user_auth_methods4.creation_date,` + + ` projections.user_auth_methods4.change_date,` + + ` projections.user_auth_methods4.resource_owner,` + + ` projections.user_auth_methods4.user_id,` + + ` projections.user_auth_methods4.sequence,` + + ` projections.user_auth_methods4.name,` + + ` projections.user_auth_methods4.state,` + + ` projections.user_auth_methods4.method_type,` + + ` COUNT(*) OVER ()` + + ` FROM projections.user_auth_methods4` + + ` AS OF SYSTEM TIME '-1 ms'` + prepareUserAuthMethodsCols = []string{ + "token_id", + "creation_date", + "change_date", + "resource_owner", + "user_id", + "sequence", + "name", + "state", + "method_type", + "count", + } +) + func Test_UserAuthMethodPrepares(t *testing.T) { type want struct { sqlExpectations sqlExpectation @@ -27,17 +54,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+ - ` projections.user_auth_methods4.creation_date,`+ - ` projections.user_auth_methods4.change_date,`+ - ` projections.user_auth_methods4.resource_owner,`+ - ` projections.user_auth_methods4.user_id,`+ - ` projections.user_auth_methods4.sequence,`+ - ` projections.user_auth_methods4.name,`+ - ` projections.user_auth_methods4.state,`+ - ` projections.user_auth_methods4.method_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods4`), + regexp.QuoteMeta(prepareUserAuthMethodsStmt), nil, nil, ), @@ -49,29 +66,8 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+ - ` projections.user_auth_methods4.creation_date,`+ - ` projections.user_auth_methods4.change_date,`+ - ` projections.user_auth_methods4.resource_owner,`+ - ` projections.user_auth_methods4.user_id,`+ - ` projections.user_auth_methods4.sequence,`+ - ` projections.user_auth_methods4.name,`+ - ` projections.user_auth_methods4.state,`+ - ` projections.user_auth_methods4.method_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods4`), - []string{ - "token_id", - "creation_date", - "change_date", - "resource_owner", - "user_id", - "sequence", - "name", - "state", - "method_type", - "count", - }, + regexp.QuoteMeta(prepareUserAuthMethodsStmt), + prepareUserAuthMethodsCols, [][]driver.Value{ { "token_id", @@ -111,29 +107,8 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+ - ` projections.user_auth_methods4.creation_date,`+ - ` projections.user_auth_methods4.change_date,`+ - ` projections.user_auth_methods4.resource_owner,`+ - ` projections.user_auth_methods4.user_id,`+ - ` projections.user_auth_methods4.sequence,`+ - ` projections.user_auth_methods4.name,`+ - ` projections.user_auth_methods4.state,`+ - ` projections.user_auth_methods4.method_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods4`), - []string{ - "token_id", - "creation_date", - "change_date", - "resource_owner", - "user_id", - "sequence", - "name", - "state", - "method_type", - "count", - }, + regexp.QuoteMeta(prepareUserAuthMethodsStmt), + prepareUserAuthMethodsCols, [][]driver.Value{ { "token_id", @@ -195,17 +170,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+ - ` projections.user_auth_methods4.creation_date,`+ - ` projections.user_auth_methods4.change_date,`+ - ` projections.user_auth_methods4.resource_owner,`+ - ` projections.user_auth_methods4.user_id,`+ - ` projections.user_auth_methods4.sequence,`+ - ` projections.user_auth_methods4.name,`+ - ` projections.user_auth_methods4.state,`+ - ` projections.user_auth_methods4.method_type,`+ - ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods4`), + regexp.QuoteMeta(prepareUserAuthMethodsStmt), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -220,7 +185,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/user_grant.go b/internal/query/user_grant.go index 9258388c7b..15df7f5839 100644 --- a/internal/query/user_grant.go +++ b/internal/query/user_grant.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/domain" "github.com/zitadel/zitadel/internal/errors" @@ -225,7 +226,7 @@ func (q *Queries) UserGrant(ctx context.Context, shouldTriggerBulk bool, withOwn projection.UserGrantProjection.Trigger(ctx) } - query, scan := prepareUserGrantQuery() + query, scan := prepareUserGrantQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -246,7 +247,7 @@ func (q *Queries) UserGrants(ctx context.Context, queries *UserGrantsQueries, wi ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := prepareUserGrantsQuery() + query, scan := prepareUserGrantsQuery(ctx, q.client) eq := sq.Eq{UserGrantInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} if !withOwnerRemoved { addUserGrantWithoutOwnerRemoved(eq) @@ -274,7 +275,7 @@ func (q *Queries) UserGrants(ctx context.Context, queries *UserGrantsQueries, wi return grants, nil } -func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, error)) { +func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*UserGrant, error)) { return sq.Select( UserGrantID.identifier(), UserGrantCreationDate.identifier(), @@ -307,7 +308,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro LeftJoin(join(HumanUserIDCol, UserGrantUserID)). LeftJoin(join(OrgColumnID, UserGrantResourceOwner)). LeftJoin(join(ProjectColumnID, UserGrantProjectID)). - LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)). + LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), @@ -382,7 +383,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro } } -func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, error)) { +func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, error)) { return sq.Select( UserGrantID.identifier(), UserGrantCreationDate.identifier(), @@ -417,7 +418,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e LeftJoin(join(HumanUserIDCol, UserGrantUserID)). LeftJoin(join(OrgColumnID, UserGrantResourceOwner)). LeftJoin(join(ProjectColumnID, UserGrantProjectID)). - LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)). + LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))). Where( sq.Eq{LoginNameIsPrimaryCol.identifier(): true}, ).PlaceholderFormat(sq.Dollar), diff --git a/internal/query/user_grant_test.go b/internal/query/user_grant_test.go index c486cbedda..d7fccea10c 100644 --- a/internal/query/user_grant_test.go +++ b/internal/query/user_grant_test.go @@ -43,6 +43,7 @@ var ( " LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" + " LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" + " LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" + + ` AS OF SYSTEM TIME '-1 ms' ` + " WHERE projections.login_names2.is_primary = $1") userGrantCols = []string{ "id", @@ -98,6 +99,7 @@ var ( " LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" + " LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" + " LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" + + ` AS OF SYSTEM TIME '-1 ms' ` + " WHERE projections.login_names2.is_primary = $1") userGrantsCols = append( userGrantCols, @@ -923,7 +925,7 @@ func Test_UserGrantPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/user_membership.go b/internal/query/user_membership.go index dfeeda9cc2..f72ef4f085 100644 --- a/internal/query/user_membership.go +++ b/internal/query/user_membership.go @@ -8,6 +8,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -108,7 +109,7 @@ func (q *Queries) Memberships(ctx context.Context, queries *MembershipSearchQuer ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, queryArgs, scan := prepareMembershipsQuery(withOwnerRemoved) + query, queryArgs, scan := prepareMembershipsQuery(ctx, q.client, withOwnerRemoved) eq := sq.Eq{membershipInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()} stmt, args, err := queries.toQuery(query).Where(eq).ToSql() if err != nil { @@ -221,7 +222,7 @@ func getMembershipFromQuery(withOwnerRemoved bool) (string, []interface{}) { args } -func prepareMembershipsQuery(withOwnerRemoved bool) (sq.SelectBuilder, []interface{}, func(*sql.Rows) (*Memberships, error)) { +func prepareMembershipsQuery(ctx context.Context, db prepareDatabase, withOwnerRemoved bool) (sq.SelectBuilder, []interface{}, func(*sql.Rows) (*Memberships, error)) { query, args := getMembershipFromQuery(withOwnerRemoved) return sq.Select( membershipUserID.identifier(), @@ -241,7 +242,7 @@ func prepareMembershipsQuery(withOwnerRemoved bool) (sq.SelectBuilder, []interfa ).From(query). LeftJoin(join(ProjectColumnID, membershipProjectID)). LeftJoin(join(OrgColumnID, membershipOrgID)). - LeftJoin(join(ProjectGrantColumnGrantID, membershipGrantID)). + LeftJoin(join(ProjectGrantColumnGrantID, membershipGrantID) + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), args, func(rows *sql.Rows) (*Memberships, error) { diff --git a/internal/query/user_membership_test.go b/internal/query/user_membership_test.go index 75ede35973..60708637ff 100644 --- a/internal/query/user_membership_test.go +++ b/internal/query/user_membership_test.go @@ -1,6 +1,7 @@ package query import ( + "context" "database/sql" "database/sql/driver" "errors" @@ -88,7 +89,8 @@ var ( ") AS memberships" + " LEFT JOIN projections.projects3 ON memberships.project_id = projections.projects3.id AND memberships.instance_id = projections.projects3.instance_id" + " LEFT JOIN projections.orgs ON memberships.org_id = projections.orgs.id AND memberships.instance_id = projections.orgs.instance_id" + - " LEFT JOIN projections.project_grants3 ON memberships.grant_id = projections.project_grants3.grant_id AND memberships.instance_id = projections.project_grants3.instance_id") + " LEFT JOIN projections.project_grants3 ON memberships.grant_id = projections.project_grants3.grant_id AND memberships.instance_id = projections.project_grants3.instance_id" + + ` AS OF SYSTEM TIME '-1 ms'`) membershipCols = []string{ "user_id", "roles", @@ -447,14 +449,14 @@ func Test_MembershipPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } -func prepareMembershipWrapper(withOwnerRemoved bool) func() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) { - builder, _, fun := prepareMembershipsQuery(withOwnerRemoved) - return func() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) { +func prepareMembershipWrapper(withOwnerRemoved bool) func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) { + return func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) { + builder, _, fun := prepareMembershipsQuery(ctx, db, withOwnerRemoved) return builder, fun } } diff --git a/internal/query/user_metadata.go b/internal/query/user_metadata.go index 20afb6fe89..b7c4c27360 100644 --- a/internal/query/user_metadata.go +++ b/internal/query/user_metadata.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/query/projection" "github.com/zitadel/zitadel/internal/telemetry/tracing" @@ -84,7 +85,7 @@ func (q *Queries) GetUserMetadataByKey(ctx context.Context, shouldTriggerBulk bo projection.UserMetadataProjection.Trigger(ctx) } - query, scan := prepareUserMetadataQuery() + query, scan := prepareUserMetadataQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -113,7 +114,7 @@ func (q *Queries) SearchUserMetadata(ctx context.Context, shouldTriggerBulk bool projection.UserMetadataProjection.Trigger(ctx) } - query, scan := prepareUserMetadataListQuery() + query, scan := prepareUserMetadataListQuery(ctx, q.client) eq := sq.Eq{ UserMetadataUserIDCol.identifier(): userID, UserMetadataInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(), @@ -163,7 +164,7 @@ func NewUserMetadataKeySearchQuery(value string, comparison TextComparison) (Sea return NewTextQuery(UserMetadataKeyCol, value, comparison) } -func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata, error)) { +func prepareUserMetadataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*UserMetadata, error)) { return sq.Select( UserMetadataCreationDateCol.identifier(), UserMetadataChangeDateCol.identifier(), @@ -172,7 +173,7 @@ func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata UserMetadataKeyCol.identifier(), UserMetadataValueCol.identifier(), ). - From(userMetadataTable.identifier()). + From(userMetadataTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*UserMetadata, error) { m := new(UserMetadata) @@ -195,7 +196,7 @@ func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata } } -func prepareUserMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserMetadataList, error)) { +func prepareUserMetadataListQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*UserMetadataList, error)) { return sq.Select( UserMetadataCreationDateCol.identifier(), UserMetadataChangeDateCol.identifier(), @@ -204,7 +205,7 @@ func prepareUserMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserMet UserMetadataKeyCol.identifier(), UserMetadataValueCol.identifier(), countColumn.identifier()). - From(userMetadataTable.identifier()). + From(userMetadataTable.identifier() + db.Timetravel(call.Took(ctx))). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*UserMetadataList, error) { metadata := make([]*UserMetadata, 0) diff --git a/internal/query/user_metadata_test.go b/internal/query/user_metadata_test.go index ba372fd78a..781caf732d 100644 --- a/internal/query/user_metadata_test.go +++ b/internal/query/user_metadata_test.go @@ -18,7 +18,8 @@ var ( ` projections.user_metadata4.sequence,` + ` projections.user_metadata4.key,` + ` projections.user_metadata4.value` + - ` FROM projections.user_metadata4` + ` FROM projections.user_metadata4` + + ` AS OF SYSTEM TIME '-1 ms'` userMetadataCols = []string{ "creation_date", "change_date", @@ -242,7 +243,7 @@ func Test_UserMetadataPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/user_otp.go b/internal/query/user_otp.go index 6d480610f8..955b7c924e 100644 --- a/internal/query/user_otp.go +++ b/internal/query/user_otp.go @@ -18,7 +18,7 @@ func (q *Queries) GetHumanOTPSecret(ctx context.Context, userID, resourceowner s if userID == "" { return "", errors.ThrowPreconditionFailed(nil, "QUERY-8N9ds", "Errors.User.UserIDMissing") } - existingOTP, err := q.otpWriteModelByID(ctx, userID, resourceowner) + existingOTP, err := q.otpReadModelByID(ctx, userID, resourceowner) if err != nil { return "", err } @@ -29,35 +29,39 @@ func (q *Queries) GetHumanOTPSecret(ctx context.Context, userID, resourceowner s return crypto.DecryptString(existingOTP.Secret, q.multifactors.OTP.CryptoMFA) } -func (q *Queries) otpWriteModelByID(ctx context.Context, userID, resourceOwner string) (writeModel *HumanOTPWriteModel, err error) { +func (q *Queries) otpReadModelByID(ctx context.Context, userID, resourceOwner string) (readModel *HumanOTPReadModel, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - writeModel = NewHumanOTPWriteModel(userID, resourceOwner) - err = q.eventstore.FilterToQueryReducer(ctx, writeModel) + readModel = NewHumanOTPReadModel(userID, resourceOwner) + err = q.eventstore.FilterToQueryReducer(ctx, readModel) if err != nil { return nil, err } - return writeModel, nil + return readModel, nil } -type HumanOTPWriteModel struct { - eventstore.WriteModel +type HumanOTPReadModel struct { + *eventstore.ReadModel State domain.MFAState Secret *crypto.CryptoValue } -func NewHumanOTPWriteModel(userID, resourceOwner string) *HumanOTPWriteModel { - return &HumanOTPWriteModel{ - WriteModel: eventstore.WriteModel{ +func (rm *HumanOTPReadModel) AppendEvents(events ...eventstore.Event) { + rm.ReadModel.AppendEvents(events...) +} + +func NewHumanOTPReadModel(userID, resourceOwner string) *HumanOTPReadModel { + return &HumanOTPReadModel{ + ReadModel: &eventstore.ReadModel{ AggregateID: userID, ResourceOwner: resourceOwner, }, } } -func (wm *HumanOTPWriteModel) Reduce() error { +func (wm *HumanOTPReadModel) Reduce() error { for _, event := range wm.Events { switch e := event.(type) { case *user.HumanOTPAddedEvent: @@ -71,10 +75,10 @@ func (wm *HumanOTPWriteModel) Reduce() error { wm.State = domain.MFAStateRemoved } } - return wm.WriteModel.Reduce() + return wm.ReadModel.Reduce() } -func (wm *HumanOTPWriteModel) Query() *eventstore.SearchQueryBuilder { +func (wm *HumanOTPReadModel) Query() *eventstore.SearchQueryBuilder { query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). AddQuery(). AggregateTypes(user.AggregateType). diff --git a/internal/query/user_password.go b/internal/query/user_password.go index 66cebb6148..715c9ed871 100644 --- a/internal/query/user_password.go +++ b/internal/query/user_password.go @@ -12,8 +12,8 @@ import ( "github.com/zitadel/zitadel/internal/telemetry/tracing" ) -type HumanPasswordWriteModel struct { - eventstore.WriteModel +type HumanPasswordReadModel struct { + *eventstore.ReadModel Secret *crypto.CryptoValue SecretChangeRequired bool @@ -33,7 +33,7 @@ func (q *Queries) GetHumanPassword(ctx context.Context, orgID, userID string) (p if userID == "" { return nil, "", errors.ThrowInvalidArgument(nil, "QUERY-4Mfsf", "Errors.User.UserIDMissing") } - existingPassword, err := q.passwordWriteModel(ctx, userID, orgID) + existingPassword, err := q.passwordReadModel(ctx, userID, orgID) if err != nil { return nil, "", errors.ThrowInternal(nil, "QUERY-p1k1n2i", "Errors.User.NotFound") } @@ -48,28 +48,32 @@ func (q *Queries) GetHumanPassword(ctx context.Context, orgID, userID string) (p return nil, "", nil } -func (q *Queries) passwordWriteModel(ctx context.Context, userID, resourceOwner string) (writeModel *HumanPasswordWriteModel, err error) { +func (q *Queries) passwordReadModel(ctx context.Context, userID, resourceOwner string) (readModel *HumanPasswordReadModel, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - writeModel = NewHumanPasswordWriteModel(userID, resourceOwner) - err = q.eventstore.FilterToQueryReducer(ctx, writeModel) + readModel = NewHumanPasswordReadModel(userID, resourceOwner) + err = q.eventstore.FilterToQueryReducer(ctx, readModel) if err != nil { return nil, err } - return writeModel, nil + return readModel, nil } -func NewHumanPasswordWriteModel(userID, resourceOwner string) *HumanPasswordWriteModel { - return &HumanPasswordWriteModel{ - WriteModel: eventstore.WriteModel{ +func NewHumanPasswordReadModel(userID, resourceOwner string) *HumanPasswordReadModel { + return &HumanPasswordReadModel{ + ReadModel: &eventstore.ReadModel{ AggregateID: userID, ResourceOwner: resourceOwner, }, } } -func (wm *HumanPasswordWriteModel) Reduce() error { +func (rm *HumanPasswordReadModel) AppendEvents(events ...eventstore.Event) { + rm.ReadModel.AppendEvents(events...) +} + +func (wm *HumanPasswordReadModel) Reduce() error { for _, event := range wm.Events { switch e := event.(type) { case *user.HumanAddedEvent: @@ -107,11 +111,12 @@ func (wm *HumanPasswordWriteModel) Reduce() error { wm.UserState = domain.UserStateDeleted } } - return wm.WriteModel.Reduce() + return wm.ReadModel.Reduce() } -func (wm *HumanPasswordWriteModel) Query() *eventstore.SearchQueryBuilder { +func (wm *HumanPasswordReadModel) Query() *eventstore.SearchQueryBuilder { query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent). + AllowTimeTravel(). AddQuery(). AggregateTypes(user.AggregateType). AggregateIDs(wm.AggregateID). diff --git a/internal/query/user_personal_access_token.go b/internal/query/user_personal_access_token.go index b16d75a005..4afab7ec89 100644 --- a/internal/query/user_personal_access_token.go +++ b/internal/query/user_personal_access_token.go @@ -9,6 +9,7 @@ import ( sq "github.com/Masterminds/squirrel" "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/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -92,7 +93,7 @@ func (q *Queries) PersonalAccessTokenByID(ctx context.Context, shouldTriggerBulk projection.PersonalAccessTokenProjection.Trigger(ctx) } - query, scan := preparePersonalAccessTokenQuery() + query, scan := preparePersonalAccessTokenQuery(ctx, q.client) for _, q := range queries { query = q.toQuery(query) } @@ -116,7 +117,7 @@ func (q *Queries) SearchPersonalAccessTokens(ctx context.Context, queries *Perso ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() - query, scan := preparePersonalAccessTokensQuery() + query, scan := preparePersonalAccessTokensQuery(ctx, q.client) eq := sq.Eq{ PersonalAccessTokenColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(), } @@ -165,7 +166,7 @@ func (q *PersonalAccessTokenSearchQueries) toQuery(query sq.SelectBuilder) sq.Se return query } -func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*PersonalAccessToken, error)) { +func preparePersonalAccessTokenQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PersonalAccessToken, error)) { return sq.Select( PersonalAccessTokenColumnID.identifier(), PersonalAccessTokenColumnCreationDate.identifier(), @@ -175,7 +176,8 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso PersonalAccessTokenColumnUserID.identifier(), PersonalAccessTokenColumnExpiration.identifier(), PersonalAccessTokenColumnScopes.identifier()). - From(personalAccessTokensTable.identifier()).PlaceholderFormat(sq.Dollar), + From(personalAccessTokensTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*PersonalAccessToken, error) { p := new(PersonalAccessToken) err := row.Scan( @@ -198,7 +200,7 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso } } -func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*PersonalAccessTokens, error)) { +func preparePersonalAccessTokensQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PersonalAccessTokens, error)) { return sq.Select( PersonalAccessTokenColumnID.identifier(), PersonalAccessTokenColumnCreationDate.identifier(), @@ -209,7 +211,8 @@ func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*Per PersonalAccessTokenColumnExpiration.identifier(), PersonalAccessTokenColumnScopes.identifier(), countColumn.identifier()). - From(personalAccessTokensTable.identifier()).PlaceholderFormat(sq.Dollar), + From(personalAccessTokensTable.identifier() + db.Timetravel(call.Took(ctx))). + PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*PersonalAccessTokens, error) { personalAccessTokens := make([]*PersonalAccessToken, 0) var count uint64 diff --git a/internal/query/user_personal_access_token_test.go b/internal/query/user_personal_access_token_test.go index 3105d14b00..6a74e04de2 100644 --- a/internal/query/user_personal_access_token_test.go +++ b/internal/query/user_personal_access_token_test.go @@ -23,7 +23,8 @@ var ( " projections.personal_access_tokens3.user_id," + " projections.personal_access_tokens3.expiration," + " projections.personal_access_tokens3.scopes" + - " FROM projections.personal_access_tokens3") + " FROM projections.personal_access_tokens3" + + ` AS OF SYSTEM TIME '-1 ms'`) personalAccessTokenCols = []string{ "id", "creation_date", @@ -44,7 +45,8 @@ var ( " projections.personal_access_tokens3.expiration," + " projections.personal_access_tokens3.scopes," + " COUNT(*) OVER ()" + - " FROM projections.personal_access_tokens3") + " FROM projections.personal_access_tokens3" + + " AS OF SYSTEM TIME '-1 ms'") personalAccessTokensCols = []string{ "id", "creation_date", @@ -264,7 +266,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/query/user_test.go b/internal/query/user_test.go index 7a753e1307..d90e17b901 100644 --- a/internal/query/user_test.go +++ b/internal/query/user_test.go @@ -8,7 +8,6 @@ import ( "regexp" "testing" - sq "github.com/Masterminds/squirrel" "golang.org/x/text/language" "github.com/zitadel/zitadel/internal/database" @@ -59,7 +58,8 @@ var ( ` ON login_names.user_id = projections.users8.id AND login_names.instance_id = projections.users8.instance_id` + ` LEFT JOIN` + ` (` + preferredLoginNameQuery + `) AS preferred_login_name` + - ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` userCols = []string{ "id", "creation_date", @@ -106,7 +106,8 @@ var ( ` projections.users8_humans.gender,` + ` projections.users8_humans.avatar_key` + ` FROM projections.users8` + - ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` profileCols = []string{ "id", "creation_date", @@ -131,7 +132,8 @@ var ( ` projections.users8_humans.email,` + ` projections.users8_humans.is_email_verified` + ` FROM projections.users8` + - ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` emailCols = []string{ "id", "creation_date", @@ -151,7 +153,8 @@ var ( ` projections.users8_humans.phone,` + ` projections.users8_humans.is_phone_verified` + ` FROM projections.users8` + - ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` phoneCols = []string{ "id", "creation_date", @@ -169,7 +172,8 @@ var ( ` projections.users8_humans.email,` + ` projections.users8_humans.is_email_verified` + ` FROM projections.users8` + - ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + ` LEFT JOIN projections.users8_humans ON projections.users8.id = projections.users8_humans.user_id AND projections.users8.instance_id = projections.users8_humans.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` userUniqueCols = []string{ "id", "state", @@ -211,7 +215,8 @@ var ( ` ON login_names.user_id = projections.users8.id AND login_names.instance_id = projections.users8.instance_id` + ` LEFT JOIN` + ` (` + preferredLoginNameQuery + `) AS preferred_login_name` + - ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` notifyUserCols = []string{ "id", "creation_date", @@ -277,7 +282,8 @@ var ( ` ON login_names.user_id = projections.users8.id AND login_names.instance_id = projections.users8.instance_id` + ` LEFT JOIN` + ` (` + preferredLoginNameQuery + `) AS preferred_login_name` + - ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + ` ON preferred_login_name.user_id = projections.users8.id AND preferred_login_name.instance_id = projections.users8.instance_id` + + ` AS OF SYSTEM TIME '-1 ms'` usersCols = []string{ "id", "creation_date", @@ -324,10 +330,8 @@ func Test_UserPrepares(t *testing.T) { object interface{} }{ { - name: "prepareUserQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { - return prepareUserQuery() - }, + name: "prepareUserQuery no result", + prepare: prepareUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(userQuery), @@ -344,10 +348,8 @@ func Test_UserPrepares(t *testing.T) { object: (*User)(nil), }, { - name: "prepareUserQuery human found", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { - return prepareUserQuery() - }, + name: "prepareUserQuery human found", + prepare: prepareUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(userQuery), @@ -413,10 +415,8 @@ func Test_UserPrepares(t *testing.T) { }, }, { - name: "prepareUserQuery machine found", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { - return prepareUserQuery() - }, + name: "prepareUserQuery machine found", + prepare: prepareUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(userQuery), @@ -475,10 +475,8 @@ func Test_UserPrepares(t *testing.T) { }, }, { - name: "prepareUserQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*User, error)) { - return prepareUserQuery() - }, + name: "prepareUserQuery sql err", + prepare: prepareUserQuery, want: want{ sqlExpectations: mockQueryErr( regexp.QuoteMeta(userQuery), @@ -842,10 +840,8 @@ func Test_UserPrepares(t *testing.T) { object: nil, }, { - name: "prepareNotifyUserQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { - return prepareNotifyUserQuery() - }, + name: "prepareNotifyUserQuery no result", + prepare: prepareNotifyUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(notifyUserQuery), @@ -862,10 +858,8 @@ func Test_UserPrepares(t *testing.T) { object: (*NotifyUser)(nil), }, { - name: "prepareNotifyUserQuery notify found", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { - return prepareNotifyUserQuery() - }, + name: "prepareNotifyUserQuery notify found", + prepare: prepareNotifyUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(notifyUserQuery), @@ -927,10 +921,8 @@ func Test_UserPrepares(t *testing.T) { }, }, { - name: "prepareNotifyUserQuery not notify found (error)", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { - return prepareNotifyUserQuery() - }, + name: "prepareNotifyUserQuery not notify found (error)", + prepare: prepareNotifyUserQuery, want: want{ sqlExpectations: mockQuery( regexp.QuoteMeta(notifyUserQuery), @@ -974,10 +966,8 @@ func Test_UserPrepares(t *testing.T) { object: (*NotifyUser)(nil), }, { - name: "prepareNotifyUserQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { - return prepareNotifyUserQuery() - }, + name: "prepareNotifyUserQuery sql err", + prepare: prepareNotifyUserQuery, want: want{ sqlExpectations: mockQueryErr( regexp.QuoteMeta(notifyUserQuery), @@ -993,10 +983,8 @@ func Test_UserPrepares(t *testing.T) { object: nil, }, { - name: "prepareUsersQuery no result", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { - return prepareUsersQuery() - }, + name: "prepareUsersQuery no result", + prepare: prepareUsersQuery, want: want{ sqlExpectations: mockQueries( regexp.QuoteMeta(usersQuery), @@ -1013,10 +1001,8 @@ func Test_UserPrepares(t *testing.T) { object: &Users{Users: []*User{}}, }, { - name: "prepareUsersQuery one result", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { - return prepareUsersQuery() - }, + name: "prepareUsersQuery one result", + prepare: prepareUsersQuery, want: want{ sqlExpectations: mockQueries( regexp.QuoteMeta(usersQuery), @@ -1090,10 +1076,8 @@ func Test_UserPrepares(t *testing.T) { }, }, { - name: "prepareUsersQuery multiple results", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { - return prepareUsersQuery() - }, + name: "prepareUsersQuery multiple results", + prepare: prepareUsersQuery, want: want{ sqlExpectations: mockQueries( regexp.QuoteMeta(usersQuery), @@ -1216,10 +1200,8 @@ func Test_UserPrepares(t *testing.T) { }, }, { - name: "prepareUsersQuery sql err", - prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { - return prepareUsersQuery() - }, + name: "prepareUsersQuery sql err", + prepare: prepareUsersQuery, want: want{ sqlExpectations: mockQueryErr( regexp.QuoteMeta(usersQuery), @@ -1237,7 +1219,7 @@ func Test_UserPrepares(t *testing.T) { } for _, tt := range tests { 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...) }) } } diff --git a/internal/telemetry/otel/resource.go b/internal/telemetry/otel/resource.go index dac46e70e4..e4c8478cba 100644 --- a/internal/telemetry/otel/resource.go +++ b/internal/telemetry/otel/resource.go @@ -3,7 +3,7 @@ package otel import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.7.0" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" "github.com/zitadel/zitadel/cmd/build" )