fixup! fixup! Merge branch 'main' into import_export_merge

This commit is contained in:
Iraq Jaber
2025-06-05 10:10:14 +02:00
parent b0171c83df
commit 5b1099c90f
15 changed files with 478 additions and 111 deletions

View File

@@ -9,16 +9,16 @@ import (
)
type Instance struct {
ID string `json:"id"`
Name string `json:"name"`
DefaultOrgID string `json:"default_org_id"`
IAMProjectID string `json:"iam_project_id"`
ConsoleClientId string `json:"console_client_id"`
ConsoleAppID string `json:"console_app_id"`
DefaultLanguage string `json:"default_language"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DeletedAt *time.Time `json:"-"`
ID string `json:"id,omitempty" db:"id"`
Name string `json:"name,omitempty" db:"name"`
DefaultOrgID string `json:"default_org_id,omitempty" db:"default_org_id"`
IAMProjectID string `json:"iam_project_id,omitempty" db:"iam_project_id"`
ConsoleClientID string `json:"console_client_id,omitempty" db:"console_client_id"`
ConsoleAppID string `json:"console_app_id,omitempty" db:"console_app_id"`
DefaultLanguage string `json:"default_language,omitempty" db:"default_language"`
CreatedAt time.Time `json:"-,omitempty" db:"created_at"`
UpdatedAt time.Time `json:"-,omitempty" db:"updated_at"`
DeletedAt *time.Time `json:"-,omitempty" db:"deleted_at"`
}
type instanceCacheIndex uint8
@@ -44,8 +44,8 @@ type instanceColumns interface {
IDColumn() database.Column
// NameColumn returns the column for the name field.
NameColumn() database.Column
// DefaultOrgIdColumn returns the column for the default org id field
DefaultOrgIdColumn() database.Column
// DefaultOrgIDColumn returns the column for the default org id field
DefaultOrgIDColumn() database.Column
// IAMProjectIDColumn returns the column for the default IAM org id field
IAMProjectIDColumn() database.Column
// ConsoleClientIDColumn returns the column for the default IAM org id field
@@ -87,9 +87,10 @@ type InstanceRepository interface {
// Member() MemberRepository
Get(ctx context.Context, opts ...database.Condition) (*Instance, error)
List(ctx context.Context, opts ...database.Condition) ([]*Instance, error)
Create(ctx context.Context, instance *Instance) error
Update(ctx context.Context, condition database.Condition, changes ...database.Change) error
Update(ctx context.Context, condition database.Condition, changes ...database.Change) (int64, error)
Delete(ctx context.Context, condition database.Condition) error
}

View File

@@ -31,7 +31,7 @@ type Querier interface {
// Executor is a database client that can execute statements.
type Executor interface {
Exec(ctx context.Context, stmt string, args ...any) error
Exec(ctx context.Context, stmt string, args ...any) (int64, error)
}
// QueryExecutor is a database client that can execute queries and statements.

View File

@@ -13,9 +13,7 @@ type pgxConn struct {
*pgxpool.Conn
}
var (
_ database.Client = (*pgxConn)(nil)
)
var _ database.Client = (*pgxConn)(nil)
// Release implements [database.Client].
func (c *pgxConn) Release(_ context.Context) error {
@@ -47,9 +45,9 @@ func (c *pgxConn) QueryRow(ctx context.Context, sql string, args ...any) databas
// Exec implements [database.Pool].
// Subtle: this method shadows the method (Pool).Exec of pgxPool.Pool.
func (c *pgxConn) Exec(ctx context.Context, sql string, args ...any) error {
_, err := c.Conn.Exec(ctx, sql, args...)
return err
func (c *pgxConn) Exec(ctx context.Context, sql string, args ...any) (int64, error) {
res, err := c.Conn.Exec(ctx, sql, args...)
return res.RowsAffected(), err
}
// Migrate implements [database.Migrator].

View File

@@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS zitadel.instances(
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
id TEXT NOT NULL CHECK (id <> '') PRIMARY KEY,
name TEXT NOT NULL CHECK (name <> ''),
default_org_id TEXT, -- NOT NULL,
iam_project_id TEXT, -- NOT NULL,
console_client_id TEXT, -- NOT NULL,

View File

@@ -45,9 +45,9 @@ func (c *pgxPool) QueryRow(ctx context.Context, sql string, args ...any) databas
// Exec implements [database.Pool].
// Subtle: this method shadows the method (Pool).Exec of pgxPool.Pool.
func (c *pgxPool) Exec(ctx context.Context, sql string, args ...any) error {
_, err := c.Pool.Exec(ctx, sql, args...)
return err
func (c *pgxPool) Exec(ctx context.Context, sql string, args ...any) (int64, error) {
res, err := c.Pool.Exec(ctx, sql, args...)
return res.RowsAffected(), err
}
// Begin implements [database.Pool].

View File

@@ -46,9 +46,9 @@ func (tx *pgxTx) QueryRow(ctx context.Context, sql string, args ...any) database
// Exec implements [database.Transaction].
// Subtle: this method shadows the method (Pool).Exec of pgxPool.Pool.
func (tx *pgxTx) Exec(ctx context.Context, sql string, args ...any) error {
_, err := tx.Tx.Exec(ctx, sql, args...)
return err
func (tx *pgxTx) Exec(ctx context.Context, sql string, args ...any) (int64, error) {
res, err := tx.Tx.Exec(ctx, sql, args...)
return res.RowsAffected(), err
}
// Begin implements [database.Transaction].

View File

@@ -5,6 +5,7 @@ import (
"errors"
"time"
"github.com/jackc/pgx/v5/pgconn"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
)
@@ -37,14 +38,33 @@ func (i *instance) Get(ctx context.Context, opts ...database.Condition) (*domain
i.builder.WriteString(queryInstanceStmt)
isNotDeletedCondition := database.IsNull(i.DeletedAtColumn())
opts = append(opts, isNotDeletedCondition)
opts = append(opts, database.IsNull(i.DeletedAtColumn()))
andCondition := database.And(opts...)
andCondition.Write(&i.builder)
return scanInstance(i.client.QueryRow(ctx, i.builder.String(), i.builder.Args()...))
}
// List implements [domain.InstanceRepository].
// func (i *instance) List(ctx context.Context, opts ...database.QueryOption) (*domain.Instance, error) {
func (i *instance) List(ctx context.Context, opts ...database.Condition) ([]*domain.Instance, error) {
i.builder = database.StatementBuilder{}
i.builder.WriteString(queryInstanceStmt)
opts = append(opts, database.IsNull(i.DeletedAtColumn()))
andCondition := database.And(opts...)
andCondition.Write(&i.builder)
rows, err := i.client.Query(ctx, i.builder.String(), i.builder.Args()...)
if err != nil {
return nil, err
}
defer rows.Close()
return scanInstances(rows)
}
const createInstanceStmt = `INSERT INTO zitadel.instances (id, name, default_org_id, iam_project_id, console_client_id, console_app_id, default_language)` +
` VALUES ($1, $2, $3, $4, $5, $6, $7)` +
` RETURNING created_at, updated_at`
@@ -52,14 +72,35 @@ const createInstanceStmt = `INSERT INTO zitadel.instances (id, name, default_org
// Create implements [domain.InstanceRepository].
func (i *instance) Create(ctx context.Context, instance *domain.Instance) error {
i.builder = database.StatementBuilder{}
i.builder.AppendArgs(instance.ID, instance.Name, instance.DefaultOrgID, instance.IAMProjectID, instance.ConsoleClientId, instance.ConsoleAppID, instance.DefaultLanguage)
i.builder.AppendArgs(instance.ID, instance.Name, instance.DefaultOrgID, instance.IAMProjectID, instance.ConsoleClientID, instance.ConsoleAppID, instance.DefaultLanguage)
i.builder.WriteString(createInstanceStmt)
return i.client.QueryRow(ctx, i.builder.String(), i.builder.Args()...).Scan(&instance.CreatedAt, &instance.UpdatedAt)
err := i.client.QueryRow(ctx, i.builder.String(), i.builder.Args()...).Scan(&instance.CreatedAt, &instance.UpdatedAt)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
// constraint violation
if pgErr.Code == "23514" {
if pgErr.ConstraintName == "instances_name_check" {
return errors.New("instnace name not provided")
}
if pgErr.ConstraintName == "instances_id_check" {
return errors.New("instnace id not provided")
}
}
// duplicate
if pgErr.Code == "23505" {
if pgErr.ConstraintName == "instances_pkey" {
return errors.New("instnace id already exists")
}
}
}
}
return err
}
// Update implements [domain.InstanceRepository].
func (i instance) Update(ctx context.Context, condition database.Condition, changes ...database.Change) error {
func (i instance) Update(ctx context.Context, condition database.Condition, changes ...database.Change) (int64, error) {
i.builder = database.StatementBuilder{}
i.builder.WriteString(`UPDATE zitadel.instances SET `)
database.Changes(changes).Write(&i.builder)
@@ -67,7 +108,8 @@ func (i instance) Update(ctx context.Context, condition database.Condition, chan
stmt := i.builder.String()
return i.client.Exec(ctx, stmt, i.builder.Args()...)
rowsAffected, err := i.client.Exec(ctx, stmt, i.builder.Args()...)
return rowsAffected, err
}
// Delete implements [domain.InstanceRepository].
@@ -80,7 +122,8 @@ func (i instance) Delete(ctx context.Context, condition database.Condition) erro
i.builder.AppendArgs(time.Now())
i.writeCondition(condition)
return i.client.Exec(ctx, i.builder.String(), i.builder.Args()...)
_, err := i.client.Exec(ctx, i.builder.String(), i.builder.Args()...)
return err
}
// -------------------------------------------------------------
@@ -126,7 +169,7 @@ func (instance) CreatedAtColumn() database.Column {
}
// DefaultOrgIdColumn implements [domain.instanceColumns].
func (instance) DefaultOrgIdColumn() database.Column {
func (instance) DefaultOrgIDColumn() database.Column {
return database.NewColumn("default_org_id")
}
@@ -175,7 +218,7 @@ func scanInstance(scanner database.Scanner) (*domain.Instance, error) {
&instance.Name,
&instance.DefaultOrgID,
&instance.IAMProjectID,
&instance.ConsoleClientId,
&instance.ConsoleClientID,
&instance.ConsoleAppID,
&instance.DefaultLanguage,
&instance.CreatedAt,
@@ -194,3 +237,30 @@ func scanInstance(scanner database.Scanner) (*domain.Instance, error) {
return &instance, nil
}
func scanInstances(rows database.Rows) ([]*domain.Instance, error) {
instances := make([]*domain.Instance, 0)
for rows.Next() {
var instance domain.Instance
err := rows.Scan(
&instance.ID,
&instance.Name,
&instance.DefaultOrgID,
&instance.IAMProjectID,
&instance.ConsoleClientID,
&instance.ConsoleAppID,
&instance.DefaultLanguage,
&instance.CreatedAt,
&instance.UpdatedAt,
&instance.DeletedAt,
)
if err != nil {
return nil, err
}
instances = append(instances, &instance)
}
return instances, nil
}

View File

@@ -2,12 +2,12 @@ package repository_test
import (
"context"
"errors"
"testing"
"time"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
@@ -15,81 +15,363 @@ import (
)
func TestCreateInstance(t *testing.T) {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
tests := []struct {
name string
testFunc func() *domain.Instance
instance domain.Instance
err error
}{
{
name: "happy path",
instance: func() domain.Instance {
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
instance := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
return instance
}(),
},
{
name: "create instance wihtout name",
instance: func() domain.Instance {
instanceId := gofakeit.Name()
// instanceName := gofakeit.Name()
instance := domain.Instance{
ID: instanceId,
Name: "",
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
return instance
}(),
err: errors.New("instnace name not provided"),
},
{
name: "adding same instance twice",
testFunc: func() *domain.Instance {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientId: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
return &inst
},
err: errors.New("instnace id already exists"),
},
{
name: "adding instance with no id",
instance: func() domain.Instance {
// instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
instance := domain.Instance{
// ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
return instance
}(),
err: errors.New("instnace id not provided"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
beforeCreate := time.Now()
err := instanceRepo.Create(ctx, &inst)
require.NoError(t, err)
afterCreate := time.Now()
var instance *domain.Instance
if tt.testFunc != nil {
instance = tt.testFunc()
} else {
instance = &tt.instance
}
instanceRepo := repository.InstanceRepository(pool)
instance, err := instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
require.Equal(t, inst.ID, instance.ID)
require.Equal(t, inst.Name, instance.Name)
require.Equal(t, inst.DefaultOrgID, instance.DefaultOrgID)
require.Equal(t, inst.IAMProjectID, instance.IAMProjectID)
require.Equal(t, inst.ConsoleClientId, instance.ConsoleClientId)
require.Equal(t, inst.ConsoleAppID, instance.ConsoleAppID)
require.Equal(t, inst.DefaultLanguage, instance.DefaultLanguage)
assert.WithinRange(t, instance.CreatedAt, beforeCreate, afterCreate)
assert.WithinRange(t, instance.UpdatedAt, beforeCreate, afterCreate)
require.Nil(t, instance.DeletedAt)
require.NoError(t, err)
// create instance
beforeCreate := time.Now()
err := instanceRepo.Create(ctx, instance)
assert.Equal(t, tt.err, err)
if err != nil {
return
}
afterCreate := time.Now()
// check instance values
instance, err = instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instance.Name),
)
assert.Equal(t, tt.instance.ID, instance.ID)
assert.Equal(t, tt.instance.Name, instance.Name)
assert.Equal(t, tt.instance.DefaultOrgID, instance.DefaultOrgID)
assert.Equal(t, tt.instance.IAMProjectID, instance.IAMProjectID)
assert.Equal(t, tt.instance.ConsoleClientID, instance.ConsoleClientID)
assert.Equal(t, tt.instance.ConsoleAppID, instance.ConsoleAppID)
assert.Equal(t, tt.instance.DefaultLanguage, instance.DefaultLanguage)
assert.WithinRange(t, instance.CreatedAt, beforeCreate, afterCreate)
assert.WithinRange(t, instance.UpdatedAt, beforeCreate, afterCreate)
assert.Nil(t, instance.DeletedAt)
assert.NoError(t, err)
})
}
}
func TestUpdateNameInstance(t *testing.T) {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
tests := []struct {
name string
testFunc func() *domain.Instance
rowsAffected int64
}{
{
name: "happy path",
testFunc: func() *domain.Instance {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientId: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
return &inst
},
rowsAffected: 1,
},
{
name: "update non existent instance",
testFunc: func() *domain.Instance {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
}
return &inst
},
rowsAffected: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
beforeUpdate := time.Now()
err := instanceRepo.Create(ctx, &inst)
require.NoError(t, err)
ctx := context.Background()
instanceRepo := repository.InstanceRepository(pool)
_, err = instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
require.NoError(t, err)
instance := tt.testFunc()
// update name
err = instanceRepo.Update(ctx,
instanceRepo.IDCondition(instanceId),
instanceRepo.SetName("new_name"),
)
require.NoError(t, err)
// update name
newName := "new_" + instance.Name
rowsAffected, err := instanceRepo.Update(ctx,
instanceRepo.IDCondition(instance.ID),
instanceRepo.SetName(newName),
)
afterUpdate := time.Now()
assert.NoError(t, err)
instance, err := instanceRepo.Get(ctx,
instanceRepo.IDCondition(instanceId),
)
require.NoError(t, err)
require.Equal(t, "new_name", instance.Name)
assert.Equal(t, tt.rowsAffected, rowsAffected)
if rowsAffected == 0 {
return
}
// check instance values
instance, err = instanceRepo.Get(ctx,
instanceRepo.IDCondition(instance.ID),
)
assert.NoError(t, err)
assert.Equal(t, newName, instance.Name)
assert.WithinRange(t, instance.UpdatedAt, beforeUpdate, afterUpdate)
assert.Nil(t, instance.DeletedAt)
})
}
}
func TestUpdeDeleteInstance(t *testing.T) {
func TestGetInstance(t *testing.T) {
tests := []struct {
name string
testFunc func() *domain.Instance
noInstanceReturned bool
}{
{
name: "happy path",
testFunc: func() *domain.Instance {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
return &inst
},
},
{
name: "get non existent instance",
testFunc: func() *domain.Instance {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
}
return &inst
},
noInstanceReturned: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
instanceRepo := repository.InstanceRepository(pool)
var instance *domain.Instance
if tt.testFunc != nil {
instance = tt.testFunc()
}
// check instance values
returnedInstance, err := instanceRepo.Get(ctx,
instanceRepo.IDCondition(instance.ID),
)
assert.NoError(t, err)
if tt.noInstanceReturned {
assert.Nil(t, returnedInstance)
return
}
assert.Equal(t, returnedInstance.ID, instance.ID)
assert.Equal(t, returnedInstance.Name, instance.Name)
assert.Equal(t, returnedInstance.DefaultOrgID, instance.DefaultOrgID)
assert.Equal(t, returnedInstance.IAMProjectID, instance.IAMProjectID)
assert.Equal(t, returnedInstance.ConsoleClientID, instance.ConsoleClientID)
assert.Equal(t, returnedInstance.ConsoleAppID, instance.ConsoleAppID)
assert.Equal(t, returnedInstance.DefaultLanguage, instance.DefaultLanguage)
assert.NoError(t, err)
})
}
}
func TestListInstance(t *testing.T) {
tests := []struct {
name string
testFunc func() *domain.Instance
noInstanceReturned bool
}{
{
name: "happy path",
testFunc: func() *domain.Instance {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
return &inst
},
},
{
name: "get non existent instance",
testFunc: func() *domain.Instance {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
}
return &inst
},
noInstanceReturned: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
instanceRepo := repository.InstanceRepository(pool)
var instance *domain.Instance
if tt.testFunc != nil {
instance = tt.testFunc()
}
// check instance values
returnedInstance, err := instanceRepo.List(ctx,
instanceRepo.IDCondition(instance.ID),
)
assert.NoError(t, err)
if tt.noInstanceReturned {
assert.Nil(t, returnedInstance)
return
}
assert.Equal(t, returnedInstance.ID, instance.ID)
assert.Equal(t, returnedInstance.Name, instance.Name)
assert.Equal(t, returnedInstance.DefaultOrgID, instance.DefaultOrgID)
assert.Equal(t, returnedInstance.IAMProjectID, instance.IAMProjectID)
assert.Equal(t, returnedInstance.ConsoleClientID, instance.ConsoleClientID)
assert.Equal(t, returnedInstance.ConsoleAppID, instance.ConsoleAppID)
assert.Equal(t, returnedInstance.DefaultLanguage, instance.DefaultLanguage)
assert.NoError(t, err)
})
}
}
func TestUpdateDeleteInstance(t *testing.T) {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
@@ -100,29 +382,29 @@ func TestUpdeDeleteInstance(t *testing.T) {
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientId: "consoleCLient",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
err := instanceRepo.Create(ctx, &inst)
require.NoError(t, err)
assert.NoError(t, err)
instance, err := instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
require.NotNil(t, instance)
require.NoError(t, err)
assert.NotNil(t, instance)
assert.NoError(t, err)
// delete instance
err = instanceRepo.Delete(ctx,
instanceRepo.IDCondition(instanceId),
)
require.NoError(t, err)
assert.NoError(t, err)
instance, err = instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
require.NoError(t, err)
require.Nil(t, instance)
assert.NoError(t, err)
assert.Nil(t, instance)
}

View File

@@ -3,7 +3,6 @@ package repository
import "github.com/zitadel/zitadel/backend/v3/storage/database"
type repository struct {
// we can't reuse builder after it's been used already, I think we should remove it
builder database.StatementBuilder
client database.QueryExecutor
}

View File

@@ -120,7 +120,8 @@ func (u *user) Create(ctx context.Context, user *domain.User) error {
func (u *user) Delete(ctx context.Context, condition database.Condition) error {
u.builder.WriteString("DELETE FROM users")
u.writeCondition(condition)
return u.client.Exec(ctx, u.builder.String(), u.builder.Args()...)
_, err := u.client.Exec(ctx, u.builder.String(), u.builder.Args()...)
return err
}
// -------------------------------------------------------------

View File

@@ -46,7 +46,8 @@ func (h userHuman) Update(ctx context.Context, condition database.Condition, cha
stmt := h.builder.String()
return h.client.Exec(ctx, stmt, h.builder.Args()...)
_, err := h.client.Exec(ctx, stmt, h.builder.Args()...)
return err
}
// -------------------------------------------------------------

View File

@@ -18,13 +18,14 @@ var _ domain.MachineRepository = (*userMachine)(nil)
// -------------------------------------------------------------
// Update implements [domain.MachineRepository].
func (m userMachine) Update(ctx context.Context, condition database.Condition, changes ...database.Change) (err error) {
func (m userMachine) Update(ctx context.Context, condition database.Condition, changes ...database.Change) error {
m.builder.WriteString("UPDATE user_machines SET ")
database.Changes(changes).Write(&m.builder)
m.writeCondition(condition)
m.writeReturning()
return m.client.Exec(ctx, m.builder.String(), m.builder.Args()...)
_, err := m.client.Exec(ctx, m.builder.String(), m.builder.Args()...)
return err
}
// -------------------------------------------------------------

View File

@@ -15,7 +15,8 @@ type Event struct {
func Publish(ctx context.Context, events []*Event, db database.Executor) error {
for _, event := range events {
if err := db.Exec(ctx, `INSERT INTO events (aggregate_type, aggregate_id) VALUES ($1, $2)`, event.AggregateType, event.AggregateID); err != nil {
_, err := db.Exec(ctx, `INSERT INTO events (aggregate_type, aggregate_id) VALUES ($1, $2)`, event.AggregateType, event.AggregateID)
if err != nil {
return err
}
}

4
go.mod
View File

@@ -43,6 +43,7 @@ require (
github.com/h2non/gock v1.2.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/improbable-eng/grpc-web v0.15.0
github.com/jackc/pgconn v1.14.3
github.com/jackc/pgx/v5 v5.7.3
github.com/jackc/tern/v2 v2.3.3
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52
@@ -135,6 +136,9 @@ require (
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/lib/pq v1.10.9 // indirect

9
go.sum
View File

@@ -449,10 +449,19 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/chunkreader/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 v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w=
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
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/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag=
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.3 h1:PO1wNKj/bTAwxSJnO1Z4Ai8j4magtqg2SLNjEDzcXQo=