feat: Sync Config::{MdnsEnabled,ShowEmails} across devices (#4954)

Motivation: Syncing these options will improve UX in very most cases and should be done. Other
candidates are less clear or are advanced options, we can reconsider that at some point later.

Approach:
- Sync options one-by-one when the corresponding option is set (even if to the same value).
- Don't sync when an option is reset to a default as defaults may differ across client versions.
- Check on both sides that the option should be synced so that if there are different client
  versions, the synchronisation of the option is either done or not done in both directions.
  Moreover, receivers of a config value need to check if a key can be synced because some settings
  (e.g. Avatar path) could otherwise lead to exfiltration of files from a receiver's device if we
  assume an attacker to have control of a device in a multi-device setting or if multiple users are
  sharing an account.
- Don't sync `SyncMsgs` itself.
This commit is contained in:
iequidoo
2023-11-16 21:42:20 -03:00
committed by iequidoo
parent 084434d3b4
commit a47fec7f6c
3 changed files with 135 additions and 2 deletions

View File

@@ -20,7 +20,7 @@ use crate::tools::time;
use crate::{stock_str, token};
/// Whether to send device sync messages. Aimed for usage in the internal API.
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub(crate) enum Sync {
Nosync,
Sync,
@@ -35,6 +35,15 @@ impl From<Sync> for bool {
}
}
impl From<bool> for Sync {
fn from(sync: bool) -> Sync {
match sync {
false => Sync::Nosync,
true => Sync::Sync,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct QrTokenData {
pub(crate) invitenumber: String,
@@ -50,6 +59,10 @@ pub(crate) enum SyncData {
id: chat::SyncId,
action: chat::SyncAction,
},
Config {
key: Config,
val: String,
},
}
#[derive(Debug, Serialize, Deserialize)]
@@ -263,6 +276,10 @@ impl Context {
AddQrToken(token) => self.add_qr_token(token).await,
DeleteQrToken(token) => self.delete_qr_token(token).await,
AlterChat { id, action } => self.sync_alter_chat(id, action).await,
SyncData::Config { key, val } => match key.is_synced() {
true => self.set_config_ex(Sync::Nosync, *key, Some(val)).await,
false => Ok(()),
},
},
SyncDataOrUnknown::Unknown(data) => {
warn!(self, "Ignored unknown sync item: {data}.");