feat(network): support for eap peap networks

This commit is contained in:
Ashley Wulber 2025-03-10 18:52:42 -04:00 committed by Ashley Wulber
parent 6afa338fdb
commit 43eae80b55
4 changed files with 105 additions and 17 deletions

2
Cargo.lock generated
View file

@ -1771,7 +1771,7 @@ dependencies = [
[[package]]
name = "cosmic-settings-subscriptions"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-settings-subscriptions#f666c7cfcad79547e55a368640784bca51081bd2"
source = "git+https://github.com/pop-os/cosmic-settings-subscriptions?branch=eap-peap#ad9c0d0d2df220b8c9336602be8458227e162b74"
dependencies = [
"bluez-zbus",
"cosmic-dbus-networkmanager",

View file

@ -90,6 +90,7 @@ num-derive = "0.4"
[dependencies.cosmic-settings-subscriptions]
git = "https://github.com/pop-os/cosmic-settings-subscriptions"
branch = "eap-peap"
#TODO: only select features as needed
features = ["network_manager", "pipewire", "pulse", "bluetooth"]
optional = true

View file

@ -10,12 +10,17 @@ use anyhow::Context;
use cosmic::{
iced::{Alignment, Length},
iced_core::text::Wrapping,
widget::{self, icon},
iced_widget::focus_next,
widget::{self, column, icon},
Apply, Element, Task,
};
use cosmic_settings_page::{self as page, section, Section};
use cosmic_settings_subscriptions::network_manager::{
self, available_wifi::AccessPoint, current_networks::ActiveConnectionInfo, NetworkManagerState,
self,
available_wifi::{AccessPoint, NetworkType},
current_networks::ActiveConnectionInfo,
hw_address::HwAddress,
NetworkManagerState,
};
use futures::StreamExt;
use secure_string::SecureString;
@ -36,6 +41,8 @@ pub enum Message {
Disconnect(network_manager::SSID),
/// An error occurred.
Error(String),
/// Identity update from the dialog
IdentityUpdate(String),
/// Create a dialog to ask for confirmation on forgetting a connection.
ForgetRequest(network_manager::SSID),
/// Forget a known access point.
@ -52,6 +59,8 @@ pub enum Message {
SelectDevice(Arc<network_manager::devices::DeviceInfo>),
/// Opens settings page for the access point.
Settings(network_manager::SSID),
/// Identity submitted from the dialog
SubmitIdentity,
/// Toggles visibility of the password input
TogglePasswordVisibility,
/// Update NetworkManagerState
@ -81,6 +90,8 @@ enum WiFiDialog {
Forget(network_manager::SSID),
Password {
ssid: network_manager::SSID,
hw_address: HwAddress,
identity: Option<String>,
password: SecureString,
password_hidden: bool,
},
@ -135,6 +146,7 @@ impl page::Page<crate::pages::Message> for Page {
self.dialog.as_ref().map(|dialog| match dialog {
WiFiDialog::Password {
password,
identity,
password_hidden,
..
} => {
@ -153,11 +165,25 @@ impl page::Page<crate::pages::Message> for Page {
let secondary_action =
widget::button::standard(fl!("cancel")).on_press(Message::CancelDialog);
let control: Element<_> = if let Some(identity) = identity {
column::column()
.spacing(8)
.push(
widget::text_input::text_input(fl!("identity"), identity)
.on_input(Message::IdentityUpdate)
.on_submit(|_| Message::SubmitIdentity),
)
.push(password)
.into()
} else {
password.into()
};
widget::dialog()
.title(fl!("auth-dialog"))
.icon(icon::from_name("preferences-wireless-symbolic").size(64))
.body(fl!("auth-dialog", "wifi-description"))
.control(password)
.control(control)
.primary_action(primary_action)
.secondary_action(secondary_action)
.apply(Element::from)
@ -246,21 +272,28 @@ impl Page {
}
match req {
network_manager::Request::Password(ssid, _) => {
network_manager::Request::Authenticate {
ssid,
identity,
hw_address,
..
} => {
if success {
self.connecting.remove(&ssid);
self.connecting.remove(ssid.as_str());
} else {
// Request to retry
self.dialog = Some(WiFiDialog::Password {
ssid,
ssid: ssid.into(),
identity,
hw_address,
password: SecureString::from(""),
password_hidden: true,
});
}
}
network_manager::Request::SelectAccessPoint(ssid) => {
self.connecting.remove(&ssid);
network_manager::Request::SelectAccessPoint(ssid, hw_address, network_type) => {
self.connecting.remove(ssid.as_ref());
}
_ => (),
@ -324,19 +357,54 @@ impl Page {
Message::Connect(ssid) => {
if let Some(nm) = self.nm_state.as_mut() {
let Some(ap) = nm
.state
.wireless_access_points
.iter()
.chain(nm.state.known_access_points.iter())
.find(|ap| ap.ssid == ssid)
else {
return Task::none();
};
self.connecting.insert(ssid.clone());
_ = nm
.sender
.unbounded_send(network_manager::Request::SelectAccessPoint(ssid));
.unbounded_send(network_manager::Request::SelectAccessPoint(
ssid,
ap.hw_address,
ap.network_type,
));
}
}
Message::IdentityUpdate(new_identity) => {
if let Some(WiFiDialog::Password {
ref mut identity, ..
}) = self.dialog
{
*identity = Some(new_identity);
}
}
Message::PasswordRequest(ssid) => {
self.dialog = Some(WiFiDialog::Password {
ssid,
password: SecureString::from(""),
password_hidden: true,
});
if let Some(nm) = self.nm_state.as_mut() {
let Some(ap) = nm
.state
.wireless_access_points
.iter()
.chain(nm.state.known_access_points.iter())
.find(|ap| ap.ssid == ssid)
else {
return Task::none();
};
self.dialog = Some(WiFiDialog::Password {
ssid,
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
hw_address: ap.hw_address,
password: SecureString::from(""),
password_hidden: true,
});
}
}
Message::PasswordUpdate(pass) => {
@ -353,12 +421,24 @@ impl Page {
return Task::none();
};
if let WiFiDialog::Password { ssid, password, .. } = dialog {
if let WiFiDialog::Password {
ssid,
identity,
password,
hw_address,
..
} = dialog
{
if let Some(nm) = self.nm_state.as_mut() {
self.connecting.insert(ssid.clone());
_ = nm
.sender
.unbounded_send(network_manager::Request::Password(ssid, password));
.unbounded_send(network_manager::Request::Authenticate {
ssid: ssid.to_string(),
identity,
hw_address,
password,
});
}
}
}
@ -414,6 +494,12 @@ impl Page {
}
}
Message::SubmitIdentity => {
if self.dialog.is_some() {
return focus_next();
}
}
Message::WiFiEnable(enable) => {
if let Some(nm) = self.nm_state.as_mut() {
_ = nm

View file

@ -34,6 +34,7 @@ remove = Remove
settings = Settings
username = Username
visible-networks = Visible Networks
identity = Identity
auth-dialog = Authentication Required
.vpn-description = Enter the username and password required by the VPN service.