Skip to main content

via/
redaction.rs

1#[derive(Default)]
2pub struct Redactor {
3    secrets: Vec<String>,
4}
5
6impl Redactor {
7    pub fn new() -> Self {
8        Self::default()
9    }
10
11    pub fn add(&mut self, secret: &str) {
12        if secret.is_empty() {
13            return;
14        }
15
16        self.secrets.push(secret.to_owned());
17    }
18
19    pub fn redact(&self, value: &str) -> String {
20        let mut redacted = value.to_owned();
21        for secret in &self.secrets {
22            redacted = redacted.replace(secret, "[REDACTED]");
23        }
24        redacted
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn redacts_registered_secret() {
34        let mut redactor = Redactor::new();
35        redactor.add("secret-token");
36
37        assert_eq!(redactor.redact("token=secret-token"), "token=[REDACTED]");
38    }
39
40    #[test]
41    fn ignores_empty_secret() {
42        let mut redactor = Redactor::new();
43        redactor.add("");
44
45        assert_eq!(redactor.redact("abc"), "abc");
46    }
47}