chore: drop temp_card table and all associated items (#366)

This commit is contained in:
Sanchith Hegde
2023-01-13 14:09:52 +05:30
committed by GitHub
parent ba5c3efc86
commit 89a1cd0885
22 changed files with 27 additions and 393 deletions

4
Cargo.lock generated
View File

@ -4598,9 +4598,9 @@ dependencies = [
[[package]] [[package]]
name = "wiremock" name = "wiremock"
version = "0.5.15" version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "249dc68542861d17eae4b4e5e8fb381c2f9e8f255a84f6771d5fdf8b6c03ce3c" checksum = "12316b50eb725e22b2f6b9c4cbede5b7b89984274d113a7440c86e5c3fc6f99b"
dependencies = [ dependencies = [
"assert-json-diff", "assert-json-diff",
"async-trait", "async-trait",

View File

@ -28,9 +28,6 @@ pool_size = 5
[proxy] [proxy]
[keys]
temp_card_key = "OJobAzAwOlibOhygIZOqOGideGUdEBeX" # 32 character long key
[locker] [locker]
host = "" host = ""
mock_locker = true mock_locker = true

View File

@ -68,14 +68,10 @@ level = "DEBUG"
enabled = false # boolean [true or false] enabled = false # boolean [true or false]
sampling_rate = 0.1 # decimal rate between 0.0 - 1.0 sampling_rate = 0.1 # decimal rate between 0.0 - 1.0
# This section provides configuration details for using AWS KMS to encrypt # This section provides some secret values.
# data like payment method details being sent over a network. [secrets]
[keys] admin_api_key = "test_admin" # admin API key for admin authentication
aws_key_id = "" # AWS Account Key ID jwt_secret = "secret" # JWT secret used for user authentication
aws_region = "" # AWS Account region
temp_card_key = "OJobAzAwOlibOhygIZOqOGideGUdEBeX" # AWS KMS Key
admin_api_key = "test_admin" #admin api key for merchant authentication
jwt_secret= "secret" #secret jwt for merchant
# Locker settings contain details for accessing a card locker, a # Locker settings contain details for accessing a card locker, a
# PCI Compliant storage entity which stores payment method information # PCI Compliant storage entity which stores payment method information

View File

@ -28,8 +28,7 @@ pool_size = 5
# http_url = "http proxy URL" # http_url = "http proxy URL"
# https_url = "https proxy URL" # https_url = "https proxy URL"
[keys] [secrets]
temp_card_key = "OJobAzAwOlibOhygIZOqOGideGUdEBeX" # 32 character long key
admin_api_key = "test_admin" admin_api_key = "test_admin"
jwt_secret = "secret" jwt_secret = "secret"

View File

@ -30,8 +30,7 @@ cluster_enabled = false
use_legacy_version = false use_legacy_version = false
cluster_urls = [] cluster_urls = []
[keys] [secrets]
temp_card_key = "OJobAzAwOlibOhygIZOqOGideGUdEBeX" # 32 character long key
admin_api_key = "test_admin" admin_api_key = "test_admin"
jwt_secret = "secret" jwt_secret = "secret"

View File

@ -39,7 +39,7 @@ pub struct Settings {
pub replica_database: Database, pub replica_database: Database,
pub redis: RedisSettings, pub redis: RedisSettings,
pub log: Log, pub log: Log,
pub keys: Keys, //remove this during refactoring pub secrets: Secrets,
pub locker: Locker, pub locker: Locker,
pub connectors: Connectors, pub connectors: Connectors,
pub refund: Refund, pub refund: Refund,
@ -51,12 +51,7 @@ pub struct Settings {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct Keys { pub struct Secrets {
#[cfg(feature = "kms")]
pub aws_key_id: String,
#[cfg(feature = "kms")]
pub aws_region: String,
pub temp_card_key: String,
pub jwt_secret: String, pub jwt_secret: String,
pub admin_api_key: String, pub admin_api_key: String,
} }

View File

@ -5,7 +5,6 @@ use error_stack::{report, ResultExt};
use router_env::{instrument, tracing}; use router_env::{instrument, tracing};
use crate::{ use crate::{
configs::settings,
core::{ core::{
errors::{self, StorageErrorExt}, errors::{self, StorageErrorExt},
payment_methods::transformers as payment_methods, payment_methods::transformers as payment_methods,
@ -19,7 +18,7 @@ use crate::{
storage::{self, enums}, storage::{self, enums},
transformers::ForeignInto, transformers::ForeignInto,
}, },
utils::{self, BytesExt, OptionExt, StringExt, ValueExt}, utils::{BytesExt, OptionExt, StringExt},
}; };
#[instrument(skip_all)] #[instrument(skip_all)]
@ -789,34 +788,6 @@ impl BasiliskCardSupport {
} }
} }
pub async fn get_card_info_value(
keys: &settings::Keys,
card_info: String,
) -> errors::RouterResult<serde_json::Value> {
let key = services::KeyHandler::get_encryption_key(keys)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
let enc_card_info = services::encrypt(&card_info, key.as_bytes())
.change_context(errors::ApiErrorResponse::InternalServerError)?;
utils::Encode::<Vec<u8>>::encode_to_value(&enc_card_info)
.change_context(errors::CardVaultError::RequestEncodingFailed)
.change_context(errors::ApiErrorResponse::InternalServerError)
}
pub async fn get_card_info_from_value(
keys: &settings::Keys,
card_info: serde_json::Value,
) -> errors::RouterResult<String> {
let key = services::KeyHandler::get_encryption_key(keys)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
let card_info_val: Vec<u8> = card_info
.parse_value("CardInfo")
.change_context(errors::ApiErrorResponse::InternalServerError)?;
services::decrypt(card_info_val, key.as_bytes())
.change_context(errors::ApiErrorResponse::InternalServerError)
}
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn retrieve_payment_method( pub async fn retrieve_payment_method(
state: &routes::AppState, state: &routes::AppState,

View File

@ -942,36 +942,6 @@ impl Vault {
} }
} }
#[instrument(skip_all)]
pub async fn create_temp_card(
state: &AppState,
txn_id: &str,
card: &api::CCard,
) -> RouterResult<storage::TempCard> {
let (card_info, temp_card);
card_info = format!(
"{}:::{}:::{}:::{}:::{}",
card.card_number.peek(),
card.card_exp_month.peek(),
card.card_exp_year.peek(),
card.card_holder_name.peek(),
card.card_cvc.peek()
);
let card_info_val = cards::get_card_info_value(&state.conf.keys, card_info).await?;
temp_card = storage::TempCardNew {
card_info: Some(card_info_val),
date_created: common_utils::date_time::now(),
txn_id: Some(txn_id.to_string()),
id: None,
};
state
.store
.insert_temp_card(temp_card)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
}
#[instrument(skip_all)] #[instrument(skip_all)]
pub(crate) fn validate_capture_method( pub(crate) fn validate_capture_method(
capture_method: storage_enums::CaptureMethod, capture_method: storage_enums::CaptureMethod,

View File

@ -15,7 +15,6 @@ pub mod process_tracker;
pub mod queue; pub mod queue;
pub mod refund; pub mod refund;
pub mod reverse_lookup; pub mod reverse_lookup;
pub mod temp_card;
use std::sync::Arc; use std::sync::Arc;
@ -39,7 +38,6 @@ pub trait StorageInterface:
+ mandate::MandateInterface + mandate::MandateInterface
+ address::AddressInterface + address::AddressInterface
+ configs::ConfigInterface + configs::ConfigInterface
+ temp_card::TempCardInterface
+ customers::CustomerInterface + customers::CustomerInterface
+ events::EventInterface + events::EventInterface
+ merchant_account::MerchantAccountInterface + merchant_account::MerchantAccountInterface
@ -76,7 +74,6 @@ pub struct MockDb {
payment_attempts: Arc<Mutex<Vec<storage::PaymentAttempt>>>, payment_attempts: Arc<Mutex<Vec<storage::PaymentAttempt>>>,
payment_intents: Arc<Mutex<Vec<storage::PaymentIntent>>>, payment_intents: Arc<Mutex<Vec<storage::PaymentIntent>>>,
customers: Arc<Mutex<Vec<storage::Customer>>>, customers: Arc<Mutex<Vec<storage::Customer>>>,
temp_cards: Arc<Mutex<Vec<storage::TempCard>>>,
refunds: Arc<Mutex<Vec<storage::Refund>>>, refunds: Arc<Mutex<Vec<storage::Refund>>>,
processes: Arc<Mutex<Vec<storage::ProcessTracker>>>, processes: Arc<Mutex<Vec<storage::ProcessTracker>>>,
connector_response: Arc<Mutex<Vec<storage::ConnectorResponse>>>, connector_response: Arc<Mutex<Vec<storage::ConnectorResponse>>>,
@ -91,7 +88,6 @@ impl MockDb {
payment_attempts: Default::default(), payment_attempts: Default::default(),
payment_intents: Default::default(), payment_intents: Default::default(),
customers: Default::default(), customers: Default::default(),
temp_cards: Default::default(),
refunds: Default::default(), refunds: Default::default(),
processes: Default::default(), processes: Default::default(),
connector_response: Default::default(), connector_response: Default::default(),

View File

@ -1,123 +0,0 @@
use error_stack::IntoReport;
use super::{MockDb, Store};
use crate::{
connection::pg_connection,
core::errors::{self, CustomResult},
types::storage,
};
#[async_trait::async_trait]
pub trait TempCardInterface {
async fn find_tempcard_by_token(
&self,
token: &i32,
) -> CustomResult<storage::TempCard, errors::StorageError>;
async fn insert_temp_card(
&self,
address: storage::TempCardNew,
) -> CustomResult<storage::TempCard, errors::StorageError>;
async fn find_tempcard_by_transaction_id(
&self,
transaction_id: &str,
) -> CustomResult<Option<storage::TempCard>, errors::StorageError>;
async fn insert_tempcard_with_token(
&self,
new: storage::TempCard,
) -> CustomResult<storage::TempCard, errors::StorageError>;
}
#[async_trait::async_trait]
impl TempCardInterface for Store {
async fn insert_temp_card(
&self,
address: storage::TempCardNew,
) -> CustomResult<storage::TempCard, errors::StorageError> {
let conn = pg_connection(&self.master_pool).await;
address
.insert(&conn)
.await
.map_err(Into::into)
.into_report()
}
async fn find_tempcard_by_transaction_id(
&self,
transaction_id: &str,
) -> CustomResult<Option<storage::TempCard>, errors::StorageError> {
let conn = pg_connection(&self.master_pool).await;
storage::TempCard::find_by_transaction_id(&conn, transaction_id)
.await
.map_err(Into::into)
.into_report()
}
async fn insert_tempcard_with_token(
&self,
card: storage::TempCard,
) -> CustomResult<storage::TempCard, errors::StorageError> {
let conn = pg_connection(&self.master_pool).await;
storage::TempCard::insert_with_token(card, &conn)
.await
.map_err(Into::into)
.into_report()
}
async fn find_tempcard_by_token(
&self,
token: &i32,
) -> CustomResult<storage::TempCard, errors::StorageError> {
let conn = pg_connection(&self.master_pool).await;
storage::TempCard::find_by_token(&conn, token)
.await
.map_err(Into::into)
.into_report()
}
}
#[async_trait::async_trait]
impl TempCardInterface for MockDb {
#[allow(clippy::panic)]
async fn insert_temp_card(
&self,
insert: storage::TempCardNew,
) -> CustomResult<storage::TempCard, errors::StorageError> {
let mut cards = self.temp_cards.lock().await;
let card = storage::TempCard {
#[allow(clippy::as_conversions)]
id: cards.len() as i32,
date_created: insert.date_created,
txn_id: insert.txn_id,
card_info: insert.card_info,
};
cards.push(card.clone());
Ok(card)
}
async fn find_tempcard_by_transaction_id(
&self,
_transaction_id: &str,
) -> CustomResult<Option<storage::TempCard>, errors::StorageError> {
// [#172]: Implement function for `MockDb`
Err(errors::StorageError::MockDbError)?
}
async fn insert_tempcard_with_token(
&self,
_card: storage::TempCard,
) -> CustomResult<storage::TempCard, errors::StorageError> {
// [#172]: Implement function for `MockDb`
Err(errors::StorageError::MockDbError)?
}
async fn find_tempcard_by_token(
&self,
_token: &i32,
) -> CustomResult<storage::TempCard, errors::StorageError> {
// [#172]: Implement function for `MockDb`
Err(errors::StorageError::MockDbError)?
}
}

View File

@ -55,7 +55,7 @@ impl AuthenticateAndFetch<()> for AdminApiAuth {
) -> RouterResult<()> { ) -> RouterResult<()> {
let admin_api_key = let admin_api_key =
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?; get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
if admin_api_key != state.conf.keys.admin_api_key { if admin_api_key != state.conf.secrets.admin_api_key {
Err(report!(errors::ApiErrorResponse::Unauthorized) Err(report!(errors::ApiErrorResponse::Unauthorized)
.attach_printable("Admin Authentication Failure"))?; .attach_printable("Admin Authentication Failure"))?;
} }
@ -231,7 +231,7 @@ pub fn decode_jwt<T>(token: &str, state: &AppState) -> RouterResult<T>
where where
T: serde::de::DeserializeOwned, T: serde::de::DeserializeOwned,
{ {
let secret = state.conf.keys.jwt_secret.as_bytes(); let secret = state.conf.secrets.jwt_secret.as_bytes();
let key = DecodingKey::from_secret(secret); let key = DecodingKey::from_secret(secret);
decode::<T>(token, &key, &Validation::new(Algorithm::HS256)) decode::<T>(token, &key, &Validation::new(Algorithm::HS256))
.map(|decoded| decoded.claims) .map(|decoded| decoded.claims)

View File

@ -6,7 +6,7 @@ use rand;
use ring::{aead::*, error::Unspecified}; use ring::{aead::*, error::Unspecified};
use crate::{ use crate::{
configs::settings::{Jwekey, Keys}, configs::settings::Jwekey,
core::errors::{self, CustomResult}, core::errors::{self, CustomResult},
utils, utils,
}; };
@ -102,86 +102,11 @@ mod kms {
.attach_printable("Missing plaintext in response")), .attach_printable("Missing plaintext in response")),
} }
} }
pub async fn get_encryption_key(
keys: &Keys,
) -> CustomResult<String, errors::EncryptionError> {
let kms_enc_key = keys.temp_card_key.to_string();
let region = keys.aws_region.to_string();
let key_id = keys.aws_key_id.clone();
let region_provider = RegionProviderChain::first_try(Region::new(region));
let shared_config = aws_config::from_env().region(region_provider).load().await;
let client = Client::new(&shared_config);
let data = consts::BASE64_ENGINE
.decode(kms_enc_key)
.into_report()
.change_context(errors::EncryptionError)
.attach_printable("Error decoding from base64")?;
let blob = Blob::new(data);
let resp = client
.decrypt()
.key_id(key_id)
.ciphertext_blob(blob)
.send()
.await
.into_report()
.change_context(errors::EncryptionError)
.attach_printable("Error decrypting kms encrypted data")?;
match resp.plaintext() {
Some(inner) => {
let bytes = inner.as_ref().to_vec();
let res = String::from_utf8(bytes)
.into_report()
.change_context(errors::EncryptionError)
.attach_printable("Could not convert to UTF-8")?;
Ok(res)
}
None => Err(report!(errors::EncryptionError)
.attach_printable("Missing plaintext in response")),
}
}
pub async fn set_encryption_key(
input: &str,
keys: &Keys,
) -> CustomResult<String, errors::EncryptionError> {
let region = keys.aws_region.to_string();
let key_id = keys.aws_key_id.clone();
let region_provider = RegionProviderChain::first_try(Region::new(region));
let shared_config = aws_config::from_env().region(region_provider).load().await;
let client = Client::new(&shared_config);
let blob = Blob::new(input.as_bytes());
let resp = client
.encrypt()
.key_id(key_id)
.plaintext(blob)
.send()
.await
.into_report()
.change_context(errors::EncryptionError)
.attach_printable("Error getting EncryptOutput")?;
match resp.ciphertext_blob {
Some(blob) => {
let bytes = blob.as_ref();
let encoded_res = consts::BASE64_ENGINE.encode(bytes);
Ok(encoded_res)
}
None => {
Err(report!(errors::EncryptionError)
.attach_printable("Missing ciphertext blob"))
}
}
}
} }
} }
#[cfg(not(feature = "kms"))] #[cfg(not(feature = "kms"))]
impl KeyHandler { impl KeyHandler {
// Fetching KMS decrypted key
pub async fn get_encryption_key(keys: &Keys) -> CustomResult<String, errors::EncryptionError> {
Ok(keys.temp_card_key.clone())
}
pub async fn get_kms_decrypted_key( pub async fn get_kms_decrypted_key(
_aws_keys: &Jwekey, _aws_keys: &Jwekey,
key: String, key: String,
@ -337,20 +262,6 @@ mod tests {
assert_eq!(dec_data, "Test_Encrypt".to_string()); assert_eq!(dec_data, "Test_Encrypt".to_string());
} }
#[cfg(feature = "kms")]
#[actix_rt::test]
#[ignore]
async fn test_kms() {
let conf = settings::Settings::new().unwrap();
let kms_encrypted = KeyHandler::get_encryption_key(&conf.keys)
.await
.expect("Error encode_kms");
let kms_decrypted = KeyHandler::set_encryption_key(&kms_encrypted, &conf.keys)
.await
.expect("error decode_kms");
assert_eq!("Testing KMS".to_string(), kms_decrypted)
}
#[actix_rt::test] #[actix_rt::test]
async fn test_jwe() { async fn test_jwe() {
let conf = settings::Settings::new().unwrap(); let conf = settings::Settings::new().unwrap();

View File

@ -17,7 +17,6 @@ pub mod reverse_lookup;
mod query; mod query;
pub mod refund; pub mod refund;
pub mod temp_card;
#[cfg(feature = "kv_store")] #[cfg(feature = "kv_store")]
pub mod kv; pub mod kv;
@ -26,5 +25,4 @@ pub use self::{
address::*, configs::*, connector_response::*, customers::*, events::*, locker_mock_up::*, address::*, configs::*, connector_response::*, customers::*, events::*, locker_mock_up::*,
mandate::*, merchant_account::*, merchant_connector_account::*, payment_attempt::*, mandate::*, merchant_account::*, merchant_connector_account::*, payment_attempt::*,
payment_intent::*, payment_method::*, process_tracker::*, refund::*, reverse_lookup::*, payment_intent::*, payment_method::*, process_tracker::*, refund::*, reverse_lookup::*,
temp_card::*,
}; };

View File

@ -1 +0,0 @@
pub use storage_models::temp_card::{TempCard, TempCardNew};

View File

@ -21,7 +21,6 @@ pub mod query;
pub mod refund; pub mod refund;
pub mod reverse_lookup; pub mod reverse_lookup;
pub mod schema; pub mod schema;
pub mod temp_card;
use diesel_impl::{DieselArray, OptionalDieselArray}; use diesel_impl::{DieselArray, OptionalDieselArray};

View File

@ -14,4 +14,3 @@ pub mod payment_method;
pub mod process_tracker; pub mod process_tracker;
pub mod refund; pub mod refund;
pub mod reverse_lookup; pub mod reverse_lookup;
pub mod temp_card;

View File

@ -1,44 +0,0 @@
use diesel::{associations::HasTable, ExpressionMethods};
use router_env::{instrument, tracing};
use super::generics;
use crate::{
schema::temp_card::dsl,
temp_card::{TempCard, TempCardNew},
PgPooledConn, StorageResult,
};
impl TempCardNew {
#[instrument(skip(conn))]
pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<TempCard> {
generics::generic_insert(conn, self).await
}
}
impl TempCard {
#[instrument(skip(conn))]
pub async fn insert_with_token(self, conn: &PgPooledConn) -> StorageResult<Self> {
generics::generic_insert(conn, self).await
}
#[instrument(skip(conn))]
pub async fn find_by_transaction_id(
conn: &PgPooledConn,
transaction_id: &str,
) -> StorageResult<Option<Self>> {
generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
conn,
dsl::txn_id.eq(transaction_id.to_owned()),
)
.await
}
#[instrument(skip(conn))]
pub async fn find_by_token(conn: &PgPooledConn, token: &i32) -> StorageResult<Self> {
generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
conn,
dsl::id.eq(token.to_owned()),
)
.await
}
}

View File

@ -344,18 +344,6 @@ diesel::table! {
} }
} }
diesel::table! {
use diesel::sql_types::*;
use crate::enums::diesel_exports::*;
temp_card (id) {
id -> Int4,
date_created -> Timestamp,
txn_id -> Nullable<Varchar>,
card_info -> Nullable<Json>,
}
}
diesel::allow_tables_to_appear_in_same_query!( diesel::allow_tables_to_appear_in_same_query!(
address, address,
configs, configs,
@ -372,5 +360,4 @@ diesel::allow_tables_to_appear_in_same_query!(
process_tracker, process_tracker,
refund, refund,
reverse_lookup, reverse_lookup,
temp_card,
); );

View File

@ -1,23 +0,0 @@
use diesel::{Identifiable, Insertable, Queryable};
use serde_json::Value;
use time::PrimitiveDateTime;
use crate::schema::temp_card;
#[derive(Clone, Debug, router_derive::DebugAsDisplay, Queryable, Identifiable, Insertable)]
#[diesel(table_name = temp_card)]
pub struct TempCard {
pub id: i32,
pub date_created: PrimitiveDateTime,
pub txn_id: Option<String>,
pub card_info: Option<Value>,
}
#[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
#[diesel(table_name = temp_card)]
pub struct TempCardNew {
pub id: Option<i32>,
pub card_info: Option<Value>,
pub date_created: PrimitiveDateTime,
pub txn_id: Option<String>,
}

View File

@ -21,8 +21,7 @@ host = "0.0.0.0"
[redis] [redis]
host = "redis-queue" host = "redis-queue"
[keys] [secrets]
temp_card_key = "OJobAzAwOlibOhygIZOqOGideGUdEBeX" # 32 character long key
admin_api_key = "test_admin" admin_api_key = "test_admin"
jwt_secret = "secret" jwt_secret = "secret"

View File

@ -0,0 +1,8 @@
CREATE TABLE temp_card (
id SERIAL PRIMARY KEY,
date_created TIMESTAMP NOT NULL,
txn_id VARCHAR(255),
card_info JSON
);
CREATE INDEX temp_card_txn_id_index ON temp_card (txn_id);

View File

@ -0,0 +1 @@
DROP TABLE temp_card;