enhanced debug

This commit is contained in:
2026-06-01 15:02:20 +02:00
parent d6cbe5fbe5
commit 3d449a5672
2 changed files with 113 additions and 8 deletions

View File

@ -1,7 +1,7 @@
<?php
/**
* CLI: Print why the encrypted DB cannot be opened (deploy / env / permissions).
* Usage: php cli/diagnose_db.php
* Usage: php cli/diagnose_db.php [path/to/questionnaire_database]
*/
if (php_sapi_name() !== 'cli') {
http_response_code(403);
@ -42,7 +42,14 @@ echo "QDB_MASTER_KEY: set (" . strlen($keyEnv) . " chars)\n";
$b64 = base64_decode($keyEnv, true);
echo " parses as base64: " . ($b64 !== false && strlen($b64) > 0 ? 'yes (' . strlen($b64) . ' bytes)' : 'no (uses first 32 ASCII chars)') . "\n";
$dbPath = QDB_PATH;
$dbPath = $argv[1] ?? QDB_PATH;
if ($dbPath !== QDB_PATH && !is_file($dbPath)) {
echo "File not found: $dbPath\n";
exit(1);
}
if ($dbPath !== QDB_PATH) {
echo "Note: probing alternate file (app still uses " . QDB_PATH . " at runtime)\n";
}
$uploads = dirname($dbPath);
echo "uploads dir: $uploads\n";
echo " exists: " . (is_dir($uploads) ? 'yes' : 'no') . "\n";
@ -83,34 +90,55 @@ if ($b64 !== false && strlen($b64) > 0) {
}
echo "\nDecrypt probe (which key matches questionnaire_database?):\n";
$matched = null;
$matchedLabel = null;
$matchedKey = null;
$appKey = get_master_key_bytes();
foreach ($candidates as $label => $keyBytes) {
$probe = qdb_probe_decrypt($dbPath, $keyBytes);
if ($probe['ok']) {
echo " MATCH: $label\n";
$matched = $label;
if ($matchedLabel === null) {
$matchedLabel = $label;
$matchedKey = $keyBytes;
}
} else {
echo " no: $label\n";
}
}
if ($matched === null) {
if ($matchedLabel === null) {
echo "\nNo known key opened the file. Likely causes:\n";
echo " - DB was encrypted with a different QDB_MASTER_KEY than in .env now\n";
echo " - File was corrupted (e.g. interrupted save); try an older uploads/backups copy\n";
echo " - Wrong DB path (another install under /var/www/...)\n";
echo "\nProbe other copies, e.g.:\n";
echo " php cli/diagnose_db.php /var/www/html/qdb/uploads/questionnaire_database\n";
echo "\nWiping is NOT required for schema updates. Only wipe if you accept data loss\n";
echo "and run: mv uploads/questionnaire_database uploads/questionnaire_database.bak\n";
echo "then: php seed_admin.php <user> <pass>\n";
exit(1);
}
if ($matched !== 'current .env (get_master_key_bytes)') {
echo "\nThe DB does NOT match your current .env key but matches: $matched\n";
echo "Fix: put the matching key in .env, open the DB once, then re-save — or restore a backup.\n";
$dbMatchesAppKey = $matchedKey !== null && hash_equals($matchedKey, $appKey);
if ($dbPath !== QDB_PATH && $dbMatchesAppKey) {
echo "\nThis file decrypts with your .env. Restore it into the app uploads dir:\n";
echo " cp " . escapeshellarg($dbPath) . ' ' . escapeshellarg(QDB_PATH) . "\n";
echo " chown www-data:www-data " . escapeshellarg(QDB_PATH) . "\n";
exit(0);
}
if (!$dbMatchesAppKey) {
echo "\nThe DB does NOT match get_master_key_bytes() but matches: $matchedLabel\n";
echo "Fix: align QDB_MASTER_KEY in .env and php-fpm pool env, then re-run diagnose.\n";
exit(1);
}
if ($dbPath !== QDB_PATH) {
echo "\nDecrypt OK for alternate path. Run without arguments after copying into uploads/.\n";
exit(0);
}
try {
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
$version = (int)$pdo->query('PRAGMA user_version')->fetchColumn();