mobile-connector: merge pairing+devices into one self-service Mobile App page
Nightly Build / build (push) Successful in 7m3s

The two admin-only console pages become a single "Mobile App" page
visible to every logged-in user: connection status (with the last
connection error for troubleshooting), the device list (admin sees all,
others only their own), a pairing dialog with the QR, and — admin-only —
a settings dialog hosting the plugin config, including a relay picker
(official grayed out, test, custom URL). The generic plugin-detail
config form defers to it via the new Plugin::config_in_detail_page flag.

Pairing is now self-service: any user opens a window and the device
auto-binds to them; revocation is admin-for-anyone, owner-for-self;
(re)binding to another user stays admin-only. Binding-managed plugins
(manages_own_access) now expose their non-admin pages to all users and
self-scope per caller (web_pages_for). The relay client records the
error that ends a WS session and clears it on reconnect.
This commit is contained in:
2026-07-27 23:49:50 +01:00
parent a78259551e
commit 50e1333d99
18 changed files with 834 additions and 411 deletions
+7 -6
View File
@@ -1,11 +1,12 @@
// Shared helpers for the mobile-connector console fragments.
// Shared helpers for the mobile-connector "Mobile App" page fragment.
//
// Served at `/api/plugin/mobile-connector/web/common.js` and imported by the
// two page fragments via a relative `./common.js` specifier. Everything the
// fragments need is self-contained here — the host injects no APIs (see
// `Plugin::web_pages` contract): they talk only to `/api/plugin/<id>/…` and,
// for the user directory used by the reassign dropdown, the host `/api/users`
// (the fragment runs with the logged-in admin's full session privileges).
// page fragment via a relative `./common.js` specifier. Everything the
// fragment needs is self-contained here — the host injects no APIs (see
// `Plugin::web_pages` contract): it talks only to `/api/plugin/<id>/…` and,
// for the user directory used by the admin reassign dropdown plus the caller's
// role, the host `/api/users` and `/api/auth/me` (the fragment runs with the
// logged-in user's full session privileges).
//
// i18n: the plugin ships its own dictionary (`./i18n.js`) and registers it into
// the host's shared strings via `addStrings` (imported from the app root by the