cloudiful_redactor/
service.rs1use anyhow::{Context, Result};
2
3use crate::{
4 InputKind, RedactionArtifact, RedactionSession, Redactor, RestoreResult,
5 decrypt_session_from_str, encrypt_session_to_string, ensure_restore_valid,
6 inspect_encrypted_session,
7};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct EncryptedRedactionArtifact {
11 pub artifact: RedactionArtifact,
12 pub encrypted_session: String,
13 pub session_summary: crate::SessionSummary,
14}
15
16pub fn redact_text_artifact(
17 redactor: &Redactor,
18 text: &str,
19 input_kind: InputKind,
20) -> Result<RedactionArtifact> {
21 redactor
22 .redact_artifact_with_input_kind(text, input_kind)
23 .map_err(anyhow::Error::new)
24}
25
26pub fn redact_text_with_encrypted_session(
27 redactor: &Redactor,
28 text: &str,
29 input_kind: InputKind,
30 passphrase: &str,
31) -> Result<EncryptedRedactionArtifact> {
32 let artifact =
33 redact_text_artifact(redactor, text, input_kind).context("failed to redact text input")?;
34 let encrypted_session = encrypt_session_to_string(&artifact.session, passphrase)
35 .context("failed to encrypt redaction session")?;
36 let session_summary = inspect_encrypted_session(&encrypted_session)
37 .context("failed to inspect encrypted session")?;
38
39 Ok(EncryptedRedactionArtifact {
40 artifact,
41 encrypted_session,
42 session_summary,
43 })
44}
45
46pub fn decrypt_redaction_session(
47 encrypted_session: &str,
48 passphrase: &str,
49) -> Result<RedactionSession> {
50 decrypt_session_from_str(encrypted_session, passphrase)
51 .context("failed to decrypt provided session")
52}
53
54pub fn restore_text_from_encrypted_session(
55 redactor: &Redactor,
56 text: &str,
57 encrypted_session: &str,
58 passphrase: &str,
59) -> Result<RestoreResult> {
60 let session = decrypt_redaction_session(encrypted_session, passphrase)?;
61 let restored = redactor.restore_text(text, &session);
62 ensure_restore_valid(&restored)?;
63 Ok(restored)
64}
65
66#[cfg(test)]
67mod tests {
68 use super::{
69 redact_text_artifact, redact_text_with_encrypted_session,
70 restore_text_from_encrypted_session,
71 };
72 use crate::{InputKind, RedactorBuilder};
73
74 #[test]
75 fn encrypted_redaction_matches_plain_artifact_output() {
76 let redactor = RedactorBuilder::new().build();
77 let text = "host=service.example.com secret=EJ2QEVC6AKELW0k2kkVY4NgGKONC";
78 let plain = redact_text_artifact(&redactor, text, InputKind::Text).expect("plain");
79 let encrypted =
80 redact_text_with_encrypted_session(&redactor, text, InputKind::Text, "pass")
81 .expect("encrypted");
82
83 assert_eq!(
84 encrypted.artifact.result.redacted_text,
85 plain.result.redacted_text
86 );
87 assert_eq!(
88 encrypted.artifact.session.redacted_text,
89 plain.session.redacted_text
90 );
91 }
92
93 #[test]
94 fn encrypted_session_restore_round_trips() {
95 let redactor = RedactorBuilder::new().build();
96 let text = "host=service.example.com";
97 let encrypted =
98 redact_text_with_encrypted_session(&redactor, text, InputKind::Text, "pass")
99 .expect("encrypted");
100
101 let restored = restore_text_from_encrypted_session(
102 &redactor,
103 &encrypted.artifact.result.redacted_text,
104 &encrypted.encrypted_session,
105 "pass",
106 )
107 .expect("restore");
108
109 assert_eq!(restored.restored_text, text);
110 }
111}