refactor: relational organization projection to use repository (#11621)

- Transitioned from using `handler.Statements` to a repository pattern
for managing organization data in migrations.
- Introduced a new method to set the updated timestamp for
organizations.
- Updated the projection logic to utilize the repository for creating,
updating, and deleting organization records.
This commit is contained in:
Silvan
2026-03-05 14:55:42 +01:00
committed by GitHub
parent 90faf440f4
commit 07dbb48cc7
7 changed files with 155 additions and 105 deletions
@@ -69,7 +69,9 @@ func (i idpIntentRepository) Create(ctx context.Context, client database.QueryEx
}
builder := new(database.StatementBuilder)
builder.WriteString(`INSERT INTO ` + i.qualifiedTableName() + ` (instance_id, id, success_url, failure_url, idp_id, idp_arguments, created_at, updated_at) VALUES ( `)
builder.WriteString(`INSERT INTO `)
builder.WriteString(i.qualifiedTableName())
builder.WriteString(` (instance_id, id, success_url, failure_url, idp_id, idp_arguments, created_at, updated_at) VALUES ( `)
builder.WriteArgs(intent.InstanceID, intent.ID, intent.SuccessURL.String(), intent.FailureURL.String(), intent.IDPID, intent.IDPArguments, createdAt, updatedAt)
builder.WriteString(` ) RETURNING created_at, updated_at`)
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&intent.CreatedAt, &intent.UpdatedAt)
+31 -9
View File
@@ -2,6 +2,7 @@ package repository
import (
"context"
"time"
"github.com/zitadel/zitadel/backend/v3/domain"
"github.com/zitadel/zitadel/backend/v3/storage/database"
@@ -24,6 +25,10 @@ func (o org) unqualifiedTableName() string {
return "organizations"
}
func (o org) qualifiedTableName() string {
return "zitadel.organizations"
}
func OrganizationRepository() domain.OrganizationRepository {
return new(org)
}
@@ -81,16 +86,25 @@ func (o org) List(ctx context.Context, client database.QueryExecutor, opts ...da
return scanOrganizations(ctx, client, &builder)
}
const createOrganizationStmt = `INSERT INTO zitadel.organizations (id, name, instance_id, state)` +
` VALUES ($1, $2, $3, $4)` +
` RETURNING created_at, updated_at`
// Create implements [domain.OrganizationRepository].
func (o org) Create(ctx context.Context, client database.QueryExecutor, organization *domain.Organization) error {
builder := database.StatementBuilder{}
builder.AppendArgs(organization.ID, organization.Name, organization.InstanceID, organization.State)
builder.WriteString(createOrganizationStmt)
var (
builder database.StatementBuilder
createdAt, updatedAt any = database.DefaultInstruction, database.DefaultInstruction
)
if !organization.CreatedAt.IsZero() {
createdAt = organization.CreatedAt
}
if !organization.UpdatedAt.IsZero() {
updatedAt = organization.UpdatedAt
}
builder.WriteString("INSERT INTO ")
builder.WriteString(o.qualifiedTableName())
builder.WriteString(" (id, name, instance_id, state, created_at, updated_at) VALUES (")
builder.WriteArgs(organization.ID, organization.Name, organization.InstanceID, organization.State, createdAt, updatedAt)
builder.WriteString(") RETURNING created_at, updated_at")
return client.QueryRow(ctx, builder.String(), builder.Args()...).Scan(&organization.CreatedAt, &organization.UpdatedAt)
}
@@ -107,7 +121,9 @@ func (o org) Update(ctx context.Context, client database.QueryExecutor, conditio
}
var builder database.StatementBuilder
builder.WriteString(`UPDATE zitadel.organizations SET `)
builder.WriteString(`UPDATE `)
builder.WriteString(o.qualifiedTableName())
builder.WriteString(` SET `)
err := database.Changes(changes).Write(&builder)
if err != nil {
return 0, err
@@ -127,7 +143,8 @@ func (o org) Delete(ctx context.Context, client database.QueryExecutor, conditio
}
var builder database.StatementBuilder
builder.WriteString(`DELETE FROM zitadel.organizations`)
builder.WriteString(`DELETE FROM `)
builder.WriteString(o.qualifiedTableName())
writeCondition(&builder, condition)
return client.Exec(ctx, builder.String(), builder.Args()...)
@@ -147,6 +164,11 @@ func (o org) SetState(state domain.OrgState) database.Change {
return database.NewChange(o.StateColumn(), state)
}
// SetUpdatedAt implements [domain.organizationChanges].
func (o org) SetUpdatedAt(updatedAt time.Time) database.Change {
return database.NewChange(o.UpdatedAtColumn(), updatedAt)
}
// -------------------------------------------------------------
// conditions
// -------------------------------------------------------------
@@ -39,14 +39,22 @@ func (p project) List(ctx context.Context, client database.QueryExecutor, opts .
return getMany[domain.Project](ctx, client, builder)
}
const insertProjectStmt = `INSERT INTO zitadel.projects(
instance_id, organization_id, id, name, state, should_assert_role, is_authorization_required, is_project_access_required, used_labeling_setting_owner
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING created_at, updated_at`
func (p project) Create(ctx context.Context, client database.QueryExecutor, project *domain.Project) error {
var (
builder database.StatementBuilder
createdAt, updatedAt any = database.DefaultInstruction, database.DefaultInstruction
)
if !project.CreatedAt.IsZero() {
createdAt = project.CreatedAt
}
if !project.UpdatedAt.IsZero() {
updatedAt = project.UpdatedAt
}
func (project) Create(ctx context.Context, client database.QueryExecutor, project *domain.Project) error {
builder := database.NewStatementBuilder(insertProjectStmt,
builder.WriteString("INSERT INTO ")
builder.WriteString(p.qualifiedTableName())
builder.WriteString("(instance_id, organization_id, id, name, state, should_assert_role, is_authorization_required, is_project_access_required, used_labeling_setting_owner, created_at, updated_at) VALUES (")
builder.WriteArgs(
project.InstanceID,
project.OrganizationID,
project.ID,
@@ -56,7 +64,11 @@ func (project) Create(ctx context.Context, client database.QueryExecutor, projec
project.IsAuthorizationRequired,
project.IsProjectAccessRequired,
project.UsedLabelingSettingOwner,
createdAt,
updatedAt,
)
builder.WriteString(`) RETURNING created_at, updated_at`)
return client.QueryRow(ctx, builder.String(), builder.Args()...).
Scan(&project.CreatedAt, &project.UpdatedAt)
}
@@ -141,7 +153,7 @@ func (p project) StateCondition(state domain.ProjectState) database.Condition {
// -------------------------------------------------------------
func (p project) qualifiedTableName() string {
return "zitadel." + p.unqualifiedTableName()
return "zitadel.projects"
}
func (project) unqualifiedTableName() string {
@@ -64,7 +64,9 @@ func (p projectGrant) Create(ctx context.Context, client database.QueryExecutor,
// separate statement to add roles to project grant
builder := database.NewStatementBuilder(insertProjectGrantRolesStmt, projectGrant.RoleKeys)
builder.WriteString(`INSERT INTO ` + p.qualifiedTableName() + ` (instance_id, id, project_id, granting_organization_id, granted_organization_id, state, created_at, updated_at) VALUES ( `)
builder.WriteString(`INSERT INTO `)
builder.WriteString(p.qualifiedTableName())
builder.WriteString(` (instance_id, id, project_id, granting_organization_id, granted_organization_id, state, created_at, updated_at) VALUES ( `)
builder.WriteArgs(
projectGrant.InstanceID,
projectGrant.ID,
@@ -14,6 +14,10 @@ import (
type projectRole struct{}
func (projectRole) qualifiedTableName() string {
return "zitadel.project_roles"
}
func (p projectRole) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.ProjectRole, error) {
builder, err := p.prepareQuery(opts)
if err != nil {
@@ -30,21 +34,32 @@ func (p projectRole) List(ctx context.Context, client database.QueryExecutor, op
return getMany[domain.ProjectRole](ctx, client, builder)
}
const insertProjectRoleStmt = `INSERT INTO zitadel.project_roles(
instance_id, organization_id, project_id, key, display_name, role_group
)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING created_at, updated_at`
func (p projectRole) Create(ctx context.Context, client database.QueryExecutor, role *domain.ProjectRole) error {
builder := database.NewStatementBuilder(insertProjectRoleStmt,
var (
builder database.StatementBuilder
createdAt, updatedAt any = database.DefaultInstruction, database.DefaultInstruction
)
if !role.CreatedAt.IsZero() {
createdAt = role.CreatedAt
}
if !role.UpdatedAt.IsZero() {
updatedAt = role.UpdatedAt
}
builder.WriteString("INSERT INTO ")
builder.WriteString(p.qualifiedTableName())
builder.WriteString(` (instance_id, organization_id, project_id, key, display_name, role_group, created_at, updated_at) VALUES (`)
builder.WriteArgs(
role.InstanceID,
role.OrganizationID,
role.ProjectID,
role.Key,
role.DisplayName,
role.RoleGroup,
createdAt,
updatedAt,
)
builder.WriteString(`) RETURNING created_at, updated_at`)
return client.QueryRow(ctx, builder.String(), builder.Args()...).
Scan(&role.CreatedAt, &role.UpdatedAt)
}