fix: clean-install bugs — Tor false-installed, WG port-check honesty, encrypted backup upload
Unit Tests / test (push) Successful in 13m7s
Unit Tests / test (push) Successful in 13m7s
Three independent bugs surfaced during pic1 clean-install testing: 1. Tor _exit_status hardcoded configured=True regardless of whether Tor was actually installed. Status now flows through the same store-installed / container-running bridge used by every other optional service, so Tor only reports installed when the container is present and running. 2. check_port_open compared the port from wg0.conf against the kernel-reported listening port, causing false "port closed" results whenever the conf and the running container were momentarily out of sync. The function is now an honest liveness check: any wg0 interface that is up and has a "listening port:" line in `wg show` is considered open. The check-port API endpoint now also returns the actual kernel listening_port and a port_mismatch flag so the UI can inform the user when a container recreate is needed. (The recreate machinery already exists via the port-change pending-restart path; this fix makes the mismatch visible rather than silently lying about reachability.) 3. upload_backup only handled .zip archives; encrypted .age blobs were rejected with a generic error. The endpoint now calls backup_crypto.is_encrypted() to detect Age-encrypted blobs and stores them verbatim as <id>.tar.gz.age with mode 0600 so they can be uploaded and then restored with a passphrase. The plaintext zip path is unchanged. Tests added/updated: test_connectivity_manager.py (Tor status bridge), test_wireguard_manager.py + test_wireguard_endpoints.py (port-check liveness and mismatch flag), test_config_backup_restore_http.py (encrypted upload round-trip). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -720,7 +720,9 @@ function Settings() {
|
||||
const url = URL.createObjectURL(res.data);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `${id}.zip`;
|
||||
// Encrypted archives already carry their .tar.gz.age extension; only
|
||||
// plaintext backups (served as a zip) need a .zip name appended.
|
||||
a.download = id.endsWith('.age') ? id : `${id}.zip`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} catch {
|
||||
@@ -739,7 +741,7 @@ function Settings() {
|
||||
const res = await cellAPI.listBackups();
|
||||
setBackups(res.data || []);
|
||||
} catch {
|
||||
toast('Upload failed — ensure it is a valid backup zip', 'error');
|
||||
toast('Upload failed — ensure it is a valid backup (.zip or encrypted .age) file', 'error');
|
||||
} finally {
|
||||
setBackupUploading(false);
|
||||
}
|
||||
@@ -1088,7 +1090,7 @@ function Settings() {
|
||||
<label className="btn-secondary flex items-center gap-2 text-sm cursor-pointer" title="Upload backup zip">
|
||||
{backupUploading ? <RefreshCw className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
|
||||
Upload
|
||||
<input type="file" accept=".zip" className="hidden" onChange={uploadBackup} />
|
||||
<input type="file" accept=".zip,.age" className="hidden" onChange={uploadBackup} />
|
||||
</label>
|
||||
<button
|
||||
onClick={createBackup}
|
||||
|
||||
Reference in New Issue
Block a user