summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node')
-rw-r--r--packages/meshbay-node/tests/test_packaging_win.py122
1 files changed, 84 insertions, 38 deletions
diff --git a/packages/meshbay-node/tests/test_packaging_win.py b/packages/meshbay-node/tests/test_packaging_win.py
index b52e13a..7421a8c 100644
--- a/packages/meshbay-node/tests/test_packaging_win.py
+++ b/packages/meshbay-node/tests/test_packaging_win.py
@@ -191,66 +191,112 @@ def test_the_uninstaller_clears_the_autostart_launcher():
def test_customInstall_stops_a_running_daemon_before_overwriting_it():
nsh = NSH.read_text(encoding="utf-8")
- body = nsh.split("!macro customInstall", 1)[1].split("!macroend", 1)[0]
+ body = _macro_body(nsh, "customInstall")
assert "taskkill /IM meshbay-node.exe /F" in body
-# ── the one-time elevated firewall step ─────────────────────────────────────
+# ── the autostart choice + the one-time elevated firewall step ──────────────
def _macro_body(nsh: str, name: str) -> str:
- return nsh.split(f"!macro {name}", 1)[1].split("!macroend", 1)[0]
+ # \b after the name so "customInstall" does not also match the start of
+ # "customInstallMode" (which is defined just above it in the file).
+ return re.split(rf"!macro {re.escape(name)}\b", nsh, maxsplit=1)[1] \
+ .split("!macroend", 1)[0]
-def test_the_installer_offers_a_service_mode_choice_with_one_elevation():
+def test_the_all_users_install_mode_page_is_suppressed():
"""
- Adding a firewall rule or a boot-time Scheduled Task both need admin; the
- install itself never elevates (build.nsis allowElevation:false). So this
- must be opt-in (a Yes/No the user can decline) and skipped entirely in a
- silent install — an unattended `/S` install must never pop a UAC prompt on
- its own. Choosing service mode must fold the Scheduled Task AND the
- firewall rules into ONE elevation (service-mode.ps1), never two.
+ MeshBay is per-user only — the keystore and the DPAPI-protected secrets are
+ bound to the signed-in account (MESHBAY_DESIGN.md §11.2 / §7.5), and
+ build.nsis forbids elevation — so electron-builder's "anyone who uses this
+ computer / only me" page only ever showed its first option disabled.
+ customInstallMode forcing $isForceCurrentInstall skips the page and pins
+ per-user (multiUserUi.nsh: `${if} $isForceCurrentInstall == "1"` → abort).
+ """
+ nsh = NSH.read_text(encoding="utf-8")
+ mode = _macro_body(nsh, "customInstallMode")
+ assert 'StrCpy $isForceCurrentInstall "1"' in mode
+
+
+def test_the_autostart_choice_is_a_radio_page_defaulting_to_service():
+ """
+ The old two nested Yes/No MessageBoxes are one nsDialogs page now, with the
+ same three-way meaning: only-while-open / at-sign-in / background service.
+ Background service is the default selection (MB_AutoMode "2"), set in
+ customInit so a silent install — where the page never runs — still has a
+ definite value.
+ """
+ nsh = NSH.read_text(encoding="utf-8")
+ page = _macro_body(nsh, "customPageAfterChangeDir")
+
+ assert "Page custom mbAutostartPageCreate mbAutostartPageLeave" in page
+ assert page.count("${NSD_CreateRadioButton}") == 3, (
+ "expected exactly three autostart options")
+ assert "${NSD_Check} $MB_RbService" in page, (
+ "the background-service option must be the one checked by default")
+ assert 'StrCpy $MB_AutoMode "2"' in _macro_body(nsh, "customInit"), (
+ "customInit must default MB_AutoMode to service mode for silent installs")
+ # The MessageBox-driven flow is gone from customInstall entirely.
+ assert "MessageBox MB_YESNO" not in _macro_body(nsh, "customInstall")
+
+
+def test_the_firewall_rules_are_set_up_in_every_autostart_mode():
+ """
+ A node that silently accepts no connections is the failure mode
+ MESHBAY_DESIGN.md §7.5 calls out. So the rules go in whatever the autostart
+ choice: folded into the service elevation for mode "2" (service-mode.ps1
+ does task + firewall in one UAC), their own single elevation for
+ modes "0"/"1". Still ${Silent}-guarded — an unattended /S install cannot
+ raise a UAC prompt, and falls back to Windows' own first-connection dialogs.
"""
nsh = NSH.read_text(encoding="utf-8")
install = _macro_body(nsh, "customInstall")
- assert "${IfNot} ${Silent}" in install, (
- "the mode choice is not guarded against silent installs")
- assert install.count("MessageBox MB_YESNO") == 2, (
- "expected exactly two questions: service-mode-or-not, then (only in "
- "the per-user branch) the firewall-only question")
+ assert "${IfNot} ${Silent}" in install
assert 'ExecShellWait "runas"' in install
- # Service mode: one elevated call for both jobs, not one each.
- assert 'service-mode.ps1" -Action install' in install
- assert 'firewall.ps1" add' not in install.split("mb_peruser_mode:", 1)[0], (
- "service mode must not ALSO separately elevate for firewall.ps1 — "
- "service-mode.ps1 already does that in the same elevation")
- # Per-user mode (declined the service question) keeps today's separate,
- # still-opt-in firewall step.
- peruser_branch = install.split("mb_peruser_mode:", 1)[1]
- assert 'firewall.ps1" add' in peruser_branch
+
+ i_fw_check = install.index('firewall.ps1" check')
+ i_svc_if = install.index('${If} $MB_AutoMode == "2"')
+ i_svc_install = install.index('service-mode.ps1" -Action install')
+ i_fw_add = install.index('firewall.ps1" add')
+ # firewall check (unelevated) → service branch → firewall-only branch.
+ assert i_fw_check < i_svc_if < i_svc_install < i_fw_add
+ # The service branch's single elevation is service-mode.ps1; it does not
+ # ALSO call firewall.ps1 add (service-mode.ps1 already covers that).
+ assert 'firewall.ps1" add' not in install[i_svc_if:i_fw_add]
+
+
+def test_the_signin_mode_installs_the_per_user_startup_launcher():
+ """Mode "1" ("at sign-in") drops the Startup-folder .vbs via the frozen
+ daemon's own `autostart install` verb — no admin, idempotent. The nearest
+ enclosing choice must be `$MB_AutoMode == "1"`, so modes "0"/"2" skip it."""
+ nsh = NSH.read_text(encoding="utf-8")
+ install = _macro_body(nsh, "customInstall")
+
+ i_call = install.index('meshbay-node.exe" autostart install')
+ last_if = install.rindex("${If} $MB_AutoMode ==", 0, i_call)
+ assert install[last_if:i_call].startswith('${If} $MB_AutoMode == "1"'), (
+ "the Startup launcher must be gated on the at-sign-in choice")
def test_reinstalling_with_everything_already_in_place_asks_nothing():
"""
Get-NetFirewallRule needs no admin, only New/Remove do — so customInstall
- checks the firewall rules first, unelevated, and only reaches the mode
- question (and therefore a possible UAC prompt) when something is actually
- missing. Without this, running setup a second time — an upgrade, a repair
- install — would re-ask the question (and, in service mode, re-trigger UAC)
- even though nothing needs to change. Checking the firewall rules alone is
- enough: service-mode.ps1 always sets up both together, so if the rules
- are there, so is everything else that was chosen last time.
+ checks the firewall rules first, unelevated, and only elevates when
+ something is actually missing. Without this, a repair or an upgrade that
+ changes nothing would still re-trigger UAC. In service mode the task's
+ presence is checked the same unelevated way (service.ps1 status), and both
+ must be satisfied to skip.
"""
nsh = NSH.read_text(encoding="utf-8")
install = _macro_body(nsh, "customInstall")
check_line = 'firewall.ps1" check'
assert check_line in install
- mode_question = "Run MeshBay Node as a background service?"
- # The check must run, and be evaluated, before the mode question — not after.
- assert install.index(check_line) < install.index(mode_question)
- assert "Pop $0" in install and "${If} $0 == 0" in install
- assert "Goto mb_mode_done" in install
+ # The check runs before any elevation.
+ assert install.index(check_line) < install.index('ExecShellWait "runas"')
+ assert 'service.ps1" status' in install
+ assert "Goto mb_auto_done" in install
def test_the_uninstaller_offers_to_remove_everything_privileged_default_no():
@@ -539,8 +585,8 @@ def test_the_bundled_daemon_goes_on_the_user_path_and_comes_back_off():
nsh = NSH.read_text(encoding="utf-8")
assert "!insertmacro WordAdd" in nsh and "!insertmacro un.WordAdd" in nsh
- install = nsh.split("!macro customInstall", 1)[1].split("!macroend", 1)[0]
- uninstall = nsh.split("!macro customUnInstall", 1)[1].split("!macroend", 1)[0]
+ install = _macro_body(nsh, "customInstall")
+ uninstall = _macro_body(nsh, "customUnInstall")
assert 'HKCU "Environment" "Path"' in install
assert "${WordAdd}" in install and '"+${MB_NODE_BIN}"' in install
assert "${un.WordAdd}" in uninstall and '"-${MB_NODE_BIN}"' in uninstall