captcha-sdk 0.0.1

Unified server-side CAPTCHA verification for Rust
Documentation
use std::fmt;

use zeroize::Zeroizing;

/// Private storage for provider credentials.
#[derive(PartialEq, Eq)]
pub(crate) struct Credential(Zeroizing<String>);

impl Credential {
    #[allow(dead_code)]
    pub(crate) fn new(value: impl Into<String>) -> Self {
        Self(Zeroizing::new(value.into()))
    }

    /// Exposes a credential only to provider adapters while constructing a request.
    #[allow(dead_code)]
    pub(crate) fn expose(&self) -> &str {
        self.0.as_str()
    }
}

impl fmt::Debug for Credential {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("[REDACTED]")
    }
}

#[cfg(test)]
mod tests {
    use std::fmt::Display;

    use serde::{Serialize, de::DeserializeOwned};
    use static_assertions::assert_not_impl_any;

    use super::Credential;

    assert_not_impl_any!(Credential: Clone, Display, Serialize, DeserializeOwned);

    #[test]
    fn credential_debug_output_is_redacted() {
        let credential = Credential::new("credential-test-value");

        let debug = format!("{credential:?}");

        assert_eq!(debug, "[REDACTED]");
        assert!(!debug.contains("credential-test-value"));
        assert_eq!(credential.expose(), "credential-test-value");
    }
}