From faf3b1303bed5c7d24e00e340e01146255b3166e Mon Sep 17 00:00:00 2001 From: Mike Mueller Date: Tue, 16 Jun 2026 08:54:12 +0000 Subject: [PATCH] strategy: make pushed config authoritative handle_config_options only ever inserted/overwrote the keys a strategy sent, so removing a key (or unassigning a strategy) on the server left the old value lingering on the device. Persist the set of keys applied on the previous push (strategy_managed_keys in LocalConfig) and, on each apply, reset any key the server managed before but no longer sends back to its default. Keys the server never managed (the user's own local settings) are left untouched, so this remains a managed overlay rather than a wipe. Co-Authored-By: Claude Opus 4.8 (1M context) --- vendor/rustdesk/src/hbbs_http/sync.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/vendor/rustdesk/src/hbbs_http/sync.rs b/vendor/rustdesk/src/hbbs_http/sync.rs index baf524a..66f472d 100644 --- a/vendor/rustdesk/src/hbbs_http/sync.rs +++ b/vendor/rustdesk/src/hbbs_http/sync.rs @@ -413,9 +413,28 @@ fn heartbeat_url() -> String { format!("{}/api/heartbeat", url) } +/// LocalConfig key holding the JSON list of option keys the server's strategy +/// applied on the previous push, so we can make strategies *authoritative*. +const STRATEGY_MANAGED_KEYS: &str = "strategy_managed_keys"; + fn handle_config_options(config_options: HashMap) { let mut options = Config::get_options(); let default_settings = config::DEFAULT_SETTINGS.read().unwrap().clone(); + + // hello-agent local patch — authoritative strategies. The server's strategy + // owns exactly the keys it sends. Any key it managed on the previous push + // but no longer sends is reset to its default (the override is dropped), so + // removing a key/strategy on the server actually clears it on the device. + // Keys the server never managed (the user's own local settings) are left + // untouched, so this stays a managed-config overlay rather than a wipe. + let prev_managed: Vec = + serde_json::from_str(&LocalConfig::get_option(STRATEGY_MANAGED_KEYS)).unwrap_or_default(); + for k in prev_managed.iter() { + if !config_options.contains_key(k) { + options.remove(k); + } + } + config_options .iter() .map(|(k, v)| { @@ -429,6 +448,14 @@ fn handle_config_options(config_options: HashMap) { } }) .count(); + + // Remember the keys we now manage, for the next diff. + let managed: Vec<&String> = config_options.keys().collect(); + LocalConfig::set_option( + STRATEGY_MANAGED_KEYS.to_string(), + serde_json::to_string(&managed).unwrap_or_default(), + ); + Config::set_options(options); }