diff --git a/core/src/candidate_details.rs b/core/src/candidate_details.rs index 2bf1961..dc6350a 100644 --- a/core/src/candidate_details.rs +++ b/core/src/candidate_details.rs @@ -1,8 +1,8 @@ -use chrono::{NaiveDate}; +use chrono::NaiveDate; use entity::{candidate, parent}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; -use crate::{error::ServiceError, crypto}; +use crate::{crypto, error::ServiceError}; pub const NAIVE_DATE_FMT: &str = "%Y-%m-%d"; @@ -11,16 +11,16 @@ pub struct EncryptedString(String); impl EncryptedString { pub async fn new(s: &str, recipients: &Vec<&str>) -> Result { - match crypto::encrypt_password_with_recipients(&s, &recipients).await{ + match crypto::encrypt_password_with_recipients(&s, &recipients).await { Ok(encrypted) => Ok(Self(encrypted)), - Err(_) => Err(ServiceError::CryptoEncryptFailed), + Err(_) => Err(ServiceError::CryptoEncryptFailed), } } pub async fn decrypt(&self, private_key: &String) -> Result { match crypto::decrypt_password_with_private_key(&self.0, private_key).await { Ok(decrypted) => Ok(decrypted), - Err(_) => Err(ServiceError::CryptoDecryptFailed), + Err(_) => Err(ServiceError::CryptoDecryptFailed), } } @@ -46,7 +46,8 @@ impl TryFrom> for EncryptedString { } } -impl TryFrom> for EncryptedString { // TODO: take a look at this +impl TryFrom> for EncryptedString { + // TODO: take a look at this type Error = ServiceError; fn try_from(d: Option) -> Result { @@ -79,9 +80,12 @@ pub struct EncryptedApplicationDetails { } impl EncryptedApplicationDetails { - pub async fn new(form: ApplicationDetails, recipients: Vec<&str>) -> Result { + pub async fn new( + form: ApplicationDetails, + recipients: Vec<&str>, + ) -> Result { let birthdate_str = form.birthdate.format(NAIVE_DATE_FMT).to_string(); - let d = tokio::try_join!( + let d = tokio::try_join!( EncryptedString::new(&form.name, &recipients), EncryptedString::new(&form.surname, &recipients), EncryptedString::new(&form.birthplace, &recipients), @@ -92,7 +96,6 @@ impl EncryptedApplicationDetails { EncryptedString::new(&form.email, &recipients), EncryptedString::new(&form.sex, &recipients), EncryptedString::new(&form.study, &recipients), - EncryptedString::new(&form.parent_name, &recipients), EncryptedString::new(&form.parent_surname, &recipients), EncryptedString::new(&form.parent_telephone, &recipients), @@ -119,18 +122,17 @@ impl EncryptedApplicationDetails { } pub async fn decrypt(self, priv_key: String) -> Result { - let d = tokio::try_join!( - self.name.decrypt(&priv_key), // 0 - self.surname.decrypt(&priv_key), // 1 - self.birthplace.decrypt(&priv_key), // 2 - self.birthdate.decrypt(&priv_key), // 3 - self.address.decrypt(&priv_key), // 4 - self.telephone.decrypt(&priv_key), // 5 + let d = tokio::try_join!( + self.name.decrypt(&priv_key), // 0 + self.surname.decrypt(&priv_key), // 1 + self.birthplace.decrypt(&priv_key), // 2 + self.birthdate.decrypt(&priv_key), // 3 + self.address.decrypt(&priv_key), // 4 + self.telephone.decrypt(&priv_key), // 5 self.citizenship.decrypt(&priv_key), // 6 - self.email.decrypt(&priv_key), // 7 - self.sex.decrypt(&priv_key), // 8 - self.study.decrypt(&priv_key), // 9 - + self.email.decrypt(&priv_key), // 7 + self.sex.decrypt(&priv_key), // 8 + self.study.decrypt(&priv_key), // 9 self.parent_name.decrypt(&priv_key), self.parent_surname.decrypt(&priv_key), self.parent_telephone.decrypt(&priv_key), @@ -160,7 +162,9 @@ impl EncryptedApplicationDetails { impl TryFrom<(candidate::Model, parent::Model)> for EncryptedApplicationDetails { type Error = ServiceError; - fn try_from((candidate, parent): (candidate::Model, parent::Model)) -> Result { + fn try_from( + (candidate, parent): (candidate::Model, parent::Model), + ) -> Result { Ok(EncryptedApplicationDetails { name: EncryptedString::try_from(candidate.name)?, surname: EncryptedString::try_from(candidate.surname)?, @@ -194,10 +198,135 @@ pub struct ApplicationDetails { pub email: String, pub sex: String, pub study: String, - + // Parent pub parent_name: String, pub parent_surname: String, pub parent_telephone: String, pub parent_email: String, -} \ No newline at end of file +} + +#[cfg(test)] +mod tests { + use crate::crypto; + + use super::{ApplicationDetails, EncryptedApplicationDetails, EncryptedString}; + + #[tokio::test] + async fn test_encrypted_application_details_new() { + const PUBLIC_KEY: &str = "age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5"; + const PRIVATE_KEY: &str = + "AGE-SECRET-KEY-14QG24502DMUUQDT2SPMX2YXPSES0X8UD6NT0PCTDAT6RH8V5Q3GQGSRXPS"; + let encrypted_details = EncryptedApplicationDetails::new( + ApplicationDetails { + name: "test".to_string(), + surname: "test".to_string(), + birthplace: "test".to_string(), + birthdate: chrono::offset::Local::now().date_naive(), + address: "test".to_string(), + telephone: "test".to_string(), + citizenship: "test".to_string(), + email: "test".to_string(), + parent_email: "test".to_string(), + parent_name: "test".to_string(), + parent_surname: "test".to_string(), + parent_telephone: "test".to_string(), + sex: "test".to_string(), + study: "test".to_string(), + }, + vec![PUBLIC_KEY], + ) + .await + .unwrap(); + + assert_eq!( + crypto::decrypt_password_with_private_key(&encrypted_details.name.0, PRIVATE_KEY) + .await + .unwrap(), + "test" + ); + assert_eq!( + crypto::decrypt_password_with_private_key(&encrypted_details.email.0, PRIVATE_KEY) + .await + .unwrap(), + "test" + ); + assert_eq!( + crypto::decrypt_password_with_private_key(&encrypted_details.sex.0, PRIVATE_KEY) + .await + .unwrap(), + "test" + ); + } + + #[tokio::test] + async fn test_encrypted_application_details_decrypt() { + const PUBLIC_KEY: &str = "age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5"; + const PRIVATE_KEY: &str = + "AGE-SECRET-KEY-14QG24502DMUUQDT2SPMX2YXPSES0X8UD6NT0PCTDAT6RH8V5Q3GQGSRXPS"; + let encrypted_details = EncryptedApplicationDetails::new( + ApplicationDetails { + name: "test".to_string(), + surname: "test".to_string(), + birthplace: "test".to_string(), + birthdate: chrono::offset::Local::now().date_naive(), + address: "test".to_string(), + telephone: "test".to_string(), + citizenship: "test".to_string(), + email: "test".to_string(), + parent_email: "test".to_string(), + parent_name: "test".to_string(), + parent_surname: "test".to_string(), + parent_telephone: "test".to_string(), + sex: "test".to_string(), + study: "test".to_string(), + }, + vec![PUBLIC_KEY], + ) + .await + .unwrap(); + + let application_details = encrypted_details + .decrypt(PRIVATE_KEY.to_string()) + .await + .unwrap(); + + assert_eq!(application_details.name, "test"); + assert_eq!(application_details.email, "test"); + assert_eq!(application_details.sex, "test"); + } + + #[tokio::test] + async fn test_encrypted_string_new() { + const PUBLIC_KEY: &str = "age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5"; + const PRIVATE_KEY: &str = + "AGE-SECRET-KEY-14QG24502DMUUQDT2SPMX2YXPSES0X8UD6NT0PCTDAT6RH8V5Q3GQGSRXPS"; + + let encrypted = EncryptedString::new("test", &vec![PUBLIC_KEY]) + .await + .unwrap(); + + assert_eq!( + crypto::decrypt_password_with_private_key(&encrypted.0, PRIVATE_KEY) + .await + .unwrap(), + "test" + ); + } + + #[tokio::test] + async fn test_encrypted_string_decrypt() { + const PUBLIC_KEY: &str = "age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5"; + const PRIVATE_KEY: &str = + "AGE-SECRET-KEY-14QG24502DMUUQDT2SPMX2YXPSES0X8UD6NT0PCTDAT6RH8V5Q3GQGSRXPS"; + + let encrypted = EncryptedString::new("test", &vec![PUBLIC_KEY]) + .await + .unwrap(); + + assert_eq!( + encrypted.decrypt(&PRIVATE_KEY.to_string()).await.unwrap(), + "test" + ); + } +}