gardesk/garcard / 4f454bc

Browse files

Reprompt inline on auth failure

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
4f454bc5c9356e7cc5f95d44fc58016eba0a8ac3
Parents
de56cb8
Tree
b5fa32b

4 changed files

StatusFile+-
M garcard/src/main.rs 1 0
M garcard/src/polkit_helper.rs 13 17
M garcard/src/prompt.rs 13 4
M garcard/src/prompt_ui.rs 10 7
garcard/src/main.rsmodified
@@ -85,6 +85,7 @@ async fn main() -> Result<()> {
8585
                     PromptToneArg::Success => prompt_ui::PromptTone::Success,
8686
                     PromptToneArg::Error => prompt_ui::PromptTone::Error,
8787
                 },
88
+                feedback_only: false,
8889
             };
8990
 
9091
             let outcome = match prompt_ui::run_prompt_dialog(request) {
garcard/src/polkit_helper.rsmodified
@@ -225,13 +225,20 @@ impl HelperSocketClient {
225225
                 }
226226
                 HelperEvent::Failure => {
227227
                     if saw_no_session_cookie {
228
+                        if let Some(helper) = resolve_direct_helper_path() {
229
+                            tracing::warn!(
230
+                                helper = %helper.display(),
231
+                                "Socket helper reported no session for cookie; falling back to direct helper process"
232
+                            );
233
+                            return self.authenticate_via_helper_process_with_helper(
234
+                                &helper,
235
+                                &username_line,
236
+                                &cookie_line,
237
+                                prompts,
238
+                            );
239
+                        }
228240
                         tracing::warn!(
229
-                            "Socket helper reported no session for cookie; falling back to direct helper process"
230
-                        );
231
-                        return self.authenticate_via_helper_process(
232
-                            &username_line,
233
-                            &cookie_line,
234
-                            prompts,
241
+                            "Socket helper reported no session for cookie and no viable direct helper is available; treating as authentication failure"
235242
                         );
236243
                     }
237244
                     prompts
@@ -243,17 +250,6 @@ impl HelperSocketClient {
243250
         }
244251
     }
245252
 
246
-    fn authenticate_via_helper_process<P: PromptProvider>(
247
-        &self,
248
-        username: &str,
249
-        cookie: &str,
250
-        prompts: &mut P,
251
-    ) -> Result<HelperOutcome> {
252
-        let helper = resolve_direct_helper_path()
253
-            .context("failed to locate direct polkit helper binary for socket fallback")?;
254
-        self.authenticate_via_helper_process_with_helper(&helper, username, cookie, prompts)
255
-    }
256
-
257253
     fn authenticate_via_helper_process_with_helper<P: PromptProvider>(
258254
         &self,
259255
         helper: &Path,
garcard/src/prompt.rsmodified
@@ -33,6 +33,7 @@ pub struct CommandPrompt {
3333
     prompt_timeout_secs: u64,
3434
     session: Option<PromptSession>,
3535
     session_unavailable: bool,
36
+    next_prompt_tone: Option<PromptTone>,
3637
 }
3738
 
3839
 impl Default for CommandPrompt {
@@ -48,12 +49,15 @@ impl Default for CommandPrompt {
4849
             prompt_timeout_secs,
4950
             session: None,
5051
             session_unavailable: false,
52
+            next_prompt_tone: None,
5153
         }
5254
     }
5355
 }
5456
 
5557
 impl CommandPrompt {
5658
     fn run_prompt(&mut self, prompt: &str, visible: bool) -> Result<PromptResponse> {
59
+        let tone = self.next_prompt_tone.take().unwrap_or(PromptTone::Default);
60
+
5761
         if let Some(command) = self.prompt_command.as_deref() {
5862
             tracing::debug!(visible, "Using custom prompt command backend");
5963
             return run_custom_prompt_command(command, prompt, visible);
@@ -71,7 +75,8 @@ impl CommandPrompt {
7175
                         PromptMode::Secret
7276
                     },
7377
                     timeout_secs,
74
-                    tone: UiPromptTone::Default,
78
+                    tone: to_ui_tone(tone),
79
+                    feedback_only: false,
7580
                 };
7681
                 let started = Instant::now();
7782
                 Some((session.run(request), started.elapsed()))
@@ -106,7 +111,7 @@ impl CommandPrompt {
106111
             }
107112
         }
108113
 
109
-        match run_gartk_prompt_subcommand(prompt, visible, timeout_secs) {
114
+        match run_gartk_prompt_subcommand(prompt, visible, timeout_secs, tone) {
110115
             Ok(response) => {
111116
                 tracing::debug!(visible, response = ?response, "Prompt subprocess completed");
112117
                 Ok(response)
@@ -189,11 +194,14 @@ impl PromptProvider for CommandPrompt {
189194
     }
190195
 
191196
     fn auth_succeeded(&mut self) -> Result<()> {
197
+        self.next_prompt_tone = None;
192198
         self.run_feedback("Authentication succeeded", PromptTone::Success)
193199
     }
194200
 
195201
     fn auth_failed(&mut self, message: &str) -> Result<()> {
196
-        self.run_feedback(message, PromptTone::Error)
202
+        tracing::warn!("polkit helper message: {}", message);
203
+        self.next_prompt_tone = Some(PromptTone::Error);
204
+        Ok(())
197205
     }
198206
 }
199207
 
@@ -224,6 +232,7 @@ fn run_gartk_prompt_subcommand(
224232
     prompt: &str,
225233
     visible: bool,
226234
     timeout_secs: u64,
235
+    tone: PromptTone,
227236
 ) -> Result<PromptResponse> {
228237
     let mode = if visible { "plain" } else { "secret" };
229238
     let executable =
@@ -237,7 +246,7 @@ fn run_gartk_prompt_subcommand(
237246
         .arg("--timeout-secs")
238247
         .arg(timeout_secs.to_string())
239248
         .arg("--tone")
240
-        .arg(PromptTone::Default.as_arg())
249
+        .arg(tone.as_arg())
241250
         .output()
242251
         .context("failed to launch garcard prompt subcommand")?;
243252
 
garcard/src/prompt_ui.rsmodified
@@ -1,9 +1,9 @@
11
 use anyhow::{Context, Result};
22
 use gartk_core::{Color, InputEvent, Key, KeyEvent, Rect, Theme};
3
-use gartk_render::{copy_surface_to_window, Renderer, TextStyle};
3
+use gartk_render::{Renderer, TextStyle, copy_surface_to_window};
44
 use gartk_x11::{
5
-    monitor_at_pointer, primary_monitor, Connection, EventLoop, EventLoopConfig, Window,
6
-    WindowConfig,
5
+    Connection, EventLoop, EventLoopConfig, Window, WindowConfig, monitor_at_pointer,
6
+    primary_monitor,
77
 };
88
 use std::time::{Duration, Instant};
99
 use x11rb::connection::Connection as X11Connection;
@@ -33,6 +33,7 @@ pub struct PromptRequest {
3333
     pub mode: PromptMode,
3434
     pub timeout_secs: u64,
3535
     pub tone: PromptTone,
36
+    pub feedback_only: bool,
3637
 }
3738
 
3839
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -152,6 +153,7 @@ impl PromptSession {
152153
             mode: PromptMode::Secret,
153154
             timeout_secs: 0,
154155
             tone: PromptTone::Default,
156
+            feedback_only: false,
155157
         };
156158
 
157159
         let conn = Connection::connect(None).context("failed to connect to X11 display")?;
@@ -188,6 +190,7 @@ impl PromptSession {
188190
             mode: PromptMode::Plain,
189191
             timeout_secs,
190192
             tone,
193
+            feedback_only: true,
191194
         })?;
192195
         Ok(())
193196
     }
@@ -377,7 +380,7 @@ impl PromptDialog {
377380
     }
378381
 
379382
     fn handle_key(&mut self, key_event: &KeyEvent) {
380
-        if self.request.tone != PromptTone::Default {
383
+        if self.request.feedback_only {
381384
             // Feedback dialogs are transient; ignore keypresses so the submit key
382385
             // from the previous prompt cannot dismiss success/error feedback early.
383386
             return;
@@ -547,10 +550,10 @@ impl PromptDialog {
547550
             .font_family(theme.font_family)
548551
             .font_size(12.0)
549552
             .color(theme.item_description);
550
-        let footer_text = if self.request.tone == PromptTone::Default {
551
-            "Enter submit   Esc cancel"
552
-        } else {
553
+        let footer_text = if self.request.feedback_only {
553554
             "Please wait"
555
+        } else {
556
+            "Enter submit   Esc cancel"
554557
         };
555558
         self.renderer.text(
556559
             footer_text,