fix wifi types

This commit is contained in:
Aiden McClelland
2024-04-09 15:24:05 -06:00
parent 2bc64920dd
commit e9166c4a7d
12 changed files with 85 additions and 72 deletions

View File

@@ -11,10 +11,6 @@ export type ServerInfo = {
hostname: string; hostname: string;
version: string; version: string;
lastBackup: string | null; lastBackup: string | null;
/**
* Used in the wifi to determine the region to set the system to
*/
lastWifiRegion: string | null;
eosVersionCompat: string; eosVersionCompat: string;
lanAddress: string; lanAddress: string;
onionAddress: string; onionAddress: string;
@@ -24,7 +20,7 @@ export type ServerInfo = {
torAddress: string; torAddress: string;
ipInfo: { [key: string]: IpInfo }; ipInfo: { [key: string]: IpInfo };
statusInfo: ServerStatus; statusInfo: ServerStatus;
wifi: WifiInfo | null; wifi: WifiInfo;
unreadNotificationCount: number; unreadNotificationCount: number;
passwordHash: string; passwordHash: string;
pubkey: string; pubkey: string;

View File

@@ -1,8 +1,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type WifiInfo = { export type WifiInfo = {
interface: string; interface: string | null;
ssids: Array<string>; ssids: Array<string>;
selected: string | null; selected: string | null;
connected: string | null; lastRegion: string | null;
}; };

View File

@@ -96,11 +96,7 @@ pub async fn recover_full_embassy(
.with_kind(ErrorKind::PasswordHashGeneration)?; .with_kind(ErrorKind::PasswordHashGeneration)?;
let db = ctx.db().await?; let db = ctx.db().await?;
db.put( db.put(&ROOT, &Database::init(&os_backup.account)?).await?;
&ROOT,
&Database::init(&os_backup.account, ctx.config.wifi_interface.clone())?,
)
.await?;
drop(db); drop(db);
init(&ctx.config).await?; init(&ctx.config).await?;

View File

@@ -91,8 +91,6 @@ impl ClientConfig {
pub struct ServerConfig { pub struct ServerConfig {
#[arg(short = 'c', long = "config")] #[arg(short = 'c', long = "config")]
pub config: Option<PathBuf>, pub config: Option<PathBuf>,
#[arg(long = "wifi-interface")]
pub wifi_interface: Option<String>,
#[arg(long = "ethernet-interface")] #[arg(long = "ethernet-interface")]
pub ethernet_interface: Option<String>, pub ethernet_interface: Option<String>,
#[arg(skip)] #[arg(skip)]
@@ -117,7 +115,6 @@ impl ContextConfig for ServerConfig {
self.config.take() self.config.take()
} }
fn merge_with(&mut self, other: Self) { fn merge_with(&mut self, other: Self) {
self.wifi_interface = self.wifi_interface.take().or(other.wifi_interface);
self.ethernet_interface = self.ethernet_interface.take().or(other.ethernet_interface); self.ethernet_interface = self.ethernet_interface.take().or(other.ethernet_interface);
self.os_partitions = self.os_partitions.take().or(other.os_partitions); self.os_partitions = self.os_partitions.take().or(other.os_partitions);
self.bind_rpc = self.bind_rpc.take().or(other.bind_rpc); self.bind_rpc = self.bind_rpc.take().or(other.bind_rpc);

View File

@@ -26,7 +26,7 @@ use crate::init::check_time_is_synchronized;
use crate::lxc::{LxcContainer, LxcManager}; use crate::lxc::{LxcContainer, LxcManager};
use crate::middleware::auth::HashSessionToken; use crate::middleware::auth::HashSessionToken;
use crate::net::net_controller::NetController; use crate::net::net_controller::NetController;
use crate::net::utils::find_eth_iface; use crate::net::utils::{find_eth_iface, find_wifi_iface};
use crate::net::wifi::WpaCli; use crate::net::wifi::WpaCli;
use crate::prelude::*; use crate::prelude::*;
use crate::service::ServiceMap; use crate::service::ServiceMap;
@@ -132,6 +132,8 @@ impl RpcContext {
}); });
} }
let wifi_interface = find_wifi_iface().await?;
let seed = Arc::new(RpcContextSeed { let seed = Arc::new(RpcContextSeed {
is_closed: AtomicBool::new(false), is_closed: AtomicBool::new(false),
datadir: config.datadir().to_path_buf(), datadir: config.datadir().to_path_buf(),
@@ -141,7 +143,7 @@ impl RpcContext {
ErrorKind::Filesystem, ErrorKind::Filesystem,
) )
})?, })?,
wifi_interface: config.wifi_interface.clone(), wifi_interface: wifi_interface.clone(),
ethernet_interface: if let Some(eth) = config.ethernet_interface.clone() { ethernet_interface: if let Some(eth) = config.ethernet_interface.clone() {
eth eth
} else { } else {
@@ -158,8 +160,7 @@ impl RpcContext {
lxc_manager: Arc::new(LxcManager::new()), lxc_manager: Arc::new(LxcManager::new()),
open_authed_websockets: Mutex::new(BTreeMap::new()), open_authed_websockets: Mutex::new(BTreeMap::new()),
rpc_stream_continuations: Mutex::new(BTreeMap::new()), rpc_stream_continuations: Mutex::new(BTreeMap::new()),
wifi_manager: config wifi_manager: wifi_interface
.wifi_interface
.clone() .clone()
.map(|i| Arc::new(RwLock::new(WpaCli::init(i)))), .map(|i| Arc::new(RwLock::new(WpaCli::init(i)))),
current_secret: Arc::new( current_secret: Arc::new(

View File

@@ -27,9 +27,9 @@ pub struct Database {
pub private: Private, pub private: Private,
} }
impl Database { impl Database {
pub fn init(account: &AccountInfo, wifi_interface: Option<String>) -> Result<Self, Error> { pub fn init(account: &AccountInfo) -> Result<Self, Error> {
Ok(Self { Ok(Self {
public: Public::init(account, wifi_interface)?, public: Public::init(account)?,
private: Private { private: Private {
key_store: KeyStore::new(account)?, key_store: KeyStore::new(account)?,
password: account.password.clone(), password: account.password.clone(),

View File

@@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@@ -35,7 +35,7 @@ pub struct Public {
pub ui: Value, pub ui: Value,
} }
impl Public { impl Public {
pub fn init(account: &AccountInfo, wifi_interface: Option<String>) -> Result<Self, Error> { pub fn init(account: &AccountInfo) -> Result<Self, Error> {
let lan_address = account.hostname.lan_address().parse().unwrap(); let lan_address = account.hostname.lan_address().parse().unwrap();
Ok(Self { Ok(Self {
server_info: ServerInfo { server_info: ServerInfo {
@@ -45,7 +45,6 @@ impl Public {
version: Current::new().semver().into(), version: Current::new().semver().into(),
hostname: account.hostname.no_dot_host_name(), hostname: account.hostname.no_dot_host_name(),
last_backup: None, last_backup: None,
last_wifi_region: None,
eos_version_compat: Current::new().compat().clone(), eos_version_compat: Current::new().compat().clone(),
lan_address, lan_address,
onion_address: account.tor_key.public().get_onion_address(), onion_address: account.tor_key.public().get_onion_address(),
@@ -60,12 +59,7 @@ impl Public {
shutting_down: false, shutting_down: false,
restarting: false, restarting: false,
}, },
wifi: wifi_interface.map(|interface| WifiInfo { wifi: WifiInfo::default(),
interface,
ssids: Vec::new(),
connected: None,
selected: None,
}),
unread_notification_count: 0, unread_notification_count: 0,
password_hash: account.password.clone(), password_hash: account.password.clone(),
pubkey: ssh_key::PublicKey::from(&account.ssh_key) pubkey: ssh_key::PublicKey::from(&account.ssh_key)
@@ -117,9 +111,6 @@ pub struct ServerInfo {
pub version: Version, pub version: Version,
#[ts(type = "string | null")] #[ts(type = "string | null")]
pub last_backup: Option<DateTime<Utc>>, pub last_backup: Option<DateTime<Utc>>,
/// Used in the wifi to determine the region to set the system to
#[ts(type = "string | null")]
pub last_wifi_region: Option<CountryCode>,
#[ts(type = "string")] #[ts(type = "string")]
pub eos_version_compat: VersionRange, pub eos_version_compat: VersionRange,
#[ts(type = "string")] #[ts(type = "string")]
@@ -132,7 +123,7 @@ pub struct ServerInfo {
pub ip_info: BTreeMap<String, IpInfo>, pub ip_info: BTreeMap<String, IpInfo>,
#[serde(default)] #[serde(default)]
pub status_info: ServerStatus, pub status_info: ServerStatus,
pub wifi: Option<WifiInfo>, pub wifi: WifiInfo,
#[ts(type = "number")] #[ts(type = "number")]
pub unread_notification_count: u64, pub unread_notification_count: u64,
pub password_hash: String, pub password_hash: String,
@@ -202,15 +193,16 @@ pub struct UpdateProgress {
pub downloaded: u64, pub downloaded: u64,
} }
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)] #[ts(export)]
pub struct WifiInfo { pub struct WifiInfo {
pub interface: String, pub interface: Option<String>,
pub ssids: Vec<String>, pub ssids: BTreeSet<String>,
pub selected: Option<String>, pub selected: Option<String>,
pub connected: Option<String>, #[ts(type = "string | null")]
pub last_region: Option<CountryCode>,
} }
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]

View File

@@ -232,15 +232,12 @@ pub async fn init(cfg: &ServerConfig) -> Result<InitResult, Error> {
.invoke(crate::ErrorKind::OpenSsl) .invoke(crate::ErrorKind::OpenSsl)
.await?; .await?;
if let Some(wifi_interface) = &cfg.wifi_interface { crate::net::wifi::synchronize_wpa_supplicant_conf(
crate::net::wifi::synchronize_wpa_supplicant_conf( &cfg.datadir().join("main"),
&cfg.datadir().join("main"), &mut server_info.wifi,
wifi_interface, )
&server_info.last_wifi_region, .await?;
) tracing::info!("Synchronized WiFi");
.await?;
tracing::info!("Synchronized WiFi");
}
let should_rebuild = tokio::fs::metadata(SYSTEM_REBUILD_PATH).await.is_ok() let should_rebuild = tokio::fs::metadata(SYSTEM_REBUILD_PATH).await.is_ok()
|| &*server_info.version < &emver::Version::new(0, 3, 2, 0) || &*server_info.version < &emver::Version::new(0, 3, 2, 0)

View File

@@ -16,6 +16,8 @@ use tracing::instrument;
use ts_rs::TS; use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::public::WifiInfo;
use crate::net::utils::find_wifi_iface;
use crate::prelude::*; use crate::prelude::*;
use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat}; use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
use crate::util::Invoke; use crate::util::Invoke;
@@ -137,6 +139,18 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re
ErrorKind::Wifi, ErrorKind::Wifi,
)); ));
} }
ctx.db
.mutate(|db| {
db.as_public_mut()
.as_server_info_mut()
.as_wifi_mut()
.as_ssids_mut()
.mutate(|s| {
s.insert(ssid);
Ok(())
})
})
.await?;
Ok(()) Ok(())
} }
#[derive(Deserialize, Serialize, Parser, TS)] #[derive(Deserialize, Serialize, Parser, TS)]
@@ -190,6 +204,17 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result
ErrorKind::Wifi, ErrorKind::Wifi,
)); ));
} }
ctx.db
.mutate(|db| {
let wifi = db.as_public_mut().as_server_info_mut().as_wifi_mut();
wifi.as_ssids_mut().mutate(|s| {
s.insert(ssid.clone());
Ok(())
})?;
wifi.as_selected_mut().ser(&Some(ssid))
})
.await?;
Ok(()) Ok(())
} }
@@ -215,11 +240,23 @@ pub async fn delete(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
} }
wpa_supplicant.remove_network(ctx.db.clone(), &ssid).await?; wpa_supplicant.remove_network(ctx.db.clone(), &ssid).await?;
ctx.db
.mutate(|db| {
let wifi = db.as_public_mut().as_server_info_mut().as_wifi_mut();
wifi.as_ssids_mut().mutate(|s| {
s.remove(&ssid.0);
Ok(())
})?;
wifi.as_selected_mut()
.map_mutate(|s| Ok(s.filter(|s| s == &ssid.0)))
})
.await?;
Ok(()) Ok(())
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct WiFiInfo { pub struct WifiListInfo {
ssids: HashMap<Ssid, SignalStrength>, ssids: HashMap<Ssid, SignalStrength>,
connected: Option<Ssid>, connected: Option<Ssid>,
country: Option<CountryCode>, country: Option<CountryCode>,
@@ -228,7 +265,7 @@ pub struct WiFiInfo {
} }
#[derive(serde::Serialize, serde::Deserialize, Clone)] #[derive(serde::Serialize, serde::Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct WifiListInfo { pub struct WifiListInfoLow {
strength: SignalStrength, strength: SignalStrength,
security: Vec<String>, security: Vec<String>,
} }
@@ -239,8 +276,8 @@ pub struct WifiListOut {
strength: SignalStrength, strength: SignalStrength,
security: Vec<String>, security: Vec<String>,
} }
pub type WifiList = HashMap<Ssid, WifiListInfo>; pub type WifiList = HashMap<Ssid, WifiListInfoLow>;
fn display_wifi_info(params: WithIoFormat<Empty>, info: WiFiInfo) { fn display_wifi_info(params: WithIoFormat<Empty>, info: WifiListInfo) {
use prettytable::*; use prettytable::*;
if let Some(format) = params.format { if let Some(format) = params.format {
@@ -330,7 +367,7 @@ fn display_wifi_list(params: WithIoFormat<Empty>, info: Vec<WifiListOut>) {
// #[command(display(display_wifi_info))] // #[command(display(display_wifi_info))]
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn get(ctx: RpcContext, _: Empty) -> Result<WiFiInfo, Error> { pub async fn get(ctx: RpcContext, _: Empty) -> Result<WifiListInfo, Error> {
let wifi_manager = wifi_manager(&ctx)?; let wifi_manager = wifi_manager(&ctx)?;
let wpa_supplicant = wifi_manager.read().await; let wpa_supplicant = wifi_manager.read().await;
let (list_networks, current_res, country_res, ethernet_res, signal_strengths) = tokio::join!( let (list_networks, current_res, country_res, ethernet_res, signal_strengths) = tokio::join!(
@@ -368,7 +405,7 @@ pub async fn get(ctx: RpcContext, _: Empty) -> Result<WiFiInfo, Error> {
}) })
.collect(); .collect();
let current = current_res?; let current = current_res?;
Ok(WiFiInfo { Ok(WifiListInfo {
ssids, ssids,
connected: current, connected: current,
country: country_res?, country: country_res?,
@@ -477,7 +514,7 @@ impl SignalStrength {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct WifiInfo { pub struct WifiInfoLow {
ssid: Ssid, ssid: Ssid,
device: Option<String>, device: Option<String>,
} }
@@ -604,7 +641,7 @@ impl WpaCli {
Ok(()) Ok(())
} }
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn list_networks_low(&self) -> Result<BTreeMap<NetworkId, WifiInfo>, Error> { pub async fn list_networks_low(&self) -> Result<BTreeMap<NetworkId, WifiInfoLow>, Error> {
let r = Command::new("nmcli") let r = Command::new("nmcli")
.arg("-t") .arg("-t")
.arg("c") .arg("c")
@@ -623,13 +660,13 @@ impl WpaCli {
if !connection_type.contains("wireless") { if !connection_type.contains("wireless") {
return None; return None;
} }
let info = WifiInfo { let info = WifiInfoLow {
ssid: name, ssid: name,
device: device.map(|x| x.to_owned()), device: device.map(|x| x.to_owned()),
}; };
Some((uuid, info)) Some((uuid, info))
}) })
.collect::<BTreeMap<NetworkId, WifiInfo>>()) .collect::<BTreeMap<NetworkId, WifiInfoLow>>())
} }
#[instrument(skip_all)] #[instrument(skip_all)]
@@ -652,7 +689,7 @@ impl WpaCli {
values.next()?.split(' ').map(|x| x.to_owned()).collect(); values.next()?.split(' ').map(|x| x.to_owned()).collect();
Some(( Some((
ssid, ssid,
WifiListInfo { WifiListInfoLow {
strength: signal, strength: signal,
security, security,
}, },
@@ -686,7 +723,8 @@ impl WpaCli {
db.mutate(|d| { db.mutate(|d| {
d.as_public_mut() d.as_public_mut()
.as_server_info_mut() .as_server_info_mut()
.as_last_wifi_region_mut() .as_wifi_mut()
.as_last_region_mut()
.ser(&new_country) .ser(&new_country)
}) })
.await .await
@@ -837,9 +875,12 @@ impl TypedValueParser for CountryCodeParser {
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn synchronize_wpa_supplicant_conf<P: AsRef<Path>>( pub async fn synchronize_wpa_supplicant_conf<P: AsRef<Path>>(
main_datadir: P, main_datadir: P,
wifi_iface: &str, wifi: &mut WifiInfo,
last_country_code: &Option<CountryCode>,
) -> Result<(), Error> { ) -> Result<(), Error> {
wifi.interface = find_wifi_iface().await?;
let Some(wifi_iface) = &wifi.interface else {
return Ok(());
};
let persistent = main_datadir.as_ref().join("system-connections"); let persistent = main_datadir.as_ref().join("system-connections");
tracing::debug!("persistent: {:?}", persistent); tracing::debug!("persistent: {:?}", persistent);
// let supplicant = Path::new("/etc/wpa_supplicant.conf"); // let supplicant = Path::new("/etc/wpa_supplicant.conf");
@@ -863,7 +904,7 @@ pub async fn synchronize_wpa_supplicant_conf<P: AsRef<Path>>(
.arg("up") .arg("up")
.invoke(ErrorKind::Wifi) .invoke(ErrorKind::Wifi)
.await?; .await?;
if let Some(last_country_code) = last_country_code { if let Some(last_country_code) = wifi.last_region {
tracing::info!("Setting the region"); tracing::info!("Setting the region");
let _ = Command::new("iw") let _ = Command::new("iw")
.arg("reg") .arg("reg")

View File

@@ -17,7 +17,7 @@ use crate::disk::mount::filesystem::{MountType, ReadWrite};
use crate::disk::mount::guard::{GenericMountGuard, MountGuard, TmpMountGuard}; use crate::disk::mount::guard::{GenericMountGuard, MountGuard, TmpMountGuard};
use crate::disk::util::{DiskInfo, PartitionTable}; use crate::disk::util::{DiskInfo, PartitionTable};
use crate::disk::OsPartitionInfo; use crate::disk::OsPartitionInfo;
use crate::net::utils::{find_eth_iface, find_wifi_iface}; use crate::net::utils::find_eth_iface;
use crate::util::serde::IoFormat; use crate::util::serde::IoFormat;
use crate::util::Invoke; use crate::util::Invoke;
use crate::ARCH; use crate::ARCH;
@@ -140,7 +140,6 @@ pub async fn execute(
) )
})?; })?;
let eth_iface = find_eth_iface().await?; let eth_iface = find_eth_iface().await?;
let wifi_iface = find_wifi_iface().await?;
overwrite |= disk.guid.is_none() && disk.partitions.iter().all(|p| p.guid.is_none()); overwrite |= disk.guid.is_none() && disk.partitions.iter().all(|p| p.guid.is_none());
@@ -260,7 +259,6 @@ pub async fn execute(
IoFormat::Yaml.to_vec(&ServerConfig { IoFormat::Yaml.to_vec(&ServerConfig {
os_partitions: Some(part_info.clone()), os_partitions: Some(part_info.clone()),
ethernet_interface: Some(eth_iface), ethernet_interface: Some(eth_iface),
wifi_interface: wifi_iface,
..Default::default() ..Default::default()
})?, })?,
) )

View File

@@ -419,11 +419,7 @@ async fn fresh_setup(
) -> Result<(Hostname, OnionAddressV3, X509), Error> { ) -> Result<(Hostname, OnionAddressV3, X509), Error> {
let account = AccountInfo::new(start_os_password, root_ca_start_time().await?)?; let account = AccountInfo::new(start_os_password, root_ca_start_time().await?)?;
let db = ctx.db().await?; let db = ctx.db().await?;
db.put( db.put(&ROOT, &Database::init(&account)?).await?;
&ROOT,
&Database::init(&account, ctx.config.wifi_interface.clone())?,
)
.await?;
drop(db); drop(db);
init(&ctx.config).await?; init(&ctx.config).await?;
Ok(( Ok((

View File

@@ -55,7 +55,6 @@ export const mockPatchData: DataModel = {
ipv6Range: 'FE80:CD00:0000:0CDE:1257:0000:211E:729CD/64', ipv6Range: 'FE80:CD00:0000:0CDE:1257:0000:211E:729CD/64',
}, },
}, },
lastWifiRegion: null,
unreadNotificationCount: 4, unreadNotificationCount: 4,
// password is asdfasdf // password is asdfasdf
passwordHash: passwordHash:
@@ -79,7 +78,7 @@ export const mockPatchData: DataModel = {
interface: 'wlan0', interface: 'wlan0',
ssids: [], ssids: [],
selected: null, selected: null,
connected: null, lastRegion: null,
}, },
}, },
packageData: { packageData: {