97 lines
3.9 KiB
PHP
97 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/../app/prefixed-pdo.php';
|
|
|
|
$assertSame = static function (string $expected, string $actual, string $message): void {
|
|
if ($expected !== $actual) {
|
|
fwrite(STDERR, "FEHLER: {$message}\nErwartet: {$expected}\nTatsächlich: {$actual}\n");
|
|
exit(1);
|
|
}
|
|
};
|
|
|
|
$assertSame('', app_validate_db_table_prefix(''), 'Ein leerer Prefix muss für die einmalige Datenübernahme erlaubt sein.');
|
|
$assertSame('test_', app_validate_db_table_prefix('test_'), 'Der Test-Prefix muss gültig sein.');
|
|
$assertSame('prod_', app_validate_db_table_prefix('prod_'), 'Der Produktions-Prefix muss gültig sein.');
|
|
|
|
foreach (['Test_', '1test_', 'test', 'test-'] as $invalidPrefix) {
|
|
try {
|
|
app_validate_db_table_prefix($invalidPrefix);
|
|
fwrite(STDERR, "FEHLER: Ungültiger Prefix {$invalidPrefix} wurde akzeptiert.\n");
|
|
exit(1);
|
|
} catch (RuntimeException) {
|
|
// Erwartet.
|
|
}
|
|
}
|
|
|
|
$previousAppEnv = getenv('APP_ENV');
|
|
$previousDbPrefix = getenv('DB_TABLE_PREFIX');
|
|
putenv('APP_ENV=prod');
|
|
putenv('DB_TABLE_PREFIX');
|
|
try {
|
|
app_db_table_prefix();
|
|
fwrite(STDERR, "FEHLER: Produktion wurde ohne DB_TABLE_PREFIX akzeptiert.\n");
|
|
exit(1);
|
|
} catch (RuntimeException) {
|
|
// Erwartet: Außerhalb von Dev gilt fail-closed.
|
|
} finally {
|
|
$previousAppEnv === false ? putenv('APP_ENV') : putenv('APP_ENV=' . $previousAppEnv);
|
|
$previousDbPrefix === false ? putenv('DB_TABLE_PREFIX') : putenv('DB_TABLE_PREFIX=' . $previousDbPrefix);
|
|
}
|
|
|
|
$assertSame(
|
|
'SELECT * FROM test_users JOIN test_tenants ON test_tenants.id = test_users.tenant_id',
|
|
app_prefix_database_sql('SELECT * FROM users JOIN tenants ON tenants.id = users.tenant_id', 'test_'),
|
|
'Normale Laufzeit-Abfragen müssen vollständig umgeschrieben werden.'
|
|
);
|
|
$assertSame(
|
|
'SELECT * FROM test_users',
|
|
app_prefix_database_sql('SELECT * FROM test_users', 'test_'),
|
|
'Bereits umgeschriebene Tabellennamen dürfen keinen doppelten Prefix erhalten.'
|
|
);
|
|
$assertSame(
|
|
"ALTER TABLE test_users ADD CONSTRAINT test_fk_users_tenant FOREIGN KEY (tenant_id) REFERENCES test_tenants(id)",
|
|
app_prefix_database_sql(
|
|
'ALTER TABLE users ADD CONSTRAINT fk_users_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id)',
|
|
'test_'
|
|
),
|
|
'Tabellen und Fremdschlüssel müssen gemeinsam umgeschrieben werden.'
|
|
);
|
|
$assertSame(
|
|
"WHERE TABLE_NAME = 'test_users' AND CONSTRAINT_NAME = 'test_fk_users_tenant'",
|
|
app_prefix_database_sql("WHERE TABLE_NAME = 'users' AND CONSTRAINT_NAME = 'fk_users_tenant'", 'test_'),
|
|
'Dynamische Migrationen müssen auch INFORMATION_SCHEMA-Vergleiche umschreiben.'
|
|
);
|
|
|
|
$migrationFiles = glob(__DIR__ . '/../database/migrations/*.sql') ?: [];
|
|
if (count($migrationFiles) !== 32) {
|
|
fwrite(STDERR, 'FEHLER: Erwartet wurden 32 Migrationen, gefunden wurden ' . count($migrationFiles) . ".\n");
|
|
exit(1);
|
|
}
|
|
|
|
$allMigrationSql = '';
|
|
foreach ($migrationFiles as $migrationFile) {
|
|
$contents = file_get_contents($migrationFile);
|
|
if ($contents === false) {
|
|
fwrite(STDERR, "FEHLER: Migration {$migrationFile} konnte nicht gelesen werden.\n");
|
|
exit(1);
|
|
}
|
|
$allMigrationSql .= "\n" . $contents;
|
|
}
|
|
$prefixedMigrationSql = app_prefix_database_sql($allMigrationSql, 'test_');
|
|
|
|
foreach (app_database_table_names() as $table) {
|
|
$rawPattern = '/(?<![A-Za-z0-9_])' . preg_quote($table, '/') . '(?![A-Za-z0-9_])/i';
|
|
if (preg_match($rawPattern, $allMigrationSql) === 1 && preg_match($rawPattern, $prefixedMigrationSql) === 1) {
|
|
fwrite(STDERR, "FEHLER: Tabelle {$table} blieb in den umgeschriebenen Migrationen ohne Prefix.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
if (preg_match('/(?<![A-Za-z0-9_])fk_[A-Za-z0-9_]+(?![A-Za-z0-9_])/i', $prefixedMigrationSql) === 1) {
|
|
fwrite(STDERR, "FEHLER: Mindestens ein Fremdschlüssel blieb in den Migrationen ohne Prefix.\n");
|
|
exit(1);
|
|
}
|
|
|
|
echo "DB-Prefix-Prüfung bestanden: Produktion ist fail-closed; Laufzeit-SQL und alle 32 Migrationen werden getrennt umgeschrieben.\n";
|