use async_trait::async_trait;
use credit_card::CreditCard;
use deadpool_redis::redis::{AsyncCommands};
use crate::traits::{DataVault, PoolErrors};
use crate::config::DeadpoolRedisConfig;
use crate::encryption::traits::Encryption;
use crate::tokenizer::{Tokenizer};
use std::error;
pub struct RedisDataVault<E, T> {
pool: deadpool_redis::Pool,
encryption: E,
tokenizer: T,
}
#[async_trait]
impl<E, T> DataVault for RedisDataVault<E, T>
where
E: Encryption + std::marker::Sync + std::marker::Send,
T: Tokenizer + std::marker::Sync + std::marker::Send,
{
fn new() -> Result<Self, Box<dyn error::Error>> {
let cfg = DeadpoolRedisConfig::from_env()?;
let pool = cfg.redis.create_pool()?;
let redis_data_vault = RedisDataVault {
pool,
encryption: E::new(),
tokenizer: T::new()
};
Ok(redis_data_vault)
}
async fn store(&self, token: &String, string: &String) -> Result<(), PoolErrors> {
let mut conn = self.pool.get().await?;
let encrypted_json = self.encryption.encrypt(string.as_bytes());
let _:() = conn.set(token, encrypted_json).await.unwrap();
Ok(())
}
async fn store_credit_card(&self, credit_card: &CreditCard) -> Result<String, PoolErrors> {
let token = self.tokenizer.generate(&credit_card);
let credit_card_json = serde_json::to_string(&credit_card).unwrap();
let _:() = self.store(&token, &credit_card_json).await?;
Ok(token)
}
async fn retrieve(&self, token: &String) -> Result<String, PoolErrors> {
let mut conn = self.pool.get().await?;
let encrypted_credit_card_json: Vec<u8> = conn.get(token).await.unwrap();
Ok(self.encryption.decrypt(encrypted_credit_card_json.as_slice()))
}
async fn retrieve_credit_card(&self, token: &String) -> Result<CreditCard, PoolErrors> {
let credit_card_json = self.retrieve(token).await?;
Ok(serde_json::from_str(&credit_card_json).unwrap_or_default())
}
}