Create, delete, and list deploy keys via Gitea REST API. Foundation for device authentication. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
159 lines
5.2 KiB
Rust
159 lines
5.2 KiB
Rust
mod common;
|
|
|
|
use common::TestVault;
|
|
|
|
#[test]
|
|
fn settings_roundtrip_trash_retention() {
|
|
let v = TestVault::init();
|
|
let out = v.run(&["settings", "show"]);
|
|
assert!(String::from_utf8(out.stdout).unwrap().contains("trash_retention"));
|
|
|
|
let out = v.run(&["settings", "trash-retention", "--days", "60"]);
|
|
assert!(out.status.success(), "set failed: {:?}", out);
|
|
let out = v.run(&["settings", "show"]);
|
|
let stdout = String::from_utf8(out.stdout).unwrap();
|
|
assert!(stdout.contains("60"), "expected 60: {stdout}");
|
|
}
|
|
|
|
#[test]
|
|
fn settings_rejects_conflicting_retention_flags() {
|
|
let v = TestVault::init();
|
|
let out = v.run(&["settings", "trash-retention", "--days", "30", "--forever"]);
|
|
assert!(!out.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn generate_uses_vault_default_length() {
|
|
let v = TestVault::init();
|
|
|
|
// Default vault settings: GeneratorRequest::Random { length: 20, ... }.
|
|
let out = v.run(&["generate"]);
|
|
assert!(out.status.success(), "{:?}", String::from_utf8_lossy(&out.stderr));
|
|
let pw = String::from_utf8(out.stdout).unwrap();
|
|
assert_eq!(
|
|
pw.trim().chars().count(),
|
|
20,
|
|
"expected 20 chars at default, got {pw:?}"
|
|
);
|
|
|
|
// Update the vault default length to 32.
|
|
let out = v.run(&["settings", "generator-defaults", "--length", "32"]);
|
|
assert!(
|
|
out.status.success(),
|
|
"set generator-defaults failed: {}",
|
|
String::from_utf8_lossy(&out.stderr)
|
|
);
|
|
|
|
// `generate` (no flags) should now produce 32 chars.
|
|
let out = v.run(&["generate"]);
|
|
assert!(out.status.success(), "{:?}", String::from_utf8_lossy(&out.stderr));
|
|
let pw = String::from_utf8(out.stdout).unwrap();
|
|
assert_eq!(
|
|
pw.trim().chars().count(),
|
|
32,
|
|
"expected 32 chars after update, got {pw:?}"
|
|
);
|
|
|
|
// Explicit flag overrides the vault default.
|
|
let out = v.run(&["generate", "--length", "8"]);
|
|
assert!(out.status.success());
|
|
let pw = String::from_utf8(out.stdout).unwrap();
|
|
assert_eq!(
|
|
pw.trim().chars().count(),
|
|
8,
|
|
"explicit flag should override vault default, got {pw:?}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn status_reports_item_and_attachment_counts() {
|
|
let v = TestVault::init();
|
|
v.run(&["add", "login", "--title", "active",
|
|
"--username", "u", "--password", "p"]);
|
|
v.run(&["add", "login", "--title", "to-trash",
|
|
"--username", "u", "--password", "p"]);
|
|
v.run(&["rm", "to-trash"]);
|
|
|
|
let payload = v.path().join("payload.txt");
|
|
std::fs::write(&payload, b"hello-world").unwrap();
|
|
v.run(&["attach", "active", payload.to_str().unwrap()]);
|
|
|
|
let out = v.run(&["status"]);
|
|
assert!(
|
|
out.status.success(),
|
|
"status failed:\nstdout: {}\nstderr: {}",
|
|
String::from_utf8_lossy(&out.stdout),
|
|
String::from_utf8_lossy(&out.stderr),
|
|
);
|
|
let stdout = String::from_utf8(out.stdout).unwrap();
|
|
let lower = stdout.to_lowercase();
|
|
|
|
// 1 active + 1 trashed = 2 items total.
|
|
assert!(lower.contains("items"), "missing items section: {stdout}");
|
|
assert!(stdout.contains('2') || stdout.contains("2 ")
|
|
|| lower.contains("active: 1") || lower.contains("1 active"),
|
|
"expected item counts in output: {stdout}");
|
|
assert!(lower.contains("trash"), "missing trash count: {stdout}");
|
|
|
|
// 1 attachment, 11 bytes.
|
|
assert!(lower.contains("attachment"), "missing attachment section: {stdout}");
|
|
assert!(stdout.contains("11"), "expected 11-byte size in output: {stdout}");
|
|
|
|
// device count line removed — device key system was security theater (audit B1).
|
|
|
|
// Last-commit line.
|
|
assert!(
|
|
lower.contains("last commit") || lower.contains("commit"),
|
|
"missing last-commit info: {stdout}",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn status_shows_last_backup_line() {
|
|
let v = TestVault::init();
|
|
let out = v.run(&["status"]);
|
|
assert!(out.status.success());
|
|
let stdout = String::from_utf8(out.stdout).unwrap();
|
|
assert!(stdout.contains("Last export:"), "missing last export line: {stdout}");
|
|
assert!(stdout.contains("never"), "fresh vault should report 'never': {stdout}");
|
|
}
|
|
|
|
#[test]
|
|
fn status_shows_recent_backup_after_export() {
|
|
let v = TestVault::init();
|
|
let backup_path = v.path().join("v.relbak");
|
|
v.run_with_backup_pass(
|
|
&["backup", "export", backup_path.to_str().unwrap()],
|
|
"test-backup-pass-2026",
|
|
);
|
|
let out = v.run(&["status"]);
|
|
let stdout = String::from_utf8(out.stdout).unwrap();
|
|
assert!(stdout.contains("Last export:"), "{stdout}");
|
|
assert!(!stdout.contains("never"), "should NOT say 'never' after export: {stdout}");
|
|
}
|
|
|
|
#[test]
|
|
fn generate_works_outside_vault() {
|
|
use assert_cmd::cargo::CommandCargoExt;
|
|
use std::process::{Command, Stdio};
|
|
use tempfile::TempDir;
|
|
|
|
let tmp = TempDir::new().unwrap();
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(tmp.path())
|
|
.args(["generate", "--length", "12"])
|
|
.stdin(Stdio::null())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.output()
|
|
.unwrap();
|
|
assert!(
|
|
out.status.success(),
|
|
"no-vault generate failed: {}",
|
|
String::from_utf8_lossy(&out.stderr)
|
|
);
|
|
let pw = String::from_utf8(out.stdout).unwrap();
|
|
assert_eq!(pw.trim().chars().count(), 12);
|
|
}
|