Skip to content

Commit 67308e3

Browse files
authored
Merge pull request #42 from tyvsmith/feat/pam-setup-confirm-before-mutating
feat(setup): show change preview and confirm before editing PAM files
2 parents fc60c94 + 6748ac2 commit 67308e3

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

crates/facelock-cli/src/commands/setup.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ fn run_wizard() -> anyhow::Result<()> {
211211
}
212212
};
213213

214+
print_pam_extension_hint();
215+
214216
// -- Summary --
215217
println!("\n--- Setup Complete ---\n");
216218
let encryption_label = match config.encryption.method {
@@ -1387,6 +1389,17 @@ fn download_model(entry: &ModelEntry, dest: &Path) -> anyhow::Result<()> {
13871389
// --- PAM installation ---
13881390

13891391
const PAM_LINE: &str = "auth sufficient pam_facelock.so";
1392+
1393+
/// Print a copy-pasteable hint so users can extend PAM integration to any service.
1394+
fn print_pam_extension_hint() {
1395+
println!();
1396+
println!("==> facelock PAM line for manual extension to other services:");
1397+
println!("==> {PAM_LINE}");
1398+
println!(
1399+
"==> Add the above line above the first 'auth' line in any /etc/pam.d/<service> file."
1400+
);
1401+
}
1402+
13901403
const PAM_MODULE_PATH: &str = "/lib/security/pam_facelock.so";
13911404
const SENSITIVE_SERVICES: &[&str] = &["system-auth", "login", "sshd"];
13921405

@@ -1405,7 +1418,9 @@ pub fn run_pam(service: &str, remove: bool, yes: bool) -> anyhow::Result<()> {
14051418
if remove {
14061419
pam_remove(service)
14071420
} else {
1408-
pam_install(service, yes)
1421+
pam_install(service, yes)?;
1422+
print_pam_extension_hint();
1423+
Ok(())
14091424
}
14101425
}
14111426

@@ -1444,8 +1459,39 @@ fn pam_install(service: &str, yes: bool) -> anyhow::Result<()> {
14441459
return Ok(());
14451460
}
14461461

1447-
// 4. Create backup (always, before any modification)
1462+
// 4. Preview change and confirm before any modification
14481463
let backup_path = format!("{pam_path}.facelock-backup");
1464+
1465+
// Decide where the line will go BEFORE prompting, so the preview is accurate.
1466+
let insertion_hint = if content.lines().any(|l| l.trim_start().starts_with("auth")) {
1467+
"inserted before the first 'auth' line"
1468+
} else {
1469+
"no 'auth' line found — inserted at the top of the file"
1470+
};
1471+
1472+
println!();
1473+
println!("About to modify {pam_path}:");
1474+
println!(" + {PAM_LINE} ({insertion_hint})");
1475+
println!(" Backup will be saved to: {backup_path}");
1476+
println!();
1477+
println!("(To configure manually instead, add the line above to each service yourself.)");
1478+
1479+
let proceed = if yes || !std::io::stdin().is_terminal() {
1480+
true
1481+
} else {
1482+
Confirm::new()
1483+
.with_prompt("Proceed?")
1484+
.default(true)
1485+
.interact()
1486+
.context("failed to read confirmation")?
1487+
};
1488+
1489+
if !proceed {
1490+
println!("Skipped {pam_path}.");
1491+
return Ok(());
1492+
}
1493+
1494+
// 4b. Create backup (always, before any modification)
14491495
fs::copy(pam_file, &backup_path)
14501496
.with_context(|| format!("failed to back up {pam_path} to {backup_path}"))?;
14511497
println!("Backed up {pam_path} -> {backup_path}");

crates/facelock-cli/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ enum Commands {
4040
/// Remove the PAM line instead of adding it
4141
#[arg(long)]
4242
remove: bool,
43-
/// Skip confirmation for sensitive services
44-
#[arg(short, long)]
43+
/// Skip the confirmation prompt before modifying PAM files (also: --no-confirm)
44+
#[arg(short, long, alias = "no-confirm")]
4545
yes: bool,
4646
/// Run in non-interactive mode (skip wizard)
4747
#[arg(long)]

0 commit comments

Comments
 (0)