use std::collections::HashMap;
use zvariant::Value;
use super::connection_builder::ConnectionBuilder;
use super::wifi_builder::WifiConnectionBuilder;
use crate::api::models::{self, ConnectionOptions};
#[must_use]
pub fn build_wifi_connection(
ssid: &str,
security: &models::WifiSecurity,
opts: &ConnectionOptions,
) -> HashMap<&'static str, HashMap<&'static str, Value<'static>>> {
let mut builder = WifiConnectionBuilder::new(ssid)
.options(opts)
.ipv4_auto()
.ipv6_auto();
builder = match security {
models::WifiSecurity::Open => builder.open(),
models::WifiSecurity::WpaPsk { psk } => builder.wpa_psk(psk),
models::WifiSecurity::WpaEap { opts } => builder.wpa_eap(opts.clone()),
};
builder.build()
}
#[must_use]
pub fn build_ethernet_connection(
connection_id: &str,
opts: &ConnectionOptions,
) -> HashMap<&'static str, HashMap<&'static str, Value<'static>>> {
let ethernet = HashMap::new();
ConnectionBuilder::new("802-3-ethernet", connection_id)
.options(opts)
.with_section("802-3-ethernet", ethernet)
.ipv4_auto()
.ipv6_auto()
.build()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::models::{ConnectionOptions, EapMethod, EapOptions, Phase2, WifiSecurity};
use zvariant::Value;
fn default_opts() -> ConnectionOptions {
ConnectionOptions {
autoconnect: true,
autoconnect_priority: None,
autoconnect_retries: None,
}
}
fn opts_with_priority() -> ConnectionOptions {
ConnectionOptions {
autoconnect: false,
autoconnect_priority: Some(10),
autoconnect_retries: Some(3),
}
}
#[test]
fn builds_open_wifi_connection() {
let conn = build_wifi_connection("testnet", &WifiSecurity::Open, &default_opts());
assert!(conn.contains_key("connection"));
assert!(conn.contains_key("802-11-wireless"));
assert!(conn.contains_key("ipv4"));
assert!(conn.contains_key("ipv6"));
assert!(!conn.contains_key("802-11-wireless-security"));
}
#[test]
fn open_connection_has_correct_type() {
let conn = build_wifi_connection("open_net", &WifiSecurity::Open, &default_opts());
let connection_section = conn.get("connection").unwrap();
assert_eq!(
connection_section.get("type"),
Some(&Value::from("802-11-wireless"))
);
}
#[test]
fn builds_psk_wifi_connection_with_security_section() {
let conn = build_wifi_connection(
"secure",
&WifiSecurity::WpaPsk {
psk: "pw123".into(),
},
&default_opts(),
);
assert!(
conn.contains_key("802-11-wireless-security"),
"security section missing"
);
let sec = conn.get("802-11-wireless-security").unwrap();
assert_eq!(sec.get("psk"), Some(&Value::from("pw123".to_string())));
assert_eq!(sec.get("key-mgmt"), Some(&Value::from("wpa-psk")));
}
#[test]
fn psk_connection_links_wireless_to_security() {
let conn = build_wifi_connection(
"secure",
&WifiSecurity::WpaPsk { psk: "test".into() },
&default_opts(),
);
let wireless = conn.get("802-11-wireless").unwrap();
assert_eq!(
wireless.get("security"),
Some(&Value::from("802-11-wireless-security"))
);
}
#[test]
fn builds_eap_peap_connection() {
let eap_opts = EapOptions {
identity: "user@example.com".into(),
password: "secret123".into(),
anonymous_identity: Some("anonymous@example.com".into()),
domain_suffix_match: Some("example.com".into()),
ca_cert_path: None,
system_ca_certs: true,
method: EapMethod::Peap,
phase2: Phase2::Mschapv2,
};
let conn = build_wifi_connection(
"enterprise",
&WifiSecurity::WpaEap { opts: eap_opts },
&default_opts(),
);
assert!(conn.contains_key("802-11-wireless-security"));
assert!(conn.contains_key("802-1x"));
let sec = conn.get("802-11-wireless-security").unwrap();
assert_eq!(sec.get("key-mgmt"), Some(&Value::from("wpa-eap")));
let e1x = conn.get("802-1x").unwrap();
assert_eq!(
e1x.get("identity"),
Some(&Value::from("user@example.com".to_string()))
);
assert_eq!(
e1x.get("password"),
Some(&Value::from("secret123".to_string()))
);
assert_eq!(e1x.get("phase2-auth"), Some(&Value::from("mschapv2")));
assert_eq!(e1x.get("system-ca-certs"), Some(&Value::from(true)));
}
#[test]
fn builds_eap_ttls_connection() {
let eap_opts = EapOptions {
identity: "student@uni.edu".into(),
password: "campus123".into(),
anonymous_identity: None,
domain_suffix_match: None,
ca_cert_path: Some("file:///etc/ssl/certs/ca.pem".into()),
system_ca_certs: false,
method: EapMethod::Ttls,
phase2: Phase2::Pap,
};
let conn = build_wifi_connection(
"eduroam",
&WifiSecurity::WpaEap { opts: eap_opts },
&default_opts(),
);
let e1x = conn.get("802-1x").unwrap();
assert_eq!(e1x.get("phase2-auth"), Some(&Value::from("pap")));
assert_eq!(
e1x.get("ca-cert"),
Some(&Value::from("file:///etc/ssl/certs/ca.pem".to_string()))
);
assert!(e1x.get("system-ca-certs").is_none());
}
#[test]
fn connection_with_priority_and_retries() {
let conn =
build_wifi_connection("priority_net", &WifiSecurity::Open, &opts_with_priority());
let connection_section = conn.get("connection").unwrap();
assert_eq!(
connection_section.get("autoconnect"),
Some(&Value::from(false))
);
assert_eq!(
connection_section.get("autoconnect-priority"),
Some(&Value::from(10i32))
);
assert_eq!(
connection_section.get("autoconnect-retries"),
Some(&Value::from(3i32))
);
}
#[test]
fn connection_without_optional_fields() {
let conn = build_wifi_connection("simple", &WifiSecurity::Open, &default_opts());
let connection_section = conn.get("connection").unwrap();
assert_eq!(
connection_section.get("autoconnect"),
Some(&Value::from(true))
);
assert!(connection_section.get("autoconnect-priority").is_none());
assert!(connection_section.get("autoconnect-retries").is_none());
}
#[test]
fn ssid_is_stored_as_bytes() {
let conn = build_wifi_connection("MyNetwork", &WifiSecurity::Open, &default_opts());
let wireless = conn.get("802-11-wireless").unwrap();
let ssid = wireless.get("ssid").unwrap();
assert_eq!(ssid, &Value::from(b"MyNetwork".to_vec()));
}
#[test]
fn ssid_with_special_characters() {
let conn = build_wifi_connection("Café-Wïfì_123", &WifiSecurity::Open, &default_opts());
let wireless = conn.get("802-11-wireless").unwrap();
let ssid = wireless.get("ssid").unwrap();
assert_eq!(ssid, &Value::from("Café-Wïfì_123".as_bytes().to_vec()));
}
}