diff --git a/.github/workflows/test-code.yml b/.github/workflows/test-code.yml index 34765700ef..7c1e51df71 100644 --- a/.github/workflows/test-code.yml +++ b/.github/workflows/test-code.yml @@ -13,6 +13,10 @@ jobs: env: DOCKER_BUILDKIT: 1 steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.19 - name: Source checkout uses: actions/checkout@v2 - name: Set up QEMU @@ -26,7 +30,7 @@ jobs: uses: goreleaser/goreleaser-action@v3 with: install-only: true - version: v1.8.3 + version: v1.10.3 - name: Build and Unit Test run: GOOS="linux" GOARCH="amd64" goreleaser build --id prod --snapshot --single-target --rm-dist --output .artifacts/zitadel/zitadel - name: Publish go coverage diff --git a/.github/workflows/zitadel.yml b/.github/workflows/zitadel.yml index 9b12c9e653..2fee65de3b 100644 --- a/.github/workflows/zitadel.yml +++ b/.github/workflows/zitadel.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.19 - name: Source checkout uses: actions/checkout@v2 with: @@ -65,7 +65,7 @@ jobs: if: steps.semantic.outputs.new_release_published == 'true' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' with: distribution: goreleaser - version: v1.8.3 + version: v1.11.0 args: release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml index f9018990cd..08ca8be1be 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -24,8 +24,7 @@ before: - sh -c "cp -r .artifacts/console/* internal/api/ui/console/static/" builds: - - id: prod - env: + - env: - CGO_ENABLED=0 goos: - linux @@ -36,13 +35,7 @@ builds: - arm64 ldflags: -s -w -X github.com/zitadel/zitadel/cmd/build.version={{.Version}} -X github.com/zitadel/zitadel/cmd/build.commit={{.Commit}} -X github.com/zitadel/zitadel/cmd/build.date={{.Date}} - - id: dev - env: - - CGO_ENABLED=0 - binary: zitadel-debug - gcflags: all=-N -l - ldflags: "" - + dist: .artifacts/goreleaser dockers: @@ -54,8 +47,6 @@ dockers: dockerfile: build/Dockerfile build_flag_templates: - "--platform=linux/amd64" - ids: - - prod - image_templates: - ghcr.io/zitadel/zitadel:{{ .Tag }}-arm64 - ghcr.io/zitadel/zitadel:{{ .ShortCommit }}-arm64 @@ -64,8 +55,6 @@ dockers: dockerfile: build/Dockerfile build_flag_templates: - "--platform=linux/arm64" - ids: - - prod docker_manifests: - id: zitadel-latest @@ -84,8 +73,6 @@ docker_manifests: archives: - name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}' - builds: - - prod replacements: darwin: Darwin linux: Linux @@ -138,4 +125,4 @@ brews: announce: discord: enabled: true - message_template: 'ZITADEL {{ .Tag }} is ready! Check the notes: https://github.com/zitadel/zitadel/releases/tag/{{ .Tag }}' + message_template: 'ZITADEL {{ .Tag }} is ready! Check the notes: https://github.com/zitadel/zitadel/releases/tag/{{ .Tag }}' \ No newline at end of file diff --git a/build/zitadel/Dockerfile b/build/zitadel/Dockerfile index 1b0b8ed2f7..49b14eaa5d 100644 --- a/build/zitadel/Dockerfile +++ b/build/zitadel/Dockerfile @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.17 +ARG GO_VERSION=1.19 ####################### ## Go dependencies diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index 2034957f51..2ae739a54c 100644 --- a/cmd/defaults.yaml +++ b/cmd/defaults.yaml @@ -45,6 +45,7 @@ HTTP1HostHeader: "host" WebAuthNName: ZITADEL Database: + # CockroachDB is the default datbase of ZITADEL cockroach: Host: localhost Port: 26257 @@ -69,6 +70,32 @@ Database: RootCert: "" Cert: "" Key: "" + # Postgres is used as soon as a value is set + # The values describe the possible fields to set values + postgres: + Host: + Port: + Database: + MaxOpenConns: + MaxConnLifetime: + MaxConnIdleTime: + Options: + User: + Username: + Password: + SSL: + Mode: + RootCert: + Cert: + Key: + Admin: + Username: + Password: + SSL: + Mode: + RootCert: + Cert: + Key: Machine: # Cloud hosted VMs need to specify their metadata endpoint so that the machine can be uniquely identified. diff --git a/cmd/initialise/helper.go b/cmd/initialise/helper.go index 45a66de03f..943d165086 100644 --- a/cmd/initialise/helper.go +++ b/cmd/initialise/helper.go @@ -2,27 +2,20 @@ package initialise import ( "database/sql" + "errors" + + "github.com/jackc/pgconn" ) -func exists(query string, args ...interface{}) func(*sql.DB) (exists bool, err error) { - return func(db *sql.DB) (exists bool, err error) { - row := db.QueryRow("SELECT EXISTS("+query+")", args...) - err = row.Scan(&exists) - return exists, err +func exec(db *sql.DB, stmt string, possibleErrCodes []string, args ...interface{}) error { + _, err := db.Exec(stmt, args...) + pgErr := new(pgconn.PgError) + if errors.As(err, &pgErr) { + for _, possibleCode := range possibleErrCodes { + if possibleCode == pgErr.Code { + return nil + } + } } -} - -func exec(stmt string, args ...interface{}) func(*sql.DB) error { - return func(db *sql.DB) error { - _, err := db.Exec(stmt, args...) - return err - } -} - -func verify(db *sql.DB, checkExists func(*sql.DB) (bool, error), create func(*sql.DB) error) error { - exists, err := checkExists(db) - if exists || err != nil { - return err - } - return create(db) + return err } diff --git a/cmd/initialise/init.go b/cmd/initialise/init.go index 3f06ea571a..14c4a0cfcc 100644 --- a/cmd/initialise/init.go +++ b/cmd/initialise/init.go @@ -2,7 +2,7 @@ package initialise import ( "database/sql" - _ "embed" + "embed" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -12,6 +12,26 @@ import ( "github.com/zitadel/zitadel/internal/id" ) +var ( + //go:embed sql/cockroach/* + //go:embed sql/postgres/* + stmts embed.FS + + createUserStmt string + grantStmt string + databaseStmt string + createEventstoreStmt string + createProjectionsStmt string + createSystemStmt string + createEncryptionKeysStmt string + createEventsStmt string + createSystemSequenceStmt string + createUniqueConstraints string + + roleAlreadyExistsCode = "42710" + dbAlreadyExistsCode = "42P04" +) + func New() *cobra.Command { cmd := &cobra.Command{ Use: "init", @@ -39,6 +59,7 @@ The user provided by flags needs privileges to func InitAll(config *Config) { id.Configure(config.Machine) + err := initialise(config.Database, VerifyUser(config.Database.Username(), config.Database.Password()), VerifyDatabase(config.Database.Database()), @@ -53,22 +74,85 @@ func InitAll(config *Config) { func initialise(config database.Config, steps ...func(*sql.DB) error) error { logging.Info("initialization started") + err := ReadStmts(config.Type()) + if err != nil { + return err + } + db, err := database.Connect(config, true) if err != nil { return err } - err = Initialise(db, steps...) - if err != nil { - return err - } - return db.Close() + defer db.Close() + + return Init(db, steps...) } -func Initialise(db *sql.DB, steps ...func(*sql.DB) error) error { +func Init(db *sql.DB, steps ...func(*sql.DB) error) error { for _, step := range steps { if err := step(db); err != nil { return err } } + return nil } + +func ReadStmts(typ string) (err error) { + createUserStmt, err = readStmt(typ, "01_user") + if err != nil { + return err + } + + databaseStmt, err = readStmt(typ, "02_database") + if err != nil { + return err + } + + grantStmt, err = readStmt(typ, "03_grant_user") + if err != nil { + return err + } + + createEventstoreStmt, err = readStmt(typ, "04_eventstore") + if err != nil { + return err + } + + createProjectionsStmt, err = readStmt(typ, "05_projections") + if err != nil { + return err + } + + createSystemStmt, err = readStmt(typ, "06_system") + if err != nil { + return err + } + + createEncryptionKeysStmt, err = readStmt(typ, "07_encryption_keys_table") + if err != nil { + return err + } + + createEventsStmt, err = readStmt(typ, "08_events_table") + if err != nil { + return err + } + + createSystemSequenceStmt, err = readStmt(typ, "09_system_sequence") + if err != nil { + return err + } + + createUniqueConstraints, err = readStmt(typ, "10_unique_constraints_table") + if err != nil { + return err + } + + return nil +} + +func readStmt(typ, step string) (string, error) { + stmt, err := stmts.ReadFile("sql/" + typ + "/" + step + ".sql") + return string(stmt), err +} diff --git a/cmd/initialise/init_test.go b/cmd/initialise/init_test.go index 0d995c29ea..4a1141345a 100644 --- a/cmd/initialise/init_test.go +++ b/cmd/initialise/init_test.go @@ -31,18 +31,6 @@ func prepareDB(t *testing.T, expectations ...expectation) db { type expectation func(m sqlmock.Sqlmock) -func expectExists(query string, value bool, args ...driver.Value) expectation { - return func(m sqlmock.Sqlmock) { - m.ExpectQuery(regexp.QuoteMeta(query)).WithArgs(args...).WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow(value)) - } -} - -func expectQueryErr(query string, err error, args ...driver.Value) expectation { - return func(m sqlmock.Sqlmock) { - m.ExpectQuery(regexp.QuoteMeta(query)).WithArgs(args...).WillReturnError(err) - } -} - func expectExec(stmt string, err error, args ...driver.Value) expectation { return func(m sqlmock.Sqlmock) { query := m.ExpectExec(regexp.QuoteMeta(stmt)).WithArgs(args...) diff --git a/cmd/initialise/sql/04_eventstore.sql b/cmd/initialise/sql/04_eventstore.sql deleted file mode 100644 index e62237d680..0000000000 --- a/cmd/initialise/sql/04_eventstore.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE SCHEMA eventstore \ No newline at end of file diff --git a/cmd/initialise/sql/05_projections.sql b/cmd/initialise/sql/05_projections.sql deleted file mode 100644 index ed68342c49..0000000000 --- a/cmd/initialise/sql/05_projections.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE SCHEMA projections \ No newline at end of file diff --git a/cmd/initialise/sql/06_system.sql b/cmd/initialise/sql/06_system.sql deleted file mode 100644 index 2f0c100cc7..0000000000 --- a/cmd/initialise/sql/06_system.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE SCHEMA system; diff --git a/cmd/initialise/sql/08_enable_hash_sharded_indexes.sql b/cmd/initialise/sql/08_enable_hash_sharded_indexes.sql deleted file mode 100644 index f68c5ed574..0000000000 --- a/cmd/initialise/sql/08_enable_hash_sharded_indexes.sql +++ /dev/null @@ -1 +0,0 @@ -SET experimental_enable_hash_sharded_indexes = on \ No newline at end of file diff --git a/cmd/initialise/sql/10_system_sequence.sql b/cmd/initialise/sql/10_system_sequence.sql deleted file mode 100644 index 25c3821e50..0000000000 --- a/cmd/initialise/sql/10_system_sequence.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE SEQUENCE eventstore.system_seq diff --git a/cmd/initialise/sql/01_user.sql b/cmd/initialise/sql/cockroach/01_user.sql similarity index 55% rename from cmd/initialise/sql/01_user.sql rename to cmd/initialise/sql/cockroach/01_user.sql index 194b848f19..e9473e46c2 100644 --- a/cmd/initialise/sql/01_user.sql +++ b/cmd/initialise/sql/cockroach/01_user.sql @@ -1,2 +1,2 @@ -- replace %[1]s with the name of the user -CREATE USER %[1]s WITH PASSWORD $1 +CREATE USER IF NOT EXISTS %[1]s \ No newline at end of file diff --git a/cmd/initialise/sql/02_database.sql b/cmd/initialise/sql/cockroach/02_database.sql similarity index 57% rename from cmd/initialise/sql/02_database.sql rename to cmd/initialise/sql/cockroach/02_database.sql index 50c599e3b5..8d0e37e565 100644 --- a/cmd/initialise/sql/02_database.sql +++ b/cmd/initialise/sql/cockroach/02_database.sql @@ -1,2 +1,2 @@ -- replace %[1]s with the name of the database -CREATE DATABASE %[1]s \ No newline at end of file +CREATE DATABASE IF NOT EXISTS %[1]s \ No newline at end of file diff --git a/cmd/initialise/sql/03_grant_user.sql b/cmd/initialise/sql/cockroach/03_grant_user.sql similarity index 100% rename from cmd/initialise/sql/03_grant_user.sql rename to cmd/initialise/sql/cockroach/03_grant_user.sql diff --git a/cmd/initialise/sql/cockroach/04_eventstore.sql b/cmd/initialise/sql/cockroach/04_eventstore.sql new file mode 100644 index 0000000000..fca432b3a9 --- /dev/null +++ b/cmd/initialise/sql/cockroach/04_eventstore.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS eventstore; + +GRANT ALL ON ALL TABLES IN SCHEMA eventstore TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/cockroach/05_projections.sql b/cmd/initialise/sql/cockroach/05_projections.sql new file mode 100644 index 0000000000..eafbda805f --- /dev/null +++ b/cmd/initialise/sql/cockroach/05_projections.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS projections; + +GRANT ALL ON ALL TABLES IN SCHEMA projections TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/cockroach/06_system.sql b/cmd/initialise/sql/cockroach/06_system.sql new file mode 100644 index 0000000000..f66c9dbe96 --- /dev/null +++ b/cmd/initialise/sql/cockroach/06_system.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS system; + +GRANT ALL ON ALL TABLES IN SCHEMA system TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/07_encryption_keys_table.sql b/cmd/initialise/sql/cockroach/07_encryption_keys_table.sql similarity index 54% rename from cmd/initialise/sql/07_encryption_keys_table.sql rename to cmd/initialise/sql/cockroach/07_encryption_keys_table.sql index 77b7e6cd91..61cb617fdf 100644 --- a/cmd/initialise/sql/07_encryption_keys_table.sql +++ b/cmd/initialise/sql/cockroach/07_encryption_keys_table.sql @@ -1,4 +1,4 @@ -CREATE TABLE system.encryption_keys ( +CREATE TABLE IF NOT EXISTS system.encryption_keys ( id TEXT NOT NULL , key TEXT NOT NULL diff --git a/cmd/initialise/sql/09_events_table.sql b/cmd/initialise/sql/cockroach/08_events_table.sql similarity index 92% rename from cmd/initialise/sql/09_events_table.sql rename to cmd/initialise/sql/cockroach/08_events_table.sql index f2df84f11d..78c1fba585 100644 --- a/cmd/initialise/sql/09_events_table.sql +++ b/cmd/initialise/sql/cockroach/08_events_table.sql @@ -1,4 +1,6 @@ -CREATE TABLE eventstore.events ( +SET experimental_enable_hash_sharded_indexes = on; + +CREATE TABLE IF NOT EXISTS eventstore.events ( id UUID DEFAULT gen_random_uuid() , event_type TEXT NOT NULL , aggregate_type TEXT NOT NULL @@ -22,4 +24,4 @@ CREATE TABLE eventstore.events ( , INDEX max_sequence (aggregate_type, aggregate_id, event_sequence DESC, instance_id) , CONSTRAINT previous_sequence_unique UNIQUE (previous_aggregate_sequence DESC, instance_id) , CONSTRAINT prev_agg_type_seq_unique UNIQUE(previous_aggregate_type_sequence, instance_id) -) +); \ No newline at end of file diff --git a/cmd/initialise/sql/cockroach/09_system_sequence.sql b/cmd/initialise/sql/cockroach/09_system_sequence.sql new file mode 100644 index 0000000000..596e887664 --- /dev/null +++ b/cmd/initialise/sql/cockroach/09_system_sequence.sql @@ -0,0 +1 @@ +CREATE SEQUENCE IF NOT EXISTS eventstore.system_seq diff --git a/cmd/initialise/sql/11_unique_constraints_table.sql b/cmd/initialise/sql/cockroach/10_unique_constraints_table.sql similarity index 68% rename from cmd/initialise/sql/11_unique_constraints_table.sql rename to cmd/initialise/sql/cockroach/10_unique_constraints_table.sql index d7de6a25c6..2594a248b7 100644 --- a/cmd/initialise/sql/11_unique_constraints_table.sql +++ b/cmd/initialise/sql/cockroach/10_unique_constraints_table.sql @@ -1,4 +1,4 @@ -CREATE TABLE eventstore.unique_constraints ( +CREATE TABLE IF NOT EXISTS eventstore.unique_constraints ( instance_id TEXT, unique_type TEXT, unique_field TEXT, diff --git a/cmd/initialise/sql/postgres/01_user.sql b/cmd/initialise/sql/postgres/01_user.sql new file mode 100644 index 0000000000..1afbce7ac7 --- /dev/null +++ b/cmd/initialise/sql/postgres/01_user.sql @@ -0,0 +1 @@ +CREATE USER %[1]s \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/02_database.sql b/cmd/initialise/sql/postgres/02_database.sql new file mode 100644 index 0000000000..809d3b9099 --- /dev/null +++ b/cmd/initialise/sql/postgres/02_database.sql @@ -0,0 +1 @@ +CREATE DATABASE %[1]s \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/03_grant_user.sql b/cmd/initialise/sql/postgres/03_grant_user.sql new file mode 100644 index 0000000000..f96cb22b6a --- /dev/null +++ b/cmd/initialise/sql/postgres/03_grant_user.sql @@ -0,0 +1,3 @@ +-- replace the first %[1]s with the database +-- replace the second \%[2]s with the user +GRANT ALL ON DATABASE %[1]s TO %[2]s; \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/04_eventstore.sql b/cmd/initialise/sql/postgres/04_eventstore.sql new file mode 100644 index 0000000000..fca432b3a9 --- /dev/null +++ b/cmd/initialise/sql/postgres/04_eventstore.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS eventstore; + +GRANT ALL ON ALL TABLES IN SCHEMA eventstore TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/05_projections.sql b/cmd/initialise/sql/postgres/05_projections.sql new file mode 100644 index 0000000000..eafbda805f --- /dev/null +++ b/cmd/initialise/sql/postgres/05_projections.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS projections; + +GRANT ALL ON ALL TABLES IN SCHEMA projections TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/06_system.sql b/cmd/initialise/sql/postgres/06_system.sql new file mode 100644 index 0000000000..f66c9dbe96 --- /dev/null +++ b/cmd/initialise/sql/postgres/06_system.sql @@ -0,0 +1,3 @@ +CREATE SCHEMA IF NOT EXISTS system; + +GRANT ALL ON ALL TABLES IN SCHEMA system TO %[1]s; \ No newline at end of file diff --git a/cmd/initialise/sql/postgres/07_encryption_keys_table.sql b/cmd/initialise/sql/postgres/07_encryption_keys_table.sql new file mode 100644 index 0000000000..61cb617fdf --- /dev/null +++ b/cmd/initialise/sql/postgres/07_encryption_keys_table.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS system.encryption_keys ( + id TEXT NOT NULL + , key TEXT NOT NULL + + , PRIMARY KEY (id) +); diff --git a/cmd/initialise/sql/postgres/08_events_table.sql b/cmd/initialise/sql/postgres/08_events_table.sql new file mode 100644 index 0000000000..61474e0772 --- /dev/null +++ b/cmd/initialise/sql/postgres/08_events_table.sql @@ -0,0 +1,25 @@ +CREATE TABLE IF NOT EXISTS eventstore.events ( + id UUID DEFAULT gen_random_uuid() + , event_type TEXT NOT NULL + , aggregate_type TEXT NOT NULL + , aggregate_id TEXT NOT NULL + , aggregate_version TEXT NOT NULL + , event_sequence BIGINT NOT NULL + , previous_aggregate_sequence BIGINT + , previous_aggregate_type_sequence INT8 + , creation_date TIMESTAMPTZ NOT NULL DEFAULT now() + , event_data JSONB + , editor_user TEXT NOT NULL + , editor_service TEXT NOT NULL + , resource_owner TEXT NOT NULL + , instance_id TEXT NOT NULL + + , PRIMARY KEY (event_sequence, instance_id) + , CONSTRAINT previous_sequence_unique UNIQUE(previous_aggregate_sequence, instance_id) + , CONSTRAINT prev_agg_type_seq_unique UNIQUE(previous_aggregate_type_sequence, instance_id) +); + +CREATE INDEX IF NOT EXISTS agg_type_agg_id ON eventstore.events (aggregate_type, aggregate_id, instance_id); +CREATE INDEX IF NOT EXISTS agg_type ON eventstore.events (aggregate_type, instance_id); +CREATE INDEX IF NOT EXISTS agg_type_seq ON eventstore.events (aggregate_type, event_sequence DESC, instance_id); +CREATE INDEX IF NOT EXISTS max_sequence ON eventstore.events (aggregate_type, aggregate_id, event_sequence DESC, instance_id); diff --git a/cmd/initialise/sql/postgres/09_system_sequence.sql b/cmd/initialise/sql/postgres/09_system_sequence.sql new file mode 100644 index 0000000000..15383b3878 --- /dev/null +++ b/cmd/initialise/sql/postgres/09_system_sequence.sql @@ -0,0 +1 @@ +CREATE SEQUENCE IF NOT EXISTS eventstore.system_seq; diff --git a/cmd/initialise/sql/postgres/10_unique_constraints_table.sql b/cmd/initialise/sql/postgres/10_unique_constraints_table.sql new file mode 100644 index 0000000000..61626d58c7 --- /dev/null +++ b/cmd/initialise/sql/postgres/10_unique_constraints_table.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS eventstore.unique_constraints ( + instance_id TEXT, + unique_type TEXT, + unique_field TEXT, + PRIMARY KEY (instance_id, unique_type, unique_field) +); \ No newline at end of file diff --git a/cmd/initialise/verify_database.go b/cmd/initialise/verify_database.go index 1269cdde8d..3abbfb7100 100644 --- a/cmd/initialise/verify_database.go +++ b/cmd/initialise/verify_database.go @@ -10,13 +10,6 @@ import ( "github.com/zitadel/logging" ) -var ( - searchDatabase = "SELECT database_name FROM [show databases] WHERE database_name = $1" - - //go:embed sql/02_database.sql - databaseStmt string -) - func newDatabase() *cobra.Command { return &cobra.Command{ Use: "database", @@ -40,11 +33,10 @@ The user provided by flags needs priviledge to } } -func VerifyDatabase(database string) func(*sql.DB) error { +func VerifyDatabase(databaseName string) func(*sql.DB) error { return func(db *sql.DB) error { - return verify(db, - exists(searchDatabase, database), - exec(fmt.Sprintf(databaseStmt, database)), - ) + logging.WithFields("database", databaseName).Info("verify database") + + return exec(db, fmt.Sprintf(string(databaseStmt), databaseName), []string{dbAlreadyExistsCode}) } } diff --git a/cmd/initialise/verify_database_test.go b/cmd/initialise/verify_database_test.go index 2dee733a6b..627a9192c8 100644 --- a/cmd/initialise/verify_database_test.go +++ b/cmd/initialise/verify_database_test.go @@ -7,6 +7,12 @@ import ( ) func Test_verifyDB(t *testing.T) { + err := ReadStmts("cockroach") //TODO: check all dialects + if err != nil { + t.Errorf("unable to read stmts: %v", err) + t.FailNow() + } + type args struct { db db database string @@ -16,20 +22,11 @@ func Test_verifyDB(t *testing.T) { args args targetErr error }{ - { - name: "exists fails", - args: args{ - db: prepareDB(t, expectQueryErr("SELECT EXISTS(SELECT database_name FROM [show databases] WHERE database_name = $1)", sql.ErrConnDone, "zitadel")), - database: "zitadel", - }, - targetErr: sql.ErrConnDone, - }, { name: "doesn't exists, create fails", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT database_name FROM [show databases] WHERE database_name = $1)", false, "zitadel"), - expectExec("CREATE DATABASE zitadel", sql.ErrTxDone), + expectExec("-- replace zitadel with the name of the database\nCREATE DATABASE IF NOT EXISTS zitadel", sql.ErrTxDone), ), database: "zitadel", }, @@ -39,8 +36,7 @@ func Test_verifyDB(t *testing.T) { name: "doesn't exists, create successful", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT database_name FROM [show databases] WHERE database_name = $1)", false, "zitadel"), - expectExec("CREATE DATABASE zitadel", nil), + expectExec("-- replace zitadel with the name of the database\nCREATE DATABASE IF NOT EXISTS zitadel", nil), ), database: "zitadel", }, @@ -50,7 +46,7 @@ func Test_verifyDB(t *testing.T) { name: "already exists", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT database_name FROM [show databases] WHERE database_name = $1)", true, "zitadel"), + expectExec("-- replace zitadel with the name of the database\nCREATE DATABASE IF NOT EXISTS zitadel", nil), ), database: "zitadel", }, diff --git a/cmd/initialise/verify_grant.go b/cmd/initialise/verify_grant.go index 0abbcae180..3e421a2635 100644 --- a/cmd/initialise/verify_grant.go +++ b/cmd/initialise/verify_grant.go @@ -10,12 +10,6 @@ import ( "github.com/zitadel/logging" ) -var ( - searchGrant = "SELECT * FROM [SHOW GRANTS ON DATABASE %s] where grantee = $1 AND privilege_type = 'ALL'" - //go:embed sql/03_grant_user.sql - grantStmt string -) - func newGrant() *cobra.Command { return &cobra.Command{ Use: "grant", @@ -34,12 +28,10 @@ Prereqesits: } } -func VerifyGrant(database, username string) func(*sql.DB) error { +func VerifyGrant(databaseName, username string) func(*sql.DB) error { return func(db *sql.DB) error { - logging.WithFields("user", username, "database", database).Info("verify grant") - return verify(db, - exists(fmt.Sprintf(searchGrant, database), username), - exec(fmt.Sprintf(grantStmt, database, username)), - ) + logging.WithFields("user", username, "database", databaseName).Info("verify grant") + + return exec(db, fmt.Sprintf(grantStmt, databaseName, username), nil) } } diff --git a/cmd/initialise/verify_grant_test.go b/cmd/initialise/verify_grant_test.go index a8619927d9..93196037d7 100644 --- a/cmd/initialise/verify_grant_test.go +++ b/cmd/initialise/verify_grant_test.go @@ -17,20 +17,10 @@ func Test_verifyGrant(t *testing.T) { args args targetErr error }{ - { - name: "exists fails", - args: args{ - db: prepareDB(t, expectQueryErr("SELECT EXISTS(SELECT * FROM [SHOW GRANTS ON DATABASE zitadel] where grantee = $1 AND privilege_type = 'ALL'", sql.ErrConnDone, "zitadel-user")), - database: "zitadel", - username: "zitadel-user", - }, - targetErr: sql.ErrConnDone, - }, { name: "doesn't exists, create fails", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT * FROM [SHOW GRANTS ON DATABASE zitadel] where grantee = $1 AND privilege_type = 'ALL'", false, "zitadel-user"), expectExec("GRANT ALL ON DATABASE zitadel TO zitadel-user", sql.ErrTxDone), ), database: "zitadel", @@ -42,7 +32,6 @@ func Test_verifyGrant(t *testing.T) { name: "correct", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT * FROM [SHOW GRANTS ON DATABASE zitadel] where grantee = $1 AND privilege_type = 'ALL'", false, "zitadel-user"), expectExec("GRANT ALL ON DATABASE zitadel TO zitadel-user", nil), ), database: "zitadel", @@ -54,7 +43,7 @@ func Test_verifyGrant(t *testing.T) { name: "already exists", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT * FROM [SHOW GRANTS ON DATABASE zitadel] where grantee = $1 AND privilege_type = 'ALL'", true, "zitadel-user"), + expectExec("GRANT ALL ON DATABASE zitadel TO zitadel-user", nil), ), database: "zitadel", username: "zitadel-user", diff --git a/cmd/initialise/verify_user.go b/cmd/initialise/verify_user.go index aa36c723c6..cc375ce49f 100644 --- a/cmd/initialise/verify_user.go +++ b/cmd/initialise/verify_user.go @@ -10,12 +10,6 @@ import ( "github.com/zitadel/logging" ) -var ( - searchUser = "SELECT username FROM [show roles] WHERE username = $1" - //go:embed sql/01_user.sql - createUserStmt string -) - func newUser() *cobra.Command { return &cobra.Command{ Use: "user", @@ -42,9 +36,11 @@ The user provided by flags needs priviledge to func VerifyUser(username, password string) func(*sql.DB) error { return func(db *sql.DB) error { logging.WithFields("username", username).Info("verify user") - return verify(db, - exists(searchUser, username), - exec(fmt.Sprintf(createUserStmt, username), &sql.NullString{String: password, Valid: password != ""}), - ) + + if password != "" { + createUserStmt += " WITH PASSWORD '" + password + "'" + } + + return exec(db, fmt.Sprintf(createUserStmt, username), []string{roleAlreadyExistsCode}) } } diff --git a/cmd/initialise/verify_user_test.go b/cmd/initialise/verify_user_test.go index 52d220cecf..0104319acc 100644 --- a/cmd/initialise/verify_user_test.go +++ b/cmd/initialise/verify_user_test.go @@ -7,6 +7,12 @@ import ( ) func Test_verifyUser(t *testing.T) { + err := ReadStmts("cockroach") //TODO: check all dialects + if err != nil { + t.Errorf("unable to read stmts: %v", err) + t.FailNow() + } + type args struct { db db username string @@ -17,21 +23,11 @@ func Test_verifyUser(t *testing.T) { args args targetErr error }{ - { - name: "exists fails", - args: args{ - db: prepareDB(t, expectQueryErr("SELECT EXISTS(SELECT username FROM [show roles] WHERE username = $1)", sql.ErrConnDone, "zitadel-user")), - username: "zitadel-user", - password: "", - }, - targetErr: sql.ErrConnDone, - }, { name: "doesn't exists, create fails", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT username FROM [show roles] WHERE username = $1)", false, "zitadel-user"), - expectExec("CREATE USER zitadel-user WITH PASSWORD $1", sql.ErrTxDone, nil), + expectExec("-- replace zitadel-user with the name of the user\nCREATE USER IF NOT EXISTS zitadel-user", sql.ErrTxDone), ), username: "zitadel-user", password: "", @@ -42,8 +38,7 @@ func Test_verifyUser(t *testing.T) { name: "correct without password", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT username FROM [show roles] WHERE username = $1)", false, "zitadel-user"), - expectExec("CREATE USER zitadel-user WITH PASSWORD $1", nil, nil), + expectExec("-- replace zitadel-user with the name of the user\nCREATE USER IF NOT EXISTS zitadel-user", nil), ), username: "zitadel-user", password: "", @@ -54,8 +49,7 @@ func Test_verifyUser(t *testing.T) { name: "correct with password", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT username FROM [show roles] WHERE username = $1)", false, "zitadel-user"), - expectExec("CREATE USER zitadel-user WITH PASSWORD $1", nil, "password"), + expectExec("-- replace zitadel-user with the name of the user\nCREATE USER IF NOT EXISTS zitadel-user WITH PASSWORD 'password'", nil), ), username: "zitadel-user", password: "password", @@ -66,7 +60,7 @@ func Test_verifyUser(t *testing.T) { name: "already exists", args: args{ db: prepareDB(t, - expectExists("SELECT EXISTS(SELECT username FROM [show roles] WHERE username = $1)", true, "zitadel-user"), + expectExec("-- replace zitadel-user with the name of the user\nCREATE USER IF NOT EXISTS zitadel-user WITH PASSWORD 'password'", nil), ), username: "zitadel-user", password: "", diff --git a/cmd/initialise/verify_zitadel.go b/cmd/initialise/verify_zitadel.go index c1a3c9386a..5dbfd2b056 100644 --- a/cmd/initialise/verify_zitadel.go +++ b/cmd/initialise/verify_zitadel.go @@ -3,11 +3,12 @@ package initialise import ( "database/sql" _ "embed" + "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/zitadel/logging" + "github.com/zitadel/logging" "github.com/zitadel/zitadel/internal/database" ) @@ -20,29 +21,6 @@ const ( encryptionKeysTable = "encryption_keys" ) -var ( - searchSchema = "SELECT schema_name FROM [SHOW SCHEMAS] WHERE schema_name = $1" - searchTable = "SELECT table_name FROM [SHOW TABLES] WHERE table_name = $1" - searchSystemSequence = "SELECT sequence_name FROM [SHOW SEQUENCES] WHERE sequence_name = 'system_seq'" - - //go:embed sql/04_eventstore.sql - createEventstoreStmt string - //go:embed sql/05_projections.sql - createProjectionsStmt string - //go:embed sql/06_system.sql - createSystemStmt string - //go:embed sql/07_encryption_keys_table.sql - createEncryptionKeysStmt string - //go:embed sql/08_enable_hash_sharded_indexes.sql - enableHashShardedIdx string - //go:embed sql/09_events_table.sql - createEventsStmt string - //go:embed sql/10_system_sequence.sql - createSystemSequenceStmt string - //go:embed sql/11_unique_constraints_table.sql - createUniqueConstraints string -) - func newZitadel() *cobra.Command { return &cobra.Command{ Use: "zitadel", @@ -62,44 +40,44 @@ Prereqesits: } } -func VerifyZitadel(db *sql.DB) error { - if err := verify(db, exists(searchSchema, systemSchema), exec(createSystemStmt)); err != nil { +func VerifyZitadel(db *sql.DB, config database.Config) error { + if err := exec(db, fmt.Sprintf(createSystemStmt, config.Username()), nil); err != nil { return err } - if err := verify(db, exists(searchTable, encryptionKeysTable), createEncryptionKeys); err != nil { + if err := createEncryptionKeys(db); err != nil { return err } - if err := verify(db, exists(searchSchema, projectionsSchema), exec(createProjectionsStmt)); err != nil { + if err := exec(db, fmt.Sprintf(createProjectionsStmt, config.Username()), nil); err != nil { return err } - if err := verify(db, exists(searchSchema, eventstoreSchema), exec(createEventstoreStmt)); err != nil { + if err := exec(db, fmt.Sprintf(createEventstoreStmt, config.Username()), nil); err != nil { return err } - if err := verify(db, exists(searchTable, eventsTable), createEvents); err != nil { + if err := createEvents(db); err != nil { return err } - if err := verify(db, exists(searchSystemSequence), exec(createSystemSequenceStmt)); err != nil { + if err := exec(db, createSystemSequenceStmt, nil); err != nil { return err } - if err := verify(db, exists(searchTable, uniqueConstraintsTable), exec(createUniqueConstraints)); err != nil { + if err := exec(db, createUniqueConstraints, nil); err != nil { return err } return nil } func verifyZitadel(config database.Config) error { - logging.WithFields("database", config.Database).Info("verify zitadel") + logging.WithFields("database", config.Database()).Info("verify zitadel") db, err := database.Connect(config, false) if err != nil { return err } - if err := VerifyZitadel(db); err != nil { + if err := VerifyZitadel(db, config); err != nil { return nil } @@ -124,10 +102,6 @@ func createEvents(db *sql.DB) error { if err != nil { return err } - if _, err = tx.Exec(enableHashShardedIdx); err != nil { - tx.Rollback() - return err - } if _, err = tx.Exec(createEventsStmt); err != nil { tx.Rollback() diff --git a/cmd/initialise/verify_zitadel_test.go b/cmd/initialise/verify_zitadel_test.go index fbd476a35b..d4dd552d38 100644 --- a/cmd/initialise/verify_zitadel_test.go +++ b/cmd/initialise/verify_zitadel_test.go @@ -7,6 +7,12 @@ import ( ) func Test_verifyEvents(t *testing.T) { + err := ReadStmts("cockroach") //TODO: check all dialects + if err != nil { + t.Errorf("unable to read stmts: %v", err) + t.FailNow() + } + type args struct { db db } @@ -24,23 +30,11 @@ func Test_verifyEvents(t *testing.T) { }, targetErr: sql.ErrConnDone, }, - { - name: "hash sharded indexes fails", - args: args{ - db: prepareDB(t, - expectBegin(nil), - expectExec("SET experimental_enable_hash_sharded_indexes = on", sql.ErrNoRows), - expectRollback(nil), - ), - }, - targetErr: sql.ErrNoRows, - }, { name: "create table fails", args: args{ db: prepareDB(t, expectBegin(nil), - expectExec("SET experimental_enable_hash_sharded_indexes = on", nil), expectExec(createEventsStmt, sql.ErrNoRows), expectRollback(nil), ), @@ -52,7 +46,6 @@ func Test_verifyEvents(t *testing.T) { args: args{ db: prepareDB(t, expectBegin(nil), - expectExec("SET experimental_enable_hash_sharded_indexes = on", nil), expectExec(createEventsStmt, nil), expectCommit(nil), ), @@ -60,6 +53,7 @@ func Test_verifyEvents(t *testing.T) { targetErr: nil, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := createEvents(tt.args.db.db); !errors.Is(err, tt.targetErr) { diff --git a/cmd/setup/01.go b/cmd/setup/01.go index 372d0e263c..a69c95e96e 100644 --- a/cmd/setup/01.go +++ b/cmd/setup/01.go @@ -11,8 +11,6 @@ var ( createAdminViews string //go:embed 01_sql/auth.sql createAuthViews string - //go:embed 01_sql/notification.sql - createNotificationViews string //go:embed 01_sql/projections.sql createProjections string ) @@ -22,7 +20,7 @@ type ProjectionTable struct { } func (mig *ProjectionTable) Execute(ctx context.Context) error { - stmt := createAdminViews + createAuthViews + createNotificationViews + createProjections + stmt := createAdminViews + createAuthViews + createProjections _, err := mig.dbClient.ExecContext(ctx, stmt) return err } diff --git a/cmd/setup/01_sql/adminapi.sql b/cmd/setup/01_sql/adminapi.sql index 57632660eb..1ef135e744 100644 --- a/cmd/setup/01_sql/adminapi.sql +++ b/cmd/setup/01_sql/adminapi.sql @@ -30,28 +30,28 @@ CREATE TABLE adminapi.failed_events ( ); CREATE TABLE adminapi.styling ( - aggregate_id STRING NOT NULL, + aggregate_id TEXT NOT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - label_policy_state INT2 NOT NULL DEFAULT 0:::INT2, + label_policy_state INT2 NOT NULL DEFAULT 0::INT2, sequence INT8 NULL, - primary_color STRING NULL, - background_color STRING NULL, - warn_color STRING NULL, - font_color STRING NULL, - primary_color_dark STRING NULL, - background_color_dark STRING NULL, - warn_color_dark STRING NULL, - font_color_dark STRING NULL, - logo_url STRING NULL, - icon_url STRING NULL, - logo_dark_url STRING NULL, - icon_dark_url STRING NULL, - font_url STRING NULL, + primary_color TEXT NULL, + background_color TEXT NULL, + warn_color TEXT NULL, + font_color TEXT NULL, + primary_color_dark TEXT NULL, + background_color_dark TEXT NULL, + warn_color_dark TEXT NULL, + font_color_dark TEXT NULL, + logo_url TEXT NULL, + icon_url TEXT NULL, + logo_dark_url TEXT NULL, + icon_dark_url TEXT NULL, + font_url TEXT NULL, err_msg_popup BOOL NULL, disable_watermark BOOL NULL, hide_login_name_suffix BOOL NULL, - instance_id STRING NOT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (aggregate_id, label_policy_state, instance_id) ); diff --git a/cmd/setup/01_sql/auth.sql b/cmd/setup/01_sql/auth.sql index f2d4ebac0f..0a2bba226a 100644 --- a/cmd/setup/01_sql/auth.sql +++ b/cmd/setup/01_sql/auth.sql @@ -30,48 +30,48 @@ CREATE TABLE auth.failed_events ( ); CREATE TABLE auth.users ( - id STRING NULL, + id TEXT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - resource_owner STRING NULL, + resource_owner TEXT NULL, user_state INT2 NULL, password_set BOOL NULL, password_change_required BOOL NULL, password_change TIMESTAMPTZ NULL, last_login TIMESTAMPTZ NULL, - user_name STRING NULL, - login_names STRING[] NULL, - preferred_login_name STRING NULL, - first_name STRING NULL, - last_name STRING NULL, - nick_name STRING NULL, - display_name STRING NULL, - preferred_language STRING NULL, + user_name TEXT NULL, + login_names TEXT[] NULL, + preferred_login_name TEXT NULL, + first_name TEXT NULL, + last_name TEXT NULL, + nick_name TEXT NULL, + display_name TEXT NULL, + preferred_language TEXT NULL, gender INT2 NULL, - email STRING NULL, + email TEXT NULL, is_email_verified BOOL NULL, - phone STRING NULL, + phone TEXT NULL, is_phone_verified BOOL NULL, - country STRING NULL, - locality STRING NULL, - postal_code STRING NULL, - region STRING NULL, - street_address STRING NULL, + country TEXT NULL, + locality TEXT NULL, + postal_code TEXT NULL, + region TEXT NULL, + street_address TEXT NULL, otp_state INT2 NULL, mfa_max_set_up INT2 NULL, mfa_init_skipped TIMESTAMPTZ NULL, sequence INT8 NULL, init_required BOOL NULL, username_change_required BOOL NULL, - machine_name STRING NULL, - machine_description STRING NULL, - user_type STRING NULL, - u2f_tokens BYTES NULL, - passwordless_tokens BYTES NULL, - avatar_key STRING NULL, + machine_name TEXT NULL, + machine_description TEXT NULL, + user_type TEXT NULL, + u2f_tokens BYTEA NULL, + passwordless_tokens BYTEA NULL, + avatar_key TEXT NULL, passwordless_init_required BOOL NULL, password_init_required BOOL NULL, - instance_id STRING NOT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (id, instance_id) ); @@ -79,148 +79,151 @@ CREATE TABLE auth.users ( CREATE TABLE auth.user_sessions ( creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - resource_owner STRING NULL, + resource_owner TEXT NULL, state INT2 NULL, - user_agent_id STRING NULL, - user_id STRING NULL, - user_name STRING NULL, + user_agent_id TEXT NULL, + user_id TEXT NULL, + user_name TEXT NULL, password_verification TIMESTAMPTZ NULL, second_factor_verification TIMESTAMPTZ NULL, multi_factor_verification TIMESTAMPTZ NULL, sequence INT8 NULL, second_factor_verification_type INT2 NULL, multi_factor_verification_type INT2 NULL, - user_display_name STRING NULL, - login_name STRING NULL, + user_display_name TEXT NULL, + login_name TEXT NULL, external_login_verification TIMESTAMPTZ NULL, - selected_idp_config_id STRING NULL, + selected_idp_config_id TEXT NULL, passwordless_verification TIMESTAMPTZ NULL, - avatar_key STRING NULL, - instance_id STRING NOT NULL, + avatar_key TEXT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (user_agent_id, user_id, instance_id) ); CREATE TABLE auth.user_external_idps ( - external_user_id STRING NOT NULL, - idp_config_id STRING NOT NULL, - user_id STRING NULL, - idp_name STRING NULL, - user_display_name STRING NULL, + external_user_id TEXT NOT NULL, + idp_config_id TEXT NOT NULL, + user_id TEXT NULL, + idp_name TEXT NULL, + user_display_name TEXT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, sequence INT8 NULL, - resource_owner STRING NULL, - instance_id STRING NOT NULL, + resource_owner TEXT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (external_user_id, idp_config_id, instance_id) ); CREATE TABLE auth.tokens ( - id STRING NOT NULL, + id TEXT NOT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - resource_owner STRING NULL, - application_id STRING NULL, - user_agent_id STRING NULL, - user_id STRING NULL, + resource_owner TEXT NULL, + application_id TEXT NULL, + user_agent_id TEXT NULL, + user_id TEXT NULL, expiration TIMESTAMPTZ NULL, sequence INT8 NULL, - scopes STRING[] NULL, - audience STRING[] NULL, - preferred_language STRING NULL, - refresh_token_id STRING NULL, + scopes TEXT[] NULL, + audience TEXT[] NULL, + preferred_language TEXT NULL, + refresh_token_id TEXT NULL, is_pat BOOL NOT NULL DEFAULT false, - instance_id STRING NOT NULL, + instance_id TEXT NOT NULL, - PRIMARY KEY (id, instance_id), - INDEX user_user_agent_idx (user_id, user_agent_id) + PRIMARY KEY (id, instance_id) ); +CREATE INDEX user_user_agent_idx ON auth.tokens (user_id, user_agent_id); + CREATE TABLE auth.refresh_tokens ( - id STRING NOT NULL, + id TEXT NOT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - resource_owner STRING NULL, - token STRING NULL, - client_id STRING NOT NULL, - user_agent_id STRING NOT NULL, - user_id STRING NOT NULL, + resource_owner TEXT NULL, + token TEXT NULL, + client_id TEXT NOT NULL, + user_agent_id TEXT NOT NULL, + user_id TEXT NOT NULL, auth_time TIMESTAMPTZ NULL, idle_expiration TIMESTAMPTZ NULL, expiration TIMESTAMPTZ NULL, sequence INT8 NULL, - scopes STRING[] NULL, - audience STRING[] NULL, - amr STRING[] NULL, - instance_id STRING NOT NULL, + scopes TEXT[] NULL, + audience TEXT[] NULL, + amr TEXT[] NULL, + instance_id TEXT NOT NULL, - PRIMARY KEY (id, instance_id), - UNIQUE INDEX unique_client_user_index (client_id, user_agent_id, user_id) + PRIMARY KEY (id, instance_id) ); +CREATE UNIQUE INDEX unique_client_user_index ON auth.refresh_tokens (client_id, user_agent_id, user_id); + CREATE TABLE auth.org_project_mapping ( - org_id STRING NOT NULL, - project_id STRING NOT NULL, - project_grant_id STRING NULL, - instance_id STRING NOT NULL, + org_id TEXT NOT NULL, + project_id TEXT NOT NULL, + project_grant_id TEXT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (org_id, project_id, instance_id) ); CREATE TABLE auth.idp_providers ( - aggregate_id STRING NOT NULL, - idp_config_id STRING NOT NULL, + aggregate_id TEXT NOT NULL, + idp_config_id TEXT NOT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, sequence INT8 NULL, - name STRING NULL, + name TEXT NULL, idp_config_type INT2 NULL, idp_provider_type INT2 NULL, idp_state INT2 NULL, styling_type INT2 NULL, - instance_id STRING NOT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (aggregate_id, idp_config_id, instance_id) ); CREATE TABLE auth.idp_configs ( - idp_config_id STRING NOT NULL, + idp_config_id TEXT NOT NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, sequence INT8 NULL, - aggregate_id STRING NULL, - name STRING NULL, + aggregate_id TEXT NULL, + name TEXT NULL, idp_state INT2 NULL, idp_provider_type INT2 NULL, is_oidc BOOL NULL, - oidc_client_id STRING NULL, + oidc_client_id TEXT NULL, oidc_client_secret JSONB NULL, - oidc_issuer STRING NULL, - oidc_scopes STRING[] NULL, + oidc_issuer TEXT NULL, + oidc_scopes TEXT[] NULL, oidc_idp_display_name_mapping INT2 NULL, oidc_idp_username_mapping INT2 NULL, styling_type INT2 NULL, - oauth_authorization_endpoint STRING NULL, - oauth_token_endpoint STRING NULL, + oauth_authorization_endpoint TEXT NULL, + oauth_token_endpoint TEXT NULL, auto_register BOOL NULL, - jwt_endpoint STRING NULL, - jwt_keys_endpoint STRING NULL, - jwt_header_name STRING NULL, - instance_id STRING NOT NULL, + jwt_endpoint TEXT NULL, + jwt_keys_endpoint TEXT NULL, + jwt_header_name TEXT NULL, + instance_id TEXT NOT NULL, PRIMARY KEY (idp_config_id, instance_id) ); CREATE TABLE auth.auth_requests ( - id STRING NOT NULL, + id TEXT NOT NULL, request JSONB NULL, - code STRING NULL, + code TEXT NULL, request_type INT2 NULL, creation_date TIMESTAMPTZ NULL, change_date TIMESTAMPTZ NULL, - instance_id STRING NOT NULL, + instance_id TEXT NOT NULL, - PRIMARY KEY (id, instance_id), - INDEX auth_code_idx (code) + PRIMARY KEY (id, instance_id) ); + +CREATE INDEX auth_code_idx ON auth.auth_requests (code); diff --git a/cmd/setup/01_sql/notification.sql b/cmd/setup/01_sql/notification.sql deleted file mode 100644 index b117a01ad9..0000000000 --- a/cmd/setup/01_sql/notification.sql +++ /dev/null @@ -1,55 +0,0 @@ -CREATE SCHEMA notification; - -CREATE TABLE notification.locks ( - locker_id TEXT, - locked_until TIMESTAMPTZ(3), - view_name TEXT, - instance_id TEXT NOT NULL, - - PRIMARY KEY (view_name, instance_id) -); - -CREATE TABLE notification.current_sequences ( - view_name TEXT, - current_sequence BIGINT, - event_timestamp TIMESTAMPTZ, - last_successful_spooler_run TIMESTAMPTZ, - instance_id TEXT NOT NULL, - - PRIMARY KEY (view_name, instance_id) -); - -CREATE TABLE notification.failed_events ( - view_name TEXT, - failed_sequence BIGINT, - failure_count SMALLINT, - err_msg TEXT, - instance_id TEXT NOT NULL, - - PRIMARY KEY (view_name, failed_sequence, instance_id) -); - -CREATE TABLE notification.notify_users ( - id STRING NOT NULL, - creation_date TIMESTAMPTZ NULL, - change_date TIMESTAMPTZ NULL, - resource_owner STRING NULL, - user_name STRING NULL, - first_name STRING NULL, - last_name STRING NULL, - nick_name STRING NULL, - display_name STRING NULL, - preferred_language STRING NULL, - gender INT2 NULL, - last_email STRING NULL, - verified_email STRING NULL, - last_phone STRING NULL, - verified_phone STRING NULL, - sequence INT8 NULL, - password_set BOOL NULL, - login_names STRING NULL, - preferred_login_name STRING NULL, - instance_id STRING NULL, - - PRIMARY KEY (id) -); diff --git a/cmd/setup/02.go b/cmd/setup/02.go index e326cab830..42c5968bca 100644 --- a/cmd/setup/02.go +++ b/cmd/setup/02.go @@ -13,8 +13,8 @@ CREATE TABLE system.assets ( resource_owner TEXT, name TEXT, content_type TEXT, - hash TEXT AS (md5(data)) STORED, - data BYTES, + hash TEXT GENERATED ALWAYS AS (md5(data)) STORED, + data BYTEA, updated_at TIMESTAMPTZ, PRIMARY KEY (instance_id, resource_owner, name) diff --git a/cmd/start/start_from_setup.go b/cmd/start/start_from_setup.go new file mode 100644 index 0000000000..75c2347c2b --- /dev/null +++ b/cmd/start/start_from_setup.go @@ -0,0 +1,47 @@ +package start + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/zitadel/logging" + + "github.com/zitadel/zitadel/cmd/key" + "github.com/zitadel/zitadel/cmd/setup" + "github.com/zitadel/zitadel/cmd/tls" +) + +func NewStartFromSetup() *cobra.Command { + cmd := &cobra.Command{ + Use: "start-from-setup", + Short: "cold starts zitadel", + Long: `cold starts ZITADEL. +First the initial events are created. +Last ZITADEL starts. + +Requirements: +- database +- database is initialized +`, + Run: func(cmd *cobra.Command, args []string) { + err := tls.ModeFromFlag(cmd) + logging.OnError(err).Fatal("invalid tlsMode") + + masterKey, err := key.MasterKey(cmd) + logging.OnError(err).Panic("No master key provided") + + setupConfig := setup.MustNewConfig(viper.GetViper()) + setupSteps := setup.MustNewSteps(viper.New()) + setup.Setup(setupConfig, setupSteps, masterKey) + + startConfig := MustNewConfig(viper.GetViper()) + + err = startZitadel(startConfig, masterKey) + logging.OnError(err).Fatal("unable to start zitadel") + }, + } + + startFlags(cmd) + setup.Flags(cmd) + + return cmd +} diff --git a/cmd/zitadel.go b/cmd/zitadel.go index 0077b62885..6d27546422 100644 --- a/cmd/zitadel.go +++ b/cmd/zitadel.go @@ -51,6 +51,7 @@ func New(out io.Writer, in io.Reader, args []string) *cobra.Command { setup.New(), start.New(), start.NewStartFromInit(), + start.NewStartFromSetup(), key.New(), ) diff --git a/docs/docs/concepts/architecture/software.md b/docs/docs/concepts/architecture/software.md index 0fc5d04e6c..a110a7e26f 100644 --- a/docs/docs/concepts/architecture/software.md +++ b/docs/docs/concepts/architecture/software.md @@ -144,4 +144,4 @@ The storage layer of ZITADEL is responsible for multiple things. For example: - Backup and restore operation for disaster recovery purpose ZITADEL currently supports CockroachDB as first choice of storage due to its perfect match for ZITADELs needs. -Postgresql support is work in progress and should be available soon as well. +Postgresql support is currently in beta. diff --git a/docs/docs/concepts/architecture/solution.md b/docs/docs/concepts/architecture/solution.md index c6b0bc18c8..d074d657b3 100644 --- a/docs/docs/concepts/architecture/solution.md +++ b/docs/docs/concepts/architecture/solution.md @@ -10,7 +10,7 @@ Since the storage layer takes the heavy lifting of making sure that data in sync Depending on your projects needs our general recommendation is to run ZITADEL and ZITADELs storage layer across multiple availability zones in the same region or if you need higher guarantees run the storage layer across multiple regions. Consult the [CockroachDB documentation](https://www.cockroachlabs.com/docs/) for more details or use the [CockroachCloud Service](https://www.cockroachlabs.com/docs/cockroachcloud/create-an-account.html) -> Soon ZITADEL will also support Postgres as database. +> Postgres support of ZITADEL is currently in beta. ## Scalability diff --git a/docs/docs/guides/deploy/docker-compose.yaml b/docs/docs/guides/deploy/docker-compose.yaml index d6831a561b..7b2915f6b0 100644 --- a/docs/docs/guides/deploy/docker-compose.yaml +++ b/docs/docs/guides/deploy/docker-compose.yaml @@ -8,19 +8,19 @@ services: image: 'ghcr.io/zitadel/zitadel:stable' command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled' environment: - - 'ZITADEL_DATABASE_COCKROACH_HOST=db' + - 'ZITADEL_DATABASE_COCKROACH_HOST=crdb' - 'ZITADEL_EXTERNALSECURE=false' depends_on: - db: + crdb: condition: 'service_healthy' ports: - '8080:8080' - db: + crdb: restart: 'always' networks: - 'zitadel' - image: 'cockroachdb/cockroach:v22.1.0' + image: 'cockroachdb/cockroach:v22.1.3' command: 'start-single-node --insecure' healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health?ready=1"] diff --git a/docs/docs/guides/deploy/overview.mdx b/docs/docs/guides/deploy/overview.mdx index 77844208bd..40c7a9ed94 100644 --- a/docs/docs/guides/deploy/overview.mdx +++ b/docs/docs/guides/deploy/overview.mdx @@ -15,7 +15,7 @@ By default, it runs a highly available ZITADEL instance along with a secure and ## Prerequisits - ZITADEL does not need many resources, 1 CPU and 512MB memory are more than enough. (With more CPU, the password hashing might be faster) -- A cockroachDB or [🚧 Postgresql coming soon](https://github.com/zitadel/zitadel/pull/3998) as only needed storage +- A cockroachDB or Postgresql (currently in beta) as only needed storage - If you want to front ZITADEL with a reverse proxy, web application firewall or content delivery network, make sure to support [HTTP/2](../manage/self-hosted/http2) diff --git a/docs/docs/guides/manage/self-hosted/database/_cockroachdb.mdx b/docs/docs/guides/manage/self-hosted/database/_cockroachdb.mdx new file mode 100644 index 0000000000..0a1925e89b --- /dev/null +++ b/docs/docs/guides/manage/self-hosted/database/_cockroachdb.mdx @@ -0,0 +1,32 @@ +## Cockroach + +The default database of ZITADEL is [CockroachDB](https://www.cockroachlabs.com). The SQL database provides a bunch of features like horizontal scalability, data reginality and many more. + +The default configuration of the database looks like this: +```yaml +Database: + cockroach: + Host: localhost + Port: 26257 + Database: zitadel + MaxOpenConns: 20 + MaxConnLifetime: 30m + MaxConnIdleTime: 30m + Options: "" + User: + Username: zitadel + Password: "" + SSL: + Mode: disable + RootCert: "" + Cert: "" + Key: "" + Admin: + Username: root + Password: "" + SSL: + Mode: disable + RootCert: "" + Cert: "" + Key: "" +``` \ No newline at end of file diff --git a/docs/docs/guides/manage/self-hosted/database/_postgres.mdx b/docs/docs/guides/manage/self-hosted/database/_postgres.mdx new file mode 100644 index 0000000000..ca6427cc7d --- /dev/null +++ b/docs/docs/guides/manage/self-hosted/database/_postgres.mdx @@ -0,0 +1,36 @@ +## Postgres + +:::caution +Postgres extension is currently in beta. +::: + +If you want to use a Postgres database instead of CockroachDB you can [overwrite the default configuration](../configure/configure.mdx). + +Postgres can be configured as follows: +```yaml +Database: + postgres: + Host: localhost + Port: 5432 + Database: zitadel + MaxOpenConns: 25 + MaxConnLifetime: 1h + MaxConnIdleTime: 5m + Options: + User: + Username: zitadel + Password: zitadel + SSL: + Mode: disable + RootCert: + Cert: + Key: + Admin: + Username: postgres + Password: postgres + SSL: + Mode: disable + RootCert: + Cert: + Key: +``` \ No newline at end of file diff --git a/docs/docs/guides/manage/self-hosted/database/database.mdx b/docs/docs/guides/manage/self-hosted/database/database.mdx new file mode 100644 index 0000000000..688159fd7f --- /dev/null +++ b/docs/docs/guides/manage/self-hosted/database/database.mdx @@ -0,0 +1,28 @@ +--- +title: Database +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import Cockroach from './_cockroachdb.mdx' +import Postgres from './_postgres.mdx' + +# Database Configuration + + + + + + + + + + + \ No newline at end of file diff --git a/docs/sidebars.js b/docs/sidebars.js index c6d99111cc..b2aa1fb0f3 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -86,6 +86,7 @@ module.exports = { "guides/manage/self-hosted/custom-domain", "guides/manage/self-hosted/http2", "guides/manage/self-hosted/tls_modes", + "guides/manage/self-hosted/database/database", ] }, { @@ -95,7 +96,6 @@ module.exports = { "guides/manage/console/organizations", "guides/manage/console/projects", "guides/manage/console/applications", - ] }, { diff --git a/go.mod b/go.mod index db123eb4f1..52b32b3869 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/zitadel/zitadel -go 1.17 +go 1.19 require ( cloud.google.com/go/storage v1.14.0 @@ -29,6 +29,9 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1 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/jinzhu/gorm v1.9.16 github.com/k3a/html2text v1.0.8 github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 @@ -66,7 +69,7 @@ require ( golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/text v0.3.7 - golang.org/x/tools v0.1.8 + golang.org/x/tools v0.1.11 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 @@ -115,7 +118,7 @@ require ( 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/go-cmp v0.5.6 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/gax-go/v2 v2.1.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect @@ -125,6 +128,11 @@ require ( 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/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/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52 github.com/jinzhu/inflection v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -169,7 +177,7 @@ require ( 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.5.1 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.63.0 diff --git a/go.sum b/go.sum index fc2c7bee5c..ec4c141298 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,8 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 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.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= 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= @@ -117,7 +119,6 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW 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/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= 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= @@ -125,7 +126,6 @@ github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -151,6 +151,7 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH 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 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk= 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.4 h1:VuiBJKut2Imgrzl+TNk+U5+GxLOh3hnIFxU0EzjTCnI= github.com/cockroachdb/cockroach-go/v2 v2.2.4/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= @@ -263,13 +264,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 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-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -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= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -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-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= @@ -362,8 +360,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -391,7 +390,6 @@ github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLe 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/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.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -436,7 +434,6 @@ github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= 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/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= 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= @@ -490,6 +487,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt 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= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= @@ -498,8 +496,17 @@ github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5 github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +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.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8= +github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= +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= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= @@ -508,7 +515,11 @@ 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.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= 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-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= 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= @@ -517,6 +528,9 @@ github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4 github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +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/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= @@ -524,11 +538,15 @@ github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXg github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= +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.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y= +github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ= 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.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/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/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/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -570,7 +588,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 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.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 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= @@ -596,13 +613,13 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR 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/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 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.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -779,13 +796,13 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= 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/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/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/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= @@ -864,7 +881,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zitadel/logging v0.3.4 h1:9hZsTjMMTE3X2LUi0xcF9Q9EdLo+FAezeu52ireBbHM= github.com/zitadel/logging v0.3.4/go.mod h1:aPpLQhE+v6ocNK0TWrBrd363hZ95KcI17Q1ixAQwZF0= @@ -953,9 +969,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/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-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= @@ -999,8 +1017,8 @@ 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.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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= @@ -1054,8 +1072,6 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210716203947-853a461950ff/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-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8= golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1168,17 +1184,14 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc 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-20211019181941-9d821ace8654/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-20211210111614-af8b64212486/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-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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/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= @@ -1257,8 +1270,8 @@ 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.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY= +golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= 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= @@ -1446,7 +1459,6 @@ 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.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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= diff --git a/internal/api/grpc/project/application.go b/internal/api/grpc/project/application.go index 426093cfdf..fb6ad90819 100644 --- a/internal/api/grpc/project/application.go +++ b/internal/api/grpc/project/application.go @@ -130,7 +130,7 @@ func OIDCGrantTypesFromModel(grantTypes []domain.OIDCGrantType) []app_pb.OIDCGra } func OIDCGrantTypesToDomain(grantTypes []app_pb.OIDCGrantType) []domain.OIDCGrantType { - if grantTypes == nil || len(grantTypes) == 0 { + if len(grantTypes) == 0 { return []domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode} } oidcGrantTypes := make([]domain.OIDCGrantType, len(grantTypes)) diff --git a/internal/database/cockroach/config.go b/internal/database/cockroach/config.go index e31acc6015..3fd0badfa2 100644 --- a/internal/database/cockroach/config.go +++ b/internal/database/cockroach/config.go @@ -6,9 +6,6 @@ import ( "strings" "time" - //sql import - _ "github.com/lib/pq" - "github.com/mitchellh/mapstructure" "github.com/zitadel/logging" @@ -61,13 +58,15 @@ func (c *Config) Decode(configs []interface{}) (dialect.Connector, error) { } func (c *Config) Connect(useAdmin bool) (*sql.DB, error) { - client, err := sql.Open("postgres", c.String(useAdmin)) + client, err := sql.Open("pgx", c.String(useAdmin)) if err != nil { return nil, err } + client.SetMaxOpenConns(int(c.MaxOpenConns)) client.SetConnMaxLifetime(c.MaxConnLifetime) client.SetConnMaxIdleTime(c.MaxConnIdleTime) + return client, nil } diff --git a/internal/database/database.go b/internal/database/database.go index 3f2315b926..6f216b332b 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -6,6 +6,8 @@ import ( _ "github.com/zitadel/zitadel/internal/database/cockroach" "github.com/zitadel/zitadel/internal/database/dialect" + _ "github.com/zitadel/zitadel/internal/database/postgres" + "github.com/zitadel/zitadel/internal/errors" ) type Config struct { @@ -17,23 +19,6 @@ func (c *Config) SetConnector(connector dialect.Connector) { c.connector = connector } -type User struct { - Username string - Password string - SSL SSL -} - -type SSL struct { - // type of connection security - Mode string - // RootCert Path to the CA certificate - RootCert string - // Cert Path to the client certificate - Cert string - // Key Path to the client private key - Key string -} - func Connect(config Config, useAdmin bool) (*sql.DB, error) { client, err := config.connector.Connect(useAdmin) if err != nil { @@ -41,7 +26,7 @@ func Connect(config Config, useAdmin bool) (*sql.DB, error) { } if err := client.Ping(); err != nil { - return nil, err + return nil, errors.ThrowPreconditionFailed(err, "DATAB-0pIWD", "Errors.Database.Connection.Failed") } return client, nil diff --git a/internal/database/postgres/config.go b/internal/database/postgres/config.go new file mode 100644 index 0000000000..653cb20440 --- /dev/null +++ b/internal/database/postgres/config.go @@ -0,0 +1,153 @@ +package postgres + +import ( + "database/sql" + "strconv" + "strings" + "time" + + "github.com/mitchellh/mapstructure" + "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database/dialect" +) + +const ( + sslDisabledMode = "disable" +) + +type Config struct { + Host string + Port int32 + Database string + MaxOpenConns uint32 + MaxConnLifetime time.Duration + MaxConnIdleTime time.Duration + User User + Admin User + + //Additional options to be appended as options= + //The value will be taken as is. Multiple options are space separated. + Options string +} + +func (c *Config) MatchName(name string) bool { + for _, key := range []string{"pg", "postgres"} { + if strings.TrimSpace(strings.ToLower(name)) == key { + return true + } + } + return false +} + +func (c *Config) Decode(configs []interface{}) (dialect.Connector, error) { + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + Result: c, + }) + if err != nil { + return nil, err + } + + for _, config := range configs { + if err = decoder.Decode(config); err != nil { + return nil, err + } + } + return c, nil +} + +func (c *Config) Connect(useAdmin bool) (*sql.DB, error) { + logging.Warn("postgres is currently in beta") + db, err := sql.Open("pgx", c.String(useAdmin)) + if err != nil { + return nil, err + } + + db.SetMaxOpenConns(int(c.MaxOpenConns)) + db.SetConnMaxLifetime(c.MaxConnLifetime) + db.SetConnMaxIdleTime(c.MaxConnIdleTime) + + return db, nil +} + +func (c *Config) DatabaseName() string { + return c.Database +} + +func (c *Config) Username() string { + return c.User.Username +} + +func (c *Config) Password() string { + return c.User.Password +} + +func (c *Config) Type() string { + return "postgres" +} + +type User struct { + Username string + Password string + SSL SSL +} + +type SSL struct { + // type of connection security + Mode string + // RootCert Path to the CA certificate + RootCert string + // Cert Path to the client certificate + Cert string + // Key Path to the client private key + Key string +} + +func (s *Config) checkSSL(user User) { + if user.SSL.Mode == sslDisabledMode || user.SSL.Mode == "" { + user.SSL = SSL{Mode: sslDisabledMode} + return + } + if user.SSL.RootCert == "" { + logging.WithFields( + "cert set", user.SSL.Cert != "", + "key set", user.SSL.Key != "", + "rootCert set", user.SSL.RootCert != "", + ).Fatal("at least ssl root cert has to be set") + } +} + +func (c Config) String(useAdmin bool) string { + user := c.User + if useAdmin { + user = c.Admin + } + c.checkSSL(user) + fields := []string{ + "host=" + c.Host, + "port=" + strconv.Itoa(int(c.Port)), + "user=" + user.Username, + "application_name=zitadel", + "sslmode=" + user.SSL.Mode, + } + if c.Options != "" { + fields = append(fields, "options="+c.Options) + } + if user.Password != "" { + fields = append(fields, "password="+user.Password) + } + if !useAdmin { + fields = append(fields, "dbname="+c.Database) + } + if user.SSL.Mode != sslDisabledMode { + fields = append(fields, "sslrootcert="+user.SSL.RootCert) + if user.SSL.Cert != "" { + fields = append(fields, "sslcert="+user.SSL.Cert) + } + if user.SSL.Key != "" { + fields = append(fields, "sslkey="+user.SSL.Key) + } + } + + return strings.Join(fields, " ") +} diff --git a/internal/database/postgres/pg.go b/internal/database/postgres/pg.go new file mode 100644 index 0000000000..562d79e273 --- /dev/null +++ b/internal/database/postgres/pg.go @@ -0,0 +1,14 @@ +package postgres + +import ( + + //sql import + _ "github.com/jackc/pgx/v4/stdlib" + + "github.com/zitadel/zitadel/internal/database/dialect" +) + +func init() { + config := &Config{} + dialect.Register(config, config, false) +} diff --git a/internal/database/type.go b/internal/database/type.go new file mode 100644 index 0000000000..2377aa3f10 --- /dev/null +++ b/internal/database/type.go @@ -0,0 +1,72 @@ +package database + +import ( + "database/sql/driver" + + "github.com/jackc/pgtype" +) + +type StringArray []string + +// Scan implements the `database/sql.Scanner` interface. +func (s *StringArray) Scan(src any) error { + array := new(pgtype.TextArray) + if err := array.Scan(src); err != nil { + return err + } + if err := array.AssignTo(s); err != nil { + return err + } + return nil +} + +// Value implements the `database/sql/driver.Valuer`` interface. +func (s StringArray) Value() (driver.Value, error) { + if len(s) == 0 { + return nil, nil + } + + array := pgtype.TextArray{} + if err := array.Set(s); err != nil { + return nil, err + } + + return array.Value() +} + +type enumField interface { + ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 +} + +type EnumArray[F enumField] []F + +// Scan implements the `database/sql.Scanner` interface. +func (s *EnumArray[F]) Scan(src any) error { + array := new(pgtype.Int2Array) + if err := array.Scan(src); err != nil { + return err + } + ints := make([]int32, 0, len(array.Elements)) + if err := array.AssignTo(&ints); err != nil { + return err + } + *s = make([]F, len(ints)) + for i, a := range ints { + (*s)[i] = F(a) + } + return nil +} + +// Value implements the `database/sql/driver.Valuer`` interface. +func (s EnumArray[F]) Value() (driver.Value, error) { + if len(s) == 0 { + return nil, nil + } + + array := pgtype.Int2Array{} + if err := array.Set(s); err != nil { + return nil, err + } + + return array.Value() +} diff --git a/internal/eventstore/handler/crdb/current_sequence.go b/internal/eventstore/handler/crdb/current_sequence.go index 3859237cfc..b11c17dd40 100644 --- a/internal/eventstore/handler/crdb/current_sequence.go +++ b/internal/eventstore/handler/crdb/current_sequence.go @@ -6,15 +6,15 @@ import ( "strconv" "strings" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" ) const ( - currentSequenceStmtFormat = `SELECT current_sequence, aggregate_type, instance_id FROM %s WHERE projection_name = $1 AND instance_id = ANY ($2) FOR UPDATE` - updateCurrentSequencesStmtFormat = `UPSERT INTO %s (projection_name, aggregate_type, current_sequence, instance_id, timestamp) VALUES ` + currentSequenceStmtFormat = `SELECT current_sequence, aggregate_type, instance_id FROM %s WHERE projection_name = $1 AND instance_id = ANY ($2) FOR UPDATE` + updateCurrentSequencesStmtFormat = `INSERT INTO %s (projection_name, aggregate_type, current_sequence, instance_id, timestamp) VALUES ` + updateCurrentSequencesConflictStmt = ` ON CONFLICT (projection_name, aggregate_type, instance_id) DO UPDATE SET current_sequence = EXCLUDED.current_sequence, timestamp = EXCLUDED.timestamp` ) type currentSequences map[eventstore.AggregateType][]*instanceSequence @@ -24,8 +24,8 @@ type instanceSequence struct { sequence uint64 } -func (h *StatementHandler) currentSequences(ctx context.Context, query func(context.Context, string, ...interface{}) (*sql.Rows, error), instanceIDs []string) (currentSequences, error) { - rows, err := query(ctx, h.currentSequenceStmt, h.ProjectionName, pq.StringArray(instanceIDs)) +func (h *StatementHandler) currentSequences(ctx context.Context, query func(context.Context, string, ...interface{}) (*sql.Rows, error), instanceIDs database.StringArray) (currentSequences, error) { + rows, err := query(ctx, h.currentSequenceStmt, h.ProjectionName, instanceIDs) if err != nil { return nil, err } @@ -74,7 +74,7 @@ func (h *StatementHandler) updateCurrentSequences(tx *sql.Tx, sequences currentS } } - res, err := tx.Exec(h.updateSequencesBaseStmt+strings.Join(valueQueries, ", "), values...) + res, err := tx.Exec(h.updateSequencesBaseStmt+strings.Join(valueQueries, ", ")+updateCurrentSequencesConflictStmt, values...) if err != nil { return errors.ThrowInternal(err, "CRDB-TrH2Z", "unable to exec update sequence") } diff --git a/internal/eventstore/handler/crdb/db_mock_test.go b/internal/eventstore/handler/crdb/db_mock_test.go index 39e08194ad..445b35224f 100644 --- a/internal/eventstore/handler/crdb/db_mock_test.go +++ b/internal/eventstore/handler/crdb/db_mock_test.go @@ -8,8 +8,8 @@ import ( "time" "github.com/DATA-DOG/go-sqlmock" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" ) @@ -17,7 +17,7 @@ type mockExpectation func(sqlmock.Sqlmock) func expectFailureCount(tableName string, projectionName, instanceID string, failedSeq, failureCount uint64) func(sqlmock.Sqlmock) { return func(m sqlmock.Sqlmock) { - m.ExpectQuery(`WITH failures AS \(SELECT failure_count FROM `+tableName+` WHERE projection_name = \$1 AND failed_sequence = \$2\ AND instance_id = \$3\) SELECT IF\(EXISTS\(SELECT failure_count FROM failures\), \(SELECT failure_count FROM failures\), 0\) AS failure_count`). + m.ExpectQuery(`WITH failures AS \(SELECT failure_count FROM `+tableName+` WHERE projection_name = \$1 AND failed_sequence = \$2 AND instance_id = \$3\) SELECT COALESCE\(\(SELECT failure_count FROM failures\), 0\) AS failure_count`). WithArgs(projectionName, failedSeq, instanceID). WillReturnRows( sqlmock.NewRows([]string{"failure_count"}). @@ -28,7 +28,7 @@ func expectFailureCount(tableName string, projectionName, instanceID string, fai func expectUpdateFailureCount(tableName string, projectionName, instanceID string, seq, failureCount uint64) func(sqlmock.Sqlmock) { return func(m sqlmock.Sqlmock) { - m.ExpectExec(`UPSERT INTO `+tableName+` \(projection_name, failed_sequence, failure_count, error, instance_id\) VALUES \(\$1, \$2, \$3, \$4\, \$5\)`). + m.ExpectExec(`INSERT INTO `+tableName+` \(projection_name, failed_sequence, failure_count, error, instance_id\) VALUES \(\$1, \$2, \$3, \$4\, \$5\) ON CONFLICT \(projection_name, failed_sequence, instance_id\) DO UPDATE SET failure_count = EXCLUDED\.failure_count, error = EXCLUDED\.error`). WithArgs(projectionName, seq, failureCount, sqlmock.AnyArg(), instanceID).WillReturnResult(sqlmock.NewResult(1, 1)) } } @@ -133,7 +133,7 @@ func expectCurrentSequence(tableName, projection string, seq uint64, aggregateTy m.ExpectQuery(`SELECT current_sequence, aggregate_type, instance_id FROM `+tableName+` WHERE projection_name = \$1 AND instance_id = ANY \(\$2\) FOR UPDATE`). WithArgs( projection, - pq.StringArray(instanceIDs), + database.StringArray(instanceIDs), ). WillReturnRows( rows, @@ -146,7 +146,7 @@ func expectCurrentSequenceErr(tableName, projection string, instanceIDs []string m.ExpectQuery(`SELECT current_sequence, aggregate_type, instance_id FROM `+tableName+` WHERE projection_name = \$1 AND instance_id = ANY \(\$2\) FOR UPDATE`). WithArgs( projection, - pq.StringArray(instanceIDs), + database.StringArray(instanceIDs), ). WillReturnError(err) } @@ -157,7 +157,7 @@ func expectCurrentSequenceNoRows(tableName, projection string, instanceIDs []str m.ExpectQuery(`SELECT current_sequence, aggregate_type, instance_id FROM `+tableName+` WHERE projection_name = \$1 AND instance_id = ANY \(\$2\) FOR UPDATE`). WithArgs( projection, - pq.StringArray(instanceIDs), + database.StringArray(instanceIDs), ). WillReturnRows( sqlmock.NewRows([]string{"current_sequence", "aggregate_type", "instance_id"}), @@ -170,7 +170,7 @@ func expectCurrentSequenceScanErr(tableName, projection string, instanceIDs []st m.ExpectQuery(`SELECT current_sequence, aggregate_type, instance_id FROM `+tableName+` WHERE projection_name = \$1 AND instance_id = ANY \(\$2\) FOR UPDATE`). WithArgs( projection, - pq.StringArray(instanceIDs), + database.StringArray(instanceIDs), ). WillReturnRows( sqlmock.NewRows([]string{"current_sequence", "aggregate_type", "instance_id"}). @@ -182,7 +182,7 @@ func expectCurrentSequenceScanErr(tableName, projection string, instanceIDs []st func expectUpdateCurrentSequence(tableName, projection string, seq uint64, aggregateType, instanceID string) func(sqlmock.Sqlmock) { return func(m sqlmock.Sqlmock) { - m.ExpectExec("UPSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\)`). + m.ExpectExec("INSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\) ON CONFLICT \(projection_name, aggregate_type, instance_id\) DO UPDATE SET current_sequence = EXCLUDED.current_sequence, timestamp = EXCLUDED.timestamp`). WithArgs( projection, aggregateType, @@ -213,7 +213,7 @@ func expectUpdateThreeCurrentSequence(t *testing.T, tableName, projection string matchers[i] = matcher } return func(m sqlmock.Sqlmock) { - m.ExpectExec("UPSERT INTO " + tableName + ` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\), \(\$5, \$6, \$7, \$8, NOW\(\)\), \(\$9, \$10, \$11, \$12, NOW\(\)\)`). + m.ExpectExec("INSERT INTO " + tableName + ` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\), \(\$5, \$6, \$7, \$8, NOW\(\)\), \(\$9, \$10, \$11, \$12, NOW\(\)\) ON CONFLICT \(projection_name, aggregate_type, instance_id\) DO UPDATE SET current_sequence = EXCLUDED.current_sequence, timestamp = EXCLUDED.timestamp`). WithArgs( matchers..., ). @@ -262,7 +262,7 @@ func (m *currentSequenceMatcher) Match(value driver.Value) bool { func expectUpdateCurrentSequenceErr(tableName, projection string, seq uint64, err error, aggregateType, instanceID string) func(sqlmock.Sqlmock) { return func(m sqlmock.Sqlmock) { - m.ExpectExec("UPSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\)`). + m.ExpectExec("INSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\) ON CONFLICT \(projection_name, aggregate_type, instance_id\) DO UPDATE SET current_sequence = EXCLUDED.current_sequence, timestamp = EXCLUDED.timestamp`). WithArgs( projection, aggregateType, @@ -275,7 +275,7 @@ func expectUpdateCurrentSequenceErr(tableName, projection string, seq uint64, er func expectUpdateCurrentSequenceNoRows(tableName, projection string, seq uint64, aggregateType, instanceID string) func(sqlmock.Sqlmock) { return func(m sqlmock.Sqlmock) { - m.ExpectExec("UPSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\)`). + m.ExpectExec("INSERT INTO "+tableName+` \(projection_name, aggregate_type, current_sequence, instance_id, timestamp\) VALUES \(\$1, \$2, \$3, \$4, NOW\(\)\) ON CONFLICT \(projection_name, aggregate_type, instance_id\) DO UPDATE SET current_sequence = EXCLUDED.current_sequence, timestamp = EXCLUDED.timestamp`). WithArgs( projection, aggregateType, @@ -297,10 +297,10 @@ func expectLock(lockTable, workerName string, d time.Duration, instanceID string ` WHERE `+lockTable+`\.projection_name = \$3 AND `+lockTable+`\.instance_id = ANY \(\$5\) AND \(`+lockTable+`\.locker_id = \$1 OR `+lockTable+`\.locked_until < now\(\)\)`). WithArgs( workerName, - float64(d), + d, projectionName, instanceID, - pq.StringArray{instanceID}, + database.StringArray{instanceID}, ). WillReturnResult( sqlmock.NewResult(1, 1), @@ -317,11 +317,11 @@ func expectLockMultipleInstances(lockTable, workerName string, d time.Duration, ` WHERE `+lockTable+`\.projection_name = \$3 AND `+lockTable+`\.instance_id = ANY \(\$6\) AND \(`+lockTable+`\.locker_id = \$1 OR `+lockTable+`\.locked_until < now\(\)\)`). WithArgs( workerName, - float64(d), + d, projectionName, instanceID1, instanceID2, - pq.StringArray{instanceID1, instanceID2}, + database.StringArray{instanceID1, instanceID2}, ). WillReturnResult( sqlmock.NewResult(1, 1), @@ -338,10 +338,10 @@ func expectLockNoRows(lockTable, workerName string, d time.Duration, instanceID ` WHERE `+lockTable+`\.projection_name = \$3 AND `+lockTable+`\.instance_id = ANY \(\$5\) AND \(`+lockTable+`\.locker_id = \$1 OR `+lockTable+`\.locked_until < now\(\)\)`). WithArgs( workerName, - float64(d), + d, projectionName, instanceID, - pq.StringArray{instanceID}, + database.StringArray{instanceID}, ). WillReturnResult(driver.ResultNoRows) } @@ -356,10 +356,10 @@ func expectLockErr(lockTable, workerName string, d time.Duration, instanceID str ` WHERE `+lockTable+`\.projection_name = \$3 AND `+lockTable+`\.instance_id = ANY \(\$5\) AND \(`+lockTable+`\.locker_id = \$1 OR `+lockTable+`\.locked_until < now\(\)\)`). WithArgs( workerName, - float64(d), + d, projectionName, instanceID, - pq.StringArray{instanceID}, + database.StringArray{instanceID}, ). WillReturnError(err) } diff --git a/internal/eventstore/handler/crdb/failed_stmt.go b/internal/eventstore/handler/crdb/failed_stmt.go index 4124062a17..acf918a8f0 100644 --- a/internal/eventstore/handler/crdb/failed_stmt.go +++ b/internal/eventstore/handler/crdb/failed_stmt.go @@ -10,15 +10,12 @@ import ( ) const ( - setFailureCountStmtFormat = "UPSERT INTO %s" + + setFailureCountStmtFormat = "INSERT INTO %s" + " (projection_name, failed_sequence, failure_count, error, instance_id)" + - " VALUES ($1, $2, $3, $4, $5)" + " VALUES ($1, $2, $3, $4, $5) ON CONFLICT (projection_name, failed_sequence, instance_id)" + + " DO UPDATE SET failure_count = EXCLUDED.failure_count, error = EXCLUDED.error" failureCountStmtFormat = "WITH failures AS (SELECT failure_count FROM %s WHERE projection_name = $1 AND failed_sequence = $2 AND instance_id = $3)" + - " SELECT IF(" + - "EXISTS(SELECT failure_count FROM failures)," + - " (SELECT failure_count FROM failures)," + - " 0" + - ") AS failure_count" + " SELECT COALESCE((SELECT failure_count FROM failures), 0) AS failure_count" ) func (h *StatementHandler) handleFailedStmt(tx *sql.Tx, stmt *handler.Statement, execErr error) (shouldContinue bool) { diff --git a/internal/eventstore/handler/crdb/handler_stmt.go b/internal/eventstore/handler/crdb/handler_stmt.go index 7aa921fd90..b8fe8ad88f 100644 --- a/internal/eventstore/handler/crdb/handler_stmt.go +++ b/internal/eventstore/handler/crdb/handler_stmt.go @@ -72,12 +72,12 @@ func NewStatementHandler( aggregates: aggregateTypes, reduces: reduces, bulkLimit: config.BulkLimit, - Locker: NewLocker(config.Client, config.LockTable, config.ProjectionHandlerConfig.ProjectionName), + Locker: NewLocker(config.Client, config.LockTable, config.ProjectionName), } h.ProjectionHandler = handler.NewProjectionHandler(ctx, config.ProjectionHandlerConfig, h.reduce, h.Update, h.SearchQuery, h.Lock, h.Unlock) err := h.Init(ctx, config.InitCheck) - logging.OnError(err).Fatal("unable to initialize projections") + logging.OnError(err).WithField("projection", config.ProjectionName).Fatal("unable to initialize projections") h.Subscribe(h.aggregates...) diff --git a/internal/eventstore/handler/crdb/init.go b/internal/eventstore/handler/crdb/init.go index 76fbd772fd..b928ee8b42 100644 --- a/internal/eventstore/handler/crdb/init.go +++ b/internal/eventstore/handler/crdb/init.go @@ -6,11 +6,10 @@ import ( "fmt" "strings" - "github.com/lib/pq" + "github.com/jackc/pgconn" "github.com/zitadel/logging" caos_errs "github.com/zitadel/zitadel/internal/errors" - "github.com/zitadel/zitadel/internal/eventstore/handler" ) @@ -186,7 +185,7 @@ type ForeignKey struct { RefColumns []string } -//Init implements handler.Init +// Init implements handler.Init func (h *StatementHandler) Init(ctx context.Context, checks ...*handler.Check) error { for _, check := range checks { if check == nil || check.IsNoop() { @@ -280,7 +279,7 @@ func isErrAlreadyExists(err error) bool { if !errors.As(err, &caosErr) { return false } - sqlErr, ok := caosErr.GetParent().(*pq.Error) + sqlErr, ok := caosErr.GetParent().(*pgconn.PgError) if !ok { return false } @@ -288,14 +287,11 @@ func isErrAlreadyExists(err error) bool { } func createTableStatement(table *Table, tableName string, suffix string) string { - stmt := fmt.Sprintf("CREATE TABLE %s (%s, PRIMARY KEY (%s)", + stmt := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s, PRIMARY KEY (%s)", tableName+suffix, createColumnsStatement(table.columns, tableName), strings.Join(table.primaryKey, ", "), ) - for _, index := range table.indices { - stmt += fmt.Sprintf(", INDEX %s (%s)", index.Name, strings.Join(index.Columns, ",")) - } for _, key := range table.foreignKeys { ref := tableName if len(key.RefColumns) > 0 { @@ -309,7 +305,13 @@ func createTableStatement(table *Table, tableName string, suffix string) string for _, constraint := range table.constraints { stmt += fmt.Sprintf(", CONSTRAINT %s UNIQUE (%s)", constraint.Name, strings.Join(constraint.Columns, ",")) } - return stmt + ");" + + stmt += ");" + + for _, index := range table.indices { + stmt += fmt.Sprintf("CREATE INDEX IF NOT EXISTS %s ON %s (%s);", index.Name, tableName+suffix, strings.Join(index.Columns, ",")) + } + return stmt } func createViewStatement(viewName string, selectStmt string) string { @@ -321,7 +323,7 @@ func createViewStatement(viewName string, selectStmt string) string { func createIndexStatement(index *Index) func(config execConfig) string { return func(config execConfig) string { - stmt := fmt.Sprintf("CREATE INDEX %s ON %s (%s)", + stmt := fmt.Sprintf("CREATE INDEX IF NOT EXISTS %s ON %s (%s)", index.Name, config.tableName, strings.Join(index.Columns, ","), @@ -380,9 +382,8 @@ func columnType(columnType ColumnType) string { case ColumnTypeJSONB: return "JSONB" case ColumnTypeBytes: - return "BYTES" + return "BYTEA" default: panic("unknown column type") - return "" } } diff --git a/internal/eventstore/handler/crdb/lock.go b/internal/eventstore/handler/crdb/lock.go index bc7894efa4..d101a34091 100644 --- a/internal/eventstore/handler/crdb/lock.go +++ b/internal/eventstore/handler/crdb/lock.go @@ -8,9 +8,9 @@ import ( "strings" "time" - "github.com/lib/pq" "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/id" ) @@ -91,17 +91,17 @@ func (h *locker) Unlock(instanceIDs ...string) error { return nil } -func (h *locker) lockStatement(lockDuration time.Duration, instanceIDs []string) (string, []interface{}) { +func (h *locker) lockStatement(lockDuration time.Duration, instanceIDs database.StringArray) (string, []interface{}) { valueQueries := make([]string, len(instanceIDs)) values := make([]interface{}, len(instanceIDs)+4) values[0] = h.workerName //the unit of crdb interval is seconds (https://www.cockroachlabs.com/docs/stable/interval.html). - values[1] = lockDuration.Seconds() + values[1] = lockDuration values[2] = h.projectionName for i, instanceID := range instanceIDs { valueQueries[i] = "($1, now()+$2::INTERVAL, $3, $" + strconv.Itoa(i+4) + ")" values[i+3] = instanceID } - values[len(values)-1] = pq.StringArray(instanceIDs) + values[len(values)-1] = instanceIDs return h.lockStmt(strings.Join(valueQueries, ", "), len(values)), values } diff --git a/internal/eventstore/handler/crdb/lock_test.go b/internal/eventstore/handler/crdb/lock_test.go index 9280e430b6..fe18253b5b 100644 --- a/internal/eventstore/handler/crdb/lock_test.go +++ b/internal/eventstore/handler/crdb/lock_test.go @@ -10,6 +10,7 @@ import ( "github.com/DATA-DOG/go-sqlmock" + "github.com/zitadel/zitadel/internal/database" z_errs "github.com/zitadel/zitadel/internal/errors" ) @@ -43,9 +44,9 @@ func TestStatementHandler_handleLock(t *testing.T) { name: "lock fails", want: want{ expectations: []mockExpectation{ - expectLock(lockTable, workerName, 2, "instanceID"), - expectLock(lockTable, workerName, 2, "instanceID"), - expectLockErr(lockTable, workerName, 2, "instanceID", errLock), + expectLock(lockTable, workerName, 2*time.Second, "instanceID"), + expectLock(lockTable, workerName, 2*time.Second, "instanceID"), + expectLockErr(lockTable, workerName, 2*time.Second, "instanceID", errLock), }, }, args: args{ @@ -63,8 +64,8 @@ func TestStatementHandler_handleLock(t *testing.T) { name: "success", want: want{ expectations: []mockExpectation{ - expectLock(lockTable, workerName, 2, "instanceID"), - expectLock(lockTable, workerName, 2, "instanceID"), + expectLock(lockTable, workerName, 2*time.Second, "instanceID"), + expectLock(lockTable, workerName, 2*time.Second, "instanceID"), }, }, args: args{ @@ -81,8 +82,8 @@ func TestStatementHandler_handleLock(t *testing.T) { name: "success with multiple", want: want{ expectations: []mockExpectation{ - expectLockMultipleInstances(lockTable, workerName, 2, "instanceID1", "instanceID2"), - expectLockMultipleInstances(lockTable, workerName, 2, "instanceID1", "instanceID2"), + expectLockMultipleInstances(lockTable, workerName, 2*time.Second, "instanceID1", "instanceID2"), + expectLockMultipleInstances(lockTable, workerName, 2*time.Second, "instanceID1", "instanceID2"), }, }, args: args{ @@ -149,7 +150,7 @@ func TestStatementHandler_renewLock(t *testing.T) { name: "lock fails", want: want{ expectations: []mockExpectation{ - expectLockErr(lockTable, workerName, 1, "instanceID", sql.ErrTxDone), + expectLockErr(lockTable, workerName, 1*time.Second, "instanceID", sql.ErrTxDone), }, isErr: func(err error) bool { return errors.Is(err, sql.ErrTxDone) @@ -157,14 +158,14 @@ func TestStatementHandler_renewLock(t *testing.T) { }, args: args{ lockDuration: 1 * time.Second, - instanceIDs: []string{"instanceID"}, + instanceIDs: database.StringArray{"instanceID"}, }, }, { name: "lock no rows", want: want{ expectations: []mockExpectation{ - expectLockNoRows(lockTable, workerName, 2, "instanceID"), + expectLockNoRows(lockTable, workerName, 2*time.Second, "instanceID"), }, isErr: func(err error) bool { return errors.Is(err, renewNoRowsAffectedErr) @@ -172,14 +173,14 @@ func TestStatementHandler_renewLock(t *testing.T) { }, args: args{ lockDuration: 2 * time.Second, - instanceIDs: []string{"instanceID"}, + instanceIDs: database.StringArray{"instanceID"}, }, }, { name: "success", want: want{ expectations: []mockExpectation{ - expectLock(lockTable, workerName, 3, "instanceID"), + expectLock(lockTable, workerName, 3*time.Second, "instanceID"), }, isErr: func(err error) bool { return errors.Is(err, nil) @@ -187,14 +188,14 @@ func TestStatementHandler_renewLock(t *testing.T) { }, args: args{ lockDuration: 3 * time.Second, - instanceIDs: []string{"instanceID"}, + instanceIDs: database.StringArray{"instanceID"}, }, }, { name: "success with multiple", want: want{ expectations: []mockExpectation{ - expectLockMultipleInstances(lockTable, workerName, 3, "instanceID1", "instanceID2"), + expectLockMultipleInstances(lockTable, workerName, 3*time.Second, "instanceID1", "instanceID2"), }, isErr: func(err error) bool { return errors.Is(err, nil) diff --git a/internal/eventstore/handler/crdb/statement.go b/internal/eventstore/handler/crdb/statement.go index c4bc2db9d5..8f0235fd63 100644 --- a/internal/eventstore/handler/crdb/statement.go +++ b/internal/eventstore/handler/crdb/statement.go @@ -4,8 +4,7 @@ import ( "strconv" "strings" - "github.com/lib/pq" - + "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" @@ -51,10 +50,13 @@ func NewCreateStatement(event eventstore.Event, values []handler.Column, opts .. } } -func NewUpsertStatement(event eventstore.Event, values []handler.Column, opts ...execOption) *handler.Statement { +func NewUpsertStatement(event eventstore.Event, conflictCols []handler.Column, values []handler.Column, opts ...execOption) *handler.Statement { cols, params, args := columnsToQuery(values) - columnNames := strings.Join(cols, ", ") - valuesPlaceholder := strings.Join(params, ", ") + + conflictTarget := make([]string, len(conflictCols)) + for i, col := range conflictCols { + conflictTarget[i] = col.Name + } config := execConfig{ args: args, @@ -64,8 +66,14 @@ func NewUpsertStatement(event eventstore.Event, values []handler.Column, opts .. config.err = handler.ErrNoValues } + updateCols, updateVals := getUpdateCols(cols, conflictTarget) + if len(updateCols) == 0 || len(updateVals) == 0 { + config.err = handler.ErrNoValues + } + q := func(config execConfig) string { - return "UPSERT INTO " + config.tableName + " (" + columnNames + ") VALUES (" + valuesPlaceholder + ")" + return "INSERT INTO " + config.tableName + " (" + strings.Join(cols, ", ") + ") VALUES (" + strings.Join(params, ", ") + ")" + + " ON CONFLICT (" + strings.Join(conflictTarget, ", ") + ") DO UPDATE SET (" + strings.Join(updateCols, ", ") + ") = (" + strings.Join(updateVals, ", ") + ")" } return &handler.Statement{ @@ -77,15 +85,38 @@ func NewUpsertStatement(event eventstore.Event, values []handler.Column, opts .. } } +func getUpdateCols(cols, conflictTarget []string) (updateCols, updateVals []string) { + updateCols = make([]string, len(cols)) + updateVals = make([]string, len(cols)) + + copy(updateCols, cols) + + for i := len(updateCols) - 1; i >= 0; i-- { + updateVals[i] = "EXCLUDED." + updateCols[i] + + for _, conflict := range conflictTarget { + if conflict == updateCols[i] { + copy(updateCols[i:], updateCols[i+1:]) + updateCols[len(updateCols)-1] = "" + updateCols = updateCols[:len(updateCols)-1] + + copy(updateVals[i:], updateVals[i+1:]) + updateVals[len(updateVals)-1] = "" + updateVals = updateVals[:len(updateVals)-1] + + break + } + } + } + + return updateCols, updateVals +} + func NewUpdateStatement(event eventstore.Event, values []handler.Column, conditions []handler.Condition, opts ...execOption) *handler.Statement { cols, params, args := columnsToQuery(values) wheres, whereArgs := conditionsToWhere(conditions, len(params)) args = append(args, whereArgs...) - columnNames := strings.Join(cols, ", ") - valuesPlaceholder := strings.Join(params, ", ") - wheresPlaceholders := strings.Join(wheres, " AND ") - config := execConfig{ args: args, } @@ -99,7 +130,7 @@ func NewUpdateStatement(event eventstore.Event, values []handler.Column, conditi } q := func(config execConfig) string { - return "UPDATE " + config.tableName + " SET (" + columnNames + ") = (" + valuesPlaceholder + ") WHERE " + wheresPlaceholders + return "UPDATE " + config.tableName + " SET (" + strings.Join(cols, ", ") + ") = (" + strings.Join(params, ", ") + ") WHERE " + strings.Join(wheres, " AND ") } return &handler.Statement{ @@ -171,9 +202,9 @@ func AddCreateStatement(columns []handler.Column, opts ...execOption) func(event } } -func AddUpsertStatement(values []handler.Column, opts ...execOption) func(eventstore.Event) Exec { +func AddUpsertStatement(indexCols []handler.Column, values []handler.Column, opts ...execOption) func(eventstore.Event) Exec { return func(event eventstore.Event) Exec { - return NewUpsertStatement(event, values, opts...).Execute + return NewUpsertStatement(event, indexCols, values, opts...).Execute } } @@ -189,9 +220,9 @@ func AddDeleteStatement(conditions []handler.Condition, opts ...execOption) func } } -func AddCopyStatement(from, to []handler.Column, conditions []handler.Condition, opts ...execOption) func(eventstore.Event) Exec { +func AddCopyStatement(conflict, from, to []handler.Column, conditions []handler.Condition, opts ...execOption) func(eventstore.Event) Exec { return func(event eventstore.Event) Exec { - return NewCopyStatement(event, from, to, conditions, opts...).Execute + return NewCopyStatement(event, conflict, from, to, conditions, opts...).Execute } } @@ -218,11 +249,9 @@ func NewArrayRemoveCol(column string, value interface{}) handler.Column { func NewArrayIntersectCol(column string, value interface{}) handler.Column { var arrayType string switch value.(type) { - case pq.StringArray: - arrayType = "STRING" - case pq.Int32Array, - pq.Int64Array: - arrayType = "INT" + + case []string, database.StringArray: + arrayType = "TEXT" //TODO: handle more types if necessary } return handler.Column{ @@ -234,25 +263,29 @@ func NewArrayIntersectCol(column string, value interface{}) handler.Column { } } -//NewCopyStatement creates a new upsert statement which updates a column from an existing row +// NewCopyStatement creates a new upsert statement which updates a column from an existing row // cols represent the columns which are objective to change. // if the value of a col is empty the data will be copied from the selected row // if the value of a col is not empty the data will be set by the static value // conds represent the conditions for the selection subquery -func NewCopyStatement(event eventstore.Event, from, to []handler.Column, conds []handler.Condition, opts ...execOption) *handler.Statement { +func NewCopyStatement(event eventstore.Event, conflictCols, from, to []handler.Column, conds []handler.Condition, opts ...execOption) *handler.Statement { columnNames := make([]string, len(to)) selectColumns := make([]string, len(from)) + updateColumns := make([]string, len(columnNames)) argCounter := 0 args := []interface{}{} - for i := range from { + for i, col := range from { columnNames[i] = to[i].Name selectColumns[i] = from[i].Name - if from[i].Value != nil { + updateColumns[i] = "EXCLUDED." + col.Name + if col.Value != nil { argCounter++ selectColumns[i] = "$" + strconv.Itoa(argCounter) - args = append(args, from[i].Value) + updateColumns[i] = selectColumns[i] + args = append(args, col.Value) } + } wheres := make([]string, len(conds)) @@ -262,6 +295,11 @@ func NewCopyStatement(event eventstore.Event, from, to []handler.Column, conds [ args = append(args, cond.Value) } + conflictTargets := make([]string, len(conflictCols)) + for i, conflictCol := range conflictCols { + conflictTargets[i] = conflictCol.Name + } + config := execConfig{ args: args, } @@ -275,7 +313,7 @@ func NewCopyStatement(event eventstore.Event, from, to []handler.Column, conds [ } q := func(config execConfig) string { - return "UPSERT INTO " + + return "INSERT INTO " + config.tableName + " (" + strings.Join(columnNames, ", ") + @@ -283,7 +321,14 @@ func NewCopyStatement(event eventstore.Event, from, to []handler.Column, conds [ strings.Join(selectColumns, ", ") + " FROM " + config.tableName + " AS copy_table WHERE " + - strings.Join(wheres, " AND ") + strings.Join(wheres, " AND ") + + " ON CONFLICT (" + + strings.Join(conflictTargets, ", ") + + ") DO UPDATE SET (" + + strings.Join(columnNames, ", ") + + ") = (" + + strings.Join(updateColumns, ", ") + + ")" } return &handler.Statement{ diff --git a/internal/eventstore/handler/crdb/statement_test.go b/internal/eventstore/handler/crdb/statement_test.go index a4bea29261..f8fe6a8427 100644 --- a/internal/eventstore/handler/crdb/statement_test.go +++ b/internal/eventstore/handler/crdb/statement_test.go @@ -178,9 +178,10 @@ func TestNewCreateStatement(t *testing.T) { func TestNewUpsertStatement(t *testing.T) { type args struct { - table string - event *testEvent - values []handler.Column + table string + event *testEvent + conflictCols []handler.Column + values []handler.Column } type want struct { aggregateType eventstore.AggregateType @@ -249,7 +250,7 @@ func TestNewUpsertStatement(t *testing.T) { }, }, { - name: "correct", + name: "no update cols", args: args{ table: "my_table", event: &testEvent{ @@ -257,6 +258,9 @@ func TestNewUpsertStatement(t *testing.T) { sequence: 1, previousSequence: 0, }, + conflictCols: []handler.Column{ + handler.NewCol("col1", nil), + }, values: []handler.Column{ { Name: "col1", @@ -264,6 +268,42 @@ func TestNewUpsertStatement(t *testing.T) { }, }, }, + want: want{ + table: "my_table", + aggregateType: "agg", + sequence: 1, + previousSequence: 1, + executer: &wantExecuter{ + shouldExecute: false, + }, + isErr: func(err error) bool { + return errors.Is(err, handler.ErrNoValues) + }, + }, + }, + { + name: "correct", + args: args{ + table: "my_table", + event: &testEvent{ + aggregateType: "agg", + sequence: 1, + previousSequence: 0, + }, + conflictCols: []handler.Column{ + handler.NewCol("col1", nil), + }, + values: []handler.Column{ + { + Name: "col1", + Value: "val", + }, + { + Name: "col2", + Value: "val", + }, + }, + }, want: want{ table: "my_table", aggregateType: "agg", @@ -272,8 +312,8 @@ func TestNewUpsertStatement(t *testing.T) { executer: &wantExecuter{ params: []params{ { - query: "UPSERT INTO my_table (col1) VALUES ($1)", - args: []interface{}{"val"}, + query: "INSERT INTO my_table (col1, col2) VALUES ($1, $2) ON CONFLICT (col1) DO UPDATE SET (col2) = (EXCLUDED.col2)", + args: []interface{}{"val", "val"}, }, }, shouldExecute: true, @@ -287,7 +327,7 @@ func TestNewUpsertStatement(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.want.executer.t = t - stmt := NewUpsertStatement(tt.args.event, tt.args.values) + stmt := NewUpsertStatement(tt.args.event, tt.args.conflictCols, tt.args.values) err := stmt.Execute(tt.want.executer, tt.args.table) if !tt.want.isErr(err) { @@ -724,11 +764,18 @@ func TestNewMultiStatement(t *testing.T) { }, }), AddUpsertStatement( + []handler.Column{ + handler.NewCol("col1", nil), + }, []handler.Column{ { Name: "col1", Value: 1, }, + { + Name: "col2", + Value: 2, + }, }), AddUpdateStatement( []handler.Column{ @@ -761,8 +808,8 @@ func TestNewMultiStatement(t *testing.T) { args: []interface{}{1}, }, { - query: "UPSERT INTO my_table (col1) VALUES ($1)", - args: []interface{}{1}, + query: "INSERT INTO my_table (col1, col2) VALUES ($1, $2) ON CONFLICT (col1) DO UPDATE SET (col2) = (EXCLUDED.col2)", + args: []interface{}{1, 2}, }, { query: "UPDATE my_table SET (col1) = ($1) WHERE (col1 = $2)", @@ -799,11 +846,12 @@ func TestNewMultiStatement(t *testing.T) { func TestNewCopyStatement(t *testing.T) { type args struct { - table string - event *testEvent - from []handler.Column - to []handler.Column - conds []handler.Condition + table string + event *testEvent + conflictingCols []handler.Column + from []handler.Column + to []handler.Column + conds []handler.Condition } type want struct { aggregateType eventstore.AggregateType @@ -1004,7 +1052,7 @@ func TestNewCopyStatement(t *testing.T) { executer: &wantExecuter{ params: []params{ { - query: "UPSERT INTO my_table (state, id, col_a, col_b) SELECT $1, id, col_a, col_b FROM my_table AS copy_table WHERE copy_table.id = $2 AND copy_table.state = $3", + query: "INSERT INTO my_table (state, id, col_a, col_b) SELECT $1, id, col_a, col_b FROM my_table AS copy_table WHERE copy_table.id = $2 AND copy_table.state = $3 ON CONFLICT () DO UPDATE SET (state, id, col_a, col_b) = ($1, EXCLUDED.id, EXCLUDED.col_a, EXCLUDED.col_b)", args: []interface{}{1, 2, 3}, }, }, @@ -1071,7 +1119,7 @@ func TestNewCopyStatement(t *testing.T) { executer: &wantExecuter{ params: []params{ { - query: "UPSERT INTO my_table (state, id, col_c, col_d) SELECT $1, id, col_a, col_b FROM my_table AS copy_table WHERE copy_table.id = $2 AND copy_table.state = $3", + query: "INSERT INTO my_table (state, id, col_c, col_d) SELECT $1, id, col_a, col_b FROM my_table AS copy_table WHERE copy_table.id = $2 AND copy_table.state = $3 ON CONFLICT () DO UPDATE SET (state, id, col_c, col_d) = ($1, EXCLUDED.id, EXCLUDED.col_a, EXCLUDED.col_b)", args: []interface{}{1, 2, 3}, }, }, @@ -1086,7 +1134,7 @@ func TestNewCopyStatement(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.want.executer.t = t - stmt := NewCopyStatement(tt.args.event, tt.args.from, tt.args.to, tt.args.conds) + stmt := NewCopyStatement(tt.args.event, tt.args.conflictingCols, tt.args.from, tt.args.to, tt.args.conds) err := stmt.Execute(tt.want.executer, tt.args.table) if !tt.want.isErr(err) { diff --git a/internal/eventstore/local_crdb_test.go b/internal/eventstore/local_crdb_test.go index aea9e57bda..1ac0e6779e 100644 --- a/internal/eventstore/local_crdb_test.go +++ b/internal/eventstore/local_crdb_test.go @@ -9,6 +9,8 @@ import ( "github.com/zitadel/logging" "github.com/zitadel/zitadel/cmd/initialise" + "github.com/zitadel/zitadel/internal/database" + "github.com/zitadel/zitadel/internal/database/cockroach" ) var ( @@ -45,13 +47,20 @@ func TestMain(m *testing.M) { } func initDB(db *sql.DB) error { - username := "zitadel" - database := "zitadel" - err := initialise.Initialise(db, initialise.VerifyUser(username, ""), - initialise.VerifyDatabase(database), - initialise.VerifyGrant(database, username)) + initialise.ReadStmts("cockroach") + config := new(database.Config) + config.SetConnector(&cockroach.Config{ + User: cockroach.User{ + Username: "zitadel", + }, + Database: "zitadel", + }) + err := initialise.Init(db, + initialise.VerifyUser(config.Username(), ""), + initialise.VerifyDatabase(config.Database()), + initialise.VerifyGrant(config.Database(), config.Username())) if err != nil { return err } - return initialise.VerifyZitadel(db) + return initialise.VerifyZitadel(db, *config) } diff --git a/internal/eventstore/repository/sql/crdb.go b/internal/eventstore/repository/sql/crdb.go index 28c466f9b5..cc42611385 100644 --- a/internal/eventstore/repository/sql/crdb.go +++ b/internal/eventstore/repository/sql/crdb.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/cockroachdb/cockroach-go/v2/crdb" + "github.com/jackc/pgconn" "github.com/lib/pq" "github.com/zitadel/logging" @@ -30,7 +31,7 @@ const ( " SELECT MAX(event_sequence) seq, 1 join_me" + " FROM eventstore.events" + " WHERE aggregate_type = $2" + - " AND (CASE WHEN $9::STRING IS NULL THEN instance_id is null else instance_id = $9::STRING END)" + + " AND (CASE WHEN $9::TEXT IS NULL THEN instance_id is null else instance_id = $9::TEXT END)" + ") AS agg_type " + // combined with "LEFT JOIN " + @@ -39,7 +40,7 @@ const ( " SELECT event_sequence seq, resource_owner ro, 1 join_me" + " FROM eventstore.events" + " WHERE aggregate_type = $2 AND aggregate_id = $3" + - " AND (CASE WHEN $9::STRING IS NULL THEN instance_id is null else instance_id = $9::STRING END)" + + " AND (CASE WHEN $9::TEXT IS NULL THEN instance_id is null else instance_id = $9::TEXT END)" + " ORDER BY event_sequence DESC" + " LIMIT 1" + ") AS agg USING(join_me)" + @@ -69,9 +70,9 @@ const ( " $5::JSONB AS event_data," + " $6::VARCHAR AS editor_user," + " $7::VARCHAR AS editor_service," + - " IFNULL((resource_owner), $8::VARCHAR) AS resource_owner," + + " COALESCE((resource_owner), $8::VARCHAR) AS resource_owner," + " $9::VARCHAR AS instance_id," + - " NEXTVAL(CONCAT('eventstore.', IF($9 <> '', CONCAT('i_', $9), 'system'), '_seq'))," + + " NEXTVAL(CONCAT('eventstore.', (CASE WHEN $9 <> '' THEN CONCAT('i_', $9) ELSE 'system' END), '_seq'))," + " aggregate_sequence AS previous_aggregate_sequence," + " aggregate_type_sequence AS previous_aggregate_type_sequence " + "FROM previous_data " + @@ -156,7 +157,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, '_seq')", instanceID) + row := db.client.QueryRowContext(ctx, "SELECT CONCAT('eventstore.i_', $1::TEXT, '_seq')", instanceID) if row.Err() != nil { return caos_errs.ThrowInvalidArgument(row.Err(), "SQL-7gtFA", "Errors.InvalidArgument") } @@ -218,7 +219,7 @@ func (db *CRDB) Filter(ctx context.Context, searchQuery *repository.SearchQuery) return events, nil } -//LatestSequence returns the latest sequence found by the search query +// LatestSequence returns the latest sequence found by the search query func (db *CRDB) LatestSequence(ctx context.Context, searchQuery *repository.SearchQuery) (uint64, error) { var seq Sequence err := query(ctx, db, searchQuery, &seq) @@ -228,7 +229,7 @@ func (db *CRDB) LatestSequence(ctx context.Context, searchQuery *repository.Sear return uint64(seq), nil } -//InstanceIDs returns the instance ids found by the search query +// InstanceIDs returns the instance ids found by the search query func (db *CRDB) InstanceIDs(ctx context.Context, searchQuery *repository.SearchQuery) ([]string, error) { var ids []string err := query(ctx, db, searchQuery, &ids) @@ -331,7 +332,7 @@ var ( placeholder = regexp.MustCompile(`\?`) ) -//placeholder replaces all "?" with postgres placeholders ($) +// placeholder replaces all "?" with postgres placeholders ($) func (db *CRDB) placeholder(query string) string { occurances := placeholder.FindAllStringIndex(query, -1) if len(occurances) == 0 { @@ -355,5 +356,10 @@ func (db *CRDB) isUniqueViolationError(err error) bool { return true } } + if pgxErr, ok := err.(*pgconn.PgError); ok { + if pgxErr.Code == "23505" { + return true + } + } return false } diff --git a/internal/eventstore/repository/sql/crdb_test.go b/internal/eventstore/repository/sql/crdb_test.go index 9a0c7eb541..369012baa9 100644 --- a/internal/eventstore/repository/sql/crdb_test.go +++ b/internal/eventstore/repository/sql/crdb_test.go @@ -6,8 +6,7 @@ import ( "sync" "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore/repository" ) @@ -279,7 +278,7 @@ func TestCRDB_Push_OneAggregate(t *testing.T) { uniqueCount int assetCount int aggType repository.AggregateType - aggID []string + aggID database.StringArray } type res struct { wantErr bool @@ -430,7 +429,7 @@ func TestCRDB_Push_OneAggregate(t *testing.T) { t.Errorf("CRDB.Push() error = %v, wantErr %v", err, tt.res.wantErr) } - countEventRow := testCRDBClient.QueryRow("SELECT COUNT(*) FROM eventstore.events where aggregate_type = $1 AND aggregate_id = ANY($2)", tt.res.eventsRes.aggType, pq.Array(tt.res.eventsRes.aggID)) + countEventRow := testCRDBClient.QueryRow("SELECT COUNT(*) FROM eventstore.events where aggregate_type = $1 AND aggregate_id = ANY($2)", tt.res.eventsRes.aggType, tt.res.eventsRes.aggID) var eventCount int err := countEventRow.Scan(&eventCount) if err != nil { @@ -462,8 +461,8 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) { } type eventsRes struct { pushedEventsCount int - aggType []repository.AggregateType - aggID []string + aggType database.StringArray + aggID database.StringArray } type res struct { wantErr bool @@ -487,7 +486,7 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) { eventsRes: eventsRes{ pushedEventsCount: 2, aggID: []string{"100", "101"}, - aggType: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggType: database.StringArray{t.Name()}, }, }, }, @@ -506,7 +505,7 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) { eventsRes: eventsRes{ pushedEventsCount: 4, aggID: []string{"102", "103"}, - aggType: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggType: database.StringArray{t.Name()}, }, }, }, @@ -533,7 +532,7 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) { eventsRes: eventsRes{ pushedEventsCount: 12, aggID: []string{"106", "107", "108"}, - aggType: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggType: database.StringArray{t.Name()}, }, }, }, @@ -547,7 +546,7 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) { t.Errorf("CRDB.Push() error = %v, wantErr %v", err, tt.res.wantErr) } - countRow := testCRDBClient.QueryRow("SELECT COUNT(*) FROM eventstore.events where aggregate_type = ANY($1) AND aggregate_id = ANY($2)", pq.Array(tt.res.eventsRes.aggType), pq.Array(tt.res.eventsRes.aggID)) + countRow := testCRDBClient.QueryRow("SELECT COUNT(*) FROM eventstore.events where aggregate_type = ANY($1) AND aggregate_id = ANY($2)", tt.res.eventsRes.aggType, tt.res.eventsRes.aggID) var count int err := countRow.Scan(&count) if err != nil { @@ -645,8 +644,8 @@ func TestCRDB_Push_Parallel(t *testing.T) { } type eventsRes struct { pushedEventsCount int - aggTypes []repository.AggregateType - aggIDs []string + aggTypes database.StringArray + aggIDs database.StringArray } type res struct { errCount int @@ -681,7 +680,7 @@ func TestCRDB_Push_Parallel(t *testing.T) { eventsRes: eventsRes{ aggIDs: []string{"200", "201", "202", "203"}, pushedEventsCount: 9, - aggTypes: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggTypes: database.StringArray{t.Name()}, }, }, }, @@ -718,7 +717,7 @@ func TestCRDB_Push_Parallel(t *testing.T) { eventsRes: eventsRes{ aggIDs: []string{"204", "205", "206"}, pushedEventsCount: 14, - aggTypes: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggTypes: database.StringArray{t.Name()}, }, }, }, @@ -748,7 +747,7 @@ func TestCRDB_Push_Parallel(t *testing.T) { eventsRes: eventsRes{ aggIDs: []string{"207", "208"}, pushedEventsCount: 11, - aggTypes: []repository.AggregateType{repository.AggregateType(t.Name())}, + aggTypes: database.StringArray{t.Name()}, }, }, }, @@ -781,7 +780,7 @@ func TestCRDB_Push_Parallel(t *testing.T) { t.Errorf("CRDB.Push() error count = %d, wanted err count %d, errs: %v", len(errs), tt.res.errCount, errs) } - rows, err := testCRDBClient.Query("SELECT event_data FROM eventstore.events where aggregate_type = ANY($1) AND aggregate_id = ANY($2) order by event_sequence", pq.Array(tt.res.eventsRes.aggTypes), pq.Array(tt.res.eventsRes.aggIDs)) + rows, err := testCRDBClient.Query("SELECT event_data FROM eventstore.events where aggregate_type = ANY($1) AND aggregate_id = ANY($2) order by event_sequence", tt.res.eventsRes.aggTypes, tt.res.eventsRes.aggIDs) if err != nil { t.Error("unable to query inserted rows: ", err) return @@ -993,10 +992,10 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) { events []*repository.Event } type res struct { - resourceOwners []string + resourceOwners database.StringArray } type fields struct { - aggregateIDs []string + aggregateIDs database.StringArray aggregateType string } tests := []struct { @@ -1128,7 +1127,7 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) { } } - rows, err := testCRDBClient.Query("SELECT resource_owner FROM eventstore.events WHERE aggregate_type = $1 AND aggregate_id = ANY($2) ORDER BY event_sequence", tt.fields.aggregateType, pq.Array(tt.fields.aggregateIDs)) + rows, err := testCRDBClient.Query("SELECT resource_owner FROM eventstore.events WHERE aggregate_type = $1 AND aggregate_id = ANY($2) ORDER BY event_sequence", tt.fields.aggregateType, tt.fields.aggregateIDs) if err != nil { t.Error("unable to query inserted rows: ", err) return diff --git a/internal/eventstore/repository/sql/local_crdb_test.go b/internal/eventstore/repository/sql/local_crdb_test.go index ded13a49a5..4e63bbee6c 100644 --- a/internal/eventstore/repository/sql/local_crdb_test.go +++ b/internal/eventstore/repository/sql/local_crdb_test.go @@ -9,6 +9,8 @@ import ( "github.com/zitadel/logging" "github.com/zitadel/zitadel/cmd/initialise" + "github.com/zitadel/zitadel/internal/database" + "github.com/zitadel/zitadel/internal/database/cockroach" ) var ( @@ -42,15 +44,22 @@ func TestMain(m *testing.M) { } func initDB(db *sql.DB) error { - username := "zitadel" - database := "zitadel" - err := initialise.Initialise(db, initialise.VerifyUser(username, ""), - initialise.VerifyDatabase(database), - initialise.VerifyGrant(database, username)) + config := new(database.Config) + config.SetConnector(&cockroach.Config{User: cockroach.User{Username: "zitadel"}, Database: "zitadel"}) + + if err := initialise.ReadStmts("cockroach"); err != nil { + return err + } + + err := initialise.Init(db, + initialise.VerifyUser(config.Username(), ""), + initialise.VerifyDatabase(config.Database()), + initialise.VerifyGrant(config.Database(), config.Username())) if err != nil { return err } - return initialise.VerifyZitadel(db) + + return initialise.VerifyZitadel(db, *config) } func fillUniqueData(unique_type, field, instanceID string) error { diff --git a/internal/eventstore/repository/sql/query.go b/internal/eventstore/repository/sql/query.go index b0977654cb..9b97014658 100644 --- a/internal/eventstore/repository/sql/query.go +++ b/internal/eventstore/repository/sql/query.go @@ -8,7 +8,6 @@ import ( "fmt" "strings" - "github.com/lib/pq" "github.com/zitadel/logging" z_errors "github.com/zitadel/zitadel/internal/errors" @@ -170,8 +169,6 @@ func prepareCondition(criteria querier, filters [][]*repository.Filter) (clause for _, f := range filter { value := f.Value switch value.(type) { - case []bool, []float64, []int64, []string, []repository.AggregateType, []repository.EventType, *[]bool, *[]float64, *[]int64, *[]string, *[]repository.AggregateType, *[]repository.EventType: - value = pq.Array(value) case map[string]interface{}: var err error value, err = json.Marshal(value) diff --git a/internal/eventstore/repository/sql/query_test.go b/internal/eventstore/repository/sql/query_test.go index eada55b69b..a1b6abc95d 100644 --- a/internal/eventstore/repository/sql/query_test.go +++ b/internal/eventstore/repository/sql/query_test.go @@ -9,7 +9,6 @@ import ( "time" "github.com/DATA-DOG/go-sqlmock" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore/repository" @@ -265,7 +264,7 @@ func Test_prepareCondition(t *testing.T) { }, res: res{ clause: " WHERE ( aggregate_type = ANY(?) )", - values: []interface{}{pq.Array([]repository.AggregateType{"user", "org"})}, + values: []interface{}{[]repository.AggregateType{"user", "org"}}, }, }, { @@ -281,7 +280,7 @@ func Test_prepareCondition(t *testing.T) { }, res: res{ clause: " WHERE ( aggregate_type = ANY(?) AND aggregate_id = ? AND event_type = ANY(?) )", - values: []interface{}{pq.Array([]repository.AggregateType{"user", "org"}), "1234", pq.Array([]repository.EventType{"user.created", "org.created"})}, + values: []interface{}{[]repository.AggregateType{"user", "org"}, "1234", []repository.EventType{"user.created", "org.created"}}, }, }, } diff --git a/internal/eventstore/search_query.go b/internal/eventstore/search_query.go index c697cf9236..38013580b9 100644 --- a/internal/eventstore/search_query.go +++ b/internal/eventstore/search_query.go @@ -3,11 +3,12 @@ package eventstore import ( "database/sql" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore/repository" ) -//SearchQueryBuilder represents the builder for your filter +// SearchQueryBuilder represents the builder for your filter // if invalid data are set the filter will fail type SearchQueryBuilder struct { columns repository.Columns @@ -79,51 +80,51 @@ func (builder *SearchQueryBuilder) Matches(event Event, existingLen int) (matche return false } -//Columns defines which fields are set +// Columns defines which fields are set func (builder *SearchQueryBuilder) Columns(columns Columns) *SearchQueryBuilder { builder.columns = repository.Columns(columns) return builder } -//Limit defines how many events are returned maximally. +// Limit defines how many events are returned maximally. func (builder *SearchQueryBuilder) Limit(limit uint64) *SearchQueryBuilder { builder.limit = limit return builder } -//ResourceOwner defines the resource owner (org) of the events +// ResourceOwner defines the resource owner (org) of the events func (builder *SearchQueryBuilder) ResourceOwner(resourceOwner string) *SearchQueryBuilder { builder.resourceOwner = resourceOwner return builder } -//InstanceID defines the instanceID (system) of the events +// InstanceID defines the instanceID (system) of the events func (builder *SearchQueryBuilder) InstanceID(instanceID string) *SearchQueryBuilder { builder.instanceID = instanceID return builder } -//OrderDesc changes the sorting order of the returned events to descending +// OrderDesc changes the sorting order of the returned events to descending func (builder *SearchQueryBuilder) OrderDesc() *SearchQueryBuilder { builder.desc = true return builder } -//OrderAsc changes the sorting order of the returned events to ascending +// OrderAsc changes the sorting order of the returned events to ascending func (builder *SearchQueryBuilder) OrderAsc() *SearchQueryBuilder { builder.desc = false return builder } -//SetTx ensures that the eventstore library uses the existing transaction +// SetTx ensures that the eventstore library uses the existing transaction func (builder *SearchQueryBuilder) SetTx(tx *sql.Tx) *SearchQueryBuilder { builder.tx = tx 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. +// 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. func (builder *SearchQueryBuilder) AddQuery() *SearchQuery { query := &SearchQuery{ builder: builder, @@ -133,61 +134,61 @@ func (builder *SearchQueryBuilder) AddQuery() *SearchQuery { return query } -//Or creates a new sub query on the search query builder +// Or creates a new sub query on the search query builder func (query SearchQuery) Or() *SearchQuery { return query.builder.AddQuery() } -//AggregateTypes filters for events with the given aggregate types +// AggregateTypes filters for events with the given aggregate types func (query *SearchQuery) AggregateTypes(types ...AggregateType) *SearchQuery { query.aggregateTypes = types return query } -//SequenceGreater filters for events with sequence greater the requested sequence +// SequenceGreater filters for events with sequence greater the requested sequence func (query *SearchQuery) SequenceGreater(sequence uint64) *SearchQuery { query.eventSequenceGreater = sequence return query } -//SequenceLess filters for events with sequence less the requested sequence +// SequenceLess filters for events with sequence less the requested sequence func (query *SearchQuery) SequenceLess(sequence uint64) *SearchQuery { query.eventSequenceLess = sequence return query } -//AggregateIDs filters for events with the given aggregate id's +// AggregateIDs filters for events with the given aggregate id's func (query *SearchQuery) AggregateIDs(ids ...string) *SearchQuery { query.aggregateIDs = ids return query } -//InstanceID filters for events with the given instanceID +// InstanceID filters for events with the given instanceID func (query *SearchQuery) InstanceID(instanceID string) *SearchQuery { query.instanceID = instanceID return query } -//ExcludedInstanceID filters for events not having the given instanceIDs +// ExcludedInstanceID filters for events not having the given instanceIDs func (query *SearchQuery) ExcludedInstanceID(instanceIDs ...string) *SearchQuery { query.excludedInstanceIDs = instanceIDs return query } -//EventTypes filters for events with the given event types +// EventTypes filters for events with the given event types func (query *SearchQuery) EventTypes(types ...EventType) *SearchQuery { query.eventTypes = types return query } -//EventData filters for events with the given event data. -//Use this call with care as it will be slower than the other filters. +// EventData filters for events with the given event data. +// Use this call with care as it will be slower than the other filters. func (query *SearchQuery) EventData(data map[string]interface{}) *SearchQuery { query.eventData = data return query } -//Builder returns the SearchQueryBuilder of the sub query +// Builder returns the SearchQueryBuilder of the sub query func (query *SearchQuery) Builder() *SearchQueryBuilder { return query.builder } @@ -262,7 +263,7 @@ func (query *SearchQuery) aggregateIDFilter() *repository.Filter { if len(query.aggregateIDs) == 1 { return repository.NewFilter(repository.FieldAggregateID, query.aggregateIDs[0], repository.OperationEquals) } - return repository.NewFilter(repository.FieldAggregateID, query.aggregateIDs, repository.OperationIn) + return repository.NewFilter(repository.FieldAggregateID, database.StringArray(query.aggregateIDs), repository.OperationIn) } func (query *SearchQuery) eventTypeFilter() *repository.Filter { @@ -272,9 +273,9 @@ func (query *SearchQuery) eventTypeFilter() *repository.Filter { if len(query.eventTypes) == 1 { return repository.NewFilter(repository.FieldEventType, repository.EventType(query.eventTypes[0]), repository.OperationEquals) } - eventTypes := make([]repository.EventType, len(query.eventTypes)) + eventTypes := make(database.StringArray, len(query.eventTypes)) for i, eventType := range query.eventTypes { - eventTypes[i] = repository.EventType(eventType) + eventTypes[i] = string(eventType) } return repository.NewFilter(repository.FieldEventType, eventTypes, repository.OperationIn) } @@ -286,9 +287,9 @@ func (query *SearchQuery) aggregateTypeFilter() *repository.Filter { if len(query.aggregateTypes) == 1 { return repository.NewFilter(repository.FieldAggregateType, repository.AggregateType(query.aggregateTypes[0]), repository.OperationEquals) } - aggregateTypes := make([]repository.AggregateType, len(query.aggregateTypes)) + aggregateTypes := make(database.StringArray, len(query.aggregateTypes)) for i, aggregateType := range query.aggregateTypes { - aggregateTypes[i] = repository.AggregateType(aggregateType) + aggregateTypes[i] = string(aggregateType) } return repository.NewFilter(repository.FieldAggregateType, aggregateTypes, repository.OperationIn) } @@ -326,7 +327,7 @@ func (query *SearchQuery) excludedInstanceIDFilter() *repository.Filter { if len(query.excludedInstanceIDs) == 0 { return nil } - return repository.NewFilter(repository.FieldInstanceID, query.excludedInstanceIDs, repository.OperationNotIn) + return repository.NewFilter(repository.FieldInstanceID, database.StringArray(query.excludedInstanceIDs), repository.OperationNotIn) } func (builder *SearchQueryBuilder) resourceOwnerFilter() *repository.Filter { diff --git a/internal/eventstore/search_query_test.go b/internal/eventstore/search_query_test.go index 97e05562e1..c5e295c0d7 100644 --- a/internal/eventstore/search_query_test.go +++ b/internal/eventstore/search_query_test.go @@ -5,6 +5,7 @@ import ( "reflect" "testing" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore/repository" ) @@ -312,7 +313,7 @@ func TestSearchQuerybuilderBuild(t *testing.T) { Limit: 0, Filters: [][]*repository.Filter{ { - repository.NewFilter(repository.FieldAggregateType, []repository.AggregateType{"user", "org"}, repository.OperationIn), + repository.NewFilter(repository.FieldAggregateType, database.StringArray{"user", "org"}, repository.OperationIn), }, }, }, @@ -483,7 +484,7 @@ func TestSearchQuerybuilderBuild(t *testing.T) { Filters: [][]*repository.Filter{ { repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals), - repository.NewFilter(repository.FieldAggregateID, []string{"1234", "0815"}, repository.OperationIn), + repository.NewFilter(repository.FieldAggregateID, database.StringArray{"1234", "0815"}, repository.OperationIn), }, }, }, @@ -561,7 +562,7 @@ func TestSearchQuerybuilderBuild(t *testing.T) { Filters: [][]*repository.Filter{ { repository.NewFilter(repository.FieldAggregateType, repository.AggregateType("user"), repository.OperationEquals), - repository.NewFilter(repository.FieldEventType, []repository.EventType{"user.created", "user.changed"}, repository.OperationIn), + repository.NewFilter(repository.FieldEventType, database.StringArray{"user.created", "user.changed"}, repository.OperationIn), }, }, }, @@ -740,10 +741,10 @@ func assertRepoQuery(t *testing.T, want, got *repository.SearchQuery) { if !reflect.DeepEqual(got.Columns, want.Columns) { t.Errorf("wrong columns in query: got: %v want: %v", got.Columns, want.Columns) } - if !reflect.DeepEqual(got.Desc, want.Desc) { + if got.Desc != want.Desc { t.Errorf("wrong desc in query: got: %v want: %v", got.Desc, want.Desc) } - if !reflect.DeepEqual(got.Limit, want.Limit) { + if got.Limit != want.Limit { t.Errorf("wrong limit in query: got: %v want: %v", got.Limit, want.Limit) } diff --git a/internal/eventstore/v1/internal/repository/sql/config.go b/internal/eventstore/v1/internal/repository/sql/config.go index 8011ee9ac0..08bea22d98 100644 --- a/internal/eventstore/v1/internal/repository/sql/config.go +++ b/internal/eventstore/v1/internal/repository/sql/config.go @@ -2,8 +2,6 @@ package sql import ( "database/sql" - - _ "github.com/lib/pq" ) func Start(client *sql.DB) *SQL { diff --git a/internal/eventstore/v1/internal/repository/sql/query.go b/internal/eventstore/v1/internal/repository/sql/query.go index c8251d64e8..2fa6d1ff55 100644 --- a/internal/eventstore/v1/internal/repository/sql/query.go +++ b/internal/eventstore/v1/internal/repository/sql/query.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - "github.com/lib/pq" "github.com/zitadel/logging" z_errors "github.com/zitadel/zitadel/internal/errors" @@ -72,10 +71,6 @@ func prepareCondition(filters [][]*es_models.Filter) (clause string, values []in subClauses := make([]string, 0, len(filter)) for _, f := range filter { value := f.GetValue() - switch value.(type) { - case []bool, []float64, []int64, []string, []es_models.AggregateType, []es_models.EventType, *[]bool, *[]float64, *[]int64, *[]string, *[]es_models.AggregateType, *[]es_models.EventType: - value = pq.Array(value) - } subClauses = append(subClauses, getCondition(f)) if subClauses[len(subClauses)-1] == "" { diff --git a/internal/eventstore/v1/internal/repository/sql/query_test.go b/internal/eventstore/v1/internal/repository/sql/query_test.go index a8dfd671af..e6ee3afda2 100644 --- a/internal/eventstore/v1/internal/repository/sql/query_test.go +++ b/internal/eventstore/v1/internal/repository/sql/query_test.go @@ -6,8 +6,6 @@ import ( "testing" "time" - "github.com/lib/pq" - "github.com/zitadel/zitadel/internal/errors" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" ) @@ -365,7 +363,7 @@ func Test_prepareCondition(t *testing.T) { }, res: res{ clause: " WHERE ( aggregate_type = ANY(?) )", - values: []interface{}{pq.Array([]es_models.AggregateType{"user", "org"})}, + values: []interface{}{[]es_models.AggregateType{"user", "org"}}, }, }, { @@ -381,7 +379,7 @@ func Test_prepareCondition(t *testing.T) { }, res: res{ clause: " WHERE ( aggregate_type = ANY(?) AND aggregate_id = ? AND event_type = ANY(?) )", - values: []interface{}{pq.Array([]es_models.AggregateType{"user", "org"}), "1234", pq.Array([]es_models.EventType{"user.created", "org.created"})}, + values: []interface{}{[]es_models.AggregateType{"user", "org"}, "1234", []es_models.EventType{"user.created", "org.created"}}, }, }, } diff --git a/internal/eventstore/v1/internal/repository/sql/sql.go b/internal/eventstore/v1/internal/repository/sql/sql.go index 32016946e8..6afa768919 100644 --- a/internal/eventstore/v1/internal/repository/sql/sql.go +++ b/internal/eventstore/v1/internal/repository/sql/sql.go @@ -3,9 +3,6 @@ package sql import ( "context" "database/sql" - - //sql import - _ "github.com/lib/pq" ) type SQL struct { diff --git a/internal/eventstore/v1/locker/lock.go b/internal/eventstore/v1/locker/lock.go index 4a24b55b07..dc0682ba54 100644 --- a/internal/eventstore/v1/locker/lock.go +++ b/internal/eventstore/v1/locker/lock.go @@ -31,7 +31,7 @@ func Renew(dbClient *sql.DB, lockTable, lockerID, viewModel, instanceID string, return crdb.ExecuteTx(context.Background(), dbClient, nil, func(tx *sql.Tx) error { insert := fmt.Sprintf(insertStmtFormat, lockTable) result, err := tx.Exec(insert, - lockerID, waitTime.Milliseconds()/millisecondsAsSeconds, viewModel, instanceID) + lockerID, waitTime, viewModel, instanceID) if err != nil { tx.Rollback() diff --git a/internal/eventstore/v1/query/handler.go b/internal/eventstore/v1/query/handler.go index a60709832b..1aa2a27781 100755 --- a/internal/eventstore/v1/query/handler.go +++ b/internal/eventstore/v1/query/handler.go @@ -38,7 +38,12 @@ func ReduceEvent(handler Handler, event *models.Event) { if err != nil { handler.Subscription().Unsubscribe() - logging.WithFields("cause", err, "stack", string(debug.Stack())).Error("reduce panicked") + logging.WithFields( + "cause", err, + "stack", string(debug.Stack()), + "sequence", event.Sequence, + "instnace", event.InstanceID, + ).Error("reduce panicked") } }() currentSequence, err := handler.CurrentSequence(event.InstanceID) diff --git a/internal/eventstore/v1/spooler/spooler.go b/internal/eventstore/v1/spooler/spooler.go index 9233b10391..5cfa220442 100644 --- a/internal/eventstore/v1/spooler/spooler.go +++ b/internal/eventstore/v1/spooler/spooler.go @@ -75,7 +75,10 @@ func (s *spooledHandler) load(workerID string) { err := recover() if err != nil { - logging.WithFields("cause", err, "stack", string(debug.Stack())).Error("reduce panicked") + logging.WithFields( + "cause", err, + "stack", string(debug.Stack()), + ).Error("reduce panicked") } }() ctx, cancel := context.WithCancel(context.Background()) @@ -167,7 +170,7 @@ func (s *spooledHandler) query(ctx context.Context, instanceIDs ...string) ([]*m return s.eventstore.FilterEvents(ctx, query) } -//lock ensures the lock on the database. +// lock ensures the lock on the database. // the returned channel will be closed if ctx is done or an error occured durring lock func (s *spooledHandler) lock(ctx context.Context, errs chan<- error, workerID string) chan bool { renewTimer := time.After(0) diff --git a/internal/iam/repository/view/model/idp_config.go b/internal/iam/repository/view/model/idp_config.go index 6f86293797..cdb420de3e 100644 --- a/internal/iam/repository/view/model/idp_config.go +++ b/internal/iam/repository/view/model/idp_config.go @@ -5,11 +5,11 @@ import ( "time" "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/repository/instance" "github.com/zitadel/zitadel/internal/repository/org" - "github.com/lib/pq" "github.com/zitadel/logging" caos_errs "github.com/zitadel/zitadel/internal/errors" @@ -36,18 +36,18 @@ type IDPConfigView struct { IDPProviderType int32 `json:"-" gorm:"column:idp_provider_type"` AutoRegister bool `json:"autoRegister" gorm:"column:auto_register"` - IsOIDC bool `json:"-" gorm:"column:is_oidc"` - OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"` - OIDCClientSecret *crypto.CryptoValue `json:"clientSecret" gorm:"column:oidc_client_secret"` - OIDCIssuer string `json:"issuer" gorm:"column:oidc_issuer"` - OIDCScopes pq.StringArray `json:"scopes" gorm:"column:oidc_scopes"` - OIDCIDPDisplayNameMapping int32 `json:"idpDisplayNameMapping" gorm:"column:oidc_idp_display_name_mapping"` - OIDCUsernameMapping int32 `json:"usernameMapping" gorm:"column:oidc_idp_username_mapping"` - OAuthAuthorizationEndpoint string `json:"authorizationEndpoint" gorm:"column:oauth_authorization_endpoint"` - OAuthTokenEndpoint string `json:"tokenEndpoint" gorm:"column:oauth_token_endpoint"` - JWTEndpoint string `json:"jwtEndpoint" gorm:"jwt_endpoint"` - JWTKeysEndpoint string `json:"keysEndpoint" gorm:"jwt_keys_endpoint"` - JWTHeaderName string `json:"headerName" gorm:"jwt_header_name"` + IsOIDC bool `json:"-" gorm:"column:is_oidc"` + OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"` + OIDCClientSecret *crypto.CryptoValue `json:"clientSecret" gorm:"column:oidc_client_secret"` + OIDCIssuer string `json:"issuer" gorm:"column:oidc_issuer"` + OIDCScopes database.StringArray `json:"scopes" gorm:"column:oidc_scopes"` + OIDCIDPDisplayNameMapping int32 `json:"idpDisplayNameMapping" gorm:"column:oidc_idp_display_name_mapping"` + OIDCUsernameMapping int32 `json:"usernameMapping" gorm:"column:oidc_idp_username_mapping"` + OAuthAuthorizationEndpoint string `json:"authorizationEndpoint" gorm:"column:oauth_authorization_endpoint"` + OAuthTokenEndpoint string `json:"tokenEndpoint" gorm:"column:oauth_token_endpoint"` + JWTEndpoint string `json:"jwtEndpoint" gorm:"jwt_endpoint"` + JWTKeysEndpoint string `json:"keysEndpoint" gorm:"jwt_keys_endpoint"` + JWTHeaderName string `json:"headerName" gorm:"jwt_header_name"` Sequence uint64 `json:"-" gorm:"column:sequence"` InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` diff --git a/internal/id/sonyflake.go b/internal/id/sonyflake.go index 7a5f773804..0eb156c1f4 100644 --- a/internal/id/sonyflake.go +++ b/internal/id/sonyflake.go @@ -51,7 +51,7 @@ func SonyFlakeGenerator() Generator { } // the following is a copy of sonyflake (https://github.com/sony/sonyflake/blob/master/sonyflake.go) -//with the change of using the "POD-IP" if no private ip is found +// with the change of using the "POD-IP" if no private ip is found func privateIPv4() (net.IP, error) { as, err := net.InterfaceAddrs() if err != nil { @@ -88,7 +88,7 @@ func isPrivateIPv4(ip net.IP) bool { func machineID() (uint16, error) { if GeneratorConfig == nil { - return 0, errors.New("Cannot create a unique ID for the machine, generator has not been configured.") + return 0, errors.New("cannot create a unique id for the machine, generator has not been configured") } errors := []string{} diff --git a/internal/project/repository/view/model/application.go b/internal/project/repository/view/model/application.go index c0738ea937..49933f8841 100644 --- a/internal/project/repository/view/model/application.go +++ b/internal/project/repository/view/model/application.go @@ -4,10 +4,10 @@ import ( "encoding/json" "time" - "github.com/lib/pq" "github.com/zitadel/logging" http_util "github.com/zitadel/zitadel/internal/api/http" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" caos_errs "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -37,30 +37,30 @@ type ApplicationView struct { HasProjectCheck bool `json:"hasProjectCheck" gorm:"column:has_project_check"` PrivateLabelingSetting domain.PrivateLabelingSetting `json:"privateLabelingSetting" gorm:"column:private_labeling_setting"` - IsOIDC bool `json:"-" gorm:"column:is_oidc"` - OIDCVersion int32 `json:"oidcVersion" gorm:"column:oidc_version"` - OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"` - OIDCRedirectUris pq.StringArray `json:"redirectUris" gorm:"column:oidc_redirect_uris"` - OIDCResponseTypes pq.Int64Array `json:"responseTypes" gorm:"column:oidc_response_types"` - OIDCGrantTypes pq.Int64Array `json:"grantTypes" gorm:"column:oidc_grant_types"` - OIDCApplicationType int32 `json:"applicationType" gorm:"column:oidc_application_type"` - OIDCAuthMethodType int32 `json:"authMethodType" gorm:"column:oidc_auth_method_type"` - OIDCPostLogoutRedirectUris pq.StringArray `json:"postLogoutRedirectUris" gorm:"column:oidc_post_logout_redirect_uris"` - NoneCompliant bool `json:"-" gorm:"column:none_compliant"` - ComplianceProblems pq.StringArray `json:"-" gorm:"column:compliance_problems"` - DevMode bool `json:"devMode" gorm:"column:dev_mode"` - OriginAllowList pq.StringArray `json:"-" gorm:"column:origin_allow_list"` - AdditionalOrigins pq.StringArray `json:"additionalOrigins" gorm:"column:additional_origins"` - AccessTokenType int32 `json:"accessTokenType" gorm:"column:access_token_type"` - AccessTokenRoleAssertion bool `json:"accessTokenRoleAssertion" gorm:"column:access_token_role_assertion"` - IDTokenRoleAssertion bool `json:"idTokenRoleAssertion" gorm:"column:id_token_role_assertion"` - IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion" gorm:"column:id_token_userinfo_assertion"` - ClockSkew time.Duration `json:"clockSkew" gorm:"column:clock_skew"` + IsOIDC bool `json:"-" gorm:"column:is_oidc"` + OIDCVersion int32 `json:"oidcVersion" gorm:"column:oidc_version"` + OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"` + OIDCRedirectUris database.StringArray `json:"redirectUris" gorm:"column:oidc_redirect_uris"` + OIDCResponseTypes database.EnumArray[domain.OIDCResponseType] `json:"responseTypes" gorm:"column:oidc_response_types"` + OIDCGrantTypes database.EnumArray[domain.OIDCGrantType] `json:"grantTypes" gorm:"column:oidc_grant_types"` + OIDCApplicationType int32 `json:"applicationType" gorm:"column:oidc_application_type"` + OIDCAuthMethodType int32 `json:"authMethodType" gorm:"column:oidc_auth_method_type"` + OIDCPostLogoutRedirectUris database.StringArray `json:"postLogoutRedirectUris" gorm:"column:oidc_post_logout_redirect_uris"` + NoneCompliant bool `json:"-" gorm:"column:none_compliant"` + ComplianceProblems database.StringArray `json:"-" gorm:"column:compliance_problems"` + DevMode bool `json:"devMode" gorm:"column:dev_mode"` + OriginAllowList database.StringArray `json:"-" gorm:"column:origin_allow_list"` + AdditionalOrigins database.StringArray `json:"additionalOrigins" gorm:"column:additional_origins"` + AccessTokenType int32 `json:"accessTokenType" gorm:"column:access_token_type"` + AccessTokenRoleAssertion bool `json:"accessTokenRoleAssertion" gorm:"column:access_token_role_assertion"` + IDTokenRoleAssertion bool `json:"idTokenRoleAssertion" gorm:"column:id_token_role_assertion"` + IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion" gorm:"column:id_token_userinfo_assertion"` + ClockSkew time.Duration `json:"clockSkew" gorm:"column:clock_skew"` Sequence uint64 `json:"-" gorm:"sequence"` } -func OIDCResponseTypesToModel(oidctypes []int64) []model.OIDCResponseType { +func OIDCResponseTypesToModel(oidctypes []domain.OIDCResponseType) []model.OIDCResponseType { result := make([]model.OIDCResponseType, len(oidctypes)) for i, t := range oidctypes { result[i] = model.OIDCResponseType(t) @@ -68,7 +68,7 @@ func OIDCResponseTypesToModel(oidctypes []int64) []model.OIDCResponseType { return result } -func OIDCGrantTypesToModel(granttypes []int64) []model.OIDCGrantType { +func OIDCGrantTypesToModel(granttypes []domain.OIDCGrantType) []model.OIDCGrantType { result := make([]model.OIDCGrantType, len(granttypes)) for i, t := range granttypes { result[i] = model.OIDCGrantType(t) @@ -169,7 +169,7 @@ func (a *ApplicationView) SetData(event *models.Event) error { } func (a *ApplicationView) setOriginAllowList() error { - allowList := make([]string, 0) + allowList := make(database.StringArray, 0) for _, redirect := range a.OIDCRedirectUris { origin, err := http_util.GetOriginFromURLString(redirect) if err != nil { diff --git a/internal/project/repository/view/model/project_grant.go b/internal/project/repository/view/model/project_grant.go index fc6a0816aa..399e82a610 100644 --- a/internal/project/repository/view/model/project_grant.go +++ b/internal/project/repository/view/model/project_grant.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -24,18 +24,18 @@ const ( ) type ProjectGrantView struct { - GrantID string `json:"-" gorm:"column:grant_id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id"` - OrgID string `json:"-" gorm:"column:org_id"` - Name string `json:"name" gorm:"column:project_name"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - State int32 `json:"-" gorm:"column:project_state"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - ResourceOwnerName string `json:"-" gorm:"column:resource_owner_name"` - OrgName string `json:"-" gorm:"column:org_name"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - GrantedRoleKeys pq.StringArray `json:"-" gorm:"column:granted_role_keys"` + GrantID string `json:"-" gorm:"column:grant_id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id"` + OrgID string `json:"-" gorm:"column:org_id"` + Name string `json:"name" gorm:"column:project_name"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + State int32 `json:"-" gorm:"column:project_state"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + ResourceOwnerName string `json:"-" gorm:"column:resource_owner_name"` + OrgName string `json:"-" gorm:"column:org_name"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + GrantedRoleKeys database.StringArray `json:"-" gorm:"column:granted_role_keys"` } type ProjectGrant struct { diff --git a/internal/project/repository/view/model/project_grant_member.go b/internal/project/repository/view/model/project_grant_member.go index 95de529490..1c17022618 100644 --- a/internal/project/repository/view/model/project_grant_member.go +++ b/internal/project/repository/view/model/project_grant_member.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -24,19 +24,19 @@ const ( ) type ProjectGrantMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - GrantID string `json:"grantId" gorm:"column:grant_id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` - AvatarKey string `json:"-" gorm:"column:avatar_key"` - UserResourceOwner string `json:"-" gorm:"column:user_resource_owner"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + GrantID string `json:"grantId" gorm:"column:grant_id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles database.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` + AvatarKey string `json:"-" gorm:"column:avatar_key"` + UserResourceOwner string `json:"-" gorm:"column:user_resource_owner"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` diff --git a/internal/project/repository/view/model/project_grant_member_test.go b/internal/project/repository/view/model/project_grant_member_test.go index c508ebb4ea..ca9d19be77 100644 --- a/internal/project/repository/view/model/project_grant_member_test.go +++ b/internal/project/repository/view/model/project_grant_member_test.go @@ -5,8 +5,6 @@ import ( "reflect" "testing" - "github.com/lib/pq" - es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" es_model "github.com/zitadel/zitadel/internal/project/repository/eventsourcing/model" "github.com/zitadel/zitadel/internal/repository/project" @@ -30,18 +28,18 @@ func TestGrantedProjectMemberAppendEvent(t *testing.T) { { name: "append added member event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantMemberAddedType), ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: pq.StringArray{"Role"}})}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantMemberAddedType), ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}})}, member: &ProjectGrantMemberView{}, }, - result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"Role"}}, + result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: []string{"Role"}}, }, { name: "append changed member event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantMemberAddedType), ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", Roles: pq.StringArray{"RoleChanged"}})}, - member: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"Role"}}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantMemberAddedType), ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", Roles: []string{"RoleChanged"}})}, + member: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: []string{"Role"}}, }, - result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"RoleChanged"}}, + result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: []string{"RoleChanged"}}, }, } for _, tt := range tests { diff --git a/internal/project/repository/view/model/project_grant_test.go b/internal/project/repository/view/model/project_grant_test.go index 8e50d8e06c..9aca2dd927 100644 --- a/internal/project/repository/view/model/project_grant_test.go +++ b/internal/project/repository/view/model/project_grant_test.go @@ -5,8 +5,6 @@ import ( "reflect" "testing" - "github.com/lib/pq" - es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" "github.com/zitadel/zitadel/internal/project/model" es_model "github.com/zitadel/zitadel/internal/project/repository/eventsourcing/model" @@ -36,34 +34,34 @@ func TestProjectGrantAppendEvent(t *testing.T) { { name: "append added project grant event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantAddedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: pq.StringArray{"Role"}})}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantAddedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Role"}})}, project: &ProjectGrantView{}, }, - result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}}, + result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: []string{"Role"}}, }, { name: "append change project grant event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantChangedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", RoleKeys: pq.StringArray{"RoleChanged"}})}, - project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantChangedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", RoleKeys: []string{"RoleChanged"}})}, + project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: []string{"Role"}}, }, - result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"RoleChanged"}}, + result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: []string{"RoleChanged"}}, }, { name: "append deactivate project grant event", args: args{ event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantDeactivatedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID"})}, - project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}}, + project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: []string{"Role"}}, }, - result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: pq.StringArray{"Role"}}, + result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: []string{"Role"}}, }, { name: "append reactivate project grant event", args: args{ event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.GrantReactivatedType), ResourceOwner: "GrantedOrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID"})}, - project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: pq.StringArray{"Role"}}, + project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: []string{"Role"}}, }, - result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}}, + result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "GrantedOrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: []string{"Role"}}, }, } for _, tt := range tests { diff --git a/internal/project/repository/view/model/project_member.go b/internal/project/repository/view/model/project_member.go index 1822d05248..1cf664a8db 100644 --- a/internal/project/repository/view/model/project_member.go +++ b/internal/project/repository/view/model/project_member.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -23,18 +23,18 @@ const ( ) type ProjectMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id;primary_key"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` - AvatarKey string `json:"-" gorm:"column:avatar_key"` - UserResourceOwner string `json:"-" gorm:"column:user_resource_owner"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id;primary_key"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles database.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` + AvatarKey string `json:"-" gorm:"column:avatar_key"` + UserResourceOwner string `json:"-" gorm:"column:user_resource_owner"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` diff --git a/internal/project/repository/view/model/project_member_test.go b/internal/project/repository/view/model/project_member_test.go index f4daf31c38..0dbee2535d 100644 --- a/internal/project/repository/view/model/project_member_test.go +++ b/internal/project/repository/view/model/project_member_test.go @@ -5,8 +5,6 @@ import ( "reflect" "testing" - "github.com/lib/pq" - es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" es_model "github.com/zitadel/zitadel/internal/project/repository/eventsourcing/model" "github.com/zitadel/zitadel/internal/repository/project" @@ -30,18 +28,18 @@ func TestProjectMemberAppendEvent(t *testing.T) { { name: "append added member event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.MemberAddedType), ResourceOwner: "OrgID", Data: mockProjectMemberData(&es_model.ProjectMember{UserID: "UserID", Roles: pq.StringArray{"Role"}})}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.MemberAddedType), ResourceOwner: "OrgID", Data: mockProjectMemberData(&es_model.ProjectMember{UserID: "UserID", Roles: []string{"Role"}})}, member: &ProjectMemberView{}, }, - result: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: pq.StringArray{"Role"}}, + result: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: []string{"Role"}}, }, { name: "append changed member event", args: args{ - event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.MemberAddedType), ResourceOwner: "OrgID", Data: mockProjectMemberData(&es_model.ProjectMember{UserID: "UserID", Roles: pq.StringArray{"RoleChanged"}})}, - member: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: pq.StringArray{"Role"}}, + event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_models.EventType(project.MemberAddedType), ResourceOwner: "OrgID", Data: mockProjectMemberData(&es_model.ProjectMember{UserID: "UserID", Roles: []string{"RoleChanged"}})}, + member: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: []string{"Role"}}, }, - result: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: pq.StringArray{"RoleChanged"}}, + result: &ProjectMemberView{ProjectID: "AggregateID", UserID: "UserID", Roles: []string{"RoleChanged"}}, }, } for _, tt := range tests { diff --git a/internal/query/action_flow.go b/internal/query/action_flow.go index 303d8584d9..983ce1fe26 100644 --- a/internal/query/action_flow.go +++ b/internal/query/action_flow.go @@ -6,7 +6,6 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" @@ -216,8 +215,8 @@ func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Row for rows.Next() { var ( actionID sql.NullString - actionCreationDate pq.NullTime - actionChangeDate pq.NullTime + actionCreationDate sql.NullTime + actionChangeDate sql.NullTime actionResourceOwner sql.NullString actionState sql.NullInt32 actionSequence sql.NullInt64 diff --git a/internal/query/action_flow_test.go b/internal/query/action_flow_test.go index 7151cefdcc..9609bde9bc 100644 --- a/internal/query/action_flow_test.go +++ b/internal/query/action_flow_test.go @@ -31,14 +31,14 @@ func Test_FlowPrepares(t *testing.T) { }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ ` projections.flows_triggers.trigger_type,`+ ` projections.flows_triggers.trigger_sequence,`+ ` projections.flows_triggers.flow_type,`+ @@ -46,7 +46,7 @@ func Test_FlowPrepares(t *testing.T) { ` projections.flows_triggers.sequence,`+ ` projections.flows_triggers.resource_owner`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), nil, nil, ), @@ -63,14 +63,14 @@ func Test_FlowPrepares(t *testing.T) { }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ ` projections.flows_triggers.trigger_type,`+ ` projections.flows_triggers.trigger_sequence,`+ ` projections.flows_triggers.flow_type,`+ @@ -78,7 +78,7 @@ func Test_FlowPrepares(t *testing.T) { ` projections.flows_triggers.sequence,`+ ` projections.flows_triggers.resource_owner`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), []string{ "id", "creation_date", @@ -144,14 +144,14 @@ func Test_FlowPrepares(t *testing.T) { }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ ` projections.flows_triggers.trigger_type,`+ ` projections.flows_triggers.trigger_sequence,`+ ` projections.flows_triggers.flow_type,`+ @@ -159,7 +159,7 @@ func Test_FlowPrepares(t *testing.T) { ` projections.flows_triggers.sequence,`+ ` projections.flows_triggers.resource_owner`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), []string{ "id", "creation_date", @@ -253,14 +253,14 @@ func Test_FlowPrepares(t *testing.T) { }, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ ` projections.flows_triggers.trigger_type,`+ ` projections.flows_triggers.trigger_sequence,`+ ` projections.flows_triggers.flow_type,`+ @@ -268,7 +268,7 @@ func Test_FlowPrepares(t *testing.T) { ` projections.flows_triggers.sequence,`+ ` projections.flows_triggers.resource_owner`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), []string{ "id", "creation_date", @@ -321,14 +321,14 @@ func Test_FlowPrepares(t *testing.T) { }, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ ` projections.flows_triggers.trigger_type,`+ ` projections.flows_triggers.trigger_sequence,`+ ` projections.flows_triggers.flow_type,`+ @@ -336,7 +336,7 @@ func Test_FlowPrepares(t *testing.T) { ` projections.flows_triggers.sequence,`+ ` projections.flows_triggers.resource_owner`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -353,16 +353,16 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), nil, nil, ), @@ -374,16 +374,16 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), []string{ "id", "creation_date", @@ -426,16 +426,16 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), []string{ "id", "creation_date", @@ -498,16 +498,16 @@ func Test_FlowPrepares(t *testing.T) { prepare: prepareTriggerActionsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.action_state,`+ - ` projections.actions.sequence,`+ - ` projections.actions.name,`+ - ` projections.actions.script`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script`+ ` FROM projections.flows_triggers`+ - ` LEFT JOIN projections.actions ON projections.flows_triggers.action_id = projections.actions.id`), + ` LEFT JOIN projections.actions2 ON projections.flows_triggers.action_id = projections.actions2.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/action_test.go b/internal/query/action_test.go index 673ac7c953..55f86cbdfe 100644 --- a/internal/query/action_test.go +++ b/internal/query/action_test.go @@ -29,18 +29,18 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.actions`), + ` FROM projections.actions2`), nil, nil, ), @@ -52,18 +52,18 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.actions`), + ` FROM projections.actions2`), []string{ "id", "creation_date", @@ -118,18 +118,18 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.actions`), + ` FROM projections.actions2`), []string{ "id", "creation_date", @@ -208,18 +208,18 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail,`+ + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.actions`), + ` FROM projections.actions2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -236,17 +236,17 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail`+ - ` FROM projections.actions`), + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail`+ + ` FROM projections.actions2`), nil, nil, ), @@ -264,17 +264,17 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail`+ - ` FROM projections.actions`), + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail`+ + ` FROM projections.actions2`), []string{ "id", "creation_date", @@ -319,17 +319,17 @@ func Test_ActionPrepares(t *testing.T) { prepare: prepareActionQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.actions.id,`+ - ` projections.actions.creation_date,`+ - ` projections.actions.change_date,`+ - ` projections.actions.resource_owner,`+ - ` projections.actions.sequence,`+ - ` projections.actions.action_state,`+ - ` projections.actions.name,`+ - ` projections.actions.script,`+ - ` projections.actions.timeout,`+ - ` projections.actions.allowed_to_fail`+ - ` FROM projections.actions`), + regexp.QuoteMeta(`SELECT projections.actions2.id,`+ + ` projections.actions2.creation_date,`+ + ` projections.actions2.change_date,`+ + ` projections.actions2.resource_owner,`+ + ` projections.actions2.sequence,`+ + ` projections.actions2.action_state,`+ + ` projections.actions2.name,`+ + ` projections.actions2.script,`+ + ` projections.actions2.timeout,`+ + ` projections.actions2.allowed_to_fail`+ + ` FROM projections.actions2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/app.go b/internal/query/app.go index 063c25b3bd..6a405c8447 100644 --- a/internal/query/app.go +++ b/internal/query/app.go @@ -7,12 +7,10 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" - - "github.com/zitadel/zitadel/internal/api/authz" - "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -39,23 +37,23 @@ type App struct { } type OIDCApp struct { - RedirectURIs []string - ResponseTypes []domain.OIDCResponseType - GrantTypes []domain.OIDCGrantType + RedirectURIs database.StringArray + ResponseTypes database.EnumArray[domain.OIDCResponseType] + GrantTypes database.EnumArray[domain.OIDCGrantType] AppType domain.OIDCApplicationType ClientID string AuthMethodType domain.OIDCAuthMethodType - PostLogoutRedirectURIs []string + PostLogoutRedirectURIs database.StringArray Version domain.OIDCVersion - ComplianceProblems []string + ComplianceProblems database.StringArray IsDevMode bool AccessTokenType domain.OIDCTokenType AssertAccessTokenRole bool AssertIDTokenRole bool AssertIDTokenUserinfo bool ClockSkew time.Duration - AdditionalOrigins []string - AllowedOrigins []string + AdditionalOrigins database.StringArray + AllowedOrigins database.StringArray } type APIApp struct { @@ -613,7 +611,7 @@ func prepareClientIDsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]string, error LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)). LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]string, error) { - ids := []string{} + ids := database.StringArray{} for rows.Next() { var apiID sql.NullString @@ -639,19 +637,19 @@ type sqlOIDCConfig struct { appID sql.NullString version sql.NullInt32 clientID sql.NullString - redirectUris pq.StringArray + redirectUris database.StringArray applicationType sql.NullInt16 authMethodType sql.NullInt16 - postLogoutRedirectUris pq.StringArray + postLogoutRedirectUris database.StringArray devMode sql.NullBool accessTokenType sql.NullInt16 accessTokenRoleAssertion sql.NullBool iDTokenRoleAssertion sql.NullBool iDTokenUserinfoAssertion sql.NullBool clockSkew sql.NullInt64 - additionalOrigins pq.StringArray - responseTypes pq.Int32Array - grantTypes pq.Int32Array + additionalOrigins database.StringArray + responseTypes database.EnumArray[domain.OIDCResponseType] + grantTypes database.EnumArray[domain.OIDCGrantType] } func (c sqlOIDCConfig) set(app *App) { @@ -672,8 +670,8 @@ func (c sqlOIDCConfig) set(app *App) { AssertIDTokenUserinfo: c.iDTokenUserinfoAssertion.Bool, ClockSkew: time.Duration(c.clockSkew.Int64), AdditionalOrigins: c.additionalOrigins, - ResponseTypes: oidcResponseTypesToDomain(c.responseTypes), - GrantTypes: oidcGrantTypesToDomain(c.grantTypes), + ResponseTypes: c.responseTypes, + GrantTypes: c.grantTypes, } compliance := domain.GetOIDCCompliance(app.OIDCConfig.Version, app.OIDCConfig.AppType, app.OIDCConfig.GrantTypes, app.OIDCConfig.ResponseTypes, app.OIDCConfig.AuthMethodType, app.OIDCConfig.RedirectURIs) app.OIDCConfig.ComplianceProblems = compliance.Problems @@ -698,19 +696,3 @@ func (c sqlAPIConfig) set(app *App) { AuthMethodType: domain.APIAuthMethodType(c.authMethod.Int16), } } - -func oidcResponseTypesToDomain(t pq.Int32Array) []domain.OIDCResponseType { - types := make([]domain.OIDCResponseType, len(t)) - for i, typ := range t { - types[i] = domain.OIDCResponseType(typ) - } - return types -} - -func oidcGrantTypesToDomain(t pq.Int32Array) []domain.OIDCGrantType { - types := make([]domain.OIDCGrantType, len(t)) - for i, typ := range t { - types[i] = domain.OIDCGrantType(typ) - } - return types -} diff --git a/internal/query/app_test.go b/internal/query/app_test.go index b969dadb27..76a759ff4b 100644 --- a/internal/query/app_test.go +++ b/internal/query/app_test.go @@ -9,104 +9,103 @@ import ( "testing" "time" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) var ( - expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps.id,` + - ` projections.apps.name,` + - ` projections.apps.project_id,` + - ` projections.apps.creation_date,` + - ` projections.apps.change_date,` + - ` projections.apps.resource_owner,` + - ` projections.apps.state,` + - ` projections.apps.sequence,` + + expectedAppQuery = regexp.QuoteMeta(`SELECT projections.apps2.id,` + + ` projections.apps2.name,` + + ` projections.apps2.project_id,` + + ` projections.apps2.creation_date,` + + ` projections.apps2.change_date,` + + ` projections.apps2.resource_owner,` + + ` projections.apps2.state,` + + ` projections.apps2.sequence,` + // api config - ` projections.apps_api_configs.app_id,` + - ` projections.apps_api_configs.client_id,` + - ` projections.apps_api_configs.auth_method,` + + ` projections.apps2_api_configs.app_id,` + + ` projections.apps2_api_configs.client_id,` + + ` projections.apps2_api_configs.auth_method,` + // oidc config - ` projections.apps_oidc_configs.app_id,` + - ` projections.apps_oidc_configs.version,` + - ` projections.apps_oidc_configs.client_id,` + - ` projections.apps_oidc_configs.redirect_uris,` + - ` projections.apps_oidc_configs.response_types,` + - ` projections.apps_oidc_configs.grant_types,` + - ` projections.apps_oidc_configs.application_type,` + - ` projections.apps_oidc_configs.auth_method_type,` + - ` projections.apps_oidc_configs.post_logout_redirect_uris,` + - ` projections.apps_oidc_configs.is_dev_mode,` + - ` projections.apps_oidc_configs.access_token_type,` + - ` projections.apps_oidc_configs.access_token_role_assertion,` + - ` projections.apps_oidc_configs.id_token_role_assertion,` + - ` projections.apps_oidc_configs.id_token_userinfo_assertion,` + - ` projections.apps_oidc_configs.clock_skew,` + - ` projections.apps_oidc_configs.additional_origins` + - ` FROM projections.apps` + - ` LEFT JOIN projections.apps_api_configs ON projections.apps.id = projections.apps_api_configs.app_id` + - ` LEFT JOIN projections.apps_oidc_configs ON projections.apps.id = projections.apps_oidc_configs.app_id`) - expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps.id,` + - ` projections.apps.name,` + - ` projections.apps.project_id,` + - ` projections.apps.creation_date,` + - ` projections.apps.change_date,` + - ` projections.apps.resource_owner,` + - ` projections.apps.state,` + - ` projections.apps.sequence,` + + ` projections.apps2_oidc_configs.app_id,` + + ` projections.apps2_oidc_configs.version,` + + ` projections.apps2_oidc_configs.client_id,` + + ` projections.apps2_oidc_configs.redirect_uris,` + + ` projections.apps2_oidc_configs.response_types,` + + ` projections.apps2_oidc_configs.grant_types,` + + ` projections.apps2_oidc_configs.application_type,` + + ` projections.apps2_oidc_configs.auth_method_type,` + + ` projections.apps2_oidc_configs.post_logout_redirect_uris,` + + ` projections.apps2_oidc_configs.is_dev_mode,` + + ` projections.apps2_oidc_configs.access_token_type,` + + ` projections.apps2_oidc_configs.access_token_role_assertion,` + + ` projections.apps2_oidc_configs.id_token_role_assertion,` + + ` projections.apps2_oidc_configs.id_token_userinfo_assertion,` + + ` projections.apps2_oidc_configs.clock_skew,` + + ` projections.apps2_oidc_configs.additional_origins` + + ` FROM projections.apps2` + + ` LEFT JOIN projections.apps2_api_configs ON projections.apps2.id = projections.apps2_api_configs.app_id` + + ` LEFT JOIN projections.apps2_oidc_configs ON projections.apps2.id = projections.apps2_oidc_configs.app_id`) + expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps2.id,` + + ` projections.apps2.name,` + + ` projections.apps2.project_id,` + + ` projections.apps2.creation_date,` + + ` projections.apps2.change_date,` + + ` projections.apps2.resource_owner,` + + ` projections.apps2.state,` + + ` projections.apps2.sequence,` + // api config - ` projections.apps_api_configs.app_id,` + - ` projections.apps_api_configs.client_id,` + - ` projections.apps_api_configs.auth_method,` + + ` projections.apps2_api_configs.app_id,` + + ` projections.apps2_api_configs.client_id,` + + ` projections.apps2_api_configs.auth_method,` + // oidc config - ` projections.apps_oidc_configs.app_id,` + - ` projections.apps_oidc_configs.version,` + - ` projections.apps_oidc_configs.client_id,` + - ` projections.apps_oidc_configs.redirect_uris,` + - ` projections.apps_oidc_configs.response_types,` + - ` projections.apps_oidc_configs.grant_types,` + - ` projections.apps_oidc_configs.application_type,` + - ` projections.apps_oidc_configs.auth_method_type,` + - ` projections.apps_oidc_configs.post_logout_redirect_uris,` + - ` projections.apps_oidc_configs.is_dev_mode,` + - ` projections.apps_oidc_configs.access_token_type,` + - ` projections.apps_oidc_configs.access_token_role_assertion,` + - ` projections.apps_oidc_configs.id_token_role_assertion,` + - ` projections.apps_oidc_configs.id_token_userinfo_assertion,` + - ` projections.apps_oidc_configs.clock_skew,` + - ` projections.apps_oidc_configs.additional_origins,` + + ` projections.apps2_oidc_configs.app_id,` + + ` projections.apps2_oidc_configs.version,` + + ` projections.apps2_oidc_configs.client_id,` + + ` projections.apps2_oidc_configs.redirect_uris,` + + ` projections.apps2_oidc_configs.response_types,` + + ` projections.apps2_oidc_configs.grant_types,` + + ` projections.apps2_oidc_configs.application_type,` + + ` projections.apps2_oidc_configs.auth_method_type,` + + ` projections.apps2_oidc_configs.post_logout_redirect_uris,` + + ` projections.apps2_oidc_configs.is_dev_mode,` + + ` projections.apps2_oidc_configs.access_token_type,` + + ` projections.apps2_oidc_configs.access_token_role_assertion,` + + ` projections.apps2_oidc_configs.id_token_role_assertion,` + + ` projections.apps2_oidc_configs.id_token_userinfo_assertion,` + + ` projections.apps2_oidc_configs.clock_skew,` + + ` projections.apps2_oidc_configs.additional_origins,` + ` COUNT(*) OVER ()` + - ` FROM projections.apps` + - ` LEFT JOIN projections.apps_api_configs ON projections.apps.id = projections.apps_api_configs.app_id` + - ` LEFT JOIN projections.apps_oidc_configs ON projections.apps.id = projections.apps_oidc_configs.app_id`) - expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps_api_configs.client_id,` + - ` projections.apps_oidc_configs.client_id` + - ` FROM projections.apps` + - ` LEFT JOIN projections.apps_api_configs ON projections.apps.id = projections.apps_api_configs.app_id` + - ` LEFT JOIN projections.apps_oidc_configs ON projections.apps.id = projections.apps_oidc_configs.app_id`) - expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps.project_id` + - ` FROM projections.apps` + - ` LEFT JOIN projections.apps_api_configs ON projections.apps.id = projections.apps_api_configs.app_id` + - ` LEFT JOIN projections.apps_oidc_configs ON projections.apps.id = projections.apps_oidc_configs.app_id`) - expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects.id,` + - ` projections.projects.creation_date,` + - ` projections.projects.change_date,` + - ` projections.projects.resource_owner,` + - ` projections.projects.state,` + - ` projections.projects.sequence,` + - ` projections.projects.name,` + - ` projections.projects.project_role_assertion,` + - ` projections.projects.project_role_check,` + - ` projections.projects.has_project_check,` + - ` projections.projects.private_labeling_setting` + - ` FROM projections.projects` + - ` JOIN projections.apps ON projections.projects.id = projections.apps.project_id` + - ` LEFT JOIN projections.apps_api_configs ON projections.apps.id = projections.apps_api_configs.app_id` + - ` LEFT JOIN projections.apps_oidc_configs ON projections.apps.id = projections.apps_oidc_configs.app_id`) + ` FROM projections.apps2` + + ` LEFT JOIN projections.apps2_api_configs ON projections.apps2.id = projections.apps2_api_configs.app_id` + + ` LEFT JOIN projections.apps2_oidc_configs ON projections.apps2.id = projections.apps2_oidc_configs.app_id`) + expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps2_api_configs.client_id,` + + ` projections.apps2_oidc_configs.client_id` + + ` FROM projections.apps2` + + ` LEFT JOIN projections.apps2_api_configs ON projections.apps2.id = projections.apps2_api_configs.app_id` + + ` LEFT JOIN projections.apps2_oidc_configs ON projections.apps2.id = projections.apps2_oidc_configs.app_id`) + expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps2.project_id` + + ` FROM projections.apps2` + + ` LEFT JOIN projections.apps2_api_configs ON projections.apps2.id = projections.apps2_api_configs.app_id` + + ` LEFT JOIN projections.apps2_oidc_configs ON projections.apps2.id = projections.apps2_oidc_configs.app_id`) + expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects2.id,` + + ` projections.projects2.creation_date,` + + ` projections.projects2.change_date,` + + ` projections.projects2.resource_owner,` + + ` projections.projects2.state,` + + ` projections.projects2.sequence,` + + ` projections.projects2.name,` + + ` projections.projects2.project_role_assertion,` + + ` projections.projects2.project_role_check,` + + ` projections.projects2.has_project_check,` + + ` projections.projects2.private_labeling_setting` + + ` FROM projections.projects2` + + ` JOIN projections.apps2 ON projections.projects2.id = projections.apps2.project_id` + + ` LEFT JOIN projections.apps2_api_configs ON projections.apps2.id = projections.apps2_api_configs.app_id` + + ` LEFT JOIN projections.apps2_oidc_configs ON projections.apps2.id = projections.apps2_oidc_configs.app_id`) - appCols = []string{ + appCols = database.StringArray{ "id", "name", "project_id", @@ -312,19 +311,19 @@ func Test_AppsPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -346,21 +345,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -391,19 +390,19 @@ func Test_AppsPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, false, domain.OIDCTokenTypeJWT, false, false, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -425,21 +424,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: false, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: false, AssertIDTokenRole: false, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -470,19 +469,19 @@ func Test_AppsPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, false, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -504,21 +503,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: false, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -549,19 +548,19 @@ func Test_AppsPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, false, domain.OIDCTokenTypeJWT, false, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -583,21 +582,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: false, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: false, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -628,19 +627,19 @@ func Test_AppsPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, false, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -662,21 +661,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: false, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -707,19 +706,19 @@ func Test_AppsPrepare(t *testing.T) { "oidc-app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, { "api-app-id", @@ -772,21 +771,21 @@ func Test_AppsPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, { @@ -993,19 +992,19 @@ func Test_AppPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -1022,21 +1021,21 @@ func Test_AppPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -1065,19 +1064,19 @@ func Test_AppPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, false, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -1094,21 +1093,21 @@ func Test_AppPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: false, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -1137,19 +1136,19 @@ func Test_AppPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, false, true, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -1166,21 +1165,21 @@ func Test_AppPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: false, AssertIDTokenRole: true, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -1209,19 +1208,19 @@ func Test_AppPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, false, true, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -1238,21 +1237,21 @@ func Test_AppPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: false, AssertIDTokenUserinfo: true, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -1281,19 +1280,19 @@ func Test_AppPrepare(t *testing.T) { "app-id", domain.OIDCVersionV1, "oidc-client-id", - pq.StringArray{"https://redirect.to/me"}, - pq.Int32Array{int32(domain.OIDCResponseTypeIDTokenToken)}, - pq.Int32Array{int32(domain.OIDCGrantTypeImplicit)}, + database.StringArray{"https://redirect.to/me"}, + database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, domain.OIDCApplicationTypeUserAgent, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"post.logout.ch"}, + database.StringArray{"post.logout.ch"}, true, domain.OIDCTokenTypeJWT, true, true, false, 1 * time.Second, - pq.StringArray{"additional.origin"}, + database.StringArray{"additional.origin"}, }, }, ), @@ -1310,21 +1309,21 @@ func Test_AppPrepare(t *testing.T) { OIDCConfig: &OIDCApp{ Version: domain.OIDCVersionV1, ClientID: "oidc-client-id", - RedirectURIs: []string{"https://redirect.to/me"}, - ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeIDTokenToken}, - GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeImplicit}, + RedirectURIs: database.StringArray{"https://redirect.to/me"}, + ResponseTypes: database.EnumArray[domain.OIDCResponseType]{domain.OIDCResponseTypeIDTokenToken}, + GrantTypes: database.EnumArray[domain.OIDCGrantType]{domain.OIDCGrantTypeImplicit}, AppType: domain.OIDCApplicationTypeUserAgent, AuthMethodType: domain.OIDCAuthMethodTypeNone, - PostLogoutRedirectURIs: []string{"post.logout.ch"}, + PostLogoutRedirectURIs: database.StringArray{"post.logout.ch"}, IsDevMode: true, AccessTokenType: domain.OIDCTokenTypeJWT, AssertAccessTokenRole: true, AssertIDTokenRole: true, AssertIDTokenUserinfo: false, ClockSkew: 1 * time.Second, - AdditionalOrigins: []string{"additional.origin"}, + AdditionalOrigins: database.StringArray{"additional.origin"}, ComplianceProblems: nil, - AllowedOrigins: []string{"https://redirect.to", "additional.origin"}, + AllowedOrigins: database.StringArray{"https://redirect.to", "additional.origin"}, }, }, }, @@ -1382,7 +1381,7 @@ func Test_AppIDsPrepare(t *testing.T) { want: want{ sqlExpectations: mockQueries( expectedAppIDsQuery, - []string{"client_id", "client_id"}, + database.StringArray{"client_id", "client_id"}, [][]driver.Value{ { "app-id", @@ -1399,7 +1398,7 @@ func Test_AppIDsPrepare(t *testing.T) { want: want{ sqlExpectations: mockQueries( expectedAppIDsQuery, - []string{"client_id", "client_id"}, + database.StringArray{"client_id", "client_id"}, [][]driver.Value{ { nil, @@ -1474,7 +1473,7 @@ func Test_ProjectIDByAppPrepare(t *testing.T) { want: want{ sqlExpectations: mockQuery( expectedProjectIDByAppQuery, - []string{"project_id"}, + database.StringArray{"project_id"}, []driver.Value{"project-id"}, ), }, diff --git a/internal/query/current_sequence.go b/internal/query/current_sequence.go index 940dd93cc9..7b286d2ed1 100644 --- a/internal/query/current_sequence.go +++ b/internal/query/current_sequence.go @@ -194,7 +194,7 @@ func prepareLatestSequence() (sq.SelectBuilder, func(*sql.Row) (*LatestSequence, return sq.Select( CurrentSequenceColCurrentSequence.identifier(), CurrentSequenceColTimestamp.identifier()). - From(currentSequencesTable.identifier() + " AS OF SYSTEM TIME '-1ms'").PlaceholderFormat(sq.Dollar), + From(currentSequencesTable.identifier()).PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*LatestSequence, error) { seq := new(LatestSequence) err := row.Scan( diff --git a/internal/query/iam_member.go b/internal/query/iam_member.go index 0454b6a95d..8ec6cb5b55 100644 --- a/internal/query/iam_member.go +++ b/internal/query/iam_member.go @@ -5,7 +5,6 @@ import ( "database/sql" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" @@ -117,7 +116,6 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, for rows.Next() { member := new(Member) - roles := pq.StringArray{} var ( preferredLoginName = sql.NullString{} @@ -135,7 +133,7 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, &member.Sequence, &member.ResourceOwner, &member.UserID, - &roles, + &member.Roles, &preferredLoginName, &email, &firstName, @@ -151,7 +149,6 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, return nil, err } - member.Roles = roles member.PreferredLoginName = preferredLoginName.String member.Email = email.String member.FirstName = firstName.String diff --git a/internal/query/iam_member_test.go b/internal/query/iam_member_test.go index 50896e73d0..e4755bb2a9 100644 --- a/internal/query/iam_member_test.go +++ b/internal/query/iam_member_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" ) var ( @@ -20,18 +20,18 @@ var ( ", members.user_id" + ", members.roles" + ", projections.login_names.login_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.display_name" + - ", projections.users2_machines.name" + - ", projections.users2_humans.avatar_key" + + ", projections.users3_humans.email" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.display_name" + + ", projections.users3_machines.name" + + ", projections.users3_humans.avatar_key" + ", COUNT(*) OVER () " + - "FROM projections.instance_members as members " + - "LEFT JOIN projections.users2_humans " + - "ON members.user_id = projections.users2_humans.user_id " + - "LEFT JOIN projections.users2_machines " + - "ON members.user_id = projections.users2_machines.user_id " + + "FROM projections.instance_members2 AS members " + + "LEFT JOIN projections.users3_humans " + + "ON members.user_id = projections.users3_humans.user_id " + + "LEFT JOIN projections.users3_machines " + + "ON members.user_id = projections.users3_machines.user_id " + "LEFT JOIN projections.login_names " + "ON members.user_id = projections.login_names.user_id " + "WHERE projections.login_names.is_primary = $1") @@ -92,7 +92,7 @@ func Test_IAMMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -115,7 +115,7 @@ func Test_IAMMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -140,7 +140,7 @@ func Test_IAMMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -163,7 +163,7 @@ func Test_IAMMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", @@ -188,7 +188,7 @@ func Test_IAMMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-1", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -203,7 +203,7 @@ func Test_IAMMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-2", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -226,7 +226,7 @@ func Test_IAMMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-1", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -240,7 +240,7 @@ func Test_IAMMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-2", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", diff --git a/internal/query/idp.go b/internal/query/idp.go index dee1c5e6cf..873ddf7aa8 100644 --- a/internal/query/idp.go +++ b/internal/query/idp.go @@ -7,9 +7,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/domain" @@ -42,7 +42,7 @@ type OIDCIDP struct { ClientID string ClientSecret *crypto.CryptoValue Issuer string - Scopes []string + Scopes database.StringArray DisplayNameMapping domain.OIDCMappingField UsernameMapping domain.OIDCMappingField AuthorizationEndpoint string @@ -307,7 +307,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) { oidcClientID := sql.NullString{} oidcClientSecret := new(crypto.CryptoValue) oidcIssuer := sql.NullString{} - oidcScopes := pq.StringArray{} + oidcScopes := database.StringArray{} oidcDisplayNameMapping := sql.NullInt32{} oidcUsernameMapping := sql.NullInt32{} oidcAuthorizationEndpoint := sql.NullString{} @@ -419,7 +419,7 @@ func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) { oidcClientID := sql.NullString{} oidcClientSecret := new(crypto.CryptoValue) oidcIssuer := sql.NullString{} - oidcScopes := pq.StringArray{} + oidcScopes := database.StringArray{} oidcDisplayNameMapping := sql.NullInt32{} oidcUsernameMapping := sql.NullInt32{} oidcAuthorizationEndpoint := sql.NullString{} diff --git a/internal/query/idp_login_policy_link_test.go b/internal/query/idp_login_policy_link_test.go index 46ed85b8d3..265d1c94ca 100644 --- a/internal/query/idp_login_policy_link_test.go +++ b/internal/query/idp_login_policy_link_test.go @@ -12,12 +12,12 @@ import ( ) var ( - loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_login_policy_links.idp_id,` + - ` projections.idps.name,` + - ` projections.idps.type,` + + loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_login_policy_links2.idp_id,` + + ` projections.idps2.name,` + + ` projections.idps2.type,` + ` COUNT(*) OVER ()` + - ` FROM projections.idp_login_policy_links` + - ` LEFT JOIN projections.idps ON projections.idp_login_policy_links.idp_id = projections.idps.id`) + ` FROM projections.idp_login_policy_links2` + + ` LEFT JOIN projections.idps2 ON projections.idp_login_policy_links2.idp_id = projections.idps2.id`) loginPolicyIDPLinksCols = []string{ "idp_id", "name", diff --git a/internal/query/idp_test.go b/internal/query/idp_test.go index 903b442d70..be362fd703 100644 --- a/internal/query/idp_test.go +++ b/internal/query/idp_test.go @@ -8,9 +8,8 @@ import ( "regexp" "testing" - "github.com/lib/pq" - "github.com/zitadel/zitadel/internal/crypto" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) @@ -31,33 +30,33 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPByIDQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint`+ + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), nil, nil, ), @@ -75,33 +74,33 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPByIDQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint`+ + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -146,7 +145,7 @@ func Test_IDPPrepares(t *testing.T) { "oidc-client-id", nil, "oidc-issuer", - pq.StringArray{"scope"}, + database.StringArray{"scope"}, domain.OIDCMappingFieldEmail, domain.OIDCMappingFieldPreferredLoginName, "auth.endpoint.ch", @@ -176,7 +175,7 @@ func Test_IDPPrepares(t *testing.T) { ClientID: "oidc-client-id", ClientSecret: &crypto.CryptoValue{}, Issuer: "oidc-issuer", - Scopes: []string{"scope"}, + Scopes: database.StringArray{"scope"}, DisplayNameMapping: domain.OIDCMappingFieldEmail, UsernameMapping: domain.OIDCMappingFieldPreferredLoginName, AuthorizationEndpoint: "auth.endpoint.ch", @@ -189,33 +188,33 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPByIDQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint`+ + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -299,33 +298,33 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPByIDQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint`+ + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -402,33 +401,33 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPByIDQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint`+ + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -445,34 +444,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), nil, nil, ), @@ -490,34 +489,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -564,7 +563,7 @@ func Test_IDPPrepares(t *testing.T) { "oidc-client-id", nil, "oidc-issuer", - pq.StringArray{"scope"}, + database.StringArray{"scope"}, domain.OIDCMappingFieldEmail, domain.OIDCMappingFieldPreferredLoginName, "auth.endpoint.ch", @@ -600,7 +599,7 @@ func Test_IDPPrepares(t *testing.T) { ClientID: "oidc-client-id", ClientSecret: &crypto.CryptoValue{}, Issuer: "oidc-issuer", - Scopes: []string{"scope"}, + Scopes: database.StringArray{"scope"}, DisplayNameMapping: domain.OIDCMappingFieldEmail, UsernameMapping: domain.OIDCMappingFieldPreferredLoginName, AuthorizationEndpoint: "auth.endpoint.ch", @@ -615,34 +614,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -735,34 +734,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -848,34 +847,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), []string{ "id", "resource_owner", @@ -949,7 +948,7 @@ func Test_IDPPrepares(t *testing.T) { "oidc-client-id", nil, "oidc-issuer", - pq.StringArray{"scope"}, + database.StringArray{"scope"}, domain.OIDCMappingFieldEmail, domain.OIDCMappingFieldPreferredLoginName, "auth.endpoint.ch", @@ -1025,7 +1024,7 @@ func Test_IDPPrepares(t *testing.T) { ClientID: "oidc-client-id", ClientSecret: &crypto.CryptoValue{}, Issuer: "oidc-issuer", - Scopes: []string{"scope"}, + Scopes: database.StringArray{"scope"}, DisplayNameMapping: domain.OIDCMappingFieldEmail, UsernameMapping: domain.OIDCMappingFieldPreferredLoginName, AuthorizationEndpoint: "auth.endpoint.ch", @@ -1059,34 +1058,34 @@ func Test_IDPPrepares(t *testing.T) { prepare: prepareIDPsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.idps.id,`+ - ` projections.idps.resource_owner,`+ - ` projections.idps.creation_date,`+ - ` projections.idps.change_date,`+ - ` projections.idps.sequence,`+ - ` projections.idps.state,`+ - ` projections.idps.name,`+ - ` projections.idps.styling_type,`+ - ` projections.idps.owner_type,`+ - ` projections.idps.auto_register,`+ - ` projections.idps_oidc_config.idp_id,`+ - ` projections.idps_oidc_config.client_id,`+ - ` projections.idps_oidc_config.client_secret,`+ - ` projections.idps_oidc_config.issuer,`+ - ` projections.idps_oidc_config.scopes,`+ - ` projections.idps_oidc_config.display_name_mapping,`+ - ` projections.idps_oidc_config.username_mapping,`+ - ` projections.idps_oidc_config.authorization_endpoint,`+ - ` projections.idps_oidc_config.token_endpoint,`+ - ` projections.idps_jwt_config.idp_id,`+ - ` projections.idps_jwt_config.issuer,`+ - ` projections.idps_jwt_config.keys_endpoint,`+ - ` projections.idps_jwt_config.header_name,`+ - ` projections.idps_jwt_config.endpoint,`+ + regexp.QuoteMeta(`SELECT projections.idps2.id,`+ + ` projections.idps2.resource_owner,`+ + ` projections.idps2.creation_date,`+ + ` projections.idps2.change_date,`+ + ` projections.idps2.sequence,`+ + ` projections.idps2.state,`+ + ` projections.idps2.name,`+ + ` projections.idps2.styling_type,`+ + ` projections.idps2.owner_type,`+ + ` projections.idps2.auto_register,`+ + ` projections.idps2_oidc_config.idp_id,`+ + ` projections.idps2_oidc_config.client_id,`+ + ` projections.idps2_oidc_config.client_secret,`+ + ` projections.idps2_oidc_config.issuer,`+ + ` projections.idps2_oidc_config.scopes,`+ + ` projections.idps2_oidc_config.display_name_mapping,`+ + ` projections.idps2_oidc_config.username_mapping,`+ + ` projections.idps2_oidc_config.authorization_endpoint,`+ + ` projections.idps2_oidc_config.token_endpoint,`+ + ` projections.idps2_jwt_config.idp_id,`+ + ` projections.idps2_jwt_config.issuer,`+ + ` projections.idps2_jwt_config.keys_endpoint,`+ + ` projections.idps2_jwt_config.header_name,`+ + ` projections.idps2_jwt_config.endpoint,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.idps`+ - ` LEFT JOIN projections.idps_oidc_config ON projections.idps.id = projections.idps_oidc_config.idp_id`+ - ` LEFT JOIN projections.idps_jwt_config ON projections.idps.id = projections.idps_jwt_config.idp_id`), + ` FROM projections.idps2`+ + ` LEFT JOIN projections.idps2_oidc_config ON projections.idps2.id = projections.idps2_oidc_config.idp_id`+ + ` LEFT JOIN projections.idps2_jwt_config ON projections.idps2.id = projections.idps2_jwt_config.idp_id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/idp_user_link_test.go b/internal/query/idp_user_link_test.go index af1bf621ec..4078662559 100644 --- a/internal/query/idp_user_link_test.go +++ b/internal/query/idp_user_link_test.go @@ -12,16 +12,16 @@ import ( ) var ( - idpUserLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_user_links.idp_id,` + - ` projections.idp_user_links.user_id,` + - ` projections.idps.name,` + - ` projections.idp_user_links.external_user_id,` + - ` projections.idp_user_links.display_name,` + - ` projections.idps.type,` + - ` projections.idp_user_links.resource_owner,` + + idpUserLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_user_links2.idp_id,` + + ` projections.idp_user_links2.user_id,` + + ` projections.idps2.name,` + + ` projections.idp_user_links2.external_user_id,` + + ` projections.idp_user_links2.display_name,` + + ` projections.idps2.type,` + + ` projections.idp_user_links2.resource_owner,` + ` COUNT(*) OVER ()` + - ` FROM projections.idp_user_links` + - ` LEFT JOIN projections.idps ON projections.idp_user_links.idp_id = projections.idps.id`) + ` FROM projections.idp_user_links2` + + ` LEFT JOIN projections.idps2 ON projections.idp_user_links2.idp_id = projections.idps2.id`) idpUserLinksCols = []string{ "idp_id", "user_id", diff --git a/internal/query/key_test.go b/internal/query/key_test.go index 3dac38b6de..5d00060cd2 100644 --- a/internal/query/key_test.go +++ b/internal/query/key_test.go @@ -31,18 +31,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_public.expiry,`+ - ` projections.keys_public.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_public.expiry,`+ + ` projections.keys2_public.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_public ON projections.keys.id = projections.keys_public.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_public ON projections.keys2.id = projections.keys2_public.id`), nil, nil, ), @@ -60,18 +60,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_public.expiry,`+ - ` projections.keys_public.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_public.expiry,`+ + ` projections.keys2_public.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_public ON projections.keys.id = projections.keys_public.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_public ON projections.keys2.id = projections.keys2_public.id`), []string{ "id", "creation_date", @@ -128,18 +128,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePublicKeysQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_public.expiry,`+ - ` projections.keys_public.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_public.expiry,`+ + ` projections.keys2_public.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_public ON projections.keys.id = projections.keys_public.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_public ON projections.keys2.id = projections.keys2_public.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -156,18 +156,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_private.expiry,`+ - ` projections.keys_private.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_private.expiry,`+ + ` projections.keys2_private.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_private ON projections.keys.id = projections.keys_private.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_private ON projections.keys2.id = projections.keys2_private.id`), nil, nil, ), @@ -185,18 +185,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_private.expiry,`+ - ` projections.keys_private.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_private.expiry,`+ + ` projections.keys2_private.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_private ON projections.keys.id = projections.keys_private.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_private ON projections.keys2.id = projections.keys2_private.id`), []string{ "id", "creation_date", @@ -255,18 +255,18 @@ func Test_KeyPrepares(t *testing.T) { prepare: preparePrivateKeysQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.keys.id,`+ - ` projections.keys.creation_date,`+ - ` projections.keys.change_date,`+ - ` projections.keys.sequence,`+ - ` projections.keys.resource_owner,`+ - ` projections.keys.algorithm,`+ - ` projections.keys.use,`+ - ` projections.keys_private.expiry,`+ - ` projections.keys_private.key,`+ + regexp.QuoteMeta(`SELECT projections.keys2.id,`+ + ` projections.keys2.creation_date,`+ + ` projections.keys2.change_date,`+ + ` projections.keys2.sequence,`+ + ` projections.keys2.resource_owner,`+ + ` projections.keys2.algorithm,`+ + ` projections.keys2.use,`+ + ` projections.keys2_private.expiry,`+ + ` projections.keys2_private.key,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.keys`+ - ` LEFT JOIN projections.keys_private ON projections.keys.id = projections.keys_private.id`), + ` FROM projections.keys2`+ + ` LEFT JOIN projections.keys2_private ON projections.keys2.id = projections.keys2_private.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/login_policy.go b/internal/query/login_policy.go index 6c3512e0dd..db279f0b89 100644 --- a/internal/query/login_policy.go +++ b/internal/query/login_policy.go @@ -7,9 +7,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -24,8 +24,8 @@ type LoginPolicy struct { AllowUsernamePassword bool AllowExternalIDPs bool ForceMFA bool - SecondFactors []domain.SecondFactorType - MultiFactors []domain.MultiFactorType + SecondFactors database.EnumArray[domain.SecondFactorType] + MultiFactors database.EnumArray[domain.MultiFactorType] PasswordlessType domain.PasswordlessType IsDefault bool HidePasswordReset bool @@ -41,12 +41,12 @@ type LoginPolicy struct { type SecondFactors struct { SearchResponse - Factors []domain.SecondFactorType + Factors database.EnumArray[domain.SecondFactorType] } type MultiFactors struct { SearchResponse - Factors []domain.MultiFactorType + Factors database.EnumArray[domain.MultiFactorType] } var ( @@ -320,8 +320,6 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*LoginPolicy, error) { p := new(LoginPolicy) - secondFactors := pq.Int32Array{} - multiFactors := pq.Int32Array{} defaultRedirectURI := sql.NullString{} links := make([]*IDPLoginPolicyLink, 0) for rows.Next() { @@ -339,8 +337,8 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, &p.AllowUsernamePassword, &p.AllowExternalIDPs, &p.ForceMFA, - &secondFactors, - &multiFactors, + &p.SecondFactors, + &p.MultiFactors, &p.PasswordlessType, &p.IsDefault, &p.HidePasswordReset, @@ -376,14 +374,6 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, return nil, errors.ThrowNotFound(nil, "QUERY-QsUBJ", "Errors.LoginPolicy.NotFound") } p.DefaultRedirectURI = defaultRedirectURI.String - p.MultiFactors = make([]domain.MultiFactorType, len(multiFactors)) - for i, mfa := range multiFactors { - p.MultiFactors[i] = domain.MultiFactorType(mfa) - } - p.SecondFactors = make([]domain.SecondFactorType, len(secondFactors)) - for i, mfa := range secondFactors { - p.SecondFactors[i] = domain.SecondFactorType(mfa) - } p.IDPLinks = links return p, nil } @@ -395,9 +385,8 @@ func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFac ).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SecondFactors, error) { p := new(SecondFactors) - secondFactors := pq.Int32Array{} err := row.Scan( - &secondFactors, + &p.Factors, ) if err != nil { if errs.Is(err, sql.ErrNoRows) { @@ -406,11 +395,7 @@ func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFac return nil, errors.ThrowInternal(err, "QUERY-Mr6H3", "Errors.Internal") } - p.Factors = make([]domain.SecondFactorType, len(secondFactors)) - p.Count = uint64(len(secondFactors)) - for i, mfa := range secondFactors { - p.Factors[i] = domain.SecondFactorType(mfa) - } + p.Count = uint64(len(p.Factors)) return p, nil } } @@ -421,9 +406,8 @@ func prepareLoginPolicyMFAsQuery() (sq.SelectBuilder, func(*sql.Row) (*MultiFact ).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*MultiFactors, error) { p := new(MultiFactors) - multiFactors := pq.Int32Array{} err := row.Scan( - &multiFactors, + &p.Factors, ) if err != nil { if errs.Is(err, sql.ErrNoRows) { @@ -432,11 +416,7 @@ func prepareLoginPolicyMFAsQuery() (sq.SelectBuilder, func(*sql.Row) (*MultiFact return nil, errors.ThrowInternal(err, "QUERY-Mr6H3", "Errors.Internal") } - p.Factors = make([]domain.MultiFactorType, len(multiFactors)) - p.Count = uint64(len(multiFactors)) - for i, mfa := range multiFactors { - p.Factors[i] = domain.MultiFactorType(mfa) - } + p.Count = uint64(len(p.Factors)) return p, nil } } diff --git a/internal/query/login_policy_test.go b/internal/query/login_policy_test.go index 6f097c0a58..c281d0cd6f 100644 --- a/internal/query/login_policy_test.go +++ b/internal/query/login_policy_test.go @@ -9,8 +9,7 @@ import ( "testing" "time" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) @@ -51,14 +50,14 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.login_policies.mfa_init_skip_lifetime,`+ ` projections.login_policies.second_factor_check_lifetime,`+ ` projections.login_policies.multi_factor_check_lifetime,`+ - ` projections.idp_login_policy_links.idp_id,`+ - ` projections.idps.name,`+ - ` projections.idps.type`+ + ` projections.idp_login_policy_links2.idp_id,`+ + ` projections.idps2.name,`+ + ` projections.idps2.type`+ ` FROM projections.login_policies`+ - ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ - ` LEFT JOIN projections.idps ON`+ - ` projections.idp_login_policy_links.idp_id = projections.idps.id`), + ` LEFT JOIN projections.idp_login_policy_links2 ON `+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links2.aggregate_id`+ + ` LEFT JOIN projections.idps2 ON`+ + ` projections.idp_login_policy_links2.idp_id = projections.idps2.id`), nil, nil, ), @@ -96,14 +95,14 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.login_policies.mfa_init_skip_lifetime,`+ ` projections.login_policies.second_factor_check_lifetime,`+ ` projections.login_policies.multi_factor_check_lifetime,`+ - ` projections.idp_login_policy_links.idp_id,`+ - ` projections.idps.name,`+ - ` projections.idps.type`+ + ` projections.idp_login_policy_links2.idp_id,`+ + ` projections.idps2.name,`+ + ` projections.idps2.type`+ ` FROM projections.login_policies`+ - ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ - ` LEFT JOIN projections.idps ON`+ - ` projections.idp_login_policy_links.idp_id = projections.idps.id`), + ` LEFT JOIN projections.idp_login_policy_links2 ON `+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links2.aggregate_id`+ + ` LEFT JOIN projections.idps2 ON`+ + ` projections.idp_login_policy_links2.idp_id = projections.idps2.id`), []string{ "aggregate_id", "creation_date", @@ -138,8 +137,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { true, true, true, - pq.Int32Array{int32(domain.SecondFactorTypeOTP)}, - pq.Int32Array{int32(domain.MultiFactorTypeU2FWithPIN)}, + database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, + database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, domain.PasswordlessTypeAllowed, true, true, @@ -165,8 +164,8 @@ func Test_LoginPolicyPrepares(t *testing.T) { AllowUsernamePassword: true, AllowExternalIDPs: true, ForceMFA: true, - SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, - MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN}, + SecondFactors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, + MultiFactors: database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, PasswordlessType: domain.PasswordlessTypeAllowed, IsDefault: true, HidePasswordReset: true, @@ -211,14 +210,14 @@ func Test_LoginPolicyPrepares(t *testing.T) { ` projections.login_policies.mfa_init_skip_lifetime,`+ ` projections.login_policies.second_factor_check_lifetime,`+ ` projections.login_policies.multi_factor_check_lifetime,`+ - ` projections.idp_login_policy_links.idp_id,`+ - ` projections.idps.name,`+ - ` projections.idps.type`+ + ` projections.idp_login_policy_links2.idp_id,`+ + ` projections.idps2.name,`+ + ` projections.idps2.type`+ ` FROM projections.login_policies`+ - ` LEFT JOIN projections.idp_login_policy_links ON `+ - ` projections.login_policies.aggregate_id = projections.idp_login_policy_links.aggregate_id`+ - ` LEFT JOIN projections.idps ON`+ - ` projections.idp_login_policy_links.idp_id = projections.idps.id`), + ` LEFT JOIN projections.idp_login_policy_links2 ON `+ + ` projections.login_policies.aggregate_id = projections.idp_login_policy_links2.aggregate_id`+ + ` LEFT JOIN projections.idps2 ON`+ + ` projections.idp_login_policy_links2.idp_id = projections.idps2.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -262,7 +261,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { "second_factors", }, []driver.Value{ - pq.Int32Array{int32(domain.SecondFactorTypeOTP)}, + database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, }, ), }, @@ -270,7 +269,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { SearchResponse: SearchResponse{ Count: 1, }, - Factors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, + Factors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, }, }, { @@ -284,11 +283,11 @@ func Test_LoginPolicyPrepares(t *testing.T) { "second_factors", }, []driver.Value{ - pq.Int32Array{}, + database.EnumArray[domain.SecondFactorType]{}, }, ), }, - object: &SecondFactors{Factors: []domain.SecondFactorType{}}, + object: &SecondFactors{Factors: database.EnumArray[domain.SecondFactorType]{}}, }, { name: "prepareLoginPolicy2FAsQuery sql err", @@ -308,7 +307,6 @@ func Test_LoginPolicyPrepares(t *testing.T) { }, object: nil, }, - { name: "prepareLoginPolicyMFAsQuery no result", prepare: prepareLoginPolicyMFAsQuery, @@ -341,7 +339,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { "multi_factors", }, []driver.Value{ - pq.Int32Array{int32(domain.MultiFactorTypeU2FWithPIN)}, + database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, }, ), }, @@ -349,7 +347,7 @@ func Test_LoginPolicyPrepares(t *testing.T) { SearchResponse: SearchResponse{ Count: 1, }, - Factors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN}, + Factors: database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, }, }, { @@ -363,11 +361,11 @@ func Test_LoginPolicyPrepares(t *testing.T) { "multi_factors", }, []driver.Value{ - pq.Int32Array{}, + database.EnumArray[domain.MultiFactorType]{}, }, ), }, - object: &MultiFactors{Factors: []domain.MultiFactorType{}}, + object: &MultiFactors{Factors: database.EnumArray[domain.MultiFactorType]{}}, }, { name: "prepareLoginPolicyMFAsQuery sql err", diff --git a/internal/query/member.go b/internal/query/member.go index a6ee5d409a..ed30dcd665 100644 --- a/internal/query/member.go +++ b/internal/query/member.go @@ -3,6 +3,7 @@ package query import ( "time" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/query/projection" sq "github.com/Masterminds/squirrel" @@ -52,7 +53,7 @@ type Member struct { ResourceOwner string UserID string - Roles []string + Roles database.StringArray PreferredLoginName string Email string FirstName string diff --git a/internal/query/org_member.go b/internal/query/org_member.go index 6706ba953f..68c1b8c37f 100644 --- a/internal/query/org_member.go +++ b/internal/query/org_member.go @@ -9,7 +9,6 @@ import ( "github.com/zitadel/zitadel/internal/query/projection" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" ) var ( @@ -120,7 +119,6 @@ func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, erro member := new(Member) var ( - roles = pq.StringArray{} preferredLoginName = sql.NullString{} email = sql.NullString{} firstName = sql.NullString{} @@ -136,7 +134,7 @@ func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, erro &member.Sequence, &member.ResourceOwner, &member.UserID, - &roles, + &member.Roles, &preferredLoginName, &email, &firstName, @@ -152,7 +150,6 @@ func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, erro return nil, err } - member.Roles = roles member.PreferredLoginName = preferredLoginName.String member.Email = email.String member.FirstName = firstName.String diff --git a/internal/query/org_member_test.go b/internal/query/org_member_test.go index 4b89ad59df..185ed451c5 100644 --- a/internal/query/org_member_test.go +++ b/internal/query/org_member_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" ) var ( @@ -20,18 +20,18 @@ var ( ", members.user_id" + ", members.roles" + ", projections.login_names.login_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.display_name" + - ", projections.users2_machines.name" + - ", projections.users2_humans.avatar_key" + + ", projections.users3_humans.email" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.display_name" + + ", projections.users3_machines.name" + + ", projections.users3_humans.avatar_key" + ", COUNT(*) OVER () " + - "FROM projections.org_members as members " + - "LEFT JOIN projections.users2_humans " + - "ON members.user_id = projections.users2_humans.user_id " + - "LEFT JOIN projections.users2_machines " + - "ON members.user_id = projections.users2_machines.user_id " + + "FROM projections.org_members2 AS members " + + "LEFT JOIN projections.users3_humans " + + "ON members.user_id = projections.users3_humans.user_id " + + "LEFT JOIN projections.users3_machines " + + "ON members.user_id = projections.users3_machines.user_id " + "LEFT JOIN projections.login_names " + "ON members.user_id = projections.login_names.user_id " + "WHERE projections.login_names.is_primary = $1") @@ -92,7 +92,7 @@ func Test_OrgMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -115,7 +115,7 @@ func Test_OrgMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -140,7 +140,7 @@ func Test_OrgMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -163,7 +163,7 @@ func Test_OrgMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", @@ -188,7 +188,7 @@ func Test_OrgMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-1", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -203,7 +203,7 @@ func Test_OrgMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-2", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -226,7 +226,7 @@ func Test_OrgMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-1", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -240,7 +240,7 @@ func Test_OrgMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-2", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", diff --git a/internal/query/project_grant.go b/internal/query/project_grant.go index e802780209..c4094dd7a6 100644 --- a/internal/query/project_grant.go +++ b/internal/query/project_grant.go @@ -7,9 +7,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/query/projection" "github.com/zitadel/zitadel/internal/domain" @@ -92,7 +92,7 @@ type ProjectGrant struct { ProjectName string GrantedOrgID string OrgName string - GrantedRoleKeys pq.StringArray + GrantedRoleKeys database.StringArray ResourceOwnerName string } diff --git a/internal/query/project_grant_member.go b/internal/query/project_grant_member.go index d5494b19c8..0751228e71 100644 --- a/internal/query/project_grant_member.go +++ b/internal/query/project_grant_member.go @@ -5,7 +5,6 @@ import ( "database/sql" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" @@ -133,7 +132,6 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb for rows.Next() { member := new(Member) - roles := pq.StringArray{} var ( preferredLoginName = sql.NullString{} @@ -151,7 +149,7 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb &member.Sequence, &member.ResourceOwner, &member.UserID, - &roles, + &member.Roles, &preferredLoginName, &email, &firstName, @@ -167,7 +165,6 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb return nil, err } - member.Roles = roles member.PreferredLoginName = preferredLoginName.String member.Email = email.String member.FirstName = firstName.String diff --git a/internal/query/project_grant_member_test.go b/internal/query/project_grant_member_test.go index d449dd926e..3ca6783cc3 100644 --- a/internal/query/project_grant_member_test.go +++ b/internal/query/project_grant_member_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" ) var ( @@ -20,22 +20,22 @@ var ( ", members.user_id" + ", members.roles" + ", projections.login_names.login_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.display_name" + - ", projections.users2_machines.name" + - ", projections.users2_humans.avatar_key" + + ", projections.users3_humans.email" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.display_name" + + ", projections.users3_machines.name" + + ", projections.users3_humans.avatar_key" + ", COUNT(*) OVER () " + - "FROM projections.project_grant_members as members " + - "LEFT JOIN projections.users2_humans " + - "ON members.user_id = projections.users2_humans.user_id " + - "LEFT JOIN projections.users2_machines " + - "ON members.user_id = projections.users2_machines.user_id " + + "FROM projections.project_grant_members2 AS members " + + "LEFT JOIN projections.users3_humans " + + "ON members.user_id = projections.users3_humans.user_id " + + "LEFT JOIN projections.users3_machines " + + "ON members.user_id = projections.users3_machines.user_id " + "LEFT JOIN projections.login_names " + "ON members.user_id = projections.login_names.user_id " + - "LEFT JOIN projections.project_grants " + - "ON members.grant_id = projections.project_grants.grant_id " + + "LEFT JOIN projections.project_grants2 " + + "ON members.grant_id = projections.project_grants2.grant_id " + "WHERE projections.login_names.is_primary = $1") projectGrantMembersColumns = []string{ "creation_date", @@ -94,7 +94,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -117,7 +117,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -142,7 +142,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -165,7 +165,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", @@ -190,7 +190,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-1", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -205,7 +205,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-2", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -228,7 +228,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-1", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -242,7 +242,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-2", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", diff --git a/internal/query/project_grant_test.go b/internal/query/project_grant_test.go index 7415bd0f88..aa4c7d0d64 100644 --- a/internal/query/project_grant_test.go +++ b/internal/query/project_grant_test.go @@ -8,8 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) @@ -30,23 +29,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), nil, nil, ), @@ -58,23 +57,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.project_grants`+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id`+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2`+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id`+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -102,7 +101,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, }, @@ -124,7 +123,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -135,23 +134,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -179,7 +178,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { nil, "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, }, @@ -201,7 +200,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -212,23 +211,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -256,7 +255,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", nil, - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, }, @@ -278,7 +277,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -289,23 +288,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -333,7 +332,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, nil, }, }, @@ -355,7 +354,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "", }, }, @@ -366,23 +365,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -410,7 +409,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, { @@ -424,7 +423,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, }, @@ -446,7 +445,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, { @@ -460,7 +459,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -471,23 +470,23 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name,`+ ` COUNT(*) OVER () `+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -504,22 +503,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), nil, nil, ), @@ -537,22 +536,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -578,7 +577,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, ), @@ -594,7 +593,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -603,22 +602,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -644,7 +643,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", nil, - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, ), @@ -660,7 +659,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -669,22 +668,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -710,7 +709,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { "project-name", "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, nil, }, ), @@ -726,7 +725,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "project-name", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "", }, }, @@ -735,22 +734,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), []string{ "project_id", "grant_id", @@ -776,7 +775,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { nil, "org-id", "org-name", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, "ro-name", }, ), @@ -792,7 +791,7 @@ func Test_ProjectGrantPrepares(t *testing.T) { ProjectName: "", GrantedOrgID: "org-id", OrgName: "org-name", - GrantedRoleKeys: pq.StringArray{"role-key"}, + GrantedRoleKeys: database.StringArray{"role-key"}, ResourceOwnerName: "ro-name", }, }, @@ -801,22 +800,22 @@ func Test_ProjectGrantPrepares(t *testing.T) { prepare: prepareProjectGrantQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(` SELECT projections.project_grants.project_id,`+ - ` projections.project_grants.grant_id,`+ - ` projections.project_grants.creation_date,`+ - ` projections.project_grants.change_date,`+ - ` projections.project_grants.resource_owner,`+ - ` projections.project_grants.state,`+ - ` projections.project_grants.sequence,`+ - ` projections.projects.name,`+ - ` projections.project_grants.granted_org_id,`+ + regexp.QuoteMeta(` SELECT projections.project_grants2.project_id,`+ + ` projections.project_grants2.grant_id,`+ + ` projections.project_grants2.creation_date,`+ + ` projections.project_grants2.change_date,`+ + ` projections.project_grants2.resource_owner,`+ + ` projections.project_grants2.state,`+ + ` projections.project_grants2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.project_grants2.granted_org_id,`+ ` o.name,`+ - ` projections.project_grants.granted_role_keys,`+ + ` projections.project_grants2.granted_role_keys,`+ ` r.name`+ - ` FROM projections.project_grants `+ - ` LEFT JOIN projections.projects ON projections.project_grants.project_id = projections.projects.id `+ - ` LEFT JOIN projections.orgs as r ON projections.project_grants.resource_owner = r.id`+ - ` LEFT JOIN projections.orgs as o ON projections.project_grants.granted_org_id = o.id`), + ` FROM projections.project_grants2 `+ + ` LEFT JOIN projections.projects2 ON projections.project_grants2.project_id = projections.projects2.id `+ + ` LEFT JOIN projections.orgs AS r ON projections.project_grants2.resource_owner = r.id`+ + ` LEFT JOIN projections.orgs AS o ON projections.project_grants2.granted_org_id = o.id`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/project_member.go b/internal/query/project_member.go index c1a87faa44..20c3b4c85f 100644 --- a/internal/query/project_member.go +++ b/internal/query/project_member.go @@ -5,7 +5,6 @@ import ( "database/sql" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" @@ -119,7 +118,6 @@ func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, for rows.Next() { member := new(Member) - roles := pq.StringArray{} var ( preferredLoginName = sql.NullString{} @@ -137,7 +135,7 @@ func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, &member.Sequence, &member.ResourceOwner, &member.UserID, - &roles, + &member.Roles, &preferredLoginName, &email, &firstName, @@ -153,7 +151,6 @@ func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, return nil, err } - member.Roles = roles member.PreferredLoginName = preferredLoginName.String member.Email = email.String member.FirstName = firstName.String diff --git a/internal/query/project_member_test.go b/internal/query/project_member_test.go index dbef1b8283..610b976b0f 100644 --- a/internal/query/project_member_test.go +++ b/internal/query/project_member_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" ) var ( @@ -20,18 +20,18 @@ var ( ", members.user_id" + ", members.roles" + ", projections.login_names.login_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.display_name" + - ", projections.users2_machines.name" + - ", projections.users2_humans.avatar_key" + + ", projections.users3_humans.email" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.display_name" + + ", projections.users3_machines.name" + + ", projections.users3_humans.avatar_key" + ", COUNT(*) OVER () " + - "FROM projections.project_members as members " + - "LEFT JOIN projections.users2_humans " + - "ON members.user_id = projections.users2_humans.user_id " + - "LEFT JOIN projections.users2_machines " + - "ON members.user_id = projections.users2_machines.user_id " + + "FROM projections.project_members2 AS members " + + "LEFT JOIN projections.users3_humans " + + "ON members.user_id = projections.users3_humans.user_id " + + "LEFT JOIN projections.users3_machines " + + "ON members.user_id = projections.users3_machines.user_id " + "LEFT JOIN projections.login_names " + "ON members.user_id = projections.login_names.user_id " + "WHERE projections.login_names.is_primary = $1") @@ -92,7 +92,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -115,7 +115,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -140,7 +140,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -163,7 +163,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", @@ -188,7 +188,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-1", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "gigi@caos-ag.zitadel.ch", "gigi@caos.ch", "first-name", @@ -203,7 +203,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { uint64(20211206), "ro", "user-id-2", - pq.StringArray{"role-1", "role-2"}, + database.StringArray{"role-1", "role-2"}, "machine@caos-ag.zitadel.ch", nil, nil, @@ -226,7 +226,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-1", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "gigi@caos-ag.zitadel.ch", Email: "gigi@caos.ch", FirstName: "first-name", @@ -240,7 +240,7 @@ func Test_ProjectMemberPrepares(t *testing.T) { Sequence: 20211206, ResourceOwner: "ro", UserID: "user-id-2", - Roles: []string{"role-1", "role-2"}, + Roles: database.StringArray{"role-1", "role-2"}, PreferredLoginName: "machine@caos-ag.zitadel.ch", Email: "", FirstName: "", diff --git a/internal/query/project_test.go b/internal/query/project_test.go index e391bc54cb..3a55a29ad9 100644 --- a/internal/query/project_test.go +++ b/internal/query/project_test.go @@ -44,19 +44,19 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting,`+ + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.projects`), + ` FROM projections.projects2`), nil, nil, ), @@ -68,19 +68,19 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting,`+ + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.projects`), + ` FROM projections.projects2`), []string{ "id", "creation_date", @@ -138,19 +138,19 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting,`+ + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.projects`), + ` FROM projections.projects2`), []string{ "id", "creation_date", @@ -234,19 +234,19 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting,`+ + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.projects`), + ` FROM projections.projects2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -263,18 +263,18 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting`+ - ` FROM projections.projects`, + `SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting`+ + ` FROM projections.projects2`, nil, nil, ), @@ -292,18 +292,18 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting`+ - ` FROM projections.projects`), + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting`+ + ` FROM projections.projects2`), []string{ "id", "creation_date", @@ -351,18 +351,18 @@ func Test_ProjectPrepares(t *testing.T) { prepare: prepareProjectQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.projects.id,`+ - ` projections.projects.creation_date,`+ - ` projections.projects.change_date,`+ - ` projections.projects.resource_owner,`+ - ` projections.projects.state,`+ - ` projections.projects.sequence,`+ - ` projections.projects.name,`+ - ` projections.projects.project_role_assertion,`+ - ` projections.projects.project_role_check,`+ - ` projections.projects.has_project_check,`+ - ` projections.projects.private_labeling_setting`+ - ` FROM projections.projects`), + regexp.QuoteMeta(`SELECT projections.projects2.id,`+ + ` projections.projects2.creation_date,`+ + ` projections.projects2.change_date,`+ + ` projections.projects2.resource_owner,`+ + ` projections.projects2.state,`+ + ` projections.projects2.sequence,`+ + ` projections.projects2.name,`+ + ` projections.projects2.project_role_assertion,`+ + ` projections.projects2.project_role_check,`+ + ` projections.projects2.has_project_check,`+ + ` projections.projects2.private_labeling_setting`+ + ` FROM projections.projects2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/projection/action.go b/internal/query/projection/action.go index 0a7c9ea1e1..4fcf2782e3 100644 --- a/internal/query/projection/action.go +++ b/internal/query/projection/action.go @@ -12,7 +12,7 @@ import ( ) const ( - ActionTable = "projections.actions" + ActionTable = "projections.actions2" ActionIDCol = "id" ActionCreationDateCol = "creation_date" ActionChangeDateCol = "change_date" @@ -49,7 +49,7 @@ func newActionProjection(ctx context.Context, config crdb.StatementHandlerConfig crdb.NewColumn(ActionAllowedToFailCol, crdb.ColumnTypeBool, crdb.Default(false)), }, crdb.NewPrimaryKey(ActionInstanceIDCol, ActionIDCol), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{ActionResourceOwnerCol})), + crdb.WithIndex(crdb.NewIndex("actions_ro_idx", []string{ActionResourceOwnerCol})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) diff --git a/internal/query/projection/action_test.go b/internal/query/projection/action_test.go index 5148dd300d..7ae8e018f2 100644 --- a/internal/query/projection/action_test.go +++ b/internal/query/projection/action_test.go @@ -40,7 +40,7 @@ func TestActionProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.actions (id, creation_date, change_date, resource_owner, instance_id, sequence, name, script, timeout, allowed_to_fail, action_state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", + expectedStmt: "INSERT INTO projections.actions2 (id, creation_date, change_date, resource_owner, instance_id, sequence, name, script, timeout, allowed_to_fail, action_state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -77,7 +77,7 @@ func TestActionProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.actions SET (change_date, sequence, name, script) = ($1, $2, $3, $4) WHERE (id = $5)", + expectedStmt: "UPDATE projections.actions2 SET (change_date, sequence, name, script) = ($1, $2, $3, $4) WHERE (id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -108,7 +108,7 @@ func TestActionProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.actions SET (change_date, sequence, action_state) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.actions2 SET (change_date, sequence, action_state) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -138,7 +138,7 @@ func TestActionProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.actions SET (change_date, sequence, action_state) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.actions2 SET (change_date, sequence, action_state) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -168,7 +168,7 @@ func TestActionProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.actions WHERE (id = $1)", + expectedStmt: "DELETE FROM projections.actions2 WHERE (id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/app.go b/internal/query/projection/app.go index 12a8f24ae2..af85ce1109 100644 --- a/internal/query/projection/app.go +++ b/internal/query/projection/app.go @@ -3,8 +3,7 @@ package projection import ( "context" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -14,7 +13,7 @@ import ( ) const ( - AppProjectionTable = "projections.apps" + AppProjectionTable = "projections.apps2" AppAPITable = AppProjectionTable + "_" + appAPITableSuffix AppOIDCTable = AppProjectionTable + "_" + appOIDCTableSuffix @@ -76,9 +75,9 @@ func newAppProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(AppColumnState, crdb.ColumnTypeEnum), crdb.NewColumn(AppColumnSequence, crdb.ColumnTypeInt64), }, - crdb.NewPrimaryKey(AppColumnID, AppColumnInstanceID), - crdb.WithIndex(crdb.NewIndex("project_id_idx", []string{AppColumnProjectID})), - crdb.WithConstraint(crdb.NewConstraint("id_unique", []string{AppColumnID})), + crdb.NewPrimaryKey(AppColumnInstanceID, AppColumnID), + crdb.WithIndex(crdb.NewIndex("app_project_id_idx", []string{AppColumnProjectID})), + crdb.WithConstraint(crdb.NewConstraint("app_id_unique", []string{AppColumnID})), ), crdb.NewSuffixedTable([]*crdb.Column{ crdb.NewColumn(AppAPIConfigColumnAppID, crdb.ColumnTypeText), @@ -87,15 +86,15 @@ func newAppProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(AppAPIConfigColumnClientSecret, crdb.ColumnTypeJSONB, crdb.Nullable()), crdb.NewColumn(AppAPIConfigColumnAuthMethod, crdb.ColumnTypeEnum), }, - crdb.NewPrimaryKey(AppAPIConfigColumnAppID, AppAPIConfigColumnInstanceID), + crdb.NewPrimaryKey(AppAPIConfigColumnInstanceID, AppAPIConfigColumnAppID), appAPITableSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_api_ref_apps")), - crdb.WithIndex(crdb.NewIndex("client_id_idx", []string{AppAPIConfigColumnClientID})), + crdb.WithIndex(crdb.NewIndex("api_client_id_idx", []string{AppAPIConfigColumnClientID})), ), crdb.NewSuffixedTable([]*crdb.Column{ crdb.NewColumn(AppOIDCConfigColumnAppID, crdb.ColumnTypeText), crdb.NewColumn(AppOIDCConfigColumnInstanceID, crdb.ColumnTypeText), - crdb.NewColumn(AppOIDCConfigColumnVersion, crdb.ColumnTypeText), + crdb.NewColumn(AppOIDCConfigColumnVersion, crdb.ColumnTypeEnum), crdb.NewColumn(AppOIDCConfigColumnClientID, crdb.ColumnTypeText), crdb.NewColumn(AppOIDCConfigColumnClientSecret, crdb.ColumnTypeJSONB, crdb.Nullable()), crdb.NewColumn(AppOIDCConfigColumnRedirectUris, crdb.ColumnTypeTextArray, crdb.Nullable()), @@ -112,10 +111,10 @@ func newAppProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(AppOIDCConfigColumnClockSkew, crdb.ColumnTypeInt64, crdb.Default(0)), crdb.NewColumn(AppOIDCConfigColumnAdditionalOrigins, crdb.ColumnTypeTextArray, crdb.Nullable()), }, - crdb.NewPrimaryKey(AppOIDCConfigColumnAppID, AppOIDCConfigColumnInstanceID), + crdb.NewPrimaryKey(AppOIDCConfigColumnInstanceID, AppOIDCConfigColumnAppID), appOIDCTableSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_oidc_ref_apps")), - crdb.WithIndex(crdb.NewIndex("client_id_idx", []string{AppOIDCConfigColumnClientID})), + crdb.WithIndex(crdb.NewIndex("oidc_client_id_idx", []string{AppOIDCConfigColumnClientID})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) @@ -401,19 +400,19 @@ func (p *appProjection) reduceOIDCConfigAdded(event eventstore.Event) (*handler. handler.NewCol(AppOIDCConfigColumnVersion, e.Version), handler.NewCol(AppOIDCConfigColumnClientID, e.ClientID), handler.NewCol(AppOIDCConfigColumnClientSecret, e.ClientSecret), - handler.NewCol(AppOIDCConfigColumnRedirectUris, pq.StringArray(e.RedirectUris)), - handler.NewCol(AppOIDCConfigColumnResponseTypes, pq.Array(e.ResponseTypes)), - handler.NewCol(AppOIDCConfigColumnGrantTypes, pq.Array(e.GrantTypes)), + handler.NewCol(AppOIDCConfigColumnRedirectUris, database.StringArray(e.RedirectUris)), + handler.NewCol(AppOIDCConfigColumnResponseTypes, database.EnumArray[domain.OIDCResponseType](e.ResponseTypes)), + handler.NewCol(AppOIDCConfigColumnGrantTypes, database.EnumArray[domain.OIDCGrantType](e.GrantTypes)), handler.NewCol(AppOIDCConfigColumnApplicationType, e.ApplicationType), handler.NewCol(AppOIDCConfigColumnAuthMethodType, e.AuthMethodType), - handler.NewCol(AppOIDCConfigColumnPostLogoutRedirectUris, pq.StringArray(e.PostLogoutRedirectUris)), + handler.NewCol(AppOIDCConfigColumnPostLogoutRedirectUris, database.StringArray(e.PostLogoutRedirectUris)), handler.NewCol(AppOIDCConfigColumnDevMode, e.DevMode), handler.NewCol(AppOIDCConfigColumnAccessTokenType, e.AccessTokenType), handler.NewCol(AppOIDCConfigColumnAccessTokenRoleAssertion, e.AccessTokenRoleAssertion), handler.NewCol(AppOIDCConfigColumnIDTokenRoleAssertion, e.IDTokenRoleAssertion), handler.NewCol(AppOIDCConfigColumnIDTokenUserinfoAssertion, e.IDTokenUserinfoAssertion), handler.NewCol(AppOIDCConfigColumnClockSkew, e.ClockSkew), - handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, pq.StringArray(e.AdditionalOrigins)), + handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(e.AdditionalOrigins)), }, crdb.WithTableSuffix(appOIDCTableSuffix), ), @@ -441,13 +440,13 @@ func (p *appProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle cols = append(cols, handler.NewCol(AppOIDCConfigColumnVersion, *e.Version)) } if e.RedirectUris != nil { - cols = append(cols, handler.NewCol(AppOIDCConfigColumnRedirectUris, pq.StringArray(*e.RedirectUris))) + cols = append(cols, handler.NewCol(AppOIDCConfigColumnRedirectUris, database.StringArray(*e.RedirectUris))) } if e.ResponseTypes != nil { - cols = append(cols, handler.NewCol(AppOIDCConfigColumnResponseTypes, pq.Array(*e.ResponseTypes))) + cols = append(cols, handler.NewCol(AppOIDCConfigColumnResponseTypes, database.EnumArray[domain.OIDCResponseType](*e.ResponseTypes))) } if e.GrantTypes != nil { - cols = append(cols, handler.NewCol(AppOIDCConfigColumnGrantTypes, pq.Array(*e.GrantTypes))) + cols = append(cols, handler.NewCol(AppOIDCConfigColumnGrantTypes, database.EnumArray[domain.OIDCGrantType](*e.GrantTypes))) } if e.ApplicationType != nil { cols = append(cols, handler.NewCol(AppOIDCConfigColumnApplicationType, *e.ApplicationType)) @@ -456,7 +455,7 @@ func (p *appProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle cols = append(cols, handler.NewCol(AppOIDCConfigColumnAuthMethodType, *e.AuthMethodType)) } if e.PostLogoutRedirectUris != nil { - cols = append(cols, handler.NewCol(AppOIDCConfigColumnPostLogoutRedirectUris, pq.StringArray(*e.PostLogoutRedirectUris))) + cols = append(cols, handler.NewCol(AppOIDCConfigColumnPostLogoutRedirectUris, database.StringArray(*e.PostLogoutRedirectUris))) } if e.DevMode != nil { cols = append(cols, handler.NewCol(AppOIDCConfigColumnDevMode, *e.DevMode)) @@ -477,7 +476,7 @@ func (p *appProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle cols = append(cols, handler.NewCol(AppOIDCConfigColumnClockSkew, *e.ClockSkew)) } if e.AdditionalOrigins != nil { - cols = append(cols, handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, pq.StringArray(*e.AdditionalOrigins))) + cols = append(cols, handler.NewCol(AppOIDCConfigColumnAdditionalOrigins, database.StringArray(*e.AdditionalOrigins))) } if len(cols) == 0 { diff --git a/internal/query/projection/app_test.go b/internal/query/projection/app_test.go index f4eb9048d0..ed5d4db707 100644 --- a/internal/query/projection/app_test.go +++ b/internal/query/projection/app_test.go @@ -4,8 +4,7 @@ import ( "testing" "time" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -45,7 +44,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.apps (id, name, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.apps2 (id, name, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "app-id", "my-app", @@ -83,7 +82,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps SET (name, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.apps2 SET (name, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ "my-app", anyArg{}, @@ -116,7 +115,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.apps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.AppStateInactive, anyArg{}, @@ -149,7 +148,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.apps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.AppStateActive, anyArg{}, @@ -182,7 +181,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.apps WHERE (id = $1) AND (instance_id = $2)", + expectedStmt: "DELETE FROM projections.apps2 WHERE (id = $1) AND (instance_id = $2)", expectedArgs: []interface{}{ "app-id", "instance-id", @@ -210,7 +209,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.apps WHERE (project_id = $1) AND (instance_id = $2)", + expectedStmt: "DELETE FROM projections.apps2 WHERE (project_id = $1) AND (instance_id = $2)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -243,7 +242,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.apps_api_configs (app_id, instance_id, client_id, client_secret, auth_method) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.apps2_api_configs (app_id, instance_id, client_id, client_secret, auth_method) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "app-id", "instance-id", @@ -253,7 +252,7 @@ func TestAppProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -288,7 +287,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps_api_configs SET (client_secret, auth_method) = ($1, $2) WHERE (app_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2_api_configs SET (client_secret, auth_method) = ($1, $2) WHERE (app_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, domain.APIAuthMethodTypePrivateKeyJWT, @@ -297,7 +296,7 @@ func TestAppProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -352,7 +351,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps_api_configs SET (client_secret) = ($1) WHERE (app_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.apps2_api_configs SET (client_secret) = ($1) WHERE (app_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ anyArg{}, "app-id", @@ -360,7 +359,7 @@ func TestAppProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -408,30 +407,30 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.apps_oidc_configs (app_id, instance_id, version, client_id, client_secret, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)", + expectedStmt: "INSERT INTO projections.apps2_oidc_configs (app_id, instance_id, version, client_id, client_secret, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)", expectedArgs: []interface{}{ "app-id", "instance-id", domain.OIDCVersionV1, "client-id", anyArg{}, - pq.StringArray{"redirect.one.ch", "redirect.two.ch"}, - pq.Array([]domain.OIDCResponseType{1, 2}), - pq.Array([]domain.OIDCGrantType{1, 2}), + database.StringArray{"redirect.one.ch", "redirect.two.ch"}, + database.EnumArray[domain.OIDCResponseType]{1, 2}, + database.EnumArray[domain.OIDCGrantType]{1, 2}, domain.OIDCApplicationTypeNative, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"logout.one.ch", "logout.two.ch"}, + database.StringArray{"logout.one.ch", "logout.two.ch"}, true, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Microsecond, - pq.StringArray{"origin.one.ch", "origin.two.ch"}, + database.StringArray{"origin.one.ch", "origin.two.ch"}, }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -477,28 +476,28 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps_oidc_configs SET (version, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) WHERE (app_id = $15) AND (instance_id = $16)", + expectedStmt: "UPDATE projections.apps2_oidc_configs SET (version, redirect_uris, response_types, grant_types, application_type, auth_method_type, post_logout_redirect_uris, is_dev_mode, access_token_type, access_token_role_assertion, id_token_role_assertion, id_token_userinfo_assertion, clock_skew, additional_origins) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) WHERE (app_id = $15) AND (instance_id = $16)", expectedArgs: []interface{}{ domain.OIDCVersionV1, - pq.StringArray{"redirect.one.ch", "redirect.two.ch"}, - pq.Array([]domain.OIDCResponseType{1, 2}), - pq.Array([]domain.OIDCGrantType{1, 2}), + database.StringArray{"redirect.one.ch", "redirect.two.ch"}, + database.EnumArray[domain.OIDCResponseType]{1, 2}, + database.EnumArray[domain.OIDCGrantType]{1, 2}, domain.OIDCApplicationTypeNative, domain.OIDCAuthMethodTypeNone, - pq.StringArray{"logout.one.ch", "logout.two.ch"}, + database.StringArray{"logout.one.ch", "logout.two.ch"}, true, domain.OIDCTokenTypeJWT, true, true, true, 1 * time.Microsecond, - pq.StringArray{"origin.one.ch", "origin.two.ch"}, + database.StringArray{"origin.one.ch", "origin.two.ch"}, "app-id", "instance-id", }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -553,7 +552,7 @@ func TestAppProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.apps_oidc_configs SET (client_secret) = ($1) WHERE (app_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.apps2_oidc_configs SET (client_secret) = ($1) WHERE (app_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ anyArg{}, "app-id", @@ -561,7 +560,7 @@ func TestAppProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.apps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.apps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), diff --git a/internal/query/projection/custom_text.go b/internal/query/projection/custom_text.go index 1a71de7351..d22f3e54ea 100644 --- a/internal/query/projection/custom_text.go +++ b/internal/query/projection/custom_text.go @@ -109,6 +109,13 @@ func (p *customTextProjection) reduceSet(event eventstore.Event) (*handler.State } return crdb.NewUpsertStatement( &customTextEvent, + []handler.Column{ + handler.NewCol(CustomTextInstanceIDCol, nil), + handler.NewCol(CustomTextAggregateIDCol, nil), + handler.NewCol(CustomTextTemplateCol, nil), + handler.NewCol(CustomTextKeyCol, nil), + handler.NewCol(CustomTextLanguageCol, nil), + }, []handler.Column{ handler.NewCol(CustomTextAggregateIDCol, customTextEvent.Aggregate().ID), handler.NewCol(CustomTextInstanceIDCol, customTextEvent.Aggregate().InstanceID), diff --git a/internal/query/projection/custom_text_test.go b/internal/query/projection/custom_text_test.go index 9721e88f08..c770f3ea09 100644 --- a/internal/query/projection/custom_text_test.go +++ b/internal/query/projection/custom_text_test.go @@ -44,7 +44,7 @@ func TestCustomTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.custom_texts (aggregate_id, instance_id, creation_date, change_date, sequence, is_default, template, language, key, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.custom_texts (aggregate_id, instance_id, creation_date, change_date, sequence, is_default, template, language, key, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, aggregate_id, template, key, language) DO UPDATE SET (creation_date, change_date, sequence, is_default, text) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.is_default, EXCLUDED.text)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -152,7 +152,7 @@ func TestCustomTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.custom_texts (aggregate_id, instance_id, creation_date, change_date, sequence, is_default, template, language, key, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.custom_texts (aggregate_id, instance_id, creation_date, change_date, sequence, is_default, template, language, key, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, aggregate_id, template, key, language) DO UPDATE SET (creation_date, change_date, sequence, is_default, text) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.is_default, EXCLUDED.text)", expectedArgs: []interface{}{ "agg-id", "instance-id", diff --git a/internal/query/projection/failed_events.go b/internal/query/projection/failed_events.go deleted file mode 100644 index 9a3c751139..0000000000 --- a/internal/query/projection/failed_events.go +++ /dev/null @@ -1,8 +0,0 @@ -package projection - -const ( - FailedEventsColumnProjectionName = "projection_name" - FailedEventsColumnFailedSequence = "failed_sequence" - FailedEventsColumnFailureCount = "failure_count" - FailedEventsColumnError = "error" -) diff --git a/internal/query/projection/idp.go b/internal/query/projection/idp.go index 889afb57ba..d1e687d0c7 100644 --- a/internal/query/projection/idp.go +++ b/internal/query/projection/idp.go @@ -3,8 +3,7 @@ package projection import ( "context" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -16,7 +15,7 @@ import ( ) const ( - IDPTable = "projections.idps" + IDPTable = "projections.idps2" IDPOIDCTable = IDPTable + "_" + IDPOIDCSuffix IDPJWTTable = IDPTable + "_" + IDPJWTSuffix @@ -78,9 +77,9 @@ func newIDPProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(IDPAutoRegisterCol, crdb.ColumnTypeBool, crdb.Default(false)), crdb.NewColumn(IDPTypeCol, crdb.ColumnTypeEnum, crdb.Nullable()), }, - crdb.NewPrimaryKey(IDPIDCol, IDPInstanceIDCol), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{IDPResourceOwnerCol})), - crdb.WithConstraint(crdb.NewConstraint("id_unique", []string{IDPIDCol})), + crdb.NewPrimaryKey(IDPInstanceIDCol, IDPIDCol), + crdb.WithIndex(crdb.NewIndex("idp_ro_idx", []string{IDPResourceOwnerCol})), + crdb.WithConstraint(crdb.NewConstraint("idp_id_unique", []string{IDPIDCol})), ), crdb.NewSuffixedTable([]*crdb.Column{ crdb.NewColumn(OIDCConfigIDPIDCol, crdb.ColumnTypeText), @@ -94,7 +93,7 @@ func newIDPProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(OIDCConfigAuthorizationEndpointCol, crdb.ColumnTypeText, crdb.Nullable()), crdb.NewColumn(OIDCConfigTokenEndpointCol, crdb.ColumnTypeText, crdb.Nullable()), }, - crdb.NewPrimaryKey(OIDCConfigIDPIDCol, OIDCConfigInstanceIDCol), + crdb.NewPrimaryKey(OIDCConfigInstanceIDCol, OIDCConfigIDPIDCol), IDPOIDCSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_oidc_ref_idp")), ), @@ -106,7 +105,7 @@ func newIDPProjection(ctx context.Context, config crdb.StatementHandlerConfig) * crdb.NewColumn(JWTConfigHeaderNameCol, crdb.ColumnTypeText, crdb.Nullable()), crdb.NewColumn(JWTConfigEndpointCol, crdb.ColumnTypeText, crdb.Nullable()), }, - crdb.NewPrimaryKey(JWTConfigIDPIDCol, JWTConfigInstanceIDCol), + crdb.NewPrimaryKey(JWTConfigInstanceIDCol, JWTConfigIDPIDCol), IDPJWTSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_jwt_ref_idp")), ), @@ -374,7 +373,7 @@ func (p *idpProjection) reduceOIDCConfigAdded(event eventstore.Event) (*handler. handler.NewCol(OIDCConfigClientIDCol, idpEvent.ClientID), handler.NewCol(OIDCConfigClientSecretCol, idpEvent.ClientSecret), handler.NewCol(OIDCConfigIssuerCol, idpEvent.Issuer), - handler.NewCol(OIDCConfigScopesCol, pq.StringArray(idpEvent.Scopes)), + handler.NewCol(OIDCConfigScopesCol, database.StringArray(idpEvent.Scopes)), handler.NewCol(OIDCConfigDisplayNameMappingCol, idpEvent.IDPDisplayNameMapping), handler.NewCol(OIDCConfigUsernameMappingCol, idpEvent.UserNameMapping), handler.NewCol(OIDCConfigAuthorizationEndpointCol, idpEvent.AuthorizationEndpoint), @@ -414,7 +413,7 @@ func (p *idpProjection) reduceOIDCConfigChanged(event eventstore.Event) (*handle cols = append(cols, handler.NewCol(OIDCConfigTokenEndpointCol, *idpEvent.TokenEndpoint)) } if idpEvent.Scopes != nil { - cols = append(cols, handler.NewCol(OIDCConfigScopesCol, pq.StringArray(idpEvent.Scopes))) + cols = append(cols, handler.NewCol(OIDCConfigScopesCol, database.StringArray(idpEvent.Scopes))) } if idpEvent.IDPDisplayNameMapping != nil { cols = append(cols, handler.NewCol(OIDCConfigDisplayNameMappingCol, *idpEvent.IDPDisplayNameMapping)) diff --git a/internal/query/projection/idp_login_policy_link.go b/internal/query/projection/idp_login_policy_link.go index 17bdf6eae8..9d0dfce299 100644 --- a/internal/query/projection/idp_login_policy_link.go +++ b/internal/query/projection/idp_login_policy_link.go @@ -14,7 +14,7 @@ import ( ) const ( - IDPLoginPolicyLinkTable = "projections.idp_login_policy_links" + IDPLoginPolicyLinkTable = "projections.idp_login_policy_links2" IDPLoginPolicyLinkIDPIDCol = "idp_id" IDPLoginPolicyLinkAggregateIDCol = "aggregate_id" @@ -46,7 +46,7 @@ func newIDPLoginPolicyLinkProjection(ctx context.Context, config crdb.StatementH crdb.NewColumn(IDPLoginPolicyLinkProviderTypeCol, crdb.ColumnTypeText), }, crdb.NewPrimaryKey(IDPLoginPolicyLinkInstanceIDCol, IDPLoginPolicyLinkAggregateIDCol, IDPLoginPolicyLinkIDPIDCol), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{IDPLoginPolicyLinkResourceOwnerCol})), + crdb.WithIndex(crdb.NewIndex("link_ro_idx", []string{IDPLoginPolicyLinkResourceOwnerCol})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) diff --git a/internal/query/projection/idp_login_policy_link_test.go b/internal/query/projection/idp_login_policy_link_test.go index 2172d5f6a9..d668dccecb 100644 --- a/internal/query/projection/idp_login_policy_link_test.go +++ b/internal/query/projection/idp_login_policy_link_test.go @@ -43,7 +43,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.idp_login_policy_links (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, instance_id, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.idp_login_policy_links2 (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, instance_id, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -80,7 +80,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (aggregate_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -111,7 +111,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (aggregate_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -142,7 +142,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.idp_login_policy_links (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, instance_id, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.idp_login_policy_links2 (idp_id, aggregate_id, creation_date, change_date, sequence, resource_owner, instance_id, provider_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -179,7 +179,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (aggregate_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -210,7 +210,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (aggregate_id = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (aggregate_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -238,7 +238,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (resource_owner = $1)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (resource_owner = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -267,7 +267,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (resource_owner = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (resource_owner = $2)", expectedArgs: []interface{}{ "idp-config-id", "ro-id", @@ -297,7 +297,7 @@ func TestIDPLoginPolicyLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_login_policy_links WHERE (idp_id = $1) AND (resource_owner = $2)", + expectedStmt: "DELETE FROM projections.idp_login_policy_links2 WHERE (idp_id = $1) AND (resource_owner = $2)", expectedArgs: []interface{}{ "idp-config-id", "ro-id", diff --git a/internal/query/projection/idp_test.go b/internal/query/projection/idp_test.go index a4b6b4a627..e1266f80ac 100644 --- a/internal/query/projection/idp_test.go +++ b/internal/query/projection/idp_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -48,7 +47,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.idps (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, styling_type, auto_register, owner_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", + expectedStmt: "INSERT INTO projections.idps2 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, styling_type, auto_register, owner_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ "idp-config-id", anyArg{}, @@ -90,7 +89,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (name, styling_type, auto_register, change_date, sequence) = ($1, $2, $3, $4, $5) WHERE (id = $6) AND (instance_id = $7)", + expectedStmt: "UPDATE projections.idps2 SET (name, styling_type, auto_register, change_date, sequence) = ($1, $2, $3, $4, $5) WHERE (id = $6) AND (instance_id = $7)", expectedArgs: []interface{}{ "custom-zitadel-instance", domain.IDPConfigStylingTypeGoogle, @@ -125,7 +124,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.IDPConfigStateInactive, anyArg{}, @@ -158,7 +157,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.IDPConfigStateActive, anyArg{}, @@ -191,7 +190,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idps WHERE (id = $1) AND (instance_id = $2)", + expectedStmt: "DELETE FROM projections.idps2 WHERE (id = $1) AND (instance_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", @@ -233,7 +232,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -243,14 +242,14 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.idps_oidc_config (idp_id, instance_id, client_id, client_secret, issuer, scopes, display_name_mapping, username_mapping, authorization_endpoint, token_endpoint) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.idps2_oidc_config (idp_id, instance_id, client_id, client_secret, issuer, scopes, display_name_mapping, username_mapping, authorization_endpoint, token_endpoint) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", "client-id", anyArg{}, "issuer", - pq.StringArray{"profile"}, + database.StringArray{"profile"}, domain.OIDCMappingFieldUnspecified, domain.OIDCMappingFieldPreferredLoginName, "https://api.zitadel.ch/authorize", @@ -293,7 +292,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -302,14 +301,14 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.idps_oidc_config SET (client_id, client_secret, issuer, authorization_endpoint, token_endpoint, scopes, display_name_mapping, username_mapping) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (idp_id = $9) AND (instance_id = $10)", + expectedStmt: "UPDATE projections.idps2_oidc_config SET (client_id, client_secret, issuer, authorization_endpoint, token_endpoint, scopes, display_name_mapping, username_mapping) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (idp_id = $9) AND (instance_id = $10)", expectedArgs: []interface{}{ "client-id", anyArg{}, "issuer", "https://api.zitadel.ch/authorize", "https://api.zitadel.ch/token", - pq.StringArray{"profile"}, + database.StringArray{"profile"}, domain.OIDCMappingFieldUnspecified, domain.OIDCMappingFieldPreferredLoginName, "idp-config-id", @@ -364,7 +363,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -374,7 +373,7 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.idps_jwt_config (idp_id, instance_id, endpoint, issuer, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)", + expectedStmt: "INSERT INTO projections.idps2_jwt_config (idp_id, instance_id, endpoint, issuer, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", @@ -412,7 +411,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -421,7 +420,7 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.idps_jwt_config SET (endpoint, issuer, keys_endpoint, header_name) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)", + expectedStmt: "UPDATE projections.idps2_jwt_config SET (endpoint, issuer, keys_endpoint, header_name) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)", expectedArgs: []interface{}{ "https://api.zitadel.ch/jwt", "issuer", @@ -479,7 +478,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.idps (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, styling_type, auto_register, owner_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", + expectedStmt: "INSERT INTO projections.idps2 (id, creation_date, change_date, sequence, resource_owner, instance_id, state, name, styling_type, auto_register, owner_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ "idp-config-id", anyArg{}, @@ -521,7 +520,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (name, styling_type, auto_register, change_date, sequence) = ($1, $2, $3, $4, $5) WHERE (id = $6) AND (instance_id = $7)", + expectedStmt: "UPDATE projections.idps2 SET (name, styling_type, auto_register, change_date, sequence) = ($1, $2, $3, $4, $5) WHERE (id = $6) AND (instance_id = $7)", expectedArgs: []interface{}{ "custom-zitadel-instance", domain.IDPConfigStylingTypeGoogle, @@ -556,7 +555,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.IDPConfigStateInactive, anyArg{}, @@ -589,7 +588,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (state, change_date, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ domain.IDPConfigStateActive, anyArg{}, @@ -622,7 +621,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idps WHERE (id = $1) AND (instance_id = $2)", + expectedStmt: "DELETE FROM projections.idps2 WHERE (id = $1) AND (instance_id = $2)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", @@ -664,7 +663,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -674,14 +673,14 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.idps_oidc_config (idp_id, instance_id, client_id, client_secret, issuer, scopes, display_name_mapping, username_mapping, authorization_endpoint, token_endpoint) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.idps2_oidc_config (idp_id, instance_id, client_id, client_secret, issuer, scopes, display_name_mapping, username_mapping, authorization_endpoint, token_endpoint) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", "client-id", anyArg{}, "issuer", - pq.StringArray{"profile"}, + database.StringArray{"profile"}, domain.OIDCMappingFieldUnspecified, domain.OIDCMappingFieldPreferredLoginName, "https://api.zitadel.ch/authorize", @@ -724,7 +723,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -733,14 +732,14 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.idps_oidc_config SET (client_id, client_secret, issuer, authorization_endpoint, token_endpoint, scopes, display_name_mapping, username_mapping) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (idp_id = $9) AND (instance_id = $10)", + expectedStmt: "UPDATE projections.idps2_oidc_config SET (client_id, client_secret, issuer, authorization_endpoint, token_endpoint, scopes, display_name_mapping, username_mapping) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (idp_id = $9) AND (instance_id = $10)", expectedArgs: []interface{}{ "client-id", anyArg{}, "issuer", "https://api.zitadel.ch/authorize", "https://api.zitadel.ch/token", - pq.StringArray{"profile"}, + database.StringArray{"profile"}, domain.OIDCMappingFieldUnspecified, domain.OIDCMappingFieldPreferredLoginName, "idp-config-id", @@ -795,7 +794,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence, type) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -805,7 +804,7 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.idps_jwt_config (idp_id, instance_id, endpoint, issuer, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)", + expectedStmt: "INSERT INTO projections.idps2_jwt_config (idp_id, instance_id, endpoint, issuer, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)", expectedArgs: []interface{}{ "idp-config-id", "instance-id", @@ -843,7 +842,7 @@ func TestIDPProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.idps SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.idps2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -852,7 +851,7 @@ func TestIDPProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.idps_jwt_config SET (endpoint, issuer, keys_endpoint, header_name) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)", + expectedStmt: "UPDATE projections.idps2_jwt_config SET (endpoint, issuer, keys_endpoint, header_name) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)", expectedArgs: []interface{}{ "https://api.zitadel.ch/jwt", "issuer", diff --git a/internal/query/projection/idp_user_link.go b/internal/query/projection/idp_user_link.go index d6e8dd2b06..cf71362d3f 100644 --- a/internal/query/projection/idp_user_link.go +++ b/internal/query/projection/idp_user_link.go @@ -13,7 +13,7 @@ import ( ) const ( - IDPUserLinkTable = "projections.idp_user_links" + IDPUserLinkTable = "projections.idp_user_links2" IDPUserLinkIDPIDCol = "idp_id" IDPUserLinkUserIDCol = "user_id" IDPUserLinkExternalUserIDCol = "external_user_id" @@ -46,7 +46,7 @@ func newIDPUserLinkProjection(ctx context.Context, config crdb.StatementHandlerC crdb.NewColumn(IDPUserLinkDisplayNameCol, crdb.ColumnTypeText), }, crdb.NewPrimaryKey(IDPUserLinkInstanceIDCol, IDPUserLinkIDPIDCol, IDPUserLinkExternalUserIDCol), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{IDPUserLinkUserIDCol})), + crdb.WithIndex(crdb.NewIndex("idp_user_idx", []string{IDPUserLinkUserIDCol})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) diff --git a/internal/query/projection/idp_user_link_test.go b/internal/query/projection/idp_user_link_test.go index 02ad44f9d6..59c74902b2 100644 --- a/internal/query/projection/idp_user_link_test.go +++ b/internal/query/projection/idp_user_link_test.go @@ -44,7 +44,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.idp_user_links (idp_id, user_id, external_user_id, creation_date, change_date, sequence, resource_owner, instance_id, display_name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.idp_user_links2 (idp_id, user_id, external_user_id, creation_date, change_date, sequence, resource_owner, instance_id, display_name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -82,7 +82,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (idp_id = $1) AND (user_id = $2) AND (external_user_id = $3)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (idp_id = $1) AND (user_id = $2) AND (external_user_id = $3)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -114,7 +114,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (idp_id = $1) AND (user_id = $2) AND (external_user_id = $3)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (idp_id = $1) AND (user_id = $2) AND (external_user_id = $3)", expectedArgs: []interface{}{ "idp-config-id", "agg-id", @@ -143,7 +143,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (resource_owner = $1)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (resource_owner = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -170,7 +170,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -199,7 +199,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (idp_id = $1) AND (resource_owner = $2)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (idp_id = $1) AND (resource_owner = $2)", expectedArgs: []interface{}{ "idp-config-id", "ro-id", @@ -229,7 +229,7 @@ func TestIDPUserLinkProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.idp_user_links WHERE (idp_id = $1) AND (resource_owner = $2)", + expectedStmt: "DELETE FROM projections.idp_user_links2 WHERE (idp_id = $1) AND (resource_owner = $2)", expectedArgs: []interface{}{ "idp-config-id", "ro-id", diff --git a/internal/query/projection/instance_member.go b/internal/query/projection/instance_member.go index 365e05201d..6a908d340f 100644 --- a/internal/query/projection/instance_member.go +++ b/internal/query/projection/instance_member.go @@ -12,7 +12,7 @@ import ( ) const ( - InstanceMemberProjectionTable = "projections.instance_members" + InstanceMemberProjectionTable = "projections.instance_members2" InstanceMemberIAMIDCol = "id" ) @@ -29,7 +29,7 @@ func newInstanceMemberProjection(ctx context.Context, config crdb.StatementHandl crdb.NewTable( append(memberColumns, crdb.NewColumn(InstanceColumnID, crdb.ColumnTypeText)), crdb.NewPrimaryKey(MemberInstanceID, InstanceColumnID, MemberUserIDCol), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{MemberUserIDCol})), + crdb.WithIndex(crdb.NewIndex("inst_memb_user_idx", []string{MemberUserIDCol})), ), ) diff --git a/internal/query/projection/instance_member_test.go b/internal/query/projection/instance_member_test.go index 27fe24358a..b835ac6f73 100644 --- a/internal/query/projection/instance_member_test.go +++ b/internal/query/projection/instance_member_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "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" @@ -44,10 +43,10 @@ func TestInstanceMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.instance_members (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.instance_members2 (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "user-id", - pq.StringArray{"role"}, + database.StringArray{"role"}, anyArg{}, anyArg{}, uint64(15), @@ -81,9 +80,9 @@ func TestInstanceMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.instance_members SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4)", + expectedStmt: "UPDATE projections.instance_members2 SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4)", expectedArgs: []interface{}{ - pq.StringArray{"role", "changed"}, + database.StringArray{"role", "changed"}, anyArg{}, uint64(15), "user-id", @@ -113,7 +112,7 @@ func TestInstanceMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.instance_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.instance_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "user-id", }, @@ -142,7 +141,7 @@ func TestInstanceMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.instance_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.instance_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "user-id", }, @@ -169,7 +168,7 @@ func TestInstanceMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.instance_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.instance_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/key.go b/internal/query/projection/key.go index 29ec2a2ea9..50cb513ebc 100644 --- a/internal/query/projection/key.go +++ b/internal/query/projection/key.go @@ -13,7 +13,7 @@ import ( ) const ( - KeyProjectionTable = "projections.keys" + KeyProjectionTable = "projections.keys2" KeyPrivateTable = KeyProjectionTable + "_" + privateKeyTableSuffix KeyPublicTable = KeyProjectionTable + "_" + publicKeyTableSuffix @@ -59,8 +59,8 @@ func newKeyProjection(ctx context.Context, config crdb.StatementHandlerConfig, k crdb.NewColumn(KeyColumnAlgorithm, crdb.ColumnTypeText, crdb.Default("")), crdb.NewColumn(KeyColumnUse, crdb.ColumnTypeEnum, crdb.Default(0)), }, - crdb.NewPrimaryKey(KeyColumnID, KeyColumnInstanceID), - crdb.WithConstraint(crdb.NewConstraint("id_unique", []string{KeyColumnID})), + crdb.NewPrimaryKey(KeyColumnInstanceID, KeyColumnID), + crdb.WithConstraint(crdb.NewConstraint("key_id_unique", []string{KeyColumnID})), ), crdb.NewSuffixedTable([]*crdb.Column{ crdb.NewColumn(KeyPrivateColumnID, crdb.ColumnTypeText), @@ -68,7 +68,7 @@ func newKeyProjection(ctx context.Context, config crdb.StatementHandlerConfig, k crdb.NewColumn(KeyPrivateColumnExpiry, crdb.ColumnTypeTimestamp), crdb.NewColumn(KeyPrivateColumnKey, crdb.ColumnTypeJSONB), }, - crdb.NewPrimaryKey(KeyPrivateColumnID, KeyPrivateColumnInstanceID), + crdb.NewPrimaryKey(KeyPrivateColumnInstanceID, KeyPrivateColumnID), privateKeyTableSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_private_ref_keys")), ), @@ -78,7 +78,7 @@ func newKeyProjection(ctx context.Context, config crdb.StatementHandlerConfig, k crdb.NewColumn(KeyPublicColumnExpiry, crdb.ColumnTypeTimestamp), crdb.NewColumn(KeyPublicColumnKey, crdb.ColumnTypeBytes), }, - crdb.NewPrimaryKey(KeyPublicColumnID, KeyPublicColumnInstanceID), + crdb.NewPrimaryKey(KeyPublicColumnInstanceID, KeyPublicColumnID), publicKeyTableSuffix, crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_public_ref_keys")), ), diff --git a/internal/query/projection/key_test.go b/internal/query/projection/key_test.go index 94461f49d7..0745dafd32 100644 --- a/internal/query/projection/key_test.go +++ b/internal/query/projection/key_test.go @@ -43,7 +43,7 @@ func TestKeyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.keys (id, creation_date, change_date, resource_owner, instance_id, sequence, algorithm, use) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.keys2 (id, creation_date, change_date, resource_owner, instance_id, sequence, algorithm, use) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -56,7 +56,7 @@ func TestKeyProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.keys_private (id, instance_id, expiry, key) VALUES ($1, $2, $3, $4)", + expectedStmt: "INSERT INTO projections.keys2_private (id, instance_id, expiry, key) VALUES ($1, $2, $3, $4)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -70,7 +70,7 @@ func TestKeyProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.keys_public (id, instance_id, expiry, key) VALUES ($1, $2, $3, $4)", + expectedStmt: "INSERT INTO projections.keys2_public (id, instance_id, expiry, key) VALUES ($1, $2, $3, $4)", expectedArgs: []interface{}{ "agg-id", "instance-id", diff --git a/internal/query/projection/label_policy.go b/internal/query/projection/label_policy.go index 3bd2f61d8f..0c443e9546 100644 --- a/internal/query/projection/label_policy.go +++ b/internal/query/projection/label_policy.go @@ -332,6 +332,11 @@ func (p *labelPolicyProjection) reduceActivated(event eventstore.Event) (*handle } return crdb.NewCopyStatement( event, + []handler.Column{ + handler.NewCol(LabelPolicyInstanceIDCol, nil), + handler.NewCol(LabelPolicyIDCol, nil), + handler.NewCol(LabelPolicyStateCol, nil), + }, []handler.Column{ handler.NewCol(LabelPolicyChangeDateCol, event.CreationDate()), handler.NewCol(LabelPolicySequenceCol, event.Sequence()), diff --git a/internal/query/projection/label_policy_test.go b/internal/query/projection/label_policy_test.go index d40cd3d1f1..68cfbf4710 100644 --- a/internal/query/projection/label_policy_test.go +++ b/internal/query/projection/label_policy_test.go @@ -146,7 +146,7 @@ func TestLabelPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.label_policies (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5 AND copy_table.instance_id = $6", + expectedStmt: "INSERT INTO projections.label_policies (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5 AND copy_table.instance_id = $6 ON CONFLICT (instance_id, id, state) DO UPDATE SET (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) = ($1, $2, $3, EXCLUDED.creation_date, EXCLUDED.resource_owner, EXCLUDED.instance_id, EXCLUDED.id, EXCLUDED.is_default, EXCLUDED.hide_login_name_suffix, EXCLUDED.font_url, EXCLUDED.watermark_disabled, EXCLUDED.should_error_popup, EXCLUDED.light_primary_color, EXCLUDED.light_warn_color, EXCLUDED.light_background_color, EXCLUDED.light_font_color, EXCLUDED.light_logo_url, EXCLUDED.light_icon_url, EXCLUDED.dark_primary_color, EXCLUDED.dark_warn_color, EXCLUDED.dark_background_color, EXCLUDED.dark_font_color, EXCLUDED.dark_logo_url, EXCLUDED.dark_icon_url)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -609,7 +609,7 @@ func TestLabelPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.label_policies (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5 AND copy_table.instance_id = $6", + expectedStmt: "INSERT INTO projections.label_policies (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) SELECT $1, $2, $3, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url FROM projections.label_policies AS copy_table WHERE copy_table.id = $4 AND copy_table.state = $5 AND copy_table.instance_id = $6 ON CONFLICT (instance_id, id, state) DO UPDATE SET (change_date, sequence, state, creation_date, resource_owner, instance_id, id, is_default, hide_login_name_suffix, font_url, watermark_disabled, should_error_popup, light_primary_color, light_warn_color, light_background_color, light_font_color, light_logo_url, light_icon_url, dark_primary_color, dark_warn_color, dark_background_color, dark_font_color, dark_logo_url, dark_icon_url) = ($1, $2, $3, EXCLUDED.creation_date, EXCLUDED.resource_owner, EXCLUDED.instance_id, EXCLUDED.id, EXCLUDED.is_default, EXCLUDED.hide_login_name_suffix, EXCLUDED.font_url, EXCLUDED.watermark_disabled, EXCLUDED.should_error_popup, EXCLUDED.light_primary_color, EXCLUDED.light_warn_color, EXCLUDED.light_background_color, EXCLUDED.light_font_color, EXCLUDED.light_logo_url, EXCLUDED.light_icon_url, EXCLUDED.dark_primary_color, EXCLUDED.dark_warn_color, EXCLUDED.dark_background_color, EXCLUDED.dark_font_color, EXCLUDED.dark_logo_url, EXCLUDED.dark_icon_url)", expectedArgs: []interface{}{ anyArg{}, uint64(15), diff --git a/internal/query/projection/login_name.go b/internal/query/projection/login_name.go index 4930181b06..772e23d587 100644 --- a/internal/query/projection/login_name.go +++ b/internal/query/projection/login_name.go @@ -44,8 +44,8 @@ const ( var ( viewStmt = fmt.Sprintf("SELECT"+ " user_id"+ - " , IF(%[1]s, CONCAT(%[2]s, '@', domain), %[2]s) AS login_name"+ - " , IFNULL(%[3]s, true) AS %[3]s"+ + " , (CASE WHEN %[1]s THEN CONCAT(%[2]s, '@', domain) ELSE %[2]s END) AS login_name"+ + " , COALESCE(%[3]s, true) AS %[3]s"+ " , %[4]s"+ " FROM ("+ " SELECT"+ @@ -62,12 +62,12 @@ var ( " , users.%[2]s"+ " , users.%[4]s"+ " , users.%[5]s"+ - " , IFNULL(policy_custom.%[1]s, policy_default.%[1]s) AS %[1]s"+ + " , COALESCE(policy_custom.%[1]s, policy_default.%[1]s) AS %[1]s"+ " FROM %[7]s users"+ " LEFT JOIN %[8]s policy_custom on policy_custom.%[9]s = users.%[5]s AND policy_custom.%[10]s = users.%[4]s"+ " LEFT JOIN %[8]s policy_default on policy_default.%[11]s = true AND policy_default.%[10]s = users.%[4]s) policy_users"+ " LEFT JOIN %[12]s domains ON policy_users.%[1]s AND policy_users.%[5]s = domains.%[13]s AND policy_users.%[10]s = domains.%[14]s"+ - ");", + ") AS login_names;", LoginNamePoliciesMustBeDomainCol, LoginNameUserUserNameCol, LoginNameDomainIsPrimaryCol, diff --git a/internal/query/projection/member.go b/internal/query/projection/member.go index d80a8d2e48..90732741bf 100644 --- a/internal/query/projection/member.go +++ b/internal/query/projection/member.go @@ -1,8 +1,7 @@ package projection import ( - "github.com/lib/pq" - + "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" @@ -57,7 +56,7 @@ func reduceMemberAdded(e member.MemberAddedEvent, opts ...reduceMemberOpt) (*han config := reduceMemberConfig{ cols: []handler.Column{ handler.NewCol(MemberUserIDCol, e.UserID), - handler.NewCol(MemberRolesCol, pq.StringArray(e.Roles)), + handler.NewCol(MemberRolesCol, database.StringArray(e.Roles)), handler.NewCol(MemberCreationDate, e.CreationDate()), handler.NewCol(MemberChangeDate, e.CreationDate()), handler.NewCol(MemberSequence, e.Sequence()), @@ -75,7 +74,7 @@ func reduceMemberAdded(e member.MemberAddedEvent, opts ...reduceMemberOpt) (*han func reduceMemberChanged(e member.MemberChangedEvent, opts ...reduceMemberOpt) (*handler.Statement, error) { config := reduceMemberConfig{ cols: []handler.Column{ - handler.NewCol(MemberRolesCol, pq.StringArray(e.Roles)), + handler.NewCol(MemberRolesCol, database.StringArray(e.Roles)), handler.NewCol(MemberChangeDate, e.CreationDate()), handler.NewCol(MemberSequence, e.Sequence()), }, diff --git a/internal/query/projection/message_text_test.go b/internal/query/projection/message_text_test.go index 34ea3ad257..f1f44842f7 100644 --- a/internal/query/projection/message_text_test.go +++ b/internal/query/projection/message_text_test.go @@ -45,7 +45,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, title) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.title)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -85,7 +85,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, pre_header) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, pre_header) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, pre_header) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.pre_header)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -125,7 +125,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, subject) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, subject) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, subject) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.subject)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -165,7 +165,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, greeting) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, greeting) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, greeting) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.greeting)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -205,7 +205,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, text) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.text)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -245,7 +245,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, button_text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, button_text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, button_text) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.button_text)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -285,7 +285,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, footer_text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, footer_text) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, footer_text) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.footer_text)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -610,7 +610,7 @@ func TestMessageTextProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.message_texts (aggregate_id, instance_id, creation_date, change_date, sequence, state, type, language, title) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (instance_id, aggregate_id, type, language) DO UPDATE SET (creation_date, change_date, sequence, state, title) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.title)", expectedArgs: []interface{}{ "agg-id", "instance-id", diff --git a/internal/query/projection/message_texts.go b/internal/query/projection/message_texts.go index a28e567059..dc0ee89e65 100644 --- a/internal/query/projection/message_texts.go +++ b/internal/query/projection/message_texts.go @@ -152,7 +152,14 @@ func (p *messageTextProjection) reduceAdded(event eventstore.Event) (*handler.St } return crdb.NewUpsertStatement( &templateEvent, - cols), nil + []handler.Column{ + handler.NewCol(MessageTextInstanceIDCol, nil), + handler.NewCol(MessageTextAggregateIDCol, nil), + handler.NewCol(MessageTextTypeCol, nil), + handler.NewCol(MessageTextLanguageCol, nil), + }, + cols, + ), nil } func (p *messageTextProjection) reduceRemoved(event eventstore.Event) (*handler.Statement, error) { diff --git a/internal/query/projection/org_member.go b/internal/query/projection/org_member.go index 5aac0f95b6..c5d3abc450 100644 --- a/internal/query/projection/org_member.go +++ b/internal/query/projection/org_member.go @@ -12,7 +12,7 @@ import ( ) const ( - OrgMemberProjectionTable = "projections.org_members" + OrgMemberProjectionTable = "projections.org_members2" OrgMemberOrgIDCol = "org_id" ) @@ -28,7 +28,7 @@ func newOrgMemberProjection(ctx context.Context, config crdb.StatementHandlerCon crdb.NewTable( append(memberColumns, crdb.NewColumn(OrgMemberOrgIDCol, crdb.ColumnTypeText)), crdb.NewPrimaryKey(MemberInstanceID, OrgMemberOrgIDCol, MemberUserIDCol), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{MemberUserIDCol})), + crdb.WithIndex(crdb.NewIndex("org_memb_user_idx", []string{MemberUserIDCol})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) diff --git a/internal/query/projection/org_member_test.go b/internal/query/projection/org_member_test.go index 1a0b7cec17..39c3a56dd1 100644 --- a/internal/query/projection/org_member_test.go +++ b/internal/query/projection/org_member_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "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" @@ -44,10 +43,10 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.org_members (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, org_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.org_members2 (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, org_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "user-id", - pq.StringArray{"role"}, + database.StringArray{"role"}, anyArg{}, anyArg{}, uint64(15), @@ -81,9 +80,9 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.org_members SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (org_id = $5)", + expectedStmt: "UPDATE projections.org_members2 SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (org_id = $5)", expectedArgs: []interface{}{ - pq.StringArray{"role", "changed"}, + database.StringArray{"role", "changed"}, anyArg{}, uint64(15), "user-id", @@ -114,7 +113,7 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.org_members WHERE (user_id = $1) AND (org_id = $2)", + expectedStmt: "DELETE FROM projections.org_members2 WHERE (user_id = $1) AND (org_id = $2)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -144,7 +143,7 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.org_members WHERE (user_id = $1) AND (org_id = $2)", + expectedStmt: "DELETE FROM projections.org_members2 WHERE (user_id = $1) AND (org_id = $2)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -172,7 +171,7 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.org_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.org_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -199,7 +198,7 @@ func TestOrgMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.org_members WHERE (org_id = $1)", + expectedStmt: "DELETE FROM projections.org_members2 WHERE (org_id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/project.go b/internal/query/projection/project.go index d24b55a3bf..d51753c1dc 100644 --- a/internal/query/projection/project.go +++ b/internal/query/projection/project.go @@ -12,7 +12,7 @@ import ( ) const ( - ProjectProjectionTable = "projections.projects" + ProjectProjectionTable = "projections.projects2" ProjectColumnID = "id" ProjectColumnCreationDate = "creation_date" @@ -52,7 +52,7 @@ func newProjectProjection(ctx context.Context, config crdb.StatementHandlerConfi crdb.NewColumn(ProjectColumnPrivateLabelingSetting, crdb.ColumnTypeEnum), }, crdb.NewPrimaryKey(ProjectColumnInstanceID, ProjectColumnID), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{ProjectColumnResourceOwner})), + crdb.WithIndex(crdb.NewIndex("project_ro_idx", []string{ProjectColumnResourceOwner})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) diff --git a/internal/query/projection/project_grant.go b/internal/query/projection/project_grant.go index 40b2945f9d..e58e52c8f9 100644 --- a/internal/query/projection/project_grant.go +++ b/internal/query/projection/project_grant.go @@ -3,8 +3,7 @@ package projection import ( "context" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -14,7 +13,7 @@ import ( ) const ( - ProjectGrantProjectionTable = "projections.project_grants" + ProjectGrantProjectionTable = "projections.project_grants2" ProjectGrantColumnGrantID = "grant_id" ProjectGrantColumnCreationDate = "creation_date" @@ -50,7 +49,7 @@ func newProjectGrantProjection(ctx context.Context, config crdb.StatementHandler crdb.NewColumn(ProjectGrantColumnRoleKeys, crdb.ColumnTypeTextArray, crdb.Nullable()), }, crdb.NewPrimaryKey(ProjectGrantColumnInstanceID, ProjectGrantColumnGrantID), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{ProjectGrantColumnResourceOwner})), + crdb.WithIndex(crdb.NewIndex("pg_ro_idx", []string{ProjectGrantColumnResourceOwner})), crdb.WithIndex(crdb.NewIndex("granted_org_idx", []string{ProjectGrantColumnGrantedOrgID})), ), ) @@ -113,7 +112,7 @@ func (p *projectGrantProjection) reduceProjectGrantAdded(event eventstore.Event) handler.NewCol(ProjectGrantColumnState, domain.ProjectGrantStateActive), handler.NewCol(ProjectGrantColumnSequence, e.Sequence()), handler.NewCol(ProjectGrantColumnGrantedOrgID, e.GrantedOrgID), - handler.NewCol(ProjectGrantColumnRoleKeys, pq.StringArray(e.RoleKeys)), + handler.NewCol(ProjectGrantColumnRoleKeys, database.StringArray(e.RoleKeys)), }, ), nil } @@ -128,7 +127,7 @@ func (p *projectGrantProjection) reduceProjectGrantChanged(event eventstore.Even []handler.Column{ handler.NewCol(ProjectColumnChangeDate, e.CreationDate()), handler.NewCol(ProjectGrantColumnSequence, e.Sequence()), - handler.NewCol(ProjectGrantColumnRoleKeys, pq.StringArray(e.RoleKeys)), + handler.NewCol(ProjectGrantColumnRoleKeys, database.StringArray(e.RoleKeys)), }, []handler.Condition{ handler.NewCond(ProjectGrantColumnGrantID, e.GrantID), @@ -147,7 +146,7 @@ func (p *projectGrantProjection) reduceProjectGrantCascadeChanged(event eventsto []handler.Column{ handler.NewCol(ProjectGrantColumnChangeDate, e.CreationDate()), handler.NewCol(ProjectGrantColumnSequence, e.Sequence()), - handler.NewCol(ProjectGrantColumnRoleKeys, pq.StringArray(e.RoleKeys)), + handler.NewCol(ProjectGrantColumnRoleKeys, database.StringArray(e.RoleKeys)), }, []handler.Condition{ handler.NewCond(ProjectGrantColumnGrantID, e.GrantID), diff --git a/internal/query/projection/project_grant_member.go b/internal/query/projection/project_grant_member.go index 27873c3b63..414455e9f6 100644 --- a/internal/query/projection/project_grant_member.go +++ b/internal/query/projection/project_grant_member.go @@ -14,7 +14,7 @@ import ( ) const ( - ProjectGrantMemberProjectionTable = "projections.project_grant_members" + ProjectGrantMemberProjectionTable = "projections.project_grant_members2" ProjectGrantMemberProjectIDCol = "project_id" ProjectGrantMemberGrantIDCol = "grant_id" ) @@ -34,7 +34,7 @@ func newProjectGrantMemberProjection(ctx context.Context, config crdb.StatementH crdb.NewColumn(ProjectGrantMemberGrantIDCol, crdb.ColumnTypeText), ), crdb.NewPrimaryKey(MemberInstanceID, ProjectGrantMemberProjectIDCol, ProjectGrantMemberGrantIDCol, MemberUserIDCol), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{MemberUserIDCol})), + crdb.WithIndex(crdb.NewIndex("proj_grant_memb_user_idx", []string{MemberUserIDCol})), ), ) diff --git a/internal/query/projection/project_grant_member_test.go b/internal/query/projection/project_grant_member_test.go index b3b4bcd826..e1ad1cebc6 100644 --- a/internal/query/projection/project_grant_member_test.go +++ b/internal/query/projection/project_grant_member_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "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" @@ -46,10 +45,10 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.project_grant_members (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, project_id, grant_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.project_grant_members2 (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, project_id, grant_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "user-id", - pq.StringArray{"role"}, + database.StringArray{"role"}, anyArg{}, anyArg{}, uint64(15), @@ -85,9 +84,9 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_grant_members SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (project_id = $5) AND (grant_id = $6)", + expectedStmt: "UPDATE projections.project_grant_members2 SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (project_id = $5) AND (grant_id = $6)", expectedArgs: []interface{}{ - pq.StringArray{"role", "changed"}, + database.StringArray{"role", "changed"}, anyArg{}, uint64(15), "user-id", @@ -120,7 +119,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (user_id = $1) AND (project_id = $2) AND (grant_id = $3)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (user_id = $1) AND (project_id = $2) AND (grant_id = $3)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -152,7 +151,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (user_id = $1) AND (project_id = $2) AND (grant_id = $3)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (user_id = $1) AND (project_id = $2) AND (grant_id = $3)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -181,7 +180,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -208,7 +207,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (resource_owner = $1)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (resource_owner = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -235,7 +234,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (project_id = $1)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (project_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -262,7 +261,7 @@ func TestProjectGrantMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grant_members WHERE (grant_id = $1) AND (project_id = $2)", + expectedStmt: "DELETE FROM projections.project_grant_members2 WHERE (grant_id = $1) AND (project_id = $2)", expectedArgs: []interface{}{ "grant-id", "agg-id", diff --git a/internal/query/projection/project_grant_test.go b/internal/query/projection/project_grant_test.go index 69ca4bbff4..8f20e96341 100644 --- a/internal/query/projection/project_grant_test.go +++ b/internal/query/projection/project_grant_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -41,7 +40,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grants WHERE (project_id = $1)", + expectedStmt: "DELETE FROM projections.project_grants2 WHERE (project_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -68,7 +67,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_grants WHERE (grant_id = $1) AND (project_id = $2)", + expectedStmt: "DELETE FROM projections.project_grants2 WHERE (grant_id = $1) AND (project_id = $2)", expectedArgs: []interface{}{ "grant-id", "agg-id", @@ -96,7 +95,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_grants SET (change_date, sequence, state) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", + expectedStmt: "UPDATE projections.project_grants2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -127,7 +126,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_grants SET (change_date, sequence, state) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", + expectedStmt: "UPDATE projections.project_grants2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -158,11 +157,11 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_grants SET (change_date, sequence, granted_role_keys) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", + expectedStmt: "UPDATE projections.project_grants2 SET (change_date, sequence, granted_role_keys) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), - pq.StringArray{"admin", "user"}, + database.StringArray{"admin", "user"}, "grant-id", "agg-id", }, @@ -189,11 +188,11 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_grants SET (change_date, sequence, granted_role_keys) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", + expectedStmt: "UPDATE projections.project_grants2 SET (change_date, sequence, granted_role_keys) = ($1, $2, $3) WHERE (grant_id = $4) AND (project_id = $5)", expectedArgs: []interface{}{ anyArg{}, uint64(15), - pq.StringArray{"admin", "user"}, + database.StringArray{"admin", "user"}, "grant-id", "agg-id", }, @@ -220,7 +219,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.project_grants (grant_id, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence, granted_org_id, granted_role_keys) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.project_grants2 (grant_id, project_id, creation_date, change_date, resource_owner, instance_id, state, sequence, granted_org_id, granted_role_keys) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "grant-id", "agg-id", @@ -231,7 +230,7 @@ func TestProjectGrantProjection_reduces(t *testing.T) { domain.ProjectGrantStateActive, uint64(15), "granted-org-id", - pq.StringArray{"admin", "user"}, + database.StringArray{"admin", "user"}, }, }, }, diff --git a/internal/query/projection/project_member.go b/internal/query/projection/project_member.go index cb2f01deef..7d532ffea8 100644 --- a/internal/query/projection/project_member.go +++ b/internal/query/projection/project_member.go @@ -14,7 +14,7 @@ import ( ) const ( - ProjectMemberProjectionTable = "projections.project_members" + ProjectMemberProjectionTable = "projections.project_members2" ProjectMemberProjectIDCol = "project_id" ) @@ -32,7 +32,7 @@ func newProjectMemberProjection(ctx context.Context, config crdb.StatementHandle crdb.NewColumn(ProjectMemberProjectIDCol, crdb.ColumnTypeText), ), crdb.NewPrimaryKey(MemberInstanceID, ProjectMemberProjectIDCol, MemberUserIDCol), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{MemberUserIDCol})), + crdb.WithIndex(crdb.NewIndex("proj_memb_user_idx", []string{MemberUserIDCol})), ), ) diff --git a/internal/query/projection/project_member_test.go b/internal/query/projection/project_member_test.go index 665014a7e3..fa03108988 100644 --- a/internal/query/projection/project_member_test.go +++ b/internal/query/projection/project_member_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "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" @@ -45,10 +44,10 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.project_members (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, project_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.project_members2 (user_id, roles, creation_date, change_date, sequence, resource_owner, instance_id, project_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", expectedArgs: []interface{}{ "user-id", - pq.StringArray{"role"}, + database.StringArray{"role"}, anyArg{}, anyArg{}, uint64(15), @@ -82,9 +81,9 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.project_members SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (project_id = $5)", + expectedStmt: "UPDATE projections.project_members2 SET (roles, change_date, sequence) = ($1, $2, $3) WHERE (user_id = $4) AND (project_id = $5)", expectedArgs: []interface{}{ - pq.StringArray{"role", "changed"}, + database.StringArray{"role", "changed"}, anyArg{}, uint64(15), "user-id", @@ -115,7 +114,7 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_members WHERE (user_id = $1) AND (project_id = $2)", + expectedStmt: "DELETE FROM projections.project_members2 WHERE (user_id = $1) AND (project_id = $2)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -145,7 +144,7 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_members WHERE (user_id = $1) AND (project_id = $2)", + expectedStmt: "DELETE FROM projections.project_members2 WHERE (user_id = $1) AND (project_id = $2)", expectedArgs: []interface{}{ "user-id", "agg-id", @@ -173,7 +172,7 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_members WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.project_members2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -200,7 +199,7 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_members WHERE (resource_owner = $1)", + expectedStmt: "DELETE FROM projections.project_members2 WHERE (resource_owner = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -227,7 +226,7 @@ func TestProjectMemberProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.project_members WHERE (project_id = $1)", + expectedStmt: "DELETE FROM projections.project_members2 WHERE (project_id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/project_test.go b/internal/query/projection/project_test.go index 6f5e9d9c68..e10d591a5a 100644 --- a/internal/query/projection/project_test.go +++ b/internal/query/projection/project_test.go @@ -39,7 +39,7 @@ func TestProjectProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.projects WHERE (id = $1)", + expectedStmt: "DELETE FROM projections.projects2 WHERE (id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -66,7 +66,7 @@ func TestProjectProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.projects SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.projects2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -96,7 +96,7 @@ func TestProjectProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.projects SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.projects2 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -126,7 +126,7 @@ func TestProjectProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.projects SET (change_date, sequence, name, project_role_assertion, project_role_check, has_project_check, private_labeling_setting) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8)", + expectedStmt: "UPDATE projections.projects2 SET (change_date, sequence, name, project_role_assertion, project_role_check, has_project_check, private_labeling_setting) = ($1, $2, $3, $4, $5, $6, $7) WHERE (id = $8)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -178,7 +178,7 @@ func TestProjectProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.projects (id, creation_date, change_date, resource_owner, instance_id, sequence, name, project_role_assertion, project_role_check, has_project_check, private_labeling_setting, state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)", + expectedStmt: "INSERT INTO projections.projects2 (id, creation_date, change_date, resource_owner, instance_id, sequence, name, project_role_assertion, project_role_check, has_project_check, private_labeling_setting, state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)", expectedArgs: []interface{}{ "agg-id", anyArg{}, diff --git a/internal/query/projection/secret_generator.go b/internal/query/projection/secret_generator.go index cdcfdbff86..610374f977 100644 --- a/internal/query/projection/secret_generator.go +++ b/internal/query/projection/secret_generator.go @@ -11,7 +11,7 @@ import ( ) const ( - SecretGeneratorProjectionTable = "projections.secret_generators" + SecretGeneratorProjectionTable = "projections.secret_generators2" SecretGeneratorColumnGeneratorType = "generator_type" SecretGeneratorColumnAggregateID = "aggregate_id" @@ -38,7 +38,7 @@ func newSecretGeneratorProjection(ctx context.Context, config crdb.StatementHand config.Reducers = p.reducers() config.InitCheck = crdb.NewTableCheck( crdb.NewTable([]*crdb.Column{ - crdb.NewColumn(SecretGeneratorColumnGeneratorType, crdb.ColumnTypeText), + crdb.NewColumn(SecretGeneratorColumnGeneratorType, crdb.ColumnTypeEnum), crdb.NewColumn(SecretGeneratorColumnAggregateID, crdb.ColumnTypeText), crdb.NewColumn(SecretGeneratorColumnCreationDate, crdb.ColumnTypeTimestamp), crdb.NewColumn(SecretGeneratorColumnChangeDate, crdb.ColumnTypeTimestamp), diff --git a/internal/query/projection/secret_generator_test.go b/internal/query/projection/secret_generator_test.go index 347aef392b..1dddb7b6fd 100644 --- a/internal/query/projection/secret_generator_test.go +++ b/internal/query/projection/secret_generator_test.go @@ -40,7 +40,7 @@ func TestSecretGeneratorProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.secret_generators WHERE (aggregate_id = $1) AND (generator_type = $2)", + expectedStmt: "DELETE FROM projections.secret_generators2 WHERE (aggregate_id = $1) AND (generator_type = $2)", expectedArgs: []interface{}{ "agg-id", domain.SecretGeneratorTypeInitCode, @@ -68,7 +68,7 @@ func TestSecretGeneratorProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.secret_generators SET (change_date, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (aggregate_id = $9) AND (generator_type = $10)", + expectedStmt: "UPDATE projections.secret_generators2 SET (change_date, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (aggregate_id = $9) AND (generator_type = $10)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -104,7 +104,7 @@ func TestSecretGeneratorProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.secret_generators (aggregate_id, generator_type, creation_date, change_date, resource_owner, instance_id, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", + expectedStmt: "INSERT INTO projections.secret_generators2 (aggregate_id, generator_type, creation_date, change_date, resource_owner, instance_id, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", expectedArgs: []interface{}{ "agg-id", domain.SecretGeneratorTypeInitCode, diff --git a/internal/query/projection/user.go b/internal/query/projection/user.go index 4aacd26b7e..9d1c72c615 100644 --- a/internal/query/projection/user.go +++ b/internal/query/projection/user.go @@ -17,7 +17,7 @@ type userProjection struct { } const ( - UserTable = "projections.users2" + UserTable = "projections.users3" UserHumanTable = UserTable + "_" + UserHumanSuffix UserMachineTable = UserTable + "_" + UserMachineSuffix UserNotifyTable = UserTable + "_" + UserNotifySuffix @@ -89,8 +89,8 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig) }, crdb.NewPrimaryKey(UserIDCol, UserInstanceIDCol), crdb.WithIndex(crdb.NewIndex("username_idx", []string{UserUsernameCol})), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{UserResourceOwnerCol})), - crdb.WithConstraint(crdb.NewConstraint("id_unique", []string{UserIDCol})), + crdb.WithIndex(crdb.NewIndex("user_ro_idx", []string{UserResourceOwnerCol})), + crdb.WithConstraint(crdb.NewConstraint("user_id_unique", []string{UserIDCol})), ), crdb.NewSuffixedTable([]*crdb.Column{ crdb.NewColumn(HumanUserIDCol, crdb.ColumnTypeText), @@ -709,6 +709,10 @@ func (p *userProjection) reduceHumanPhoneVerified(event eventstore.Event) (*hand crdb.WithTableSuffix(UserHumanSuffix), ), crdb.AddCopyStatement( + []handler.Column{ + handler.NewCol(NotifyUserIDCol, nil), + handler.NewCol(NotifyInstanceIDCol, nil), + }, []handler.Column{ handler.NewCol(NotifyUserIDCol, nil), handler.NewCol(NotifyInstanceIDCol, nil), @@ -799,6 +803,10 @@ func (p *userProjection) reduceHumanEmailVerified(event eventstore.Event) (*hand crdb.WithTableSuffix(UserHumanSuffix), ), crdb.AddCopyStatement( + []handler.Column{ + handler.NewCol(NotifyUserIDCol, nil), + handler.NewCol(NotifyInstanceIDCol, nil), + }, []handler.Column{ handler.NewCol(NotifyUserIDCol, nil), handler.NewCol(NotifyInstanceIDCol, nil), diff --git a/internal/query/projection/user_auth_method.go b/internal/query/projection/user_auth_method.go index 7e69734e73..cf337236df 100644 --- a/internal/query/projection/user_auth_method.go +++ b/internal/query/projection/user_auth_method.go @@ -12,7 +12,7 @@ import ( ) const ( - UserAuthMethodTable = "projections.user_auth_methods" + UserAuthMethodTable = "projections.user_auth_methods2" UserAuthMethodUserIDCol = "user_id" UserAuthMethodTypeCol = "method_type" @@ -48,7 +48,7 @@ func newUserAuthMethodProjection(ctx context.Context, config crdb.StatementHandl crdb.NewColumn(UserAuthMethodNameCol, crdb.ColumnTypeText), }, crdb.NewPrimaryKey(UserAuthMethodInstanceIDCol, UserAuthMethodUserIDCol, UserAuthMethodTypeCol, UserAuthMethodTokenIDCol), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{UserAuthMethodResourceOwnerCol})), + crdb.WithIndex(crdb.NewIndex("auth_meth_ro_idx", []string{UserAuthMethodResourceOwnerCol})), ), ) p.StatementHandler = crdb.NewStatementHandler(ctx, config) @@ -119,6 +119,12 @@ func (p *userAuthMethodProjection) reduceInitAuthMethod(event eventstore.Event) return crdb.NewUpsertStatement( event, + []handler.Column{ + handler.NewCol(UserAuthMethodInstanceIDCol, nil), + handler.NewCol(UserAuthMethodUserIDCol, nil), + handler.NewCol(UserAuthMethodTypeCol, nil), + handler.NewCol(UserAuthMethodTokenIDCol, nil), + }, []handler.Column{ handler.NewCol(UserAuthMethodTokenIDCol, tokenID), handler.NewCol(UserAuthMethodCreationDateCol, event.CreationDate()), diff --git a/internal/query/projection/user_auth_method_test.go b/internal/query/projection/user_auth_method_test.go index c5055b65c6..baad8d5bf8 100644 --- a/internal/query/projection/user_auth_method_test.go +++ b/internal/query/projection/user_auth_method_test.go @@ -41,7 +41,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.user_auth_methods (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.user_auth_methods2 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)", expectedArgs: []interface{}{ "token-id", anyArg{}, @@ -79,7 +79,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.user_auth_methods (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.user_auth_methods2 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)", expectedArgs: []interface{}{ "token-id", anyArg{}, @@ -116,7 +116,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.user_auth_methods (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.user_auth_methods2 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)", expectedArgs: []interface{}{ "", anyArg{}, @@ -155,7 +155,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_auth_methods SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", + expectedStmt: "UPDATE projections.user_auth_methods2 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -192,7 +192,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_auth_methods SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", + expectedStmt: "UPDATE projections.user_auth_methods2 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -227,7 +227,7 @@ func TestUserAuthMethodProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_auth_methods SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", + expectedStmt: "UPDATE projections.user_auth_methods2 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8)", expectedArgs: []interface{}{ anyArg{}, uint64(15), diff --git a/internal/query/projection/user_grant.go b/internal/query/projection/user_grant.go index 4a54bae0f5..546eb11a93 100644 --- a/internal/query/projection/user_grant.go +++ b/internal/query/projection/user_grant.go @@ -3,8 +3,7 @@ package projection import ( "context" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -16,7 +15,7 @@ import ( ) const ( - UserGrantProjectionTable = "projections.user_grants" + UserGrantProjectionTable = "projections.user_grants2" UserGrantID = "id" UserGrantCreationDate = "creation_date" @@ -54,8 +53,8 @@ func newUserGrantProjection(ctx context.Context, config crdb.StatementHandlerCon crdb.NewColumn(UserGrantRoles, crdb.ColumnTypeTextArray, crdb.Nullable()), }, crdb.NewPrimaryKey(UserGrantInstanceID, UserGrantID), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{UserGrantUserID})), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{UserGrantResourceOwner})), + crdb.WithIndex(crdb.NewIndex("user_grant_user_idx", []string{UserGrantUserID})), + crdb.WithIndex(crdb.NewIndex("user_grant_ro_idx", []string{UserGrantResourceOwner})), ), ) @@ -152,14 +151,14 @@ func (p *userGrantProjection) reduceAdded(event eventstore.Event) (*handler.Stat handler.NewCol(UserGrantUserID, e.UserID), handler.NewCol(UserGrantProjectID, e.ProjectID), handler.NewCol(UserGrantGrantID, e.ProjectGrantID), - handler.NewCol(UserGrantRoles, pq.StringArray(e.RoleKeys)), + handler.NewCol(UserGrantRoles, database.StringArray(e.RoleKeys)), handler.NewCol(UserGrantState, domain.UserGrantStateActive), }, ), nil } func (p *userGrantProjection) reduceChanged(event eventstore.Event) (*handler.Statement, error) { - var roles pq.StringArray + var roles database.StringArray switch e := event.(type) { case *usergrant.UserGrantChangedEvent: @@ -309,7 +308,7 @@ func (p *userGrantProjection) reduceProjectGrantChanged(event eventstore.Event) return crdb.NewUpdateStatement( event, []handler.Column{ - crdb.NewArrayIntersectCol(UserGrantRoles, pq.StringArray(keys)), + crdb.NewArrayIntersectCol(UserGrantRoles, database.StringArray(keys)), }, []handler.Condition{ handler.NewCond(UserGrantGrantID, grantID), diff --git a/internal/query/projection/user_grant_test.go b/internal/query/projection/user_grant_test.go index dc76075868..38ac4c4751 100644 --- a/internal/query/projection/user_grant_test.go +++ b/internal/query/projection/user_grant_test.go @@ -3,8 +3,7 @@ package projection import ( "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" @@ -47,7 +46,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.user_grants (id, resource_owner, instance_id, creation_date, change_date, sequence, user_id, project_id, grant_id, roles, state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", + expectedStmt: "INSERT INTO projections.user_grants2 (id, resource_owner, instance_id, creation_date, change_date, sequence, user_id, project_id, grant_id, roles, state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ "agg-id", "ro-id", @@ -58,7 +57,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { "user-id", "project-id", "", - pq.StringArray{"role"}, + database.StringArray{"role"}, domain.UserGrantStateActive, }, }, @@ -86,10 +85,10 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (change_date, roles, sequence) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.user_grants2 SET (change_date, roles, sequence) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, - pq.StringArray{"role"}, + database.StringArray{"role"}, uint64(15), "agg-id", }, @@ -118,10 +117,10 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (change_date, roles, sequence) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.user_grants2 SET (change_date, roles, sequence) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, - pq.StringArray{"role"}, + database.StringArray{"role"}, uint64(15), "agg-id", }, @@ -148,7 +147,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_grants WHERE (id = $1)", + expectedStmt: "DELETE FROM projections.user_grants2 WHERE (id = $1)", expectedArgs: []interface{}{ anyArg{}, }, @@ -175,7 +174,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_grants WHERE (id = $1)", + expectedStmt: "DELETE FROM projections.user_grants2 WHERE (id = $1)", expectedArgs: []interface{}{ anyArg{}, }, @@ -202,7 +201,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.user_grants2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, domain.UserGrantStateInactive, @@ -232,7 +231,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4)", + expectedStmt: "UPDATE projections.user_grants2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4)", expectedArgs: []interface{}{ anyArg{}, domain.UserGrantStateActive, @@ -262,7 +261,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_grants WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.user_grants2 WHERE (user_id = $1)", expectedArgs: []interface{}{ anyArg{}, }, @@ -289,7 +288,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_grants WHERE (project_id = $1)", + expectedStmt: "DELETE FROM projections.user_grants2 WHERE (project_id = $1)", expectedArgs: []interface{}{ anyArg{}, }, @@ -316,7 +315,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_grants WHERE (grant_id = $1)", + expectedStmt: "DELETE FROM projections.user_grants2 WHERE (grant_id = $1)", expectedArgs: []interface{}{ "grantID", }, @@ -343,7 +342,7 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (roles) = (array_remove(roles, $1)) WHERE (project_id = $2)", + expectedStmt: "UPDATE projections.user_grants2 SET (roles) = (array_remove(roles, $1)) WHERE (project_id = $2)", expectedArgs: []interface{}{ "key", "agg-id", @@ -371,9 +370,9 @@ func TestUserGrantProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.user_grants SET (roles) = (SELECT ARRAY( SELECT UNNEST(roles) INTERSECT SELECT UNNEST ($1::STRING[]))) WHERE (grant_id = $2)", + expectedStmt: "UPDATE projections.user_grants2 SET (roles) = (SELECT ARRAY( SELECT UNNEST(roles) INTERSECT SELECT UNNEST ($1::TEXT[]))) WHERE (grant_id = $2)", expectedArgs: []interface{}{ - pq.StringArray{"key"}, + database.StringArray{"key"}, "grantID", }, }, diff --git a/internal/query/projection/user_metadata.go b/internal/query/projection/user_metadata.go index 593006dcd3..5c00fbc4de 100644 --- a/internal/query/projection/user_metadata.go +++ b/internal/query/projection/user_metadata.go @@ -11,7 +11,7 @@ import ( ) const ( - UserMetadataProjectionTable = "projections.user_metadata2" + UserMetadataProjectionTable = "projections.user_metadata3" UserMetadataColumnUserID = "user_id" UserMetadataColumnCreationDate = "creation_date" @@ -43,7 +43,7 @@ func newUserMetadataProjection(ctx context.Context, config crdb.StatementHandler crdb.NewColumn(UserMetadataColumnValue, crdb.ColumnTypeBytes, crdb.Nullable()), }, crdb.NewPrimaryKey(UserMetadataColumnInstanceID, UserMetadataColumnUserID, UserMetadataColumnKey), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{UserGrantResourceOwner})), + crdb.WithIndex(crdb.NewIndex("usr_md_ro_idx", []string{UserGrantResourceOwner})), ), ) @@ -85,13 +85,18 @@ func (p *userMetadataProjection) reduceMetadataSet(event eventstore.Event) (*han return crdb.NewUpsertStatement( e, []handler.Column{ - handler.NewCol(UserMetadataColumnUserID, e.Aggregate().ID), - handler.NewCol(UserMetadataColumnResourceOwner, e.Aggregate().ResourceOwner), + handler.NewCol(UserMetadataColumnInstanceID, nil), + handler.NewCol(UserMetadataColumnUserID, nil), + handler.NewCol(UserMetadataColumnKey, e.Key), + }, + []handler.Column{ handler.NewCol(UserMetadataColumnInstanceID, e.Aggregate().InstanceID), + handler.NewCol(UserMetadataColumnUserID, e.Aggregate().ID), + handler.NewCol(UserMetadataColumnKey, e.Key), + handler.NewCol(UserMetadataColumnResourceOwner, e.Aggregate().ResourceOwner), handler.NewCol(UserMetadataColumnCreationDate, e.CreationDate()), handler.NewCol(UserMetadataColumnChangeDate, e.CreationDate()), handler.NewCol(UserMetadataColumnSequence, e.Sequence()), - handler.NewCol(UserMetadataColumnKey, e.Key), handler.NewCol(UserMetadataColumnValue, e.Value), }, ), nil diff --git a/internal/query/projection/user_metadata_test.go b/internal/query/projection/user_metadata_test.go index eda6e37495..340ac39f28 100644 --- a/internal/query/projection/user_metadata_test.go +++ b/internal/query/projection/user_metadata_test.go @@ -41,15 +41,15 @@ func TestUserMetadataProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPSERT INTO projections.user_metadata2 (user_id, resource_owner, instance_id, creation_date, change_date, sequence, key, value) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + expectedStmt: "INSERT INTO projections.user_metadata3 (instance_id, user_id, key, resource_owner, creation_date, change_date, sequence, value) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (instance_id, user_id, key) DO UPDATE SET (resource_owner, creation_date, change_date, sequence, value) = (EXCLUDED.resource_owner, EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.value)", expectedArgs: []interface{}{ - "agg-id", - "ro-id", "instance-id", + "agg-id", + "key", + "ro-id", anyArg{}, anyArg{}, uint64(15), - "key", []byte("value"), }, }, @@ -77,7 +77,7 @@ func TestUserMetadataProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_metadata2 WHERE (user_id = $1) AND (key = $2)", + expectedStmt: "DELETE FROM projections.user_metadata3 WHERE (user_id = $1) AND (key = $2)", expectedArgs: []interface{}{ "agg-id", "key", @@ -105,7 +105,7 @@ func TestUserMetadataProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_metadata2 WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.user_metadata3 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, @@ -132,7 +132,7 @@ func TestUserMetadataProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.user_metadata2 WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.user_metadata3 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/user_personal_access_token.go b/internal/query/projection/user_personal_access_token.go index 981689dc4e..737b36c44d 100644 --- a/internal/query/projection/user_personal_access_token.go +++ b/internal/query/projection/user_personal_access_token.go @@ -3,8 +3,7 @@ package projection import ( "context" - "github.com/lib/pq" - + "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" @@ -13,7 +12,7 @@ import ( ) const ( - PersonalAccessTokenProjectionTable = "projections.personal_access_tokens" + PersonalAccessTokenProjectionTable = "projections.personal_access_tokens2" PersonalAccessTokenColumnID = "id" PersonalAccessTokenColumnCreationDate = "creation_date" @@ -47,8 +46,8 @@ func newPersonalAccessTokenProjection(ctx context.Context, config crdb.Statement crdb.NewColumn(PersonalAccessTokenColumnScopes, crdb.ColumnTypeTextArray, crdb.Nullable()), }, crdb.NewPrimaryKey(PersonalAccessTokenColumnInstanceID, PersonalAccessTokenColumnID), - crdb.WithIndex(crdb.NewIndex("user_idx", []string{PersonalAccessTokenColumnUserID})), - crdb.WithIndex(crdb.NewIndex("ro_idx", []string{PersonalAccessTokenColumnResourceOwner})), + crdb.WithIndex(crdb.NewIndex("pat_user_idx", []string{PersonalAccessTokenColumnUserID})), + crdb.WithIndex(crdb.NewIndex("pat_ro_idx", []string{PersonalAccessTokenColumnResourceOwner})), ), ) @@ -94,7 +93,7 @@ func (p *personalAccessTokenProjection) reducePersonalAccessTokenAdded(event eve handler.NewCol(PersonalAccessTokenColumnSequence, e.Sequence()), handler.NewCol(PersonalAccessTokenColumnUserID, e.Aggregate().ID), handler.NewCol(PersonalAccessTokenColumnExpiration, e.Expiration), - handler.NewCol(PersonalAccessTokenColumnScopes, pq.StringArray(e.Scopes)), + handler.NewCol(PersonalAccessTokenColumnScopes, database.StringArray(e.Scopes)), }, ), nil } diff --git a/internal/query/projection/user_personal_access_token_test.go b/internal/query/projection/user_personal_access_token_test.go index a7f78fdc75..8bd215d13f 100644 --- a/internal/query/projection/user_personal_access_token_test.go +++ b/internal/query/projection/user_personal_access_token_test.go @@ -4,8 +4,7 @@ import ( "testing" "time" - "github.com/lib/pq" - + "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" @@ -41,7 +40,7 @@ func TestPersonalAccessTokenProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.personal_access_tokens (id, creation_date, change_date, resource_owner, instance_id, sequence, user_id, expiration, scopes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.personal_access_tokens2 (id, creation_date, change_date, resource_owner, instance_id, sequence, user_id, expiration, scopes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "tokenID", anyArg{}, @@ -51,7 +50,7 @@ func TestPersonalAccessTokenProjection_reduces(t *testing.T) { uint64(15), "agg-id", time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - pq.StringArray{"openid"}, + database.StringArray{"openid"}, }, }, }, @@ -76,7 +75,7 @@ func TestPersonalAccessTokenProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.personal_access_tokens WHERE (id = $1)", + expectedStmt: "DELETE FROM projections.personal_access_tokens2 WHERE (id = $1)", expectedArgs: []interface{}{ "tokenID", }, @@ -103,7 +102,7 @@ func TestPersonalAccessTokenProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.personal_access_tokens WHERE (user_id = $1)", + expectedStmt: "DELETE FROM projections.personal_access_tokens2 WHERE (user_id = $1)", expectedArgs: []interface{}{ "agg-id", }, diff --git a/internal/query/projection/user_test.go b/internal/query/projection/user_test.go index 79737feeba..8d7e0d9934 100644 --- a/internal/query/projection/user_test.go +++ b/internal/query/projection/user_test.go @@ -50,7 +50,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -64,7 +64,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -79,7 +79,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -120,7 +120,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -134,7 +134,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -149,7 +149,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -185,7 +185,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -199,7 +199,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -214,7 +214,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -255,7 +255,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -269,7 +269,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -284,7 +284,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -325,7 +325,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -339,7 +339,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -354,7 +354,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -390,7 +390,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -404,7 +404,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -419,7 +419,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -450,7 +450,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ domain.UserStateInitial, "agg-id", @@ -479,7 +479,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ domain.UserStateInitial, "agg-id", @@ -508,7 +508,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ domain.UserStateActive, "agg-id", @@ -537,7 +537,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ domain.UserStateActive, "agg-id", @@ -566,7 +566,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, domain.UserStateLocked, @@ -597,7 +597,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, domain.UserStateActive, @@ -628,7 +628,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, domain.UserStateInactive, @@ -659,7 +659,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, domain.UserStateActive, @@ -690,7 +690,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "DELETE FROM projections.users2 WHERE (id = $1) AND (instance_id = $2)", + expectedStmt: "DELETE FROM projections.users3 WHERE (id = $1) AND (instance_id = $2)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -720,7 +720,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, "username", @@ -753,7 +753,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", + expectedStmt: "UPDATE projections.users3 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)", expectedArgs: []interface{}{ anyArg{}, "id@temporary.domain", @@ -791,7 +791,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -800,7 +800,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)", + expectedStmt: "UPDATE projections.users3_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)", expectedArgs: []interface{}{ "first-name", "last-name", @@ -841,7 +841,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -850,7 +850,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)", + expectedStmt: "UPDATE projections.users3_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)", expectedArgs: []interface{}{ "first-name", "last-name", @@ -886,7 +886,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -895,7 +895,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ "+41 00 000 00 00", false, @@ -904,7 +904,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_phone) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_phone) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ &sql.NullString{String: "+41 00 000 00 00", Valid: true}, "agg-id", @@ -935,7 +935,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -944,7 +944,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ "+41 00 000 00 00", false, @@ -953,7 +953,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_phone) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_phone) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ &sql.NullString{String: "+41 00 000 00 00", Valid: true}, "agg-id", @@ -982,7 +982,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -991,7 +991,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ nil, nil, @@ -1000,7 +1000,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ nil, nil, @@ -1030,7 +1030,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1039,7 +1039,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ nil, nil, @@ -1048,7 +1048,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ nil, nil, @@ -1078,7 +1078,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1087,7 +1087,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ true, "agg-id", @@ -1095,7 +1095,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_phone) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_phone)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1123,7 +1123,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1132,7 +1132,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ true, "agg-id", @@ -1140,7 +1140,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_phone) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_phone)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1170,7 +1170,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1179,7 +1179,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ "email@zitadel.com", false, @@ -1188,7 +1188,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_email) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_email) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ &sql.NullString{String: "email@zitadel.com", Valid: true}, "agg-id", @@ -1219,7 +1219,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1228,7 +1228,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ "email@zitadel.com", false, @@ -1237,7 +1237,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_notifications SET (last_email) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_notifications SET (last_email) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ &sql.NullString{String: "email@zitadel.com", Valid: true}, "agg-id", @@ -1266,7 +1266,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1275,7 +1275,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ true, "agg-id", @@ -1283,7 +1283,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_email) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_email)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1311,7 +1311,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1320,7 +1320,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ true, "agg-id", @@ -1328,7 +1328,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2", + expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_email) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_email)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1358,7 +1358,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1367,7 +1367,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ "users/agg-id/avatar", "agg-id", @@ -1396,7 +1396,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1405,7 +1405,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ nil, "agg-id", @@ -1437,7 +1437,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -1451,7 +1451,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)", + expectedStmt: "INSERT INTO projections.users3_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1485,7 +1485,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.users2 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", + expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)", expectedArgs: []interface{}{ "agg-id", anyArg{}, @@ -1499,7 +1499,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "INSERT INTO projections.users2_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)", + expectedStmt: "INSERT INTO projections.users3_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)", expectedArgs: []interface{}{ "agg-id", "instance-id", @@ -1532,7 +1532,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1541,7 +1541,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ "machine-name", "description", @@ -1573,7 +1573,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1582,7 +1582,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_machines SET (name) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_machines SET (name) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ "machine-name", "agg-id", @@ -1613,7 +1613,7 @@ func TestUserProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", + expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)", expectedArgs: []interface{}{ anyArg{}, uint64(15), @@ -1622,7 +1622,7 @@ func TestUserProjection_reduces(t *testing.T) { }, }, { - expectedStmt: "UPDATE projections.users2_machines SET (description) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", + expectedStmt: "UPDATE projections.users3_machines SET (description) = ($1) WHERE (user_id = $2) AND (instance_id = $3)", expectedArgs: []interface{}{ "description", "agg-id", diff --git a/internal/query/search_query.go b/internal/query/search_query.go index c2f2500cda..b9fe8a0272 100644 --- a/internal/query/search_query.go +++ b/internal/query/search_query.go @@ -5,7 +5,6 @@ import ( "reflect" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/domain" ) @@ -139,7 +138,7 @@ func (s *TextQuery) comp() sq.Sqlizer { case TextContainsIgnoreCase: return sq.ILike{s.Column.identifier(): "%" + s.Text + "%"} case TextListContains: - return &listContains{col: s.Column, args: []interface{}{pq.StringArray{s.Text}}} + return &listContains{col: s.Column, args: []interface{}{s.Text}} } return nil } @@ -228,7 +227,7 @@ func (s *NumberQuery) comp() sq.Sqlizer { case NumberGreater: return sq.Gt{s.Column.identifier(): s.Number} case NumberListContains: - return &listContains{col: s.Column, args: []interface{}{pq.GenericArray{s.Number}}} + return &listContains{col: s.Column, args: []interface{}{s.Number}} } return nil } @@ -379,7 +378,7 @@ func (t table) identifier() string { if t.alias == "" { return t.name } - return t.name + " as " + t.alias + return t.name + " AS " + t.alias } func (t table) isZero() bool { @@ -424,9 +423,9 @@ func join(join, from Column) string { type listContains struct { col Column - args []interface{} + args interface{} } func (q *listContains) ToSql() (string, []interface{}, error) { - return q.col.identifier() + " @> ? ", q.args, nil + return q.col.identifier() + " @> ? ", []interface{}{q.args}, nil } diff --git a/internal/query/search_query_test.go b/internal/query/search_query_test.go index 47ae03c9cf..e8f35a45d4 100644 --- a/internal/query/search_query_test.go +++ b/internal/query/search_query_test.go @@ -6,7 +6,6 @@ import ( "testing" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/domain" ) @@ -339,7 +338,7 @@ func TestTextQuery_comp(t *testing.T) { want: want{ query: &listContains{ col: testCol, - args: []interface{}{pq.StringArray{"Hurst"}}, + args: []interface{}{"Hurst"}, }, }, }, @@ -643,7 +642,7 @@ func TestNumberQuery_comp(t *testing.T) { want: want{ query: &listContains{ col: testCol, - args: []interface{}{pq.GenericArray{42}}, + args: []interface{}{42}, }, }, }, diff --git a/internal/query/secret_generator_test.go b/internal/query/secret_generator_test.go index d8b98cdd86..82d8269344 100644 --- a/internal/query/secret_generator_test.go +++ b/internal/query/secret_generator_test.go @@ -29,20 +29,20 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols,`+ + 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_generators`), + ` FROM projections.secret_generators2`), nil, nil, ), @@ -54,20 +54,20 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols,`+ + 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_generators`), + ` FROM projections.secret_generators2`), []string{ "aggregate_id", "generator_type", @@ -128,20 +128,20 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols,`+ + 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_generators`), + ` FROM projections.secret_generators2`), []string{ "aggregate_id", "generator_type", @@ -230,20 +230,20 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols,`+ + 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_generators`), + ` FROM projections.secret_generators2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { @@ -260,19 +260,19 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQueries( - `SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols`+ - ` FROM projections.secret_generators`, + `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`, nil, nil, ), @@ -290,19 +290,19 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQuery( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols`+ - ` FROM projections.secret_generators`), + 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", @@ -353,19 +353,19 @@ func Test_SecretGeneratorsPrepares(t *testing.T) { prepare: prepareSecretGeneratorQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.secret_generators.aggregate_id,`+ - ` projections.secret_generators.generator_type,`+ - ` projections.secret_generators.creation_date,`+ - ` projections.secret_generators.change_date,`+ - ` projections.secret_generators.resource_owner,`+ - ` projections.secret_generators.sequence,`+ - ` projections.secret_generators.length,`+ - ` projections.secret_generators.expiry,`+ - ` projections.secret_generators.include_lower_letters,`+ - ` projections.secret_generators.include_upper_letters,`+ - ` projections.secret_generators.include_digits,`+ - ` projections.secret_generators.include_symbols`+ - ` FROM projections.secret_generators`), + 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`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/user.go b/internal/query/user.go index be75173b78..d001a66255 100644 --- a/internal/query/user.go +++ b/internal/query/user.go @@ -7,10 +7,10 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "golang.org/x/text/language" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -30,7 +30,7 @@ type User struct { State domain.UserState Type domain.UserType Username string - LoginNames []string + LoginNames database.StringArray PreferredLoginName string Human *Human Machine *Machine @@ -99,7 +99,7 @@ type NotifyUser struct { State domain.UserState Type domain.UserType Username string - LoginNames []string + LoginNames database.StringArray PreferredLoginName string FirstName string LastName string @@ -534,7 +534,7 @@ func NewUserLoginNamesSearchQuery(value string) (SearchQuery, error) { func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*User, error)) { loginNamesQuery, loginNamesArgs, err := sq.Select( userLoginNamesUserIDCol.identifier(), - "ARRAY_AGG("+userLoginNamesNameCol.identifier()+") as "+userLoginNamesListCol.name). + "ARRAY_AGG("+userLoginNamesNameCol.identifier()+")::TEXT[] AS "+userLoginNamesListCol.name). From(userLoginNamesTable.identifier()). GroupBy(userLoginNamesUserIDCol.identifier()). Where(sq.Eq{ @@ -584,12 +584,11 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use From(userTable.identifier()). LeftJoin(join(HumanUserIDCol, UserIDCol)). LeftJoin(join(MachineUserIDCol, UserIDCol)). - LeftJoin("("+loginNamesQuery+") as "+userLoginNamesTable.alias+" on "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier(), loginNamesArgs...). - LeftJoin("("+preferredLoginNameQuery+") as "+userPreferredLoginNameTable.alias+" on "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). + LeftJoin("("+loginNamesQuery+") AS "+userLoginNamesTable.alias+" ON "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier(), loginNamesArgs...). + LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*User, error) { u := new(User) - loginNames := pq.StringArray{} preferredLoginName := sql.NullString{} humanID := sql.NullString{} @@ -618,7 +617,7 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use &u.State, &u.Type, &u.Username, - &loginNames, + &u.LoginNames, &preferredLoginName, &humanID, &firstName, @@ -644,10 +643,8 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use return nil, errors.ThrowInternal(err, "QUERY-Bgah2", "Errors.Internal") } - u.LoginNames = loginNames - if preferredLoginName.Valid { - u.PreferredLoginName = preferredLoginName.String - } + u.PreferredLoginName = preferredLoginName.String + if humanID.Valid { u.Human = &Human{ FirstName: firstName.String, @@ -835,7 +832,7 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) { func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) { loginNamesQuery, loginNamesArgs, err := sq.Select( userLoginNamesUserIDCol.identifier(), - "ARRAY_AGG("+userLoginNamesNameCol.identifier()+") as "+userLoginNamesListCol.name). + "ARRAY_AGG("+userLoginNamesNameCol.identifier()+") AS "+userLoginNamesListCol.name). From(userLoginNamesTable.identifier()). GroupBy(userLoginNamesUserIDCol.identifier()). Where(sq.Eq{ @@ -884,12 +881,12 @@ func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) From(userTable.identifier()). LeftJoin(join(HumanUserIDCol, UserIDCol)). LeftJoin(join(NotifyUserIDCol, UserIDCol)). - LeftJoin("("+loginNamesQuery+") as "+userLoginNamesTable.alias+" on "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier(), loginNamesArgs...). - LeftJoin("("+preferredLoginNameQuery+") as "+userPreferredLoginNameTable.alias+" on "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). + LeftJoin("("+loginNamesQuery+") AS "+userLoginNamesTable.alias+" ON "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier(), loginNamesArgs...). + LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*NotifyUser, error) { u := new(NotifyUser) - loginNames := pq.StringArray{} + loginNames := database.StringArray{} preferredLoginName := sql.NullString{} humanID := sql.NullString{} @@ -1009,7 +1006,7 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { loginNamesQuery, _, err := sq.Select( userLoginNamesUserIDCol.identifier(), - "ARRAY_AGG("+userLoginNamesNameCol.identifier()+") as "+userLoginNamesListCol.name). + "ARRAY_AGG("+userLoginNamesNameCol.identifier()+") AS "+userLoginNamesListCol.name). From(userLoginNamesTable.identifier()). GroupBy(userLoginNamesUserIDCol.identifier()). ToSql() @@ -1057,15 +1054,15 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { From(userTable.identifier()). LeftJoin(join(HumanUserIDCol, UserIDCol)). LeftJoin(join(MachineUserIDCol, UserIDCol)). - LeftJoin("("+loginNamesQuery+") as "+userLoginNamesTable.alias+" on "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier()). - LeftJoin("("+preferredLoginNameQuery+") as "+userPreferredLoginNameTable.alias+" on "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). + LeftJoin("("+loginNamesQuery+") AS "+userLoginNamesTable.alias+" ON "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier()). + LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...). PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) (*Users, error) { users := make([]*User, 0) var count uint64 for rows.Next() { u := new(User) - loginNames := pq.StringArray{} + loginNames := database.StringArray{} preferredLoginName := sql.NullString{} humanID := sql.NullString{} diff --git a/internal/query/user_auth_method_test.go b/internal/query/user_auth_method_test.go index 050e9dfc6f..23d6e780dc 100644 --- a/internal/query/user_auth_method_test.go +++ b/internal/query/user_auth_method_test.go @@ -27,17 +27,17 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods.token_id,`+ - ` projections.user_auth_methods.creation_date,`+ - ` projections.user_auth_methods.change_date,`+ - ` projections.user_auth_methods.resource_owner,`+ - ` projections.user_auth_methods.user_id,`+ - ` projections.user_auth_methods.sequence,`+ - ` projections.user_auth_methods.name,`+ - ` projections.user_auth_methods.state,`+ - ` projections.user_auth_methods.method_type,`+ + regexp.QuoteMeta(`SELECT projections.user_auth_methods2.token_id,`+ + ` projections.user_auth_methods2.creation_date,`+ + ` projections.user_auth_methods2.change_date,`+ + ` projections.user_auth_methods2.resource_owner,`+ + ` projections.user_auth_methods2.user_id,`+ + ` projections.user_auth_methods2.sequence,`+ + ` projections.user_auth_methods2.name,`+ + ` projections.user_auth_methods2.state,`+ + ` projections.user_auth_methods2.method_type,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods`), + ` FROM projections.user_auth_methods2`), nil, nil, ), @@ -49,17 +49,17 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods.token_id,`+ - ` projections.user_auth_methods.creation_date,`+ - ` projections.user_auth_methods.change_date,`+ - ` projections.user_auth_methods.resource_owner,`+ - ` projections.user_auth_methods.user_id,`+ - ` projections.user_auth_methods.sequence,`+ - ` projections.user_auth_methods.name,`+ - ` projections.user_auth_methods.state,`+ - ` projections.user_auth_methods.method_type,`+ + regexp.QuoteMeta(`SELECT projections.user_auth_methods2.token_id,`+ + ` projections.user_auth_methods2.creation_date,`+ + ` projections.user_auth_methods2.change_date,`+ + ` projections.user_auth_methods2.resource_owner,`+ + ` projections.user_auth_methods2.user_id,`+ + ` projections.user_auth_methods2.sequence,`+ + ` projections.user_auth_methods2.name,`+ + ` projections.user_auth_methods2.state,`+ + ` projections.user_auth_methods2.method_type,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods`), + ` FROM projections.user_auth_methods2`), []string{ "token_id", "creation_date", @@ -111,17 +111,17 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueries( - regexp.QuoteMeta(`SELECT projections.user_auth_methods.token_id,`+ - ` projections.user_auth_methods.creation_date,`+ - ` projections.user_auth_methods.change_date,`+ - ` projections.user_auth_methods.resource_owner,`+ - ` projections.user_auth_methods.user_id,`+ - ` projections.user_auth_methods.sequence,`+ - ` projections.user_auth_methods.name,`+ - ` projections.user_auth_methods.state,`+ - ` projections.user_auth_methods.method_type,`+ + regexp.QuoteMeta(`SELECT projections.user_auth_methods2.token_id,`+ + ` projections.user_auth_methods2.creation_date,`+ + ` projections.user_auth_methods2.change_date,`+ + ` projections.user_auth_methods2.resource_owner,`+ + ` projections.user_auth_methods2.user_id,`+ + ` projections.user_auth_methods2.sequence,`+ + ` projections.user_auth_methods2.name,`+ + ` projections.user_auth_methods2.state,`+ + ` projections.user_auth_methods2.method_type,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods`), + ` FROM projections.user_auth_methods2`), []string{ "token_id", "creation_date", @@ -195,17 +195,17 @@ func Test_UserAuthMethodPrepares(t *testing.T) { prepare: prepareUserAuthMethodsQuery, want: want{ sqlExpectations: mockQueryErr( - regexp.QuoteMeta(`SELECT projections.user_auth_methods.token_id,`+ - ` projections.user_auth_methods.creation_date,`+ - ` projections.user_auth_methods.change_date,`+ - ` projections.user_auth_methods.resource_owner,`+ - ` projections.user_auth_methods.user_id,`+ - ` projections.user_auth_methods.sequence,`+ - ` projections.user_auth_methods.name,`+ - ` projections.user_auth_methods.state,`+ - ` projections.user_auth_methods.method_type,`+ + regexp.QuoteMeta(`SELECT projections.user_auth_methods2.token_id,`+ + ` projections.user_auth_methods2.creation_date,`+ + ` projections.user_auth_methods2.change_date,`+ + ` projections.user_auth_methods2.resource_owner,`+ + ` projections.user_auth_methods2.user_id,`+ + ` projections.user_auth_methods2.sequence,`+ + ` projections.user_auth_methods2.name,`+ + ` projections.user_auth_methods2.state,`+ + ` projections.user_auth_methods2.method_type,`+ ` COUNT(*) OVER ()`+ - ` FROM projections.user_auth_methods`), + ` FROM projections.user_auth_methods2`), sql.ErrConnDone, ), err: func(err error) (error, bool) { diff --git a/internal/query/user_grant.go b/internal/query/user_grant.go index 70a2702c38..0d5568c2d9 100644 --- a/internal/query/user_grant.go +++ b/internal/query/user_grant.go @@ -7,9 +7,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" @@ -20,7 +20,7 @@ type UserGrant struct { CreationDate time.Time ChangeDate time.Time Sequence uint64 - Roles []string + Roles database.StringArray GrantID string State domain.UserGrantState @@ -281,7 +281,6 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro g := new(UserGrant) var ( - roles = pq.StringArray{} username sql.NullString firstName sql.NullString userType sql.NullInt32 @@ -304,7 +303,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro &g.ChangeDate, &g.Sequence, &g.GrantID, - &roles, + &g.Roles, &g.State, &g.UserID, @@ -332,7 +331,6 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro return nil, errors.ThrowInternal(err, "QUERY-oQPcP", "Errors.Internal") } - g.Roles = roles g.Username = username.String g.UserType = domain.UserType(userType.Int32) g.UserResourceOwner = userOwner.String @@ -396,7 +394,6 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e g := new(UserGrant) var ( - roles = pq.StringArray{} username sql.NullString userType sql.NullInt32 userOwner sql.NullString @@ -419,7 +416,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e &g.ChangeDate, &g.Sequence, &g.GrantID, - &roles, + &g.Roles, &g.State, &g.UserID, @@ -446,7 +443,6 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e return nil, err } - g.Roles = roles g.Username = username.String g.UserType = domain.UserType(userType.Int32) g.UserResourceOwner = userOwner.String diff --git a/internal/query/user_grant_test.go b/internal/query/user_grant_test.go index 9b3f24bb36..37f19512cc 100644 --- a/internal/query/user_grant_test.go +++ b/internal/query/user_grant_test.go @@ -8,42 +8,41 @@ import ( "regexp" "testing" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) var ( userGrantStmt = regexp.QuoteMeta( - "SELECT projections.user_grants.id" + - ", projections.user_grants.creation_date" + - ", projections.user_grants.change_date" + - ", projections.user_grants.sequence" + - ", projections.user_grants.grant_id" + - ", projections.user_grants.roles" + - ", projections.user_grants.state" + - ", projections.user_grants.user_id" + - ", projections.users2.username" + - ", projections.users2.type" + - ", projections.users2.resource_owner" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.display_name" + - ", projections.users2_humans.avatar_key" + + "SELECT projections.user_grants2.id" + + ", projections.user_grants2.creation_date" + + ", projections.user_grants2.change_date" + + ", projections.user_grants2.sequence" + + ", projections.user_grants2.grant_id" + + ", projections.user_grants2.roles" + + ", projections.user_grants2.state" + + ", projections.user_grants2.user_id" + + ", projections.users3.username" + + ", projections.users3.type" + + ", projections.users3.resource_owner" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.email" + + ", projections.users3_humans.display_name" + + ", projections.users3_humans.avatar_key" + ", projections.login_names.login_name" + - ", projections.user_grants.resource_owner" + + ", projections.user_grants2.resource_owner" + ", projections.orgs.name" + ", projections.orgs.primary_domain" + - ", projections.user_grants.project_id" + - ", projections.projects.name" + - " FROM projections.user_grants" + - " LEFT JOIN projections.users2 ON projections.user_grants.user_id = projections.users2.id" + - " LEFT JOIN projections.users2_humans ON projections.user_grants.user_id = projections.users2_humans.user_id" + - " LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" + - " LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" + - " LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" + + ", projections.user_grants2.project_id" + + ", projections.projects2.name" + + " FROM projections.user_grants2" + + " LEFT JOIN projections.users3 ON projections.user_grants2.user_id = projections.users3.id" + + " LEFT JOIN projections.users3_humans ON projections.user_grants2.user_id = projections.users3_humans.user_id" + + " LEFT JOIN projections.orgs ON projections.user_grants2.resource_owner = projections.orgs.id" + + " LEFT JOIN projections.projects2 ON projections.user_grants2.project_id = projections.projects2.id" + + " LEFT JOIN projections.login_names ON projections.user_grants2.user_id = projections.login_names.user_id" + " WHERE projections.login_names.is_primary = $1") userGrantCols = []string{ "id", @@ -70,35 +69,35 @@ var ( "name", //project name } userGrantsStmt = regexp.QuoteMeta( - "SELECT projections.user_grants.id" + - ", projections.user_grants.creation_date" + - ", projections.user_grants.change_date" + - ", projections.user_grants.sequence" + - ", projections.user_grants.grant_id" + - ", projections.user_grants.roles" + - ", projections.user_grants.state" + - ", projections.user_grants.user_id" + - ", projections.users2.username" + - ", projections.users2.type" + - ", projections.users2.resource_owner" + - ", projections.users2_humans.first_name" + - ", projections.users2_humans.last_name" + - ", projections.users2_humans.email" + - ", projections.users2_humans.display_name" + - ", projections.users2_humans.avatar_key" + + "SELECT projections.user_grants2.id" + + ", projections.user_grants2.creation_date" + + ", projections.user_grants2.change_date" + + ", projections.user_grants2.sequence" + + ", projections.user_grants2.grant_id" + + ", projections.user_grants2.roles" + + ", projections.user_grants2.state" + + ", projections.user_grants2.user_id" + + ", projections.users3.username" + + ", projections.users3.type" + + ", projections.users3.resource_owner" + + ", projections.users3_humans.first_name" + + ", projections.users3_humans.last_name" + + ", projections.users3_humans.email" + + ", projections.users3_humans.display_name" + + ", projections.users3_humans.avatar_key" + ", projections.login_names.login_name" + - ", projections.user_grants.resource_owner" + + ", projections.user_grants2.resource_owner" + ", projections.orgs.name" + ", projections.orgs.primary_domain" + - ", projections.user_grants.project_id" + - ", projections.projects.name" + + ", projections.user_grants2.project_id" + + ", projections.projects2.name" + ", COUNT(*) OVER ()" + - " FROM projections.user_grants" + - " LEFT JOIN projections.users2 ON projections.user_grants.user_id = projections.users2.id" + - " LEFT JOIN projections.users2_humans ON projections.user_grants.user_id = projections.users2_humans.user_id" + - " LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" + - " LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" + - " LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" + + " FROM projections.user_grants2" + + " LEFT JOIN projections.users3 ON projections.user_grants2.user_id = projections.users3.id" + + " LEFT JOIN projections.users3_humans ON projections.user_grants2.user_id = projections.users3_humans.user_id" + + " LEFT JOIN projections.orgs ON projections.user_grants2.resource_owner = projections.orgs.id" + + " LEFT JOIN projections.projects2 ON projections.user_grants2.project_id = projections.projects2.id" + + " LEFT JOIN projections.login_names ON projections.user_grants2.user_id = projections.login_names.user_id" + " WHERE projections.login_names.is_primary = $1") userGrantsCols = append( userGrantCols, @@ -148,7 +147,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -173,7 +172,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -206,7 +205,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -231,7 +230,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -264,7 +263,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -289,7 +288,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -322,7 +321,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -347,7 +346,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -380,7 +379,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -405,7 +404,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -468,7 +467,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -499,7 +498,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -535,7 +534,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -566,7 +565,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -602,7 +601,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -633,7 +632,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -669,7 +668,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -700,7 +699,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -736,7 +735,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -767,7 +766,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -803,7 +802,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -827,7 +826,7 @@ func Test_UserGrantPrepares(t *testing.T) { testNow, 20211111, "grant-id", - pq.StringArray{"role-key"}, + database.StringArray{"role-key"}, domain.UserGrantStateActive, "user-id", "username", @@ -858,7 +857,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", @@ -882,7 +881,7 @@ func Test_UserGrantPrepares(t *testing.T) { CreationDate: testNow, ChangeDate: testNow, Sequence: 20211111, - Roles: []string{"role-key"}, + Roles: database.StringArray{"role-key"}, GrantID: "grant-id", State: domain.UserGrantStateActive, UserID: "user-id", diff --git a/internal/query/user_membership.go b/internal/query/user_membership.go index 2204312367..0042f07c1b 100644 --- a/internal/query/user_membership.go +++ b/internal/query/user_membership.go @@ -6,9 +6,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/query/projection" ) @@ -20,7 +20,7 @@ type Memberships struct { type Membership struct { UserID string - Roles []string + Roles database.StringArray CreationDate time.Time ChangeDate time.Time Sequence uint64 @@ -227,14 +227,13 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, projectID = sql.NullString{} grantID = sql.NullString{} grantedOrgID = sql.NullString{} - roles = pq.StringArray{} projectName = sql.NullString{} orgName = sql.NullString{} ) err := rows.Scan( &membership.UserID, - &roles, + &membership.Roles, &membership.CreationDate, &membership.ChangeDate, &membership.Sequence, @@ -253,8 +252,6 @@ func prepareMembershipsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, return nil, err } - membership.Roles = roles - if orgID.Valid { membership.Org = &OrgMembership{ OrgID: orgID.String, @@ -305,9 +302,9 @@ func prepareOrgMember() string { OrgMemberResourceOwner.identifier(), OrgMemberInstanceID.identifier(), OrgMemberOrgID.identifier(), - "NULL::STRING AS "+membershipIAMID.name, - "NULL::STRING AS "+membershipProjectID.name, - "NULL::STRING AS "+membershipGrantID.name, + "NULL::TEXT AS "+membershipIAMID.name, + "NULL::TEXT AS "+membershipProjectID.name, + "NULL::TEXT AS "+membershipGrantID.name, ).From(orgMemberTable.identifier()).MustSql() return stmt } @@ -321,10 +318,10 @@ func prepareIAMMember() string { InstanceMemberSequence.identifier(), InstanceMemberResourceOwner.identifier(), InstanceMemberInstanceID.identifier(), - "NULL::STRING AS "+membershipOrgID.name, + "NULL::TEXT AS "+membershipOrgID.name, InstanceMemberIAMID.identifier(), - "NULL::STRING AS "+membershipProjectID.name, - "NULL::STRING AS "+membershipGrantID.name, + "NULL::TEXT AS "+membershipProjectID.name, + "NULL::TEXT AS "+membershipGrantID.name, ).From(instanceMemberTable.identifier()).MustSql() return stmt } @@ -338,10 +335,10 @@ func prepareProjectMember() string { ProjectMemberSequence.identifier(), ProjectMemberResourceOwner.identifier(), ProjectMemberInstanceID.identifier(), - "NULL::STRING AS "+membershipOrgID.name, - "NULL::STRING AS "+membershipIAMID.name, + "NULL::TEXT AS "+membershipOrgID.name, + "NULL::TEXT AS "+membershipIAMID.name, ProjectMemberProjectID.identifier(), - "NULL::STRING AS "+membershipGrantID.name, + "NULL::TEXT AS "+membershipGrantID.name, ).From(projectMemberTable.identifier()).MustSql() return stmt @@ -356,8 +353,8 @@ func prepareProjectGrantMember() string { ProjectGrantMemberSequence.identifier(), ProjectGrantMemberResourceOwner.identifier(), ProjectGrantMemberInstanceID.identifier(), - "NULL::STRING AS "+membershipOrgID.name, - "NULL::STRING AS "+membershipIAMID.name, + "NULL::TEXT AS "+membershipOrgID.name, + "NULL::TEXT AS "+membershipIAMID.name, ProjectGrantMemberProjectID.identifier(), ProjectGrantMemberGrantID.identifier(), ).From(projectGrantMemberTable.identifier()). diff --git a/internal/query/user_membership_test.go b/internal/query/user_membership_test.go index 88b74528a2..6685f2e8ee 100644 --- a/internal/query/user_membership_test.go +++ b/internal/query/user_membership_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" ) var ( @@ -23,8 +23,8 @@ var ( ", memberships.id" + ", memberships.project_id" + ", memberships.grant_id" + - ", projections.project_grants.granted_org_id" + - ", projections.projects.name" + + ", projections.project_grants2.granted_org_id" + + ", projections.projects2.name" + ", projections.orgs.name" + ", COUNT(*) OVER ()" + " FROM (" + @@ -36,10 +36,10 @@ var ( ", members.resource_owner" + ", members.instance_id" + ", members.org_id" + - ", NULL::STRING AS id" + - ", NULL::STRING AS project_id" + - ", NULL::STRING AS grant_id" + - " FROM projections.org_members as members" + + ", NULL::TEXT AS id" + + ", NULL::TEXT AS project_id" + + ", NULL::TEXT AS grant_id" + + " FROM projections.org_members2 AS members" + " UNION ALL " + "SELECT members.user_id" + ", members.roles" + @@ -48,11 +48,11 @@ var ( ", members.sequence" + ", members.resource_owner" + ", members.instance_id" + - ", NULL::STRING AS org_id" + + ", NULL::TEXT AS org_id" + ", members.id" + - ", NULL::STRING AS project_id" + - ", NULL::STRING AS grant_id" + - " FROM projections.instance_members as members" + + ", NULL::TEXT AS project_id" + + ", NULL::TEXT AS grant_id" + + " FROM projections.instance_members2 AS members" + " UNION ALL " + "SELECT members.user_id" + ", members.roles" + @@ -61,11 +61,11 @@ var ( ", members.sequence" + ", members.resource_owner" + ", members.instance_id" + - ", NULL::STRING AS org_id" + - ", NULL::STRING AS id" + + ", NULL::TEXT AS org_id" + + ", NULL::TEXT AS id" + ", members.project_id" + - ", NULL::STRING AS grant_id" + - " FROM projections.project_members as members" + + ", NULL::TEXT AS grant_id" + + " FROM projections.project_members2 AS members" + " UNION ALL " + "SELECT members.user_id" + ", members.roles" + @@ -74,15 +74,15 @@ var ( ", members.sequence" + ", members.resource_owner" + ", members.instance_id" + - ", NULL::STRING AS org_id" + - ", NULL::STRING AS id" + + ", NULL::TEXT AS org_id" + + ", NULL::TEXT AS id" + ", members.project_id" + ", members.grant_id" + - " FROM projections.project_grant_members as members" + + " FROM projections.project_grant_members2 AS members" + ") AS memberships" + - " LEFT JOIN projections.projects ON memberships.project_id = projections.projects.id" + + " LEFT JOIN projections.projects2 ON memberships.project_id = projections.projects2.id" + " LEFT JOIN projections.orgs ON memberships.org_id = projections.orgs.id" + - " LEFT JOIN projections.project_grants ON memberships.grant_id = projections.project_grants.grant_id") + " LEFT JOIN projections.project_grants2 ON memberships.grant_id = projections.project_grants2.grant_id") membershipCols = []string{ "user_id", "roles", @@ -134,7 +134,7 @@ func Test_MembershipPrepares(t *testing.T) { [][]driver.Value{ { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -157,7 +157,7 @@ func Test_MembershipPrepares(t *testing.T) { Memberships: []*Membership{ { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -177,7 +177,7 @@ func Test_MembershipPrepares(t *testing.T) { [][]driver.Value{ { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -200,7 +200,7 @@ func Test_MembershipPrepares(t *testing.T) { Memberships: []*Membership{ { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -220,7 +220,7 @@ func Test_MembershipPrepares(t *testing.T) { [][]driver.Value{ { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -243,7 +243,7 @@ func Test_MembershipPrepares(t *testing.T) { Memberships: []*Membership{ { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -263,7 +263,7 @@ func Test_MembershipPrepares(t *testing.T) { [][]driver.Value{ { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -286,7 +286,7 @@ func Test_MembershipPrepares(t *testing.T) { Memberships: []*Membership{ { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -311,7 +311,7 @@ func Test_MembershipPrepares(t *testing.T) { [][]driver.Value{ { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -326,7 +326,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -341,7 +341,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -356,7 +356,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { "user-id", - pq.StringArray{"role1", "role2"}, + database.StringArray{"role1", "role2"}, testNow, testNow, uint64(20211202), @@ -379,7 +379,7 @@ func Test_MembershipPrepares(t *testing.T) { Memberships: []*Membership{ { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -388,7 +388,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -397,7 +397,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, @@ -406,7 +406,7 @@ func Test_MembershipPrepares(t *testing.T) { }, { UserID: "user-id", - Roles: []string{"role1", "role2"}, + Roles: database.StringArray{"role1", "role2"}, CreationDate: testNow, ChangeDate: testNow, Sequence: 20211202, diff --git a/internal/query/user_metadata_test.go b/internal/query/user_metadata_test.go index c56731f0c9..969eee33ee 100644 --- a/internal/query/user_metadata_test.go +++ b/internal/query/user_metadata_test.go @@ -12,13 +12,13 @@ import ( ) var ( - userMetadataQuery = `SELECT projections.user_metadata2.creation_date,` + - ` projections.user_metadata2.change_date,` + - ` projections.user_metadata2.resource_owner,` + - ` projections.user_metadata2.sequence,` + - ` projections.user_metadata2.key,` + - ` projections.user_metadata2.value` + - ` FROM projections.user_metadata2` + userMetadataQuery = `SELECT projections.user_metadata3.creation_date,` + + ` projections.user_metadata3.change_date,` + + ` projections.user_metadata3.resource_owner,` + + ` projections.user_metadata3.sequence,` + + ` projections.user_metadata3.key,` + + ` projections.user_metadata3.value` + + ` FROM projections.user_metadata3` userMetadataCols = []string{ "creation_date", "change_date", @@ -27,14 +27,14 @@ var ( "key", "value", } - userMetadataListQuery = `SELECT projections.user_metadata2.creation_date,` + - ` projections.user_metadata2.change_date,` + - ` projections.user_metadata2.resource_owner,` + - ` projections.user_metadata2.sequence,` + - ` projections.user_metadata2.key,` + - ` projections.user_metadata2.value,` + + userMetadataListQuery = `SELECT projections.user_metadata3.creation_date,` + + ` projections.user_metadata3.change_date,` + + ` projections.user_metadata3.resource_owner,` + + ` projections.user_metadata3.sequence,` + + ` projections.user_metadata3.key,` + + ` projections.user_metadata3.value,` + ` COUNT(*) OVER ()` + - ` FROM projections.user_metadata2` + ` FROM projections.user_metadata3` userMetadataListCols = []string{ "creation_date", "change_date", diff --git a/internal/query/user_personal_access_token.go b/internal/query/user_personal_access_token.go index e25e823b2c..58aa4a9d16 100644 --- a/internal/query/user_personal_access_token.go +++ b/internal/query/user_personal_access_token.go @@ -7,9 +7,9 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/api/authz" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/query/projection" @@ -72,7 +72,7 @@ type PersonalAccessToken struct { UserID string Expiration time.Time - Scopes []string + Scopes database.StringArray } type PersonalAccessTokenSearchQueries struct { @@ -161,7 +161,6 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso From(personalAccessTokensTable.identifier()).PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*PersonalAccessToken, error) { p := new(PersonalAccessToken) - scopes := pq.StringArray{} err := row.Scan( &p.ID, &p.CreationDate, @@ -170,9 +169,8 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso &p.Sequence, &p.UserID, &p.Expiration, - &scopes, + &p.Scopes, ) - p.Scopes = scopes if err != nil { if errs.Is(err, sql.ErrNoRows) { return nil, errors.ThrowNotFound(err, "QUERY-fk2fs", "Errors.PersonalAccessToken.NotFound") @@ -200,7 +198,6 @@ func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*Per var count uint64 for rows.Next() { token := new(PersonalAccessToken) - scopes := pq.StringArray{} err := rows.Scan( &token.ID, &token.CreationDate, @@ -209,13 +206,12 @@ func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*Per &token.Sequence, &token.UserID, &token.Expiration, - &scopes, + &token.Scopes, &count, ) if err != nil { return nil, err } - token.Scopes = scopes personalAccessTokens = append(personalAccessTokens, token) } diff --git a/internal/query/user_personal_access_token_test.go b/internal/query/user_personal_access_token_test.go index 584c9be60c..72631b471b 100644 --- a/internal/query/user_personal_access_token_test.go +++ b/internal/query/user_personal_access_token_test.go @@ -9,22 +9,21 @@ import ( "testing" "time" - "github.com/lib/pq" - + "github.com/zitadel/zitadel/internal/database" errs "github.com/zitadel/zitadel/internal/errors" ) var ( personalAccessTokenStmt = regexp.QuoteMeta( - "SELECT projections.personal_access_tokens.id," + - " projections.personal_access_tokens.creation_date," + - " projections.personal_access_tokens.change_date," + - " projections.personal_access_tokens.resource_owner," + - " projections.personal_access_tokens.sequence," + - " projections.personal_access_tokens.user_id," + - " projections.personal_access_tokens.expiration," + - " projections.personal_access_tokens.scopes" + - " FROM projections.personal_access_tokens") + "SELECT projections.personal_access_tokens2.id," + + " projections.personal_access_tokens2.creation_date," + + " projections.personal_access_tokens2.change_date," + + " projections.personal_access_tokens2.resource_owner," + + " projections.personal_access_tokens2.sequence," + + " projections.personal_access_tokens2.user_id," + + " projections.personal_access_tokens2.expiration," + + " projections.personal_access_tokens2.scopes" + + " FROM projections.personal_access_tokens2") personalAccessTokenCols = []string{ "id", "creation_date", @@ -36,16 +35,16 @@ var ( "scopes", } personalAccessTokensStmt = regexp.QuoteMeta( - "SELECT projections.personal_access_tokens.id," + - " projections.personal_access_tokens.creation_date," + - " projections.personal_access_tokens.change_date," + - " projections.personal_access_tokens.resource_owner," + - " projections.personal_access_tokens.sequence," + - " projections.personal_access_tokens.user_id," + - " projections.personal_access_tokens.expiration," + - " projections.personal_access_tokens.scopes," + + "SELECT projections.personal_access_tokens2.id," + + " projections.personal_access_tokens2.creation_date," + + " projections.personal_access_tokens2.change_date," + + " projections.personal_access_tokens2.resource_owner," + + " projections.personal_access_tokens2.sequence," + + " projections.personal_access_tokens2.user_id," + + " projections.personal_access_tokens2.expiration," + + " projections.personal_access_tokens2.scopes," + " COUNT(*) OVER ()" + - " FROM projections.personal_access_tokens") + " FROM projections.personal_access_tokens2") personalAccessTokensCols = []string{ "id", "creation_date", @@ -103,7 +102,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { uint64(20211202), "user-id", time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - pq.StringArray{"openid"}, + database.StringArray{"openid"}, }, ), }, @@ -115,7 +114,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { Sequence: 20211202, UserID: "user-id", Expiration: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - Scopes: []string{"openid"}, + Scopes: database.StringArray{"openid"}, }, }, { @@ -163,7 +162,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { uint64(20211202), "user-id", time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - pq.StringArray{"openid"}, + database.StringArray{"openid"}, }, }, ), @@ -181,7 +180,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { Sequence: 20211202, UserID: "user-id", Expiration: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - Scopes: []string{"openid"}, + Scopes: database.StringArray{"openid"}, }, }, }, @@ -202,7 +201,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { uint64(20211202), "user-id", time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - pq.StringArray{"openid"}, + database.StringArray{"openid"}, }, { "token-id2", @@ -212,7 +211,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { uint64(20211202), "user-id", time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - pq.StringArray{"openid"}, + database.StringArray{"openid"}, }, }, ), @@ -230,7 +229,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { Sequence: 20211202, UserID: "user-id", Expiration: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - Scopes: []string{"openid"}, + Scopes: database.StringArray{"openid"}, }, { ID: "token-id2", @@ -240,7 +239,7 @@ func Test_PersonalAccessTokenPrepares(t *testing.T) { Sequence: 20211202, UserID: "user-id", Expiration: time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC), - Scopes: []string{"openid"}, + Scopes: database.StringArray{"openid"}, }, }, }, diff --git a/internal/query/user_test.go b/internal/query/user_test.go index 98a496511e..d9c2ac5412 100644 --- a/internal/query/user_test.go +++ b/internal/query/user_test.go @@ -9,51 +9,51 @@ import ( "testing" sq "github.com/Masterminds/squirrel" - "github.com/lib/pq" "golang.org/x/text/language" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" errs "github.com/zitadel/zitadel/internal/errors" ) var ( - userQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2.state,` + - ` projections.users2.type,` + - ` projections.users2.username,` + + userQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3.state,` + + ` projections.users3.type,` + + ` projections.users3.username,` + ` login_names.loginnames,` + ` preferred_login_name.login_name,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.first_name,` + - ` projections.users2_humans.last_name,` + - ` projections.users2_humans.nick_name,` + - ` projections.users2_humans.display_name,` + - ` projections.users2_humans.preferred_language,` + - ` projections.users2_humans.gender,` + - ` projections.users2_humans.avatar_key,` + - ` projections.users2_humans.email,` + - ` projections.users2_humans.is_email_verified,` + - ` projections.users2_humans.phone,` + - ` projections.users2_humans.is_phone_verified,` + - ` projections.users2_machines.user_id,` + - ` projections.users2_machines.name,` + - ` projections.users2_machines.description` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + - ` LEFT JOIN projections.users2_machines ON projections.users2.id = projections.users2_machines.user_id` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.first_name,` + + ` projections.users3_humans.last_name,` + + ` projections.users3_humans.nick_name,` + + ` projections.users3_humans.display_name,` + + ` projections.users3_humans.preferred_language,` + + ` projections.users3_humans.gender,` + + ` projections.users3_humans.avatar_key,` + + ` projections.users3_humans.email,` + + ` projections.users3_humans.is_email_verified,` + + ` projections.users3_humans.phone,` + + ` projections.users3_humans.is_phone_verified,` + + ` projections.users3_machines.user_id,` + + ` projections.users3_machines.name,` + + ` projections.users3_machines.description` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` + + ` LEFT JOIN projections.users3_machines ON projections.users3.id = projections.users3_machines.user_id` + ` LEFT JOIN` + - ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) as loginnames` + - ` FROM projections.login_names as login_names` + + ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name)::TEXT[] AS loginnames` + + ` FROM projections.login_names AS login_names` + ` WHERE login_names.instance_id = $1` + - ` GROUP BY login_names.user_id) as login_names` + - ` on login_names.user_id = projections.users2.id` + + ` GROUP BY login_names.user_id) AS login_names` + + ` ON login_names.user_id = projections.users3.id` + ` LEFT JOIN` + - ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names as preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) as preferred_login_name` + - ` on preferred_login_name.user_id = projections.users2.id` + ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) AS preferred_login_name` + + ` ON preferred_login_name.user_id = projections.users3.id` userCols = []string{ "id", "creation_date", @@ -83,21 +83,21 @@ var ( "name", "description", } - profileQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.first_name,` + - ` projections.users2_humans.last_name,` + - ` projections.users2_humans.nick_name,` + - ` projections.users2_humans.display_name,` + - ` projections.users2_humans.preferred_language,` + - ` projections.users2_humans.gender,` + - ` projections.users2_humans.avatar_key` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + profileQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.first_name,` + + ` projections.users3_humans.last_name,` + + ` projections.users3_humans.nick_name,` + + ` projections.users3_humans.display_name,` + + ` projections.users3_humans.preferred_language,` + + ` projections.users3_humans.gender,` + + ` projections.users3_humans.avatar_key` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` profileCols = []string{ "id", "creation_date", @@ -113,16 +113,16 @@ var ( "gender", "avatar_key", } - emailQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.email,` + - ` projections.users2_humans.is_email_verified` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + emailQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.email,` + + ` projections.users3_humans.is_email_verified` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` emailCols = []string{ "id", "creation_date", @@ -133,16 +133,16 @@ var ( "email", "is_email_verified", } - phoneQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.phone,` + - ` projections.users2_humans.is_phone_verified` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + phoneQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.phone,` + + ` projections.users3_humans.is_phone_verified` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` phoneCols = []string{ "id", "creation_date", @@ -153,14 +153,14 @@ var ( "phone", "is_phone_verified", } - userUniqueQuery = `SELECT projections.users2.id,` + - ` projections.users2.state,` + - ` projections.users2.username,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.email,` + - ` projections.users2_humans.is_email_verified` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + userUniqueQuery = `SELECT projections.users3.id,` + + ` projections.users3.state,` + + ` projections.users3.username,` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.email,` + + ` projections.users3_humans.is_email_verified` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` userUniqueCols = []string{ "id", "state", @@ -169,42 +169,42 @@ var ( "email", "is_email_verified", } - notifyUserQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2.state,` + - ` projections.users2.type,` + - ` projections.users2.username,` + + notifyUserQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3.state,` + + ` projections.users3.type,` + + ` projections.users3.username,` + ` login_names.loginnames,` + ` preferred_login_name.login_name,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.first_name,` + - ` projections.users2_humans.last_name,` + - ` projections.users2_humans.nick_name,` + - ` projections.users2_humans.display_name,` + - ` projections.users2_humans.preferred_language,` + - ` projections.users2_humans.gender,` + - ` projections.users2_humans.avatar_key,` + - ` projections.users2_notifications.user_id,` + - ` projections.users2_notifications.last_email,` + - ` projections.users2_notifications.verified_email,` + - ` projections.users2_notifications.last_phone,` + - ` projections.users2_notifications.verified_phone,` + - ` projections.users2_notifications.password_set` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + - ` LEFT JOIN projections.users2_notifications ON projections.users2.id = projections.users2_notifications.user_id` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.first_name,` + + ` projections.users3_humans.last_name,` + + ` projections.users3_humans.nick_name,` + + ` projections.users3_humans.display_name,` + + ` projections.users3_humans.preferred_language,` + + ` projections.users3_humans.gender,` + + ` projections.users3_humans.avatar_key,` + + ` projections.users3_notifications.user_id,` + + ` projections.users3_notifications.last_email,` + + ` projections.users3_notifications.verified_email,` + + ` projections.users3_notifications.last_phone,` + + ` projections.users3_notifications.verified_phone,` + + ` projections.users3_notifications.password_set` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` + + ` LEFT JOIN projections.users3_notifications ON projections.users3.id = projections.users3_notifications.user_id` + ` LEFT JOIN` + - ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) as loginnames` + - ` FROM projections.login_names as login_names` + + ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) AS loginnames` + + ` FROM projections.login_names AS login_names` + ` WHERE login_names.instance_id = $1` + - ` GROUP BY login_names.user_id) as login_names` + - ` on login_names.user_id = projections.users2.id` + + ` GROUP BY login_names.user_id) AS login_names` + + ` ON login_names.user_id = projections.users3.id` + ` LEFT JOIN` + - ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names as preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) as preferred_login_name` + - ` on preferred_login_name.user_id = projections.users2.id` + ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) AS preferred_login_name` + + ` ON preferred_login_name.user_id = projections.users3.id` notifyUserCols = []string{ "id", "creation_date", @@ -233,43 +233,43 @@ var ( "verified_phone", "password_set", } - usersQuery = `SELECT projections.users2.id,` + - ` projections.users2.creation_date,` + - ` projections.users2.change_date,` + - ` projections.users2.resource_owner,` + - ` projections.users2.sequence,` + - ` projections.users2.state,` + - ` projections.users2.type,` + - ` projections.users2.username,` + + usersQuery = `SELECT projections.users3.id,` + + ` projections.users3.creation_date,` + + ` projections.users3.change_date,` + + ` projections.users3.resource_owner,` + + ` projections.users3.sequence,` + + ` projections.users3.state,` + + ` projections.users3.type,` + + ` projections.users3.username,` + ` login_names.loginnames,` + ` preferred_login_name.login_name,` + - ` projections.users2_humans.user_id,` + - ` projections.users2_humans.first_name,` + - ` projections.users2_humans.last_name,` + - ` projections.users2_humans.nick_name,` + - ` projections.users2_humans.display_name,` + - ` projections.users2_humans.preferred_language,` + - ` projections.users2_humans.gender,` + - ` projections.users2_humans.avatar_key,` + - ` projections.users2_humans.email,` + - ` projections.users2_humans.is_email_verified,` + - ` projections.users2_humans.phone,` + - ` projections.users2_humans.is_phone_verified,` + - ` projections.users2_machines.user_id,` + - ` projections.users2_machines.name,` + - ` projections.users2_machines.description,` + + ` projections.users3_humans.user_id,` + + ` projections.users3_humans.first_name,` + + ` projections.users3_humans.last_name,` + + ` projections.users3_humans.nick_name,` + + ` projections.users3_humans.display_name,` + + ` projections.users3_humans.preferred_language,` + + ` projections.users3_humans.gender,` + + ` projections.users3_humans.avatar_key,` + + ` projections.users3_humans.email,` + + ` projections.users3_humans.is_email_verified,` + + ` projections.users3_humans.phone,` + + ` projections.users3_humans.is_phone_verified,` + + ` projections.users3_machines.user_id,` + + ` projections.users3_machines.name,` + + ` projections.users3_machines.description,` + ` COUNT(*) OVER ()` + - ` FROM projections.users2` + - ` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` + - ` LEFT JOIN projections.users2_machines ON projections.users2.id = projections.users2_machines.user_id` + + ` FROM projections.users3` + + ` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` + + ` LEFT JOIN projections.users3_machines ON projections.users3.id = projections.users3_machines.user_id` + ` LEFT JOIN` + - ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) as loginnames` + - ` FROM projections.login_names as login_names` + - ` GROUP BY login_names.user_id) as login_names` + - ` on login_names.user_id = projections.users2.id` + + ` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) AS loginnames` + + ` FROM projections.login_names AS login_names` + + ` GROUP BY login_names.user_id) AS login_names` + + ` ON login_names.user_id = projections.users3.id` + ` LEFT JOIN` + - ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names as preferred_login_name WHERE preferred_login_name.is_primary = $1) as preferred_login_name` + - ` on preferred_login_name.user_id = projections.users2.id` + ` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.is_primary = $1) AS preferred_login_name` + + ` ON preferred_login_name.user_id = projections.users3.id` usersCols = []string{ "id", "creation_date", @@ -351,7 +351,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeHuman, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human "id", @@ -382,7 +382,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeHuman, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", Human: &Human{ FirstName: "first_name", @@ -417,7 +417,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeMachine, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human nil, @@ -448,7 +448,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeMachine, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", Machine: &Machine{ Name: "name", @@ -861,7 +861,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeHuman, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human "id", @@ -891,7 +891,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeHuman, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", FirstName: "first_name", LastName: "last_name", @@ -925,7 +925,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeHuman, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human "id", @@ -1007,7 +1007,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeHuman, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human "id", @@ -1044,7 +1044,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeHuman, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", Human: &Human{ FirstName: "first_name", @@ -1080,7 +1080,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeHuman, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human "id", @@ -1109,7 +1109,7 @@ func Test_UserPrepares(t *testing.T) { domain.UserStateActive, domain.UserTypeMachine, "username", - pq.StringArray{"login_name1", "login_name2"}, + database.StringArray{"login_name1", "login_name2"}, "login_name1", //human nil, @@ -1146,7 +1146,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeHuman, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", Human: &Human{ FirstName: "first_name", @@ -1171,7 +1171,7 @@ func Test_UserPrepares(t *testing.T) { State: domain.UserStateActive, Type: domain.UserTypeMachine, Username: "username", - LoginNames: []string{"login_name1", "login_name2"}, + LoginNames: database.StringArray{"login_name1", "login_name2"}, PreferredLoginName: "login_name1", Machine: &Machine{ Name: "name", diff --git a/internal/user/repository/eventsourcing/model/token.go b/internal/user/repository/eventsourcing/model/token.go index df99ff2562..cf3b46da80 100644 --- a/internal/user/repository/eventsourcing/model/token.go +++ b/internal/user/repository/eventsourcing/model/token.go @@ -6,6 +6,7 @@ import ( "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" caos_errs "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -15,13 +16,13 @@ import ( type Token struct { es_models.ObjectRoot - TokenID string `json:"tokenId" gorm:"column:token_id"` - ApplicationID string `json:"applicationId" gorm:"column:application_id"` - UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` - Audience []string `json:"audience" gorm:"column:audience"` - Scopes []string `json:"scopes" gorm:"column:scopes"` - Expiration time.Time `json:"expiration" gorm:"column:expiration"` - PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` + TokenID string `json:"tokenId" gorm:"column:token_id"` + ApplicationID string `json:"applicationId" gorm:"column:application_id"` + UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` + Audience database.StringArray `json:"audience" gorm:"column:audience"` + Scopes database.StringArray `json:"scopes" gorm:"column:scopes"` + Expiration time.Time `json:"expiration" gorm:"column:expiration"` + PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` } func (t *Token) AppendEvents(events ...*es_models.Event) error { diff --git a/internal/user/repository/view/model/notify_user.go b/internal/user/repository/view/model/notify_user.go index 0f6efefede..a2ff48deb8 100644 --- a/internal/user/repository/view/model/notify_user.go +++ b/internal/user/repository/view/model/notify_user.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -22,27 +22,27 @@ const ( ) type NotifyUser struct { - ID string `json:"-" gorm:"column:id;primary_key"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - UserName string `json:"userName" gorm:"column:user_name"` - LoginNames pq.StringArray `json:"-" gorm:"column:login_names"` - PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` - FirstName string `json:"firstName" gorm:"column:first_name"` - LastName string `json:"lastName" gorm:"column:last_name"` - NickName string `json:"nickName" gorm:"column:nick_name"` - DisplayName string `json:"displayName" gorm:"column:display_name"` - PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` - Gender int32 `json:"gender" gorm:"column:gender"` - LastEmail string `json:"email" gorm:"column:last_email"` - VerifiedEmail string `json:"-" gorm:"column:verified_email"` - LastPhone string `json:"phone" gorm:"column:last_phone"` - VerifiedPhone string `json:"-" gorm:"column:verified_phone"` - PasswordSet bool `json:"-" gorm:"column:password_set"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - State int32 `json:"-" gorm:"-"` - InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` + ID string `json:"-" gorm:"column:id;primary_key"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + UserName string `json:"userName" gorm:"column:user_name"` + LoginNames database.StringArray `json:"-" gorm:"column:login_names"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` + FirstName string `json:"firstName" gorm:"column:first_name"` + LastName string `json:"lastName" gorm:"column:last_name"` + NickName string `json:"nickName" gorm:"column:nick_name"` + DisplayName string `json:"displayName" gorm:"column:display_name"` + PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` + Gender int32 `json:"gender" gorm:"column:gender"` + LastEmail string `json:"email" gorm:"column:last_email"` + VerifiedEmail string `json:"-" gorm:"column:verified_email"` + LastPhone string `json:"phone" gorm:"column:last_phone"` + VerifiedPhone string `json:"-" gorm:"column:verified_phone"` + PasswordSet bool `json:"-" gorm:"column:password_set"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + State int32 `json:"-" gorm:"-"` + InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` } func (u *NotifyUser) GenerateLoginName(domain string, appendDomain bool) string { diff --git a/internal/user/repository/view/model/refresh_token.go b/internal/user/repository/view/model/refresh_token.go index c9ef998e01..a0aee58bca 100644 --- a/internal/user/repository/view/model/refresh_token.go +++ b/internal/user/repository/view/model/refresh_token.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -25,22 +25,22 @@ const ( ) type RefreshTokenView struct { - ID string `json:"tokenId" gorm:"column:id;primary_key"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - Token string `json:"-" gorm:"column:token"` - UserID string `json:"-" gorm:"column:user_id"` - ClientID string `json:"clientID" gorm:"column:client_id"` - UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` - Audience pq.StringArray `json:"audience" gorm:"column:audience"` - Scopes pq.StringArray `json:"scopes" gorm:"column:scopes"` - AuthMethodsReferences pq.StringArray `json:"authMethodsReference" gorm:"column:amr"` - AuthTime time.Time `json:"authTime" gorm:"column:auth_time"` - IdleExpiration time.Time `json:"-" gorm:"column:idle_expiration"` - Expiration time.Time `json:"-" gorm:"column:expiration"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` + ID string `json:"tokenId" gorm:"column:id;primary_key"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + Token string `json:"-" gorm:"column:token"` + UserID string `json:"-" gorm:"column:user_id"` + ClientID string `json:"clientID" gorm:"column:client_id"` + UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` + Audience database.StringArray `json:"audience" gorm:"column:audience"` + Scopes database.StringArray `json:"scopes" gorm:"column:scopes"` + AuthMethodsReferences database.StringArray `json:"authMethodsReference" gorm:"column:amr"` + AuthTime time.Time `json:"authTime" gorm:"column:auth_time"` + IdleExpiration time.Time `json:"-" gorm:"column:idle_expiration"` + Expiration time.Time `json:"-" gorm:"column:expiration"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` } func RefreshTokenViewsToModel(tokens []*RefreshTokenView) []*usr_model.RefreshTokenView { diff --git a/internal/user/repository/view/model/token.go b/internal/user/repository/view/model/token.go index 972f707c10..e0b80a1921 100644 --- a/internal/user/repository/view/model/token.go +++ b/internal/user/repository/view/model/token.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -26,22 +26,22 @@ const ( ) type TokenView struct { - ID string `json:"tokenId" gorm:"column:id;primary_key"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - UserID string `json:"-" gorm:"column:user_id"` - ApplicationID string `json:"applicationId" gorm:"column:application_id"` - UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` - Audience pq.StringArray `json:"audience" gorm:"column:audience"` - Scopes pq.StringArray `json:"scopes" gorm:"column:scopes"` - Expiration time.Time `json:"expiration" gorm:"column:expiration"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` - RefreshTokenID string `json:"refreshTokenID,omitempty" gorm:"refresh_token_id"` - IsPAT bool `json:"-" gorm:"is_pat"` - Deactivated bool `json:"-" gorm:"-"` - InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` + ID string `json:"tokenId" gorm:"column:id;primary_key"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + UserID string `json:"-" gorm:"column:user_id"` + ApplicationID string `json:"applicationId" gorm:"column:application_id"` + UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"` + Audience database.StringArray `json:"audience" gorm:"column:audience"` + Scopes database.StringArray `json:"scopes" gorm:"column:scopes"` + Expiration time.Time `json:"expiration" gorm:"column:expiration"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLanguage string `json:"preferredLanguage" gorm:"column:preferred_language"` + RefreshTokenID string `json:"refreshTokenID,omitempty" gorm:"refresh_token_id"` + IsPAT bool `json:"-" gorm:"is_pat"` + Deactivated bool `json:"-" gorm:"-"` + InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` } func TokenViewToModel(token *TokenView) *usr_model.TokenView { diff --git a/internal/user/repository/view/model/user.go b/internal/user/repository/view/model/user.go index 26122d4e2b..af00f1eaaa 100644 --- a/internal/user/repository/view/model/user.go +++ b/internal/user/repository/view/model/user.go @@ -5,11 +5,11 @@ import ( "encoding/json" "time" - "github.com/lib/pq" "github.com/zitadel/logging" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" - caos_errs "github.com/zitadel/zitadel/internal/errors" + "github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore/v1/models" org_model "github.com/zitadel/zitadel/internal/org/model" @@ -42,18 +42,18 @@ const ( ) type UserView struct { - ID string `json:"-" gorm:"column:id;primary_key"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - State int32 `json:"-" gorm:"column:user_state"` - LastLogin time.Time `json:"-" gorm:"column:last_login"` - LoginNames pq.StringArray `json:"-" gorm:"column:login_names"` - PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - Type userType `json:"-" gorm:"column:user_type"` - UserName string `json:"userName" gorm:"column:user_name"` - InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` + ID string `json:"-" gorm:"column:id;primary_key"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + State int32 `json:"-" gorm:"column:user_state"` + LastLogin time.Time `json:"-" gorm:"column:last_login"` + LoginNames database.StringArray `json:"-" gorm:"column:login_names"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + Type userType `json:"-" gorm:"column:user_type"` + UserName string `json:"userName" gorm:"column:user_name"` + InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` *MachineView *HumanView } @@ -220,16 +220,15 @@ func (u *UserView) GenerateLoginName(domain string, appendDomain bool) string { } func (u *UserView) SetLoginNames(userLoginMustBeDomain bool, domains []*org_model.OrgDomain) { - loginNames := make([]string, 0) + u.LoginNames = make([]string, 0, len(domains)) for _, d := range domains { if d.Verified { - loginNames = append(loginNames, u.GenerateLoginName(d.Domain, true)) + u.LoginNames = append(u.LoginNames, u.GenerateLoginName(d.Domain, true)) } } if !userLoginMustBeDomain { - loginNames = append(loginNames, u.UserName) + u.LoginNames = append(u.LoginNames, u.GenerateLoginName(u.UserName, true)) } - u.LoginNames = loginNames } func (u *UserView) AppendEvent(event *models.Event) (err error) { @@ -312,14 +311,14 @@ func (u *UserView) AppendEvent(event *models.Event) (err error) { user.HumanMFAOTPAddedType: if u.HumanView == nil { logging.WithFields("sequence", event.Sequence, "instance", event.InstanceID).Warn("event is ignored because human not exists") - break + return errors.ThrowInvalidArgument(nil, "MODEL-p2BXx", "event ignored: human not exists") } u.OTPState = int32(model.MFAStateNotReady) case user.UserV1MFAOTPVerifiedType, user.HumanMFAOTPVerifiedType: if u.HumanView == nil { logging.WithFields("sequence", event.Sequence, "instance", event.InstanceID).Warn("event is ignored because human not exists") - break + return errors.ThrowInvalidArgument(nil, "MODEL-o6Lcq", "event ignored: human not exists") } u.OTPState = int32(model.MFAStateReady) u.MFAInitSkipped = time.Time{} @@ -369,7 +368,7 @@ func (u *UserView) setRootData(event *models.Event) { func (u *UserView) setData(event *models.Event) error { if err := json.Unmarshal(event.Data, u); err != nil { logging.Log("MODEL-lso9e").WithError(err).Error("could not unmarshal event data") - return caos_errs.ThrowInternal(nil, "MODEL-8iows", "could not unmarshal data") + return errors.ThrowInternal(nil, "MODEL-8iows", "could not unmarshal data") } return nil } @@ -378,7 +377,7 @@ func (u *UserView) setPasswordData(event *models.Event) error { password := new(es_model.Password) if err := json.Unmarshal(event.Data, password); err != nil { logging.Log("MODEL-sdw4r").WithError(err).Error("could not unmarshal event data") - return caos_errs.ThrowInternal(nil, "MODEL-6jhsw", "could not unmarshal data") + return errors.ThrowInternal(nil, "MODEL-6jhsw", "could not unmarshal data") } u.PasswordSet = password.Secret != nil u.PasswordInitRequired = !u.PasswordSet @@ -484,7 +483,7 @@ func webAuthNViewFromEvent(event *models.Event) (*WebAuthNView, error) { token := new(WebAuthNView) err := json.Unmarshal(event.Data, token) if err != nil { - return nil, caos_errs.ThrowInternal(err, "MODEL-FSaq1", "could not unmarshal data") + return nil, errors.ThrowInternal(err, "MODEL-FSaq1", "could not unmarshal data") } return token, err } diff --git a/internal/user/repository/view/model/user_membership.go b/internal/user/repository/view/model/user_membership.go index fa2a67f612..c8872d6838 100644 --- a/internal/user/repository/view/model/user_membership.go +++ b/internal/user/repository/view/model/user_membership.go @@ -4,9 +4,9 @@ import ( "encoding/json" "time" - "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" "github.com/zitadel/zitadel/internal/eventstore/v1/models" @@ -34,14 +34,14 @@ type UserMembershipView struct { AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"` ObjectID string `json:"-" gorm:"column:object_id;primary_key"` - Roles pq.StringArray `json:"-" gorm:"column:roles"` - DisplayName string `json:"-" gorm:"column:display_name"` - CreationDate time.Time `json:"-" gorm:"column:creation_date"` - ChangeDate time.Time `json:"-" gorm:"column:change_date"` - ResourceOwner string `json:"-" gorm:"column:resource_owner"` - ResourceOwnerName string `json:"-" gorm:"column:resource_owner_name"` - Sequence uint64 `json:"-" gorm:"column:sequence"` - InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` + Roles database.StringArray `json:"-" gorm:"column:roles"` + DisplayName string `json:"-" gorm:"column:display_name"` + CreationDate time.Time `json:"-" gorm:"column:creation_date"` + ChangeDate time.Time `json:"-" gorm:"column:change_date"` + ResourceOwner string `json:"-" gorm:"column:resource_owner"` + ResourceOwnerName string `json:"-" gorm:"column:resource_owner_name"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + InstanceID string `json:"instanceID" gorm:"column:instance_id;primary_key"` } func (u *UserMembershipView) AppendEvent(event *models.Event) (err error) { diff --git a/internal/user/repository/view/refresh_token_view.go b/internal/user/repository/view/refresh_token_view.go index 4cf38bd356..dabb64edbb 100644 --- a/internal/user/repository/view/refresh_token_view.go +++ b/internal/user/repository/view/refresh_token_view.go @@ -2,7 +2,6 @@ package view import ( "github.com/jinzhu/gorm" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" @@ -92,6 +91,6 @@ func DeleteUserRefreshTokens(db *gorm.DB, table, userID, instanceID string) erro } func DeleteApplicationRefreshTokens(db *gorm.DB, table string, appIDs []string) error { - delete := repository.PrepareDeleteByKey(table, usr_model.RefreshTokenSearchKey(model.RefreshTokenSearchKeyApplicationID), pq.StringArray(appIDs)) + delete := repository.PrepareDeleteByKey(table, usr_model.RefreshTokenSearchKey(model.RefreshTokenSearchKeyApplicationID), appIDs) return delete(db) } diff --git a/internal/user/repository/view/token_view.go b/internal/user/repository/view/token_view.go index f9c67a46dc..89e9322ab6 100644 --- a/internal/user/repository/view/token_view.go +++ b/internal/user/repository/view/token_view.go @@ -2,7 +2,6 @@ package view import ( "github.com/jinzhu/gorm" - "github.com/lib/pq" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/errors" @@ -92,7 +91,7 @@ func DeleteTokensFromRefreshToken(db *gorm.DB, table, refreshTokenID, instanceID func DeleteApplicationTokens(db *gorm.DB, table, instanceID string, appIDs []string) error { delete := repository.PrepareDeleteByKeys(table, - repository.Key{usr_model.TokenSearchKey(model.TokenSearchKeyApplicationID), pq.StringArray(appIDs)}, + repository.Key{usr_model.TokenSearchKey(model.TokenSearchKeyApplicationID), appIDs}, repository.Key{usr_model.TokenSearchKey(model.TokenSearchKeyInstanceID), instanceID}, ) return delete(db) diff --git a/internal/view/repository/query.go b/internal/view/repository/query.go index 94d438148c..36d41142a6 100644 --- a/internal/view/repository/query.go +++ b/internal/view/repository/query.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/jinzhu/gorm" - "github.com/lib/pq" + "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/domain" caos_errs "github.com/zitadel/zitadel/internal/errors" ) @@ -128,7 +128,7 @@ func SetQuery(query *gorm.DB, key ColumnKey, value interface{}, method domain.Se if !ok { return nil, caos_errs.ThrowInvalidArgument(nil, "VIEW-Psois", "list contains only possible for strings") } - query = query.Where("? <@ "+column, pq.Array([]string{valueText})) + query = query.Where("? <@ "+column, database.StringArray{valueText}) default: return nil, nil }