import { MigrationInterface, QueryRunner } from 'typeorm'; function quoteIdentifier(identifier: string): string { return `"${identifier.replaceAll('"', '""')}"`; } export class F67UserReusableSignature1790124600000 implements MigrationInterface { name = 'F67UserReusableSignature1790124600000'; public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE TABLE user_signature_profiles ( user_id uuid PRIMARY KEY, original_name varchar(255) NOT NULL, mime_type varchar(100) NOT NULL, size_bytes integer NOT NULL, image_sha256 char(64) NOT NULL, image_data bytea NOT NULL, updated_by uuid, created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_user_signature_profiles_png CHECK (mime_type='image/png'), CONSTRAINT chk_user_signature_profiles_size CHECK ( size_bytes BETWEEN 1 AND 1048576 AND OCTET_LENGTH(image_data)=size_bytes ), CONSTRAINT chk_user_signature_profiles_sha CHECK ( image_sha256 ~ '^[0-9a-f]{64}$' ), CONSTRAINT fk_user_signature_profiles_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, CONSTRAINT fk_user_signature_profiles_updated_by FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL ) `); const appRole = process.env.DB_APP_USER; if (!appRole) throw new Error('Missing required environment variable: DB_APP_USER'); const applicationRole = quoteIdentifier(appRole); await queryRunner.query(` GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE user_signature_profiles TO ${applicationRole} `); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query('DROP TABLE user_signature_profiles'); } }