2 Commits
Author SHA1 Message Date
bonaminandClaude Opus 5.5 f5db83f26c fix(devices): sync users.device_serials when PUT /api/devices/{id} changes user_list
DeviceUpdate accepts user_list, so a device PUT could add or remove users
without touching their device_serials - leaving the MQTT app ACL stale
(a removed user would keep access; an added user would be denied).

update_device now diffs the old vs new user_list and, in the same atomic
batch as the device write, ArrayUnion/ArrayRemoves the device's serial on
each added/removed user, then invalidates their MQTT ACL cache entries.
Dangling user references are skipped (updating a missing doc would fail
the whole batch). PUTs without user_list take the old single-update path.

Covered by tests/test_device_serials_sync.py (fake Firestore).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:44:34 +03:00
bonaminandClaude Opus 5.5 3acd89a2c6 test(mqtt-auth): cover /mqtt/auth/user and /mqtt/auth/acl
First pytest suite in the backend (backend/tests/, run from backend/ with
`python -m pytest tests`). firebase_admin.verify_id_token and Firestore
are mocked, so no network access is needed. 82 cases:

- /user devices: HMAC ok / wrong / other serial's HMAC, kiosk HMAC,
  legacy password with flag on/off, legacy rejected for non-device-shaped
  usernames and for app_ users, HMAC rejected for app_ users, legacy-login
  log rate limiting.
- /user app users: valid token (asserts check_revoked=True), token for a
  different uid, revoked, expired, blocked user, unknown uid, empty uid,
  and that a denied token never appears in logs.
- /acl app users: acc 1/2/4 allow/deny per topic, unsupported acc values,
  wildcards, foreign serial, malformed topics, wrong clientid prefixes
  (incl. uid-prefix collision), blocked/unknown users, cache hit +
  invalidate, cache expiry.
- /acl devices/kiosk/superuser: unchanged behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:04:37 +03:00