Android CI / RC / Android · lint, tests, debug APK, release compile (push) Failing after 2m3s
DH V2 CI / API · typecheck, tests, build (push) Successful in 34s
DH V2 CI / WEB · typecheck, build (push) Successful in 20s
Production dependency audit / API · production dependencies (push) Successful in 9s
Production dependency audit / WEB · production dependencies (push) Successful in 8s
DH V2 CI / Docker / scripts contract (push) Successful in 1m18s
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
await queryRunner.query('DROP TABLE user_signature_profiles');
|
|
}
|
|
}
|