From 2b8f0618de6349d1ae469cc5fbe517e44a26a1f7 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Mon, 22 Jun 2026 10:58:30 +0200 Subject: [PATCH] Generalize alias data layer to ResourceAlias The trust_center_aliases table only allowed aliasing trust center resources. Rename it to resource_aliases and scope uniqueness by tenant rather than organization so any resource can carry an alias. Replace the TrustCenterAlias coredata type with a ResourceAlias type that loads and upserts aliases by resource ID. Signed-off-by: Bryan Frimin --- pkg/coredata/migrations/20260622T074517Z.sql | 18 +++++ pkg/coredata/migrations/20260622T080513Z.sql | 22 ++++++ ...rust_center_alias.go => resource_alias.go} | 76 ++++++++----------- 3 files changed, 71 insertions(+), 45 deletions(-) create mode 100644 pkg/coredata/migrations/20260622T074517Z.sql create mode 100644 pkg/coredata/migrations/20260622T080513Z.sql rename pkg/coredata/{trust_center_alias.go => resource_alias.go} (66%) diff --git a/pkg/coredata/migrations/20260622T074517Z.sql b/pkg/coredata/migrations/20260622T074517Z.sql new file mode 100644 index 000000000..f337f7b48 --- /dev/null +++ b/pkg/coredata/migrations/20260622T074517Z.sql @@ -0,0 +1,18 @@ +-- Copyright (c) 2025-2026 Probo Inc . +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +-- PERFORMANCE OF THIS SOFTWARE. + +ALTER TABLE trust_center_aliases RENAME TO resource_aliases; + +ALTER TABLE resource_aliases +RENAME CONSTRAINT trust_center_aliases_organization_id_alias_key TO resource_aliases_organization_id_alias_key; diff --git a/pkg/coredata/migrations/20260622T080513Z.sql b/pkg/coredata/migrations/20260622T080513Z.sql new file mode 100644 index 000000000..f0ce30d37 --- /dev/null +++ b/pkg/coredata/migrations/20260622T080513Z.sql @@ -0,0 +1,22 @@ +-- Copyright (c) 2025-2026 Probo Inc . +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +-- PERFORMANCE OF THIS SOFTWARE. + +ALTER TABLE resource_aliases +DROP CONSTRAINT resource_aliases_organization_id_alias_key; + +ALTER TABLE resource_aliases +ADD CONSTRAINT resource_aliases_tenant_id_alias_key UNIQUE (tenant_id, alias); + +ALTER TABLE resource_aliases +DROP COLUMN organization_id; diff --git a/pkg/coredata/trust_center_alias.go b/pkg/coredata/resource_alias.go similarity index 66% rename from pkg/coredata/trust_center_alias.go rename to pkg/coredata/resource_alias.go index 8693035aa..e33529d46 100644 --- a/pkg/coredata/trust_center_alias.go +++ b/pkg/coredata/resource_alias.go @@ -28,18 +28,17 @@ import ( ) type ( - TrustCenterAlias struct { - OrganizationID gid.GID `db:"organization_id"` - Alias string `db:"alias"` - ResourceID gid.GID `db:"resource_id"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ResourceAlias struct { + Alias string `db:"alias"` + ResourceID gid.GID `db:"resource_id"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } - TrustCenterAliases []*TrustCenterAlias + ResourceAliases []*ResourceAlias ) -func (t *TrustCenterAlias) Upsert( +func (t *ResourceAlias) Upsert( ctx context.Context, conn pg.Querier, scope Scoper, @@ -49,9 +48,8 @@ func (t *TrustCenterAlias) Upsert( now := time.Now() q := ` -INSERT INTO trust_center_aliases ( +INSERT INTO resource_aliases ( tenant_id, - organization_id, alias, resource_id, created_at, @@ -59,11 +57,6 @@ INSERT INTO trust_center_aliases ( ) VALUES ( @tenant_id, - COALESCE( - (SELECT organization_id FROM documents WHERE id = @resource_id AND tenant_id = @tenant_id), - (SELECT organization_id FROM trust_center_files WHERE id = @resource_id AND tenant_id = @tenant_id), - (SELECT organization_id FROM files WHERE id = @resource_id AND tenant_id = @tenant_id) - ), @alias, @resource_id, @created_at, @@ -74,7 +67,6 @@ SET alias = EXCLUDED.alias, updated_at = EXCLUDED.updated_at RETURNING - organization_id, alias, resource_id, created_at, @@ -92,17 +84,17 @@ RETURNING rows, err := conn.Query(ctx, q, args) if err != nil { if pgErr, ok := errors.AsType[*pgconn.PgError](err); ok { - if pgErr.Code == "23505" && pgErr.ConstraintName == "trust_center_aliases_organization_id_alias_key" { + if pgErr.Code == "23505" && pgErr.ConstraintName == "resource_aliases_tenant_id_alias_key" { return ErrResourceAlreadyExists } } - return fmt.Errorf("cannot upsert trust center alias: %w", err) + return fmt.Errorf("cannot upsert resource alias: %w", err) } - row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterAlias]) + row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ResourceAlias]) if err != nil { - return fmt.Errorf("cannot collect trust center alias: %w", err) + return fmt.Errorf("cannot collect resource alias: %w", err) } *t = row @@ -110,25 +102,22 @@ RETURNING return nil } -func (t *TrustCenterAlias) LoadByAlias( +func (t *ResourceAlias) LoadByAlias( ctx context.Context, conn pg.Querier, scope Scoper, - organizationID gid.GID, alias string, ) error { q := ` SELECT - organization_id, alias, resource_id, created_at, updated_at FROM - trust_center_aliases + resource_aliases WHERE %s - AND organization_id = @organization_id AND alias = @alias LIMIT 1; ` @@ -136,23 +125,22 @@ LIMIT 1; q = fmt.Sprintf(q, scope.SQLFragment()) args := pgx.StrictNamedArgs{ - "organization_id": organizationID, - "alias": alias, + "alias": alias, } maps.Copy(args, scope.SQLArguments()) rows, err := conn.Query(ctx, q, args) if err != nil { - return fmt.Errorf("cannot query trust center alias: %w", err) + return fmt.Errorf("cannot query resource alias: %w", err) } - row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterAlias]) + row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ResourceAlias]) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return ErrResourceNotFound } - return fmt.Errorf("cannot collect trust center alias: %w", err) + return fmt.Errorf("cannot collect resource alias: %w", err) } *t = row @@ -160,7 +148,7 @@ LIMIT 1; return nil } -func (t *TrustCenterAlias) LoadByResourceID( +func (t *ResourceAlias) LoadByResourceID( ctx context.Context, conn pg.Querier, scope Scoper, @@ -168,13 +156,12 @@ func (t *TrustCenterAlias) LoadByResourceID( ) error { q := ` SELECT - organization_id, alias, resource_id, created_at, updated_at FROM - trust_center_aliases + resource_aliases WHERE %s AND resource_id = @resource_id @@ -188,16 +175,16 @@ LIMIT 1; rows, err := conn.Query(ctx, q, args) if err != nil { - return fmt.Errorf("cannot query trust center alias: %w", err) + return fmt.Errorf("cannot query resource alias: %w", err) } - row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[TrustCenterAlias]) + row, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ResourceAlias]) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return ErrResourceNotFound } - return fmt.Errorf("cannot collect trust center alias: %w", err) + return fmt.Errorf("cannot collect resource alias: %w", err) } *t = row @@ -205,7 +192,7 @@ LIMIT 1; return nil } -func (ts *TrustCenterAliases) LoadByResourceIDs( +func (ts *ResourceAliases) LoadByResourceIDs( ctx context.Context, conn pg.Querier, scope Scoper, @@ -219,13 +206,12 @@ func (ts *TrustCenterAliases) LoadByResourceIDs( q := ` SELECT - organization_id, alias, resource_id, created_at, updated_at FROM - trust_center_aliases + resource_aliases WHERE %s AND resource_id = ANY(@resource_ids) @@ -238,12 +224,12 @@ WHERE rows, err := conn.Query(ctx, q, args) if err != nil { - return fmt.Errorf("cannot query trust center aliases: %w", err) + return fmt.Errorf("cannot query resource aliases: %w", err) } - aliases, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[TrustCenterAlias]) + aliases, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ResourceAlias]) if err != nil { - return fmt.Errorf("cannot collect trust center aliases: %w", err) + return fmt.Errorf("cannot collect resource aliases: %w", err) } *ts = aliases @@ -251,13 +237,13 @@ WHERE return nil } -func (t *TrustCenterAlias) Delete( +func (t *ResourceAlias) Delete( ctx context.Context, conn pg.Querier, scope Scoper, ) error { q := ` -DELETE FROM trust_center_aliases +DELETE FROM resource_aliases WHERE %s AND resource_id = @resource_id @@ -270,7 +256,7 @@ WHERE _, err := conn.Exec(ctx, q, args) if err != nil { - return fmt.Errorf("cannot delete trust center alias: %w", err) + return fmt.Errorf("cannot delete resource alias: %w", err) } return nil