From 9d74a75ddbd49e7ef7fa0cbfab1528da342dd5a0 Mon Sep 17 00:00:00 2001 From: Chethan Rao <70657455+Chethan-rao@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:45:43 +0530 Subject: [PATCH] refactor(masking): move masking implementations to masking crate (#2135) --- crates/masking/src/lib.rs | 4 + crates/masking/src/maskable.rs | 100 ++++++++++++++++++++++ crates/router/src/services/api/request.rs | 78 +---------------- 3 files changed, 106 insertions(+), 76 deletions(-) create mode 100644 crates/masking/src/maskable.rs diff --git a/crates/masking/src/lib.rs b/crates/masking/src/lib.rs index 8c5b03bd4f..a0c4d3226a 100644 --- a/crates/masking/src/lib.rs +++ b/crates/masking/src/lib.rs @@ -54,3 +54,7 @@ pub mod prelude { #[cfg(feature = "diesel")] mod diesel; + +pub mod maskable; + +pub use maskable::*; diff --git a/crates/masking/src/maskable.rs b/crates/masking/src/maskable.rs new file mode 100644 index 0000000000..3469e1dd74 --- /dev/null +++ b/crates/masking/src/maskable.rs @@ -0,0 +1,100 @@ +//! +//! This module contains Masking objects and traits +//! + +use crate::{ExposeInterface, Secret}; + +/// +/// An Enum that allows us to optionally mask data, based on which enum variant that data is stored +/// in. +/// +#[derive(Clone, Eq, PartialEq)] +pub enum Maskable { + /// Variant which masks the data by wrapping in a Secret + Masked(Secret), + /// Varant which doesn't mask the data + Normal(T), +} + +impl std::fmt::Debug for Maskable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Masked(secret_value) => std::fmt::Debug::fmt(secret_value, f), + Self::Normal(value) => std::fmt::Debug::fmt(value, f), + } + } +} + +impl std::hash::Hash for Maskable { + fn hash(&self, state: &mut H) { + match self { + Self::Masked(value) => crate::PeekInterface::peek(value).hash(state), + Self::Normal(value) => value.hash(state), + } + } +} + +impl Maskable { + /// + /// Get the inner data while consuming self + /// + pub fn into_inner(self) -> T { + match self { + Self::Masked(inner_secret) => inner_secret.expose(), + Self::Normal(inner) => inner, + } + } + + /// + /// Create a new Masked data + /// + pub fn new_masked(item: Secret) -> Self { + Self::Masked(item) + } + + /// + /// Create a new non-masked data + /// + pub fn new_normal(item: T) -> Self { + Self::Normal(item) + } +} + +/// Trait for providing a method on custom types for constructing `Maskable` + +pub trait Mask { + /// The type returned by the `into_masked()` method. Must implement `PartialEq`, `Eq` and `Clone` + + type Output: Eq + Clone + PartialEq; + + /// + /// Construct a `Maskable` instance that wraps `Self::Output` by consuming `self` + /// + fn into_masked(self) -> Maskable; +} + +impl Mask for String { + type Output = Self; + fn into_masked(self) -> Maskable { + Maskable::new_masked(self.into()) + } +} + +impl Mask for Secret { + type Output = String; + fn into_masked(self) -> Maskable { + Maskable::new_masked(self) + } +} + +impl From for Maskable { + fn from(value: T) -> Self { + Self::new_normal(value) + } +} + +impl From<&str> for Maskable { + fn from(value: &str) -> Self { + Self::new_normal(value.to_string()) + } +} diff --git a/crates/router/src/services/api/request.rs b/crates/router/src/services/api/request.rs index 2a9459b593..21b4a5acdc 100644 --- a/crates/router/src/services/api/request.rs +++ b/crates/router/src/services/api/request.rs @@ -1,7 +1,8 @@ use std::{collections, str::FromStr}; use error_stack::{IntoReport, ResultExt}; -use masking::{ExposeInterface, Secret}; +use masking::Secret; +pub use masking::{Mask, Maskable}; use router_env::{instrument, tracing}; use serde::{Deserialize, Serialize}; @@ -12,81 +13,6 @@ use crate::{ pub(crate) type Headers = collections::HashSet<(String, Maskable)>; -/// -/// An Enum that allows us to optionally mask data, based on which enum variant that data is stored -/// in. -/// -#[derive(Clone, Eq, PartialEq)] -pub enum Maskable { - Masked(Secret), - Normal(T), -} - -impl std::fmt::Debug for Maskable { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Masked(secret_value) => std::fmt::Debug::fmt(secret_value, f), - Self::Normal(value) => std::fmt::Debug::fmt(value, f), - } - } -} - -impl std::hash::Hash for Maskable { - fn hash(&self, state: &mut H) { - match self { - Self::Masked(value) => masking::PeekInterface::peek(value).hash(state), - Self::Normal(value) => value.hash(state), - } - } -} - -impl Maskable { - pub fn into_inner(self) -> T { - match self { - Self::Masked(inner_secret) => inner_secret.expose(), - Self::Normal(inner) => inner, - } - } - - pub fn new_masked(item: Secret) -> Self { - Self::Masked(item) - } - pub fn new_normal(item: T) -> Self { - Self::Normal(item) - } -} - -pub trait Mask { - type Output: Eq + Clone + PartialEq; - fn into_masked(self) -> Maskable; -} - -impl Mask for String { - type Output = Self; - fn into_masked(self) -> Maskable { - Maskable::new_masked(self.into()) - } -} - -impl Mask for Secret { - type Output = String; - fn into_masked(self) -> Maskable { - Maskable::new_masked(self) - } -} - -impl From for Maskable { - fn from(value: T) -> Self { - Self::new_normal(value) - } -} - -impl From<&str> for Maskable { - fn from(value: &str) -> Self { - Self::new_normal(value.to_string()) - } -} - #[derive( Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, strum::Display, strum::EnumString, )]