Fix config restore for CLI exports (related to #646)

The v4.26.4 fix inadvertently broke CLI export compatibility. The frontend
attempted JSON.parse on all backup files and returned early with "Invalid
JSON file format" when parsing failed. This prevented the format detection
code from ever executing, breaking CLI-generated exports which are raw
base64 strings without a JSON wrapper.

Root cause:
- CLI exports (`pulse config export`) output raw base64 via
  internal/config/export.go:128
- The fix at Settings.tsx:2030-2034 called showError() and returned
  immediately on parse failure
- Format detection logic at lines 2040-2049 never executed for CLI exports

This changes the parsing flow to:
1. Try JSON.parse first (handles UI exports with {status, data} format)
2. On parse success, extract data field as before
3. On parse failure, treat entire file contents as raw base64 (CLI format)

This preserves the v4.26.4 improvements (12-char validation, better error
messages) while restoring CLI export compatibility.

Related to #646 where user confirmed v4.26.4 still failed to restore backups.
This commit is contained in:
rcourtman 2025-11-07 17:57:22 +00:00
parent 679225510e
commit d70fa88d26

View file

@ -2024,28 +2024,30 @@ const Settings: Component<SettingsProps> = (props) => {
try { try {
const fileContent = await importFile()!.text(); const fileContent = await importFile()!.text();
let exportData;
try {
exportData = JSON.parse(fileContent);
} catch (parseError) {
showError('Invalid JSON file format');
logger.error('JSON parse error', parseError);
return;
}
// Support both formats: // Support three formats:
// 1. New format: {status: "success", data: "base64string"} // 1. UI export: {status: "success", data: "base64string"}
// 2. Legacy/CLI format: raw base64 string or {data: "base64string"} // 2. Legacy format: {data: "base64string"}
// 3. CLI export: raw base64 string (no JSON wrapper)
let encryptedData: string; let encryptedData: string;
if (typeof exportData === 'string') {
// Raw base64 string from CLI export // Try to parse as JSON first
encryptedData = exportData; try {
} else if (exportData.data) { const exportData = JSON.parse(fileContent);
// Standard format with data field
encryptedData = exportData.data; if (typeof exportData === 'string') {
} else { // Raw base64 string wrapped in JSON (edge case)
showError('Invalid backup file format. Expected encrypted data in "data" field.'); encryptedData = exportData;
return; } else if (exportData.data) {
// Standard format with data field
encryptedData = exportData.data;
} else {
showError('Invalid backup file format. Expected encrypted data in "data" field.');
return;
}
} catch (parseError) {
// Not JSON - treat entire contents as raw base64 from CLI export
encryptedData = fileContent.trim();
} }
// Get CSRF token from cookie // Get CSRF token from cookie