use secrecy::SecretString;
use secure_env::{crypto, store};
use std::collections::BTreeMap;
fn sample_sets() -> store::Sets {
BTreeMap::from([
(
"db".to_string(),
BTreeMap::from([
("HOST".to_string(), "localhost".to_string()),
("PORT".to_string(), "5432".to_string()),
]),
),
(
"app".to_string(),
BTreeMap::from([
("API_KEY".to_string(), "s3cr3t!@#$%^&*()_+".to_string()),
(
"GREETING".to_string(),
"hello 'world' with \"quotes\" and emoji 🚀".to_string(),
),
]),
),
])
}
#[test]
fn encrypt_then_decrypt_preserves_values() {
let sets = sample_sets();
let passphrase = SecretString::from("correct horse battery staple".to_owned());
let toml = store::to_toml(&sets);
let ciphertext = crypto::encrypt(toml.as_bytes(), passphrase.clone()).unwrap();
let plaintext = crypto::decrypt(&ciphertext, passphrase).unwrap();
assert_eq!(plaintext, toml.as_bytes());
let decrypted = store::from_toml(&plaintext).unwrap();
assert_eq!(decrypted, sets);
}
#[test]
fn wrong_passphrase_fails_to_decrypt() {
let ciphertext = crypto::encrypt(
b"secret data",
SecretString::from("right passphrase".to_owned()),
)
.unwrap();
assert!(crypto::decrypt(&ciphertext, SecretString::from("wrong passphrase".to_owned())).is_err());
}
#[test]
fn file_roundtrip_with_atomic_write() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("secure-env.enc");
let passphrase = SecretString::from("file roundtrip passphrase".to_owned());
let sets = sample_sets();
let toml = store::to_toml(&sets);
let ciphertext = crypto::encrypt(toml.as_bytes(), passphrase.clone()).unwrap();
store::atomic_write(&path, &ciphertext).unwrap();
let loaded = store::read_plain(&path, passphrase).unwrap().unwrap();
assert_eq!(loaded, sets);
}