diff options
Diffstat (limited to 'packages/meshbay-node')
| -rw-r--r-- | packages/meshbay-node/tests/test_packaging_win.py | 122 |
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 |