pacsea/logic/
long_run_auth.rs1use crate::logic::privilege::{AuthMode, PrivilegeTool};
4use crate::theme::Settings;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum LongRunReadiness {
9 Ready,
11 ReadyViaPam,
13 ReadyWithPrompt,
15 Warn,
17 Degraded,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct LongRunAuthReadiness {
24 pub tool: Option<PrivilegeTool>,
26 pub auth_mode: AuthMode,
28 pub readiness: LongRunReadiness,
30 pub should_warn: bool,
32}
33
34#[must_use]
42pub fn evaluate_long_run_auth_readiness(settings: &Settings) -> LongRunAuthReadiness {
43 let auth_mode = crate::logic::password::resolve_auth_mode(settings);
44 let tool = crate::logic::privilege::resolve_privilege_tool(settings.privilege_mode).ok();
45 let readiness = match (tool, auth_mode) {
46 (Some(PrivilegeTool::Sudo | PrivilegeTool::Doas), AuthMode::Prompt) => {
47 LongRunReadiness::ReadyWithPrompt
48 }
49 (Some(PrivilegeTool::Sudo | PrivilegeTool::Doas), AuthMode::PasswordlessOnly) => {
50 LongRunReadiness::Ready
51 }
52 (Some(PrivilegeTool::Sudo), AuthMode::Interactive) => LongRunReadiness::Warn,
53 (Some(PrivilegeTool::Doas), AuthMode::Interactive) => LongRunReadiness::ReadyViaPam,
54 (None, _) => LongRunReadiness::Degraded,
55 };
56 let should_warn = matches!(
57 readiness,
58 LongRunReadiness::Warn | LongRunReadiness::Degraded
59 );
60 LongRunAuthReadiness {
61 tool,
62 auth_mode,
63 readiness,
64 should_warn,
65 }
66}
67
68#[must_use]
76pub fn build_long_run_warning_message(app: &crate::state::AppState) -> String {
77 [
78 crate::i18n::t(app, "app.modals.doas_persist_setup.preflight_warning_1"),
79 crate::i18n::t(app, "app.modals.doas_persist_setup.preflight_warning_2"),
80 crate::i18n::t(app, "app.modals.doas_persist_setup.preflight_warning_3"),
81 ]
82 .join("\n")
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn readiness_is_degraded_when_tool_unresolved() {
91 let _guard = crate::global_test_mutex_lock();
92 unsafe {
93 std::env::set_var("PACSEA_INTEGRATION_TEST", "1");
94 std::env::set_var("PACSEA_TEST_PRIVILEGE_AVAILABLE", "none");
95 }
96 let settings = crate::theme::Settings::default();
97 let result = evaluate_long_run_auth_readiness(&settings);
98 unsafe {
99 std::env::remove_var("PACSEA_TEST_PRIVILEGE_AVAILABLE");
100 std::env::remove_var("PACSEA_INTEGRATION_TEST");
101 }
102 assert_eq!(result.readiness, LongRunReadiness::Degraded);
103 assert!(result.should_warn);
104 }
105
106 #[test]
107 fn readiness_is_ready_via_pam_for_doas_interactive() {
108 let _guard = crate::global_test_mutex_lock();
109 unsafe {
110 std::env::set_var("PACSEA_INTEGRATION_TEST", "1");
111 std::env::set_var("PACSEA_TEST_PRIVILEGE_AVAILABLE", "doas");
112 std::env::set_var("PACSEA_TEST_AUTH_MODE", "interactive");
113 }
114 let settings = crate::theme::Settings::default();
115 let result = evaluate_long_run_auth_readiness(&settings);
116 unsafe {
117 std::env::remove_var("PACSEA_TEST_AUTH_MODE");
118 std::env::remove_var("PACSEA_TEST_PRIVILEGE_AVAILABLE");
119 std::env::remove_var("PACSEA_INTEGRATION_TEST");
120 }
121 assert_eq!(result.readiness, LongRunReadiness::ReadyViaPam);
122 assert!(!result.should_warn);
123 }
124
125 #[test]
126 fn warning_message_is_three_non_empty_lines() {
127 let app = crate::state::AppState::default();
128 let message = build_long_run_warning_message(&app);
129 let parts: Vec<&str> = message.lines().collect();
130 assert_eq!(parts.len(), 3);
131 assert!(parts.iter().all(|line| !line.trim().is_empty()));
132 }
133}