fix(expiry preservation): maintain expiry when not provided for update
Dependencies
- [2]
4KJ45IJLImplement new identity management - [3]
FOCBVLOUImplement testing for identity management - [4]
4OJWMSOWFully replace crate::Identity - [5]
KKNMDXAITweak identity subcommand - [6]
6FRPUHWKFix identity tests - [7]
DOEG3V7UOnly re-write identity data when changed - [8]
32G3GOK7Migrate from `dialoguer` to `pijul-interaction` - [9]
N26HD5PFReplace `chrono` with `jiff` - [10]
MBIKZPCCAdd flags to disable the use of the system keyring, asking to prompt the key password directly instead - [11]
YW6NICQVMigrate codebase to refactored `pijul_config` crate - [12]
VQCREHLRResolve conflicts in identity creation - [13]
TVV36VDZSolving conflicts - [14]
WTPFQPO5Add global `no_prompt` flag - [15]
5Z2Y7VGVMigrate `pijul::identity::Complete::prove` to `pijul::remote::prove` - [16]
6JKPLWMVResolve hunk order conflicts
Change contents
- replacement in pijul-identity/src/lib.rs at line 41
pub use create::CreateParams;pub use create::{CreateParams, parse_expiry_date}; - edit in pijul/tests/identity.rs at line 206
fn edit_preserves_existing_expiry() -> Result<(), Error> {use std::{fs, process::Command};let config_dir = tempfile::tempdir()?;fs::write(config_dir.path().join("config.toml"),"colors = 'never'\n[author]\nlogin = ''",)?;let new_status = Command::new(env!("CARGO_BIN_EXE_pijul")).env("PIJUL_CONFIG_DIR", config_dir.path()).args(["identity","new","--no-link","--no-prompt","my_identity","--display-name",default::FULL_NAME,"--expiry",default::EXPIRY,]).status()?;assert!(new_status.success());let edit_status = Command::new(env!("CARGO_BIN_EXE_pijul")).env("PIJUL_CONFIG_DIR", config_dir.path()).args(["identity","edit","--no-link","--no-prompt","my_identity","--email",default::EMAIL,]).status()?;assert!(edit_status.success());let identity_path = config_dir.path().join("identities").join("my_identity").join("identity.toml");let identity_data = fs::read_to_string(identity_path)?;let toml_data = identity_data.parse::<toml::Value>().unwrap();assert_eq!(toml_data.get("email").and_then(toml::Value::as_str),Some(default::EMAIL));let public_expiry = toml_data.get("public_key").and_then(|value| value.get("expires")).and_then(toml::Value::as_str).expect("expected public key expiry to be preserved").parse::<jiff::Timestamp>()?;assert_eq!(public_expiry.strftime("%Y-%m-%d").to_string(),default::EXPIRY);let secret_key = fs::read_to_string(config_dir.path().join("identities").join("my_identity").join("secret_key.json"),)?;let secret_key: pijul_core::key::SecretKey = serde_json::from_str(&secret_key)?;assert_eq!(secret_key.expires.expect("expected secret key expiry to be preserved").strftime("%Y-%m-%d").to_string(),default::EXPIRY);Ok(())}#[test] - replacement in pijul/src/commands/identity.rs at line 64
let parsed_date: Timestamp = input.parse().map_err(|error| anyhow!("Error parsing date: {error:#?}"))?;let parsed_date =pijul_identity::parse_expiry_date(input).map_err(|_| anyhow!("Invalid date"))?; - replacement in pijul/src/commands/identity.rs at line 166
Repair { no_keyring: bool },Repair {#[clap(long = "no-keyring")]no_keyring: bool,}, - edit in pijul/src/commands/identity.rs at line 178
#[clap(long = "no-keyring")] - edit in pijul/src/commands/identity.rs at line 220
no_prompt: bool,use_keyring: bool, - edit in pijul/src/commands/identity.rs at line 224
let mut public_key = default.public_key.clone();if let Some(expiry) = expiry.as_ref() {public_key.expires = Some(expiry.clone());} - replacement in pijul/src/commands/identity.rs at line 230[2.47558]→[2.47558:47572](∅→∅),[2.47572]→[11.13491:13545](∅→∅),[8.2865]→[6.5338:5383](∅→∅),[11.13545]→[6.5338:5383](∅→∅),[2.47648]→[6.5338:5383](∅→∅),[6.5383]→[2.47700:47816](∅→∅),[2.47700]→[2.47700:47816](∅→∅)
Some(pijul_interaction::Password::new(config)?.with_prompt("New password").with_confirmation("Confirm password", "Password mismatch").interact()?,)Some(read_password(config, no_prompt)?) - replacement in pijul/src/commands/identity.rs at line 236
key.expires = expiry;if let Some(password) = pw.as_deref() {let (secret_key, _) = default.decrypt(config, use_keyring)?;key = secret_key.save(Some(password));}if let Some(expiry) = expiry.as_ref() {key.expires = Some(expiry.clone());} - replacement in pijul/src/commands/identity.rs at line 260
default.public_key,public_key, - edit in pijul/src/commands/identity.rs at line 263
}fn read_password(config: &pijul_config::Config, no_prompt: bool) -> Result<String, anyhow::Error> {if no_prompt {use std::io::{BufRead, Write};fn read_line(prompt: &str) -> Result<String, anyhow::Error> {let mut stderr = std::io::stderr();writeln!(stderr, "{prompt}")?;stderr.flush()?;let mut input = String::new();let read = std::io::stdin().lock().read_line(&mut input)?;if read == 0 {anyhow::bail!("Unexpected end of standard input")}while matches!(input.chars().last(), Some('\n' | '\r')) {input.pop();}Ok(input)}loop {let password = read_line("New password")?;let confirmation = read_line("Confirm password")?;if password == confirmation {return Ok(password);}let mut stderr = std::io::stderr();writeln!(stderr, "Password mismatch")?;stderr.flush()?;}} else {Ok(pijul_interaction::Password::new(config)?.with_prompt("New password").with_confirmation("Confirm password", "Password mismatch").interact()?)} - edit in pijul/src/commands/identity.rs at line 323
options.no_prompt,!options.no_keyring, - edit in pijul/src/commands/identity.rs at line 332
link_remote: !options.no_link, - edit in pijul/src/commands/identity.rs at line 333
link_remote: !options.no_link, - edit in pijul/src/commands/identity.rs at line 503
options.no_prompt,!options.no_keyring,