mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-18 04:49:13 +00:00
fix(api-v3): address CodeRabbit findings on the blueprint split
- _redact_credentials: blank scalar descendants of objects reached
through a credential-owned list (e.g. tokens: [{"value": "secret"}])
regardless of field name -- the existing name-based walk only
protected direct dict values under a credential key, not list items.
- wifi.py: reject enabled/force/auto_enable_ap_mode values
_parse_bool_ish can't recognize (400) instead of silently treating
them as False, which could disable Wi-Fi or the radio itself.
- Starlark manifest locking: lock a stable manifest.json.lock sidecar
instead of manifest.json itself, in both the standalone route path
(_starlark_manifest_lock) and the plugin path
(StarlarkAppsPlugin._save_manifest / _update_manifest_safe).
manifest.json is replaced by an atomic rename on every write, which
swaps in a fresh inode; a lock held on the old inode does not
exclude a second locker that opens the path afresh right after the
rename and gets the new inode, so two writers could race despite
each holding "a lock". A sidecar that no write ever touches always
resolves to the same inode for every locker.
Skipped as stale: the "serialize the complete manifest
read-modify-write" finding at api_v3/__init__.py -- every standalone
handler that calls _write_starlark_manifest is already wrapped in
_starlark_manifest_lock() on this branch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -195,7 +195,7 @@ class TestRadio:
|
||||
|
||||
@pytest.mark.parametrize("raw,expected", [
|
||||
(True, True), ("true", True), ("1", True), ("yes", True),
|
||||
(False, False), ("false", False), ("off", False), (0, False),
|
||||
(False, False), ("false", False), ("no", False), (0, False),
|
||||
])
|
||||
def test_enabled_coercion_is_string_aware(
|
||||
self, api_v3_client, wifi_manager, raw, expected):
|
||||
@@ -228,6 +228,22 @@ class TestRadio:
|
||||
wifi_manager.set_wifi_radio.side_effect = RuntimeError("boom")
|
||||
assert api_v3_client.post(self.URL, json={"enabled": True}).status_code == 500
|
||||
|
||||
def test_unrecognized_enabled_value_is_rejected_not_treated_as_false(
|
||||
self, api_v3_client, wifi_manager):
|
||||
# An invalid `enabled` used to silently fall back to False, which
|
||||
# can disconnect Wi-Fi (or, with force=true, drop the caller's own
|
||||
# connection to this interface) even though nothing asked for that.
|
||||
response = api_v3_client.post(self.URL, json={"enabled": "typo"})
|
||||
assert response.status_code == 400
|
||||
wifi_manager.set_wifi_radio.assert_not_called()
|
||||
|
||||
def test_unrecognized_force_value_is_rejected_not_treated_as_false(
|
||||
self, api_v3_client, wifi_manager):
|
||||
response = api_v3_client.post(
|
||||
self.URL, json={"enabled": False, "force": "typo"})
|
||||
assert response.status_code == 400
|
||||
wifi_manager.set_wifi_radio.assert_not_called()
|
||||
|
||||
|
||||
class TestAutoEnableApMode:
|
||||
URL = "/api/v3/wifi/ap/auto-enable"
|
||||
@@ -259,6 +275,13 @@ class TestAutoEnableApMode:
|
||||
api_v3_client.post(self.URL, json={"auto_enable_ap_mode": "false"})
|
||||
assert wifi_manager.config["auto_enable_ap_mode"] is False
|
||||
|
||||
def test_unrecognized_value_is_rejected_not_treated_as_false(
|
||||
self, api_v3_client, wifi_manager):
|
||||
wifi_manager.config = {}
|
||||
response = api_v3_client.post(self.URL, json={"auto_enable_ap_mode": "typo"})
|
||||
assert response.status_code == 400
|
||||
assert "auto_enable_ap_mode" not in wifi_manager.config
|
||||
|
||||
|
||||
class TestRadioEnabledAndForceAcceptIntegers:
|
||||
"""`{"enabled": 1}` / `{"enabled": 0}` used to be mishandled: the old
|
||||
|
||||
Reference in New Issue
Block a user