Skip to content

Commit

Permalink
feat(router): add duplication_check field in stored card response(#59)
Browse files Browse the repository at this point in the history
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Nishant Joshi <[email protected]>
  • Loading branch information
3 people authored Jan 29, 2024
1 parent 7b8e116 commit 358cdb8
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
21 changes: 15 additions & 6 deletions src/routes/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use axum::middleware;

use masking::ExposeInterface;

use types::StoreCardResponse;

use crate::{
app::AppState,
crypto::{aes::GcmAes256, sha::Sha512},
Expand Down Expand Up @@ -94,7 +96,7 @@ pub async fn add_card(

let optional_hash_table = state.db.find_by_data_hash(&hash_data).await?;

let output = match optional_hash_table {
let (duplication_check, output) = match optional_hash_table {
Some(hash_table) => {
let stored_data = state
.db
Expand All @@ -107,7 +109,10 @@ pub async fn add_card(
)
.await?;

match stored_data {
let duplication_check =
transformers::validate_card_metadata(stored_data.as_ref(), &request.data)?;

let output = match stored_data {
Some(data) => data,
None => {
state
Expand All @@ -123,12 +128,14 @@ pub async fn add_card(
)
.await?
}
}
};

(duplication_check, output)
}
None => {
let hash_table = state.db.insert_hash(hash_data).await?;

state
let output = state
.db
.insert_or_get_from_locker(
(
Expand All @@ -139,11 +146,13 @@ pub async fn add_card(
.try_into()?,
&merchant_dek,
)
.await?
.await?;

(None, output)
}
};

Ok(Json(output.into()))
Ok(Json(StoreCardResponse::from((duplication_check, output))))
}

/// `/data/delete` handling the requirement of deleting cards
Expand Down
43 changes: 40 additions & 3 deletions src/routes/data/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
storage,
};

use super::types;
use super::types::{self, DataDuplicationCheck};

impl<'a> TryFrom<(super::types::StoreCardRequest, &'a str, &'a str)>
for storage::types::LockerNew<'a>
Expand Down Expand Up @@ -38,12 +38,17 @@ impl<'a> TryFrom<(super::types::StoreCardRequest, &'a str, &'a str)>
}
}

impl From<storage::types::Locker> for super::types::StoreCardResponse {
fn from(value: storage::types::Locker) -> Self {
impl From<(Option<DataDuplicationCheck>, storage::types::Locker)>
for super::types::StoreCardResponse
{
fn from(
(duplication_check, value): (Option<DataDuplicationCheck>, storage::types::Locker),
) -> Self {
Self {
status: types::Status::Ok,
payload: Some(super::types::StoreCardRespPayload {
card_reference: value.locker_id.expose(),
duplication_check,
dedup: None,
}),
}
Expand Down Expand Up @@ -71,6 +76,18 @@ impl TryFrom<storage::types::Locker> for super::types::RetrieveCardResponse {
}
}

impl std::cmp::PartialEq<types::Data> for super::types::StoredData {
fn eq(&self, other: &types::Data) -> bool {
match (self, other) {
(Self::EncData(request_enc_card_data), types::Data::EncData { enc_card_data }) => {
request_enc_card_data == enc_card_data
}
(Self::CardData(request_card), types::Data::Card { card }) => request_card == card,
_ => false,
}
}
}

/// Generate UUID v4 as strings to be used in storage layer
pub fn generate_uuid() -> String {
uuid::Uuid::new_v4().to_string()
Expand Down Expand Up @@ -98,3 +115,23 @@ where

Ok(hash_data)
}

pub fn validate_card_metadata(
stored_payload: Option<&storage::types::Locker>,
request_data: &types::Data,
) -> Result<Option<DataDuplicationCheck>, ContainerError<error::ApiError>> {
stored_payload
.map(|stored_data| {
let stored_data =
serde_json::from_slice::<types::StoredData>(stored_data.enc_data.peek())
.change_error(error::ApiError::DecodingError)?;

let is_metadata_duplicated = stored_data.eq(request_data);

Ok(match is_metadata_duplicated {
true => DataDuplicationCheck::Duplicated,
false => DataDuplicationCheck::MetaDataChanged,
})
})
.transpose()
}
14 changes: 11 additions & 3 deletions src/routes/data/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use masking::PeekInterface;

use crate::error;

#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
pub struct Card {
pub card_number: masking::StrongSecret<String>,
name_on_card: Option<String>,
Expand All @@ -25,9 +25,17 @@ pub struct Card {
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct StoreCardRespPayload {
pub card_reference: String,
pub duplication_check: Option<DataDuplicationCheck>,
pub dedup: Option<DedupResponsePayload>,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum DataDuplicationCheck {
Duplicated,
MetaDataChanged,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct DedupResponsePayload {
hash1_reference: Option<String>,
Expand All @@ -48,7 +56,7 @@ pub struct StoreCardRequest {
pub data: Data,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum Data {
EncData { enc_card_data: String },
Expand Down Expand Up @@ -94,7 +102,7 @@ pub struct DeleteCardResponse {
pub status: Status,
}

#[derive(serde::Serialize, serde::Deserialize)]
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub enum StoredData {
EncData(String),
CardData(Card),
Expand Down

0 comments on commit 358cdb8

Please sign in to comment.