Skip to content

Commit 9f090e3

Browse files
committed
Migrate settings to v9
- Change `selected_obfuscation` default to `auto`. - Migrate `selected_obfuscation` from `off` to `auto` for existing users.
1 parent a30c4f9 commit 9f090e3

File tree

5 files changed

+313
-3
lines changed

5 files changed

+313
-3
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Line wrap the file at 100 chars. Th
2525
### Added
2626
- Add ability to import server IP overrides in GUI.
2727

28+
### Changed
29+
- Change default obfuscation setting to `auto`.
30+
- Migrate obfuscation settings for existing users from `off` to `auto`.
31+
2832
#### Android
2933
- Add support for all screen orientations.
3034
- Add toggle for enabling or disabling split tunneling.

mullvad-daemon/src/migrations/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ mod v4;
5252
mod v5;
5353
mod v6;
5454
mod v7;
55+
mod v8;
5556

5657
const SETTINGS_FILE: &str = "settings.json";
5758

@@ -181,6 +182,7 @@ async fn migrate_settings(
181182
let migration_data = v5::migrate(settings)?;
182183
v6::migrate(settings)?;
183184
v7::migrate(settings)?;
185+
v8::migrate(settings)?;
184186

185187
Ok(migration_data)
186188
}

mullvad-daemon/src/migrations/v8.rs

+302
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
use super::Result;
2+
use mullvad_types::settings::SettingsVersion;
3+
4+
// This migration doesn't vendor any types.
5+
6+
/// This is a closed migraton.
7+
///
8+
/// If `ofuscation_settings.selected_obfuscation` is `off`, set it to `auto`.
9+
pub fn migrate(settings: &mut serde_json::Value) -> Result<()> {
10+
if !version_matches(settings) {
11+
return Ok(());
12+
}
13+
14+
log::info!("Migrating settings format to V9");
15+
16+
migrate_selected_obfuscaton(settings)?;
17+
18+
settings["settings_version"] = serde_json::json!(SettingsVersion::V9);
19+
20+
Ok(())
21+
}
22+
23+
fn migrate_selected_obfuscaton(settings: &mut serde_json::Value) -> Result<()> {
24+
let Some(selected_obfuscation) = settings
25+
.get_mut("obfuscation_settings")
26+
.and_then(|obfuscation_settings| obfuscation_settings.get_mut("selected_obfuscation"))
27+
else {
28+
return Ok(());
29+
};
30+
31+
if selected_obfuscation == "off" {
32+
*selected_obfuscation = "auto".into();
33+
}
34+
35+
Ok(())
36+
}
37+
38+
fn version_matches(settings: &serde_json::Value) -> bool {
39+
settings
40+
.get("settings_version")
41+
.map(|version| version == SettingsVersion::V8 as u64)
42+
.unwrap_or(false)
43+
}
44+
45+
#[cfg(test)]
46+
mod test {
47+
use super::{migrate, migrate_selected_obfuscaton, version_matches};
48+
49+
pub const V8_SETTINGS: &str = r#"
50+
{
51+
"relay_settings": {
52+
"normal": {
53+
"location": {
54+
"only": {
55+
"location": {
56+
"country": "se"
57+
}
58+
}
59+
},
60+
"providers": "any",
61+
"ownership": "any",
62+
"tunnel_protocol": "any",
63+
"wireguard_constraints": {
64+
"port": "any",
65+
"ip_version": "any",
66+
"use_multihop": false,
67+
"entry_location": {
68+
"only": {
69+
"location": {
70+
"country": "se"
71+
}
72+
}
73+
}
74+
},
75+
"openvpn_constraints": {
76+
"port": "any"
77+
}
78+
}
79+
},
80+
"bridge_settings": {
81+
"bridge_type": "normal",
82+
"normal": {
83+
"location": "any",
84+
"providers": "any",
85+
"ownership": "any"
86+
},
87+
"custom": null
88+
},
89+
"obfuscation_settings": {
90+
"selected_obfuscation": "off",
91+
"udp2tcp": {
92+
"port": "any"
93+
}
94+
},
95+
"bridge_state": "auto",
96+
"custom_lists": {
97+
"custom_lists": []
98+
},
99+
"api_access_methods": {
100+
"direct": {
101+
"id": "5b11a427-a06e-4a06-9864-0d3df7402ee4",
102+
"name": "Direct",
103+
"enabled": true,
104+
"access_method": {
105+
"built_in": "direct"
106+
}
107+
},
108+
"mullvad_bridges": {
109+
"id": "bf03faf6-229e-4b1e-a7bd-32e0786ca5cb",
110+
"name": "Mullvad Bridges",
111+
"enabled": true,
112+
"access_method": {
113+
"built_in": "bridge"
114+
}
115+
},
116+
"custom": []
117+
},
118+
"allow_lan": false,
119+
"block_when_disconnected": false,
120+
"auto_connect": false,
121+
"tunnel_options": {
122+
"openvpn": {
123+
"mssfix": null
124+
},
125+
"wireguard": {
126+
"mtu": null,
127+
"quantum_resistant": "auto",
128+
"rotation_interval": null
129+
},
130+
"generic": {
131+
"enable_ipv6": false
132+
},
133+
"dns_options": {
134+
"state": "default",
135+
"default_options": {
136+
"block_ads": false,
137+
"block_trackers": false,
138+
"block_malware": false,
139+
"block_adult_content": false,
140+
"block_gambling": false,
141+
"block_social_media": false
142+
},
143+
"custom_options": {
144+
"addresses": []
145+
}
146+
}
147+
},
148+
"relay_overrides": [],
149+
"show_beta_releases": true,
150+
"settings_version": 8
151+
}
152+
"#;
153+
154+
pub const V9_SETTINGS: &str = r#"
155+
{
156+
"relay_settings": {
157+
"normal": {
158+
"location": {
159+
"only": {
160+
"location": {
161+
"country": "se"
162+
}
163+
}
164+
},
165+
"providers": "any",
166+
"ownership": "any",
167+
"tunnel_protocol": "any",
168+
"wireguard_constraints": {
169+
"port": "any",
170+
"ip_version": "any",
171+
"use_multihop": false,
172+
"entry_location": {
173+
"only": {
174+
"location": {
175+
"country": "se"
176+
}
177+
}
178+
}
179+
},
180+
"openvpn_constraints": {
181+
"port": "any"
182+
}
183+
}
184+
},
185+
"bridge_settings": {
186+
"bridge_type": "normal",
187+
"normal": {
188+
"location": "any",
189+
"providers": "any",
190+
"ownership": "any"
191+
},
192+
"custom": null
193+
},
194+
"obfuscation_settings": {
195+
"selected_obfuscation": "auto",
196+
"udp2tcp": {
197+
"port": "any"
198+
}
199+
},
200+
"bridge_state": "auto",
201+
"custom_lists": {
202+
"custom_lists": []
203+
},
204+
"api_access_methods": {
205+
"direct": {
206+
"id": "5b11a427-a06e-4a06-9864-0d3df7402ee4",
207+
"name": "Direct",
208+
"enabled": true,
209+
"access_method": {
210+
"built_in": "direct"
211+
}
212+
},
213+
"mullvad_bridges": {
214+
"id": "bf03faf6-229e-4b1e-a7bd-32e0786ca5cb",
215+
"name": "Mullvad Bridges",
216+
"enabled": true,
217+
"access_method": {
218+
"built_in": "bridge"
219+
}
220+
},
221+
"custom": []
222+
},
223+
"allow_lan": false,
224+
"block_when_disconnected": false,
225+
"auto_connect": false,
226+
"tunnel_options": {
227+
"openvpn": {
228+
"mssfix": null
229+
},
230+
"wireguard": {
231+
"mtu": null,
232+
"quantum_resistant": "auto",
233+
"rotation_interval": null
234+
},
235+
"generic": {
236+
"enable_ipv6": false
237+
},
238+
"dns_options": {
239+
"state": "default",
240+
"default_options": {
241+
"block_ads": false,
242+
"block_trackers": false,
243+
"block_malware": false,
244+
"block_adult_content": false,
245+
"block_gambling": false,
246+
"block_social_media": false
247+
},
248+
"custom_options": {
249+
"addresses": []
250+
}
251+
}
252+
},
253+
"relay_overrides": [],
254+
"show_beta_releases": true,
255+
"settings_version": 9
256+
}
257+
"#;
258+
259+
#[test]
260+
fn test_v8_to_v9_migration() {
261+
let mut old_settings = serde_json::from_str(V8_SETTINGS).unwrap();
262+
263+
assert!(version_matches(&old_settings));
264+
migrate(&mut old_settings).unwrap();
265+
let new_settings: serde_json::Value = serde_json::from_str(V9_SETTINGS).unwrap();
266+
267+
assert_eq!(&old_settings, &new_settings);
268+
}
269+
270+
/// For obfuscation_settings
271+
/// obfuscation_settings: { selected_obfuscation: "on" } should be not be changed.
272+
#[test]
273+
fn migrate_seleted_obfuscation_from_on() {
274+
let mut migrated_settings: serde_json::Value =
275+
serde_json::from_str(r#"{ "obfuscation_settings": { "selected_obfuscation": "on" } }"#)
276+
.unwrap();
277+
let expected_settings = migrated_settings.clone();
278+
279+
migrate_selected_obfuscaton(&mut migrated_settings).unwrap();
280+
281+
assert_eq!(migrated_settings, expected_settings);
282+
}
283+
284+
/// For obfuscation_settings
285+
/// obfuscation_settings: { selected_obfuscation: "off" } should be replaced with
286+
/// obfuscation_settings: { selected_obfuscation: "auto" }
287+
#[test]
288+
fn migrate_seleted_obfuscation_from_off() {
289+
let mut migrated_settings: serde_json::Value = serde_json::from_str(
290+
r#"{ "obfuscation_settings": { "selected_obfuscation": "off" } }"#,
291+
)
292+
.unwrap();
293+
migrate_selected_obfuscaton(&mut migrated_settings).unwrap();
294+
295+
let expected_settings: serde_json::Value = serde_json::from_str(
296+
r#"{ "obfuscation_settings": { "selected_obfuscation": "auto" } }"#,
297+
)
298+
.unwrap();
299+
300+
assert_eq!(migrated_settings, expected_settings);
301+
}
302+
}

mullvad-types/src/relay_constraints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -886,8 +886,8 @@ impl BridgeSettings {
886886
#[serde(rename_all = "snake_case")]
887887
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
888888
pub enum SelectedObfuscation {
889-
Auto,
890889
#[default]
890+
Auto,
891891
Off,
892892
#[cfg_attr(feature = "clap", clap(name = "udp2tcp"))]
893893
Udp2Tcp,

mullvad-types/src/settings/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod dns;
2121
/// latest version that exists in `SettingsVersion`.
2222
/// This should be bumped when a new version is introduced along with a migration
2323
/// being added to `mullvad-daemon`.
24-
pub const CURRENT_SETTINGS_VERSION: SettingsVersion = SettingsVersion::V8;
24+
pub const CURRENT_SETTINGS_VERSION: SettingsVersion = SettingsVersion::V9;
2525

2626
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
2727
#[repr(u32)]
@@ -33,6 +33,7 @@ pub enum SettingsVersion {
3333
V6 = 6,
3434
V7 = 7,
3535
V8 = 8,
36+
V9 = 9,
3637
}
3738

3839
impl<'de> Deserialize<'de> for SettingsVersion {
@@ -48,6 +49,7 @@ impl<'de> Deserialize<'de> for SettingsVersion {
4849
v if v == SettingsVersion::V6 as u32 => Ok(SettingsVersion::V6),
4950
v if v == SettingsVersion::V7 as u32 => Ok(SettingsVersion::V7),
5051
v if v == SettingsVersion::V8 as u32 => Ok(SettingsVersion::V8),
52+
v if v == SettingsVersion::V9 as u32 => Ok(SettingsVersion::V9),
5153
v => Err(serde::de::Error::custom(format!(
5254
"{v} is not a valid SettingsVersion"
5355
))),
@@ -131,7 +133,7 @@ impl Default for Settings {
131133
}),
132134
bridge_settings: BridgeSettings::default(),
133135
obfuscation_settings: ObfuscationSettings {
134-
selected_obfuscation: SelectedObfuscation::Off,
136+
selected_obfuscation: SelectedObfuscation::Auto,
135137
..Default::default()
136138
},
137139
bridge_state: BridgeState::Auto,

0 commit comments

Comments
 (0)