dr_core/
secrets.rs

1//! Module for secrets handling
2use serde::Deserialize;
3use serde::Serialize;
4use std::fmt::Debug;
5use std::fmt::Display;
6
7/// Container that masks its value from Debug and Display attempts
8#[derive(Clone, Copy, Deserialize, Serialize)]
9pub struct Mask<T> {
10    val: T,
11}
12
13impl From<&str> for Mask<String> {
14    fn from(value: &str) -> Self {
15        Mask::new(String::from(value))
16    }
17}
18
19impl From<String> for Mask<String> {
20    fn from(value: String) -> Self {
21        Mask::new(value.clone())
22    }
23}
24
25impl<T> Mask<T> {
26    pub fn new(val: T) -> Self {
27        Mask { val }
28    }
29
30    pub fn unwrap(self) -> T {
31        self.val
32    }
33}
34
35impl<T> Display for Mask<T> {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        write!(f, "Mask(*****)")
38    }
39}
40
41impl<T> Debug for Mask<T> {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        write!(f, "Mask(*****)")
44    }
45}
46
47/// Enum for the type of available secrets
48#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
49pub enum Secret<T> {
50    Token(Mask<T>),
51    Pwd(Mask<T>),
52}
53
54#[cfg(test)]
55mod tests {
56
57    use super::*;
58
59    #[test]
60    fn test_mask() {
61        let m = Mask::new("hello");
62        assert_eq!(m.unwrap(), "hello");
63    }
64
65    #[test]
66    fn test_display_and_debug() {
67        let m = Mask::new("hello");
68        let disp = m.to_string();
69        assert_eq!(disp, String::from("Mask(*****)"));
70    }
71
72    #[test]
73    fn test_enum() {
74        let m = Mask::new("hello");
75        let pwd = Secret::Pwd(m);
76        if let Secret::Pwd(mask) = pwd {
77            assert_eq!(mask.unwrap(), "hello");
78        }
79    }
80}