Files
dh-inspeccion-v2/api-v3/src/database/migrations/1787335200000-phase-d5-2-finding-catalog-administration.ts
T

90 lines
3.3 KiB
TypeScript

import { MigrationInterface, QueryRunner } from 'typeorm';
function quoteIdentifier(identifier: string): string {
return `"${identifier.replaceAll('"', '""')}"`;
}
export class PhaseD52FindingCatalogAdministration1787335200000 implements MigrationInterface {
name = 'PhaseD52FindingCatalogAdministration1787335200000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE finding_catalog_item_versions (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
item_id uuid NOT NULL,
revision integer NOT NULL,
snapshot jsonb NOT NULL,
actor_user_id uuid,
actor_username varchar(80),
created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_finding_catalog_item_versions_revision
UNIQUE (item_id, revision),
CONSTRAINT chk_finding_catalog_item_versions_revision
CHECK (revision > 0),
CONSTRAINT chk_finding_catalog_item_versions_snapshot
CHECK (jsonb_typeof(snapshot) = 'object'),
CONSTRAINT fk_finding_catalog_item_versions_item FOREIGN KEY (item_id)
REFERENCES finding_catalog_items(id) ON DELETE RESTRICT,
CONSTRAINT fk_finding_catalog_item_versions_actor FOREIGN KEY (actor_user_id)
REFERENCES users(id) ON DELETE SET NULL
)
`);
await queryRunner.query(`
CREATE INDEX idx_finding_catalog_item_versions_item_revision
ON finding_catalog_item_versions (item_id, revision DESC)
`);
await queryRunner.query(`
CREATE INDEX idx_finding_catalog_item_versions_created_at
ON finding_catalog_item_versions (created_at DESC)
`);
await queryRunner.query(`
INSERT INTO finding_catalog_item_versions (
item_id, revision, snapshot, actor_username, created_at
)
SELECT
item.id,
item.revision,
JSONB_BUILD_OBJECT(
'id', item.id,
'categoryId', category.id,
'categoryCode', category.code,
'categoryName', category.name,
'code', item.code,
'sourceNumber', item.source_number,
'title', item.title,
'legalBasis', item.legal_basis,
'glossary', item.glossary,
'importNote', item.import_note,
'revision', item.revision,
'isActive', item.is_active
),
'migration:D5.2',
item.updated_at
FROM finding_catalog_items item
INNER JOIN finding_categories category ON category.id = item.category_id
`);
const appRole = process.env.DB_APP_USER;
if (!appRole) throw new Error('Missing required environment variable: DB_APP_USER');
const roleRows = (await queryRunner.query(
'SELECT 1 FROM pg_roles WHERE rolname = $1',
[appRole],
)) as unknown[];
if (roleRows.length !== 1) throw new Error('Configured DB_APP_USER does not exist');
const applicationRole = quoteIdentifier(appRole);
await queryRunner.query(`
GRANT SELECT, INSERT ON TABLE finding_catalog_item_versions
TO ${applicationRole}
`);
await queryRunner.query(`
REVOKE UPDATE, DELETE ON TABLE finding_catalog_item_versions
FROM ${applicationRole}
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP TABLE finding_catalog_item_versions');
}
}