98549c52be
Code-review Task 1: явный per-table GRANT-блок для import_unknown_statuses использовал несуществующие роли (crm_app_admin / crm_readonly). Реальные роли — crm_app_user / crm_admin_user / crm_migrator / crm_audit_writer / crm_supplier_worker (db/00_create_roles.sql). Блок удалён целиком из db/02_grants.sql и db/schema.sql: import_unknown_statuses — обычная tenant-scoped таблица, покрыта umbrella GRANT ... ON ALL TABLES + ALTER DEFAULT PRIVILEGES (как import_log), явный per-table grant не нужен. ImportSchemaTest: UNIQUE-тест усилен — проверяет состав колонок (status_ru, tenant_id), а не только наличие constraint'а типа 'u'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
41 lines
1.8 KiB
PHP
41 lines
1.8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Schema;
|
||
|
||
test('import_log имеет 5 новых колонок enrichment', function (): void {
|
||
foreach (['entity_type', 'source_system', 'mapping_config', 'unknown_statuses_count', 'dry_run'] as $column) {
|
||
expect(Schema::hasColumn('import_log', $column))->toBeTrue("import_log.$column отсутствует");
|
||
}
|
||
});
|
||
|
||
test('import_unknown_statuses существует с RLS', function (): void {
|
||
expect(Schema::hasTable('import_unknown_statuses'))->toBeTrue();
|
||
|
||
$rls = DB::selectOne(
|
||
"SELECT relrowsecurity FROM pg_class WHERE relname = 'import_unknown_statuses'"
|
||
);
|
||
expect($rls)->not->toBeNull('pg_class row for import_unknown_statuses не найден');
|
||
/** @var object{relrowsecurity: bool} $rls */
|
||
expect($rls->relrowsecurity)->toBeTrue('RLS не включён на import_unknown_statuses');
|
||
|
||
$policy = DB::selectOne(
|
||
"SELECT 1 AS ok FROM pg_policies WHERE tablename = 'import_unknown_statuses' AND policyname = 'tenant_isolation'"
|
||
);
|
||
expect($policy)->not->toBeNull('Политика tenant_isolation отсутствует');
|
||
});
|
||
|
||
test('import_unknown_statuses имеет UNIQUE именно по (tenant_id, status_ru)', function (): void {
|
||
$row = DB::selectOne(
|
||
"SELECT array_to_string(array_agg(a.attname ORDER BY a.attname), ',') AS cols
|
||
FROM pg_constraint c
|
||
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey)
|
||
WHERE c.conrelid = 'import_unknown_statuses'::regclass AND c.contype = 'u'"
|
||
);
|
||
expect($row)->not->toBeNull('UNIQUE-ограничение отсутствует');
|
||
/** @var object{cols: string} $row */
|
||
expect($row->cols)->toBe('status_ru,tenant_id');
|
||
});
|