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
+16 -6
View File
@@ -136,14 +136,24 @@ pub trait Plugin: Send + Sync {
/// Whether the plugin decides *who may use it* through its own binding /
/// pairing lifecycle rather than the generic `plugin_access` grants — e.g.
/// the mobile connector, whose access is the admin-mediated device→user
/// binding (§13). When `true`, the admin Plugins UI suppresses the "User
/// access" checklist (it would control nothing) and the plugin never appears
/// in a user's "My plugins" view. Default `false`: access is the admin's
/// per-user `plugin_access` grant (as Telegram usesits grant gates the
/// bot at runtime even though pairing is self-service).
/// the mobile connector, whose access is the device→user binding (§13).
/// When `true`, the admin Plugins UI suppresses the "User access"
/// checklist (it would control nothing), the plugin never appears in a
/// user's "My plugins" view, and its non-`admin_only` `web_pages()` are
/// visible to every logged-in userthe page itself scopes what each
/// caller sees (e.g. admin sees all devices, others only their own).
/// Default `false`: access is the admin's per-user `plugin_access` grant
/// (as Telegram uses — its grant gates the bot at runtime even though
/// pairing is self-service).
fn manages_own_access(&self) -> bool { false }
/// Whether the admin plugin-detail page renders the generic
/// `config_schema` form for this plugin. Default `true`. A plugin that
/// hosts its own configuration UI inside one of its `web_pages()` (e.g.
/// the mobile connector, whose Mobile App page has a settings dialog)
/// returns `false` so the config is not edited in two places.
fn config_in_detail_page(&self) -> bool { true }
/// Called whenever the enabled flag or config changes — including at startup.
/// The plugin is responsible for diffing state and restarting only what changed.
async fn reload(&self, enabled: bool, config: Value, ctx: PluginContext) -> Result<()>;