gardesk/gartray / 8eb0897

Browse files

fix WiFi password entry and connection

- use nmcli for password connections (reliable secret storage)
- fix password display: use * instead of Unicode bullet
- fix cursor positioning: measure actual text width
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
8eb0897cbfa6b0c3a19817a9e155cf662466ac81
Parents
4cb0f43
Tree
35e1ecb

2 changed files

StatusFile+-
M gartray/src/panel/network.rs 21 19
M gartray/src/panel/popup.rs 9 4
gartray/src/panel/network.rsmodified
@@ -590,32 +590,27 @@ impl NetworkModule {
590590
 
591591
     /// Connect to a WiFi network with a password
592592
     pub fn connect_with_password(&mut self, ssid: &str, password: &str) -> Result<()> {
593
-        let conn = match &self.conn {
594
-            Some(c) => c,
595
-            None => anyhow::bail!("No D-Bus connection"),
596
-        };
597
-
598593
         if !self.state.wifi_available || !self.state.wifi_enabled {
599594
             anyhow::bail!("WiFi not available or not enabled");
600595
         }
601596
 
602597
         info!("Connecting to WiFi network with password: {}", ssid);
603598
 
604
-        // Get the WiFi device
605
-        let wifi_device = match self.get_wifi_device(conn) {
606
-            Some(d) => d,
607
-            None => anyhow::bail!("No WiFi device found"),
608
-        };
609
-
610
-        // Find the access point to get security info
611
-        let ap = self.state.access_points.iter()
612
-            .find(|ap| ap.ssid == ssid)
613
-            .ok_or_else(|| anyhow::anyhow!("Access point not found: {}", ssid))?;
614
-
615
-        let ap_path = ap.path.clone();
616
-        let security = ap.security.clone();
599
+        // Use nmcli which handles secrets properly
600
+        // nmcli device wifi connect <SSID> password <password>
601
+        let output = std::process::Command::new("nmcli")
602
+            .args(["device", "wifi", "connect", ssid, "password", password])
603
+            .output()
604
+            .context("Failed to run nmcli")?;
617605
 
618
-        self.add_and_activate_connection_with_password(conn, ssid, password, &security, &wifi_device, &ap_path)
606
+        if output.status.success() {
607
+            info!("Successfully connected to {}", ssid);
608
+            Ok(())
609
+        } else {
610
+            let stderr = String::from_utf8_lossy(&output.stderr);
611
+            warn!("nmcli failed: {}", stderr);
612
+            anyhow::bail!("Failed to connect: {}", stderr.trim())
613
+        }
619614
     }
620615
 
621616
     /// Check if a network requires a password (is secured)
@@ -813,6 +808,10 @@ impl NetworkModule {
813808
         let mut connection: HashMap<&str, Value> = HashMap::new();
814809
         connection.insert("type", Value::Str("802-11-wireless".into()));
815810
         connection.insert("id", Value::Str(ssid.into()));
811
+        // Set as user-owned connection so secrets can be saved without root
812
+        let user = std::env::var("USER").unwrap_or_else(|_| "user".to_string());
813
+        let permissions = vec![Value::Str(format!("user:{}:", user).into())];
814
+        connection.insert("permissions", Value::Array(permissions.into()));
816815
 
817816
         let mut wireless: HashMap<&str, Value> = HashMap::new();
818817
         // SSID as byte array
@@ -831,6 +830,9 @@ impl NetworkModule {
831830
         };
832831
         wireless_security.insert("key-mgmt", Value::Str(key_mgmt.into()));
833832
         wireless_security.insert("psk", Value::Str(password.into()));
833
+        // Set psk-flags to 0 (NM_SETTING_SECRET_FLAG_NONE) so NM uses the embedded password
834
+        // instead of asking a secret agent
835
+        wireless_security.insert("psk-flags", Value::U32(0));
834836
 
835837
         // Also set security reference in wireless settings
836838
         wireless.insert("security", Value::Str("802-11-wireless-security".into()));
gartray/src/panel/popup.rsmodified
@@ -1374,15 +1374,20 @@ impl PopupPanel {
13741374
         self.draw_rounded_rect(ctx, input_x, y, input_width, input_height, 4.0);
13751375
         ctx.stroke().ok();
13761376
 
1377
-        // Password text (masked with dots)
1377
+        // Password text (masked with asterisks)
13781378
         ctx.set_source_rgba(0.9, 0.9, 0.9, 1.0);
13791379
         ctx.set_font_size(14.0);
1380
-        let masked: String = "●".repeat(self.password_text.len());
1380
+        let masked: String = "*".repeat(self.password_text.len());
13811381
         ctx.move_to(input_x + 8.0, y + input_height / 2.0 + 5.0);
13821382
         ctx.show_text(&masked).ok();
13831383
 
1384
-        // Cursor (blinking could be added later)
1385
-        let cursor_x = input_x + 8.0 + (self.password_text.len() as f64 * 10.0);
1384
+        // Cursor - measure actual text width for accurate positioning
1385
+        let text_width = if masked.is_empty() {
1386
+            0.0
1387
+        } else {
1388
+            ctx.text_extents(&masked).map(|e| e.x_advance()).unwrap_or(0.0)
1389
+        };
1390
+        let cursor_x = input_x + 8.0 + text_width;
13861391
         ctx.set_source_rgba(0.9, 0.9, 0.9, 1.0);
13871392
         ctx.rectangle(cursor_x, y + 6.0, 2.0, input_height - 12.0);
13881393
         ctx.fill().ok();