use super::text::TextRedactionPolicy;
mod kind_sealed {
pub trait Sealed {}
}
mod recursive_kind_sealed {
pub trait Sealed {}
}
pub trait PolicyKind: kind_sealed::Sealed {}
#[derive(Clone, Copy, Debug)]
pub struct TextPolicyKind;
impl kind_sealed::Sealed for TextPolicyKind {}
impl PolicyKind for TextPolicyKind {}
impl recursive_kind_sealed::Sealed for TextPolicyKind {}
#[derive(Clone, Copy, Debug)]
pub struct SecretPolicyKind;
impl kind_sealed::Sealed for SecretPolicyKind {}
impl PolicyKind for SecretPolicyKind {}
impl recursive_kind_sealed::Sealed for SecretPolicyKind {}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot use the legacy recursive policy traversal",
note = "use `apply_policy` or `apply_policy_ref` for kind-aware dispatch; inside IP containers wrap typed values in `SensitiveValue<T, IpAddress>`"
)]
#[doc(hidden)]
pub trait RecursivePolicyKind: PolicyKind + recursive_kind_sealed::Sealed {}
impl RecursivePolicyKind for TextPolicyKind {}
impl RecursivePolicyKind for SecretPolicyKind {}
#[derive(Clone, Copy, Debug)]
pub struct IpAddressPolicyKind;
impl kind_sealed::Sealed for IpAddressPolicyKind {}
impl PolicyKind for IpAddressPolicyKind {}
pub trait RedactionPolicy {
type Kind: PolicyKind;
fn policy() -> TextRedactionPolicy;
}
#[derive(Clone, Copy)]
pub struct Secret;
impl RedactionPolicy for Secret {
type Kind = SecretPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::default_full()
}
}
#[derive(Clone, Copy)]
pub struct BlockchainAddress;
impl RedactionPolicy for BlockchainAddress {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(6)
}
}
#[derive(Clone, Copy)]
pub struct CreditCard;
impl RedactionPolicy for CreditCard {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(4)
}
}
#[derive(Clone, Copy)]
pub struct Email;
impl RedactionPolicy for Email {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::email_local(2)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct IpAddress;
impl RedactionPolicy for IpAddress {
type Kind = IpAddressPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(4)
}
}
#[derive(Clone, Copy)]
pub struct PhoneNumber;
impl RedactionPolicy for PhoneNumber {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(4)
}
}
#[derive(Clone, Copy)]
pub struct Pii;
impl RedactionPolicy for Pii {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(2)
}
}
#[derive(Clone, Copy)]
pub struct Token;
impl RedactionPolicy for Token {
type Kind = TextPolicyKind;
fn policy() -> TextRedactionPolicy {
TextRedactionPolicy::keep_last(4)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builtin_policies_use_expected_defaults() {
let policy = Token::policy();
assert_eq!(policy.apply_to("sk_live_abc123"), "**********c123");
let policy = BlockchainAddress::policy();
assert_eq!(policy.apply_to("0x1234567890abcdef"), "************abcdef");
let policy = CreditCard::policy();
assert_eq!(policy.apply_to("4111111111111111"), "************1111");
assert_eq!(policy.apply_to("1234"), "****");
let policy = Email::policy();
assert_eq!(policy.apply_to("alice@example.com"), "al***@example.com");
let policy = PhoneNumber::policy();
assert_eq!(policy.apply_to("+1-555-123-4567"), "***********4567");
let policy = Pii::policy();
assert_eq!(policy.apply_to("John Doe"), "******oe");
}
}