From 6bd510fb38dbbdd6a2914f26f9d7df4662e29e30 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 8 Jan 2023 12:58:23 +0100 Subject: [PATCH 1/4] fix: password reset & candidate_details refactoring --- api/src/routes/candidate.rs | 1 - core/src/database/mutation/candidate.rs | 25 +-- core/src/database/mutation/parent.rs | 8 +- core/src/models/candidate.rs | 26 +-- core/src/models/candidate_details.rs | 250 +++++++++++------------ core/src/services/application_service.rs | 5 +- core/src/services/candidate_service.rs | 24 ++- 7 files changed, 173 insertions(+), 166 deletions(-) diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index 1328a91..1ebe881 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -108,7 +108,6 @@ pub async fn get_details( let private_key = session.get_private_key(); let candidate: entity::candidate::Model = session.into(); - // let handle = tokio::spawn(async move { let details = ApplicationService::decrypt_all_details(private_key, db, candidate) .await .map(|x| Json(x)) diff --git a/core/src/database/mutation/candidate.rs b/core/src/database/mutation/candidate.rs index 526a1de..e0b37d9 100644 --- a/core/src/database/mutation/candidate.rs +++ b/core/src/database/mutation/candidate.rs @@ -48,6 +48,7 @@ impl Mutation { pub_key: String, priv_key_enc: String, ) -> Result { + let application = candidate.application; let mut candidate: candidate::ActiveModel = candidate.into(); candidate.code = Set(new_password_hash); candidate.public_key = Set(pub_key); @@ -55,7 +56,7 @@ impl Mutation { let update = candidate.update(db).await?; - warn!("CANDIDATE PASSWORD CHANGED"); + warn!("CANDIDATE {} PASSWORD CHANGED", application); Ok(update) } @@ -65,17 +66,17 @@ impl Mutation { enc_candidate: EncryptedCandidateDetails, ) -> Result { let mut user: candidate::ActiveModel = user.into(); - user.name = Set(Some(enc_candidate.name.into())); - user.surname = Set(Some(enc_candidate.surname.into())); - user.birthplace = Set(Some(enc_candidate.birthplace.into())); - user.birthdate = Set(Some(enc_candidate.birthdate.into())); - user.address = Set(Some(enc_candidate.address.into())); - user.telephone = Set(Some(enc_candidate.telephone.into())); - user.citizenship = Set(Some(enc_candidate.citizenship.into())); - user.email = Set(Some(enc_candidate.email.into())); - user.sex = Set(Some(enc_candidate.sex.into())); - user.personal_identification_number = Set(enc_candidate.personal_id_number.into()); // TODO: do not set this here, it is already set in the create_candidate mutation??? - user.study = Set(Some(enc_candidate.study.into())); + user.name = Set(enc_candidate.name.map(|e| e.into())); + user.surname = Set(enc_candidate.surname.map(|e| e.into())); + user.birthplace = Set(enc_candidate.birthplace.map(|e| e.into())); + user.birthdate = Set(enc_candidate.birthdate.map(|e| e.into())); + user.address = Set(enc_candidate.address.map(|e| e.into())); + user.telephone = Set(enc_candidate.telephone.map(|e| e.into())); + user.citizenship = Set(enc_candidate.citizenship.map(|e| e.into())); + user.email = Set(enc_candidate.email.map(|e| e.into())); + user.sex = Set(enc_candidate.sex.map(|e| e.into())); + user.personal_identification_number = Set(enc_candidate.personal_id_number.map(|e| e.into()).unwrap_or_default()); // TODO: do not set this here, it is already set in the create_candidate mutation??? + user.study = Set(enc_candidate.study.map(|e| e.into())); user.updated_at = Set(chrono::offset::Local::now().naive_local()); diff --git a/core/src/database/mutation/parent.rs b/core/src/database/mutation/parent.rs index 41bdc80..51b1fae 100644 --- a/core/src/database/mutation/parent.rs +++ b/core/src/database/mutation/parent.rs @@ -21,10 +21,10 @@ impl Mutation { enc_parent: EncryptedParentDetails, ) -> Result { let mut parent: parent::ActiveModel = parent.into(); - parent.name = Set(Some(enc_parent.name.into())); - parent.surname = Set(Some(enc_parent.surname.into())); - parent.telephone = Set(Some(enc_parent.telephone.into())); - parent.email = Set(Some(enc_parent.email.into())); + parent.name = Set(enc_parent.name.map(|e| e.into())); + parent.surname = Set(enc_parent.surname.map(|e| e.into())); + parent.telephone = Set(enc_parent.telephone.map(|e| e.into())); + parent.email = Set(enc_parent.email.map(|e| e.into())); parent.updated_at = Set(chrono::offset::Local::now().naive_local()); diff --git a/core/src/models/candidate.rs b/core/src/models/candidate.rs index 60d1022..ba1c049 100644 --- a/core/src/models/candidate.rs +++ b/core/src/models/candidate.rs @@ -5,7 +5,7 @@ use serde::{Serialize, Deserialize}; use crate::{error::ServiceError, database::query::candidate::CandidateResult, services::portfolio_service::SubmissionProgress}; -use super::candidate_details::decrypt_if_exists; +use super::candidate_details::EncryptedString; /// Minimal candidate response containing database only not null fields #[derive(Debug, Serialize, Deserialize)] @@ -101,7 +101,7 @@ pub struct Row { impl NewCandidateResponse { pub async fn from_encrypted(private_key: &String, c: candidate::Model) -> Result { - let id_number = decrypt_if_exists(private_key, Some(c.personal_identification_number)).await?; + let id_number = EncryptedString::from(c.personal_identification_number).decrypt(private_key).await?; Ok( Self { application_id: c.application, @@ -117,20 +117,20 @@ impl BaseCandidateResponse { c: CandidateResult, progress: Option, ) -> Result { - let name = decrypt_if_exists(private_key, c.name).await?; - let surname = decrypt_if_exists(private_key, c.surname).await?; - let email = decrypt_if_exists(private_key, c.email).await?; - let telephone = decrypt_if_exists(private_key, c.telephone).await?; - let progress = progress.unwrap_or(SubmissionProgress::NoneInCache); + let name = EncryptedString::decrypt_option(&EncryptedString::try_from(&c.name).ok(), private_key).await?; + let surname = EncryptedString::decrypt_option(&EncryptedString::try_from(&c.surname).ok(), private_key).await?; + let email = EncryptedString::decrypt_option(&EncryptedString::try_from(&c.email).ok(), private_key).await?; + let telephone = EncryptedString::decrypt_option(&EncryptedString::try_from(&c.telephone).ok(), private_key).await?; + Ok( Self { application_id: c.application, - name, - surname, - email, - telephone, - study: c.study.unwrap_or("".to_string()), - progress, + name: name.unwrap_or_default(), + surname: surname.unwrap_or_default(), + email: email.unwrap_or_default(), + telephone: telephone.unwrap_or_default(), + study: c.study.unwrap_or_default(), + progress: progress.unwrap_or(SubmissionProgress::NoneInCache), } ) } diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index a012599..3f41344 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -14,25 +14,25 @@ pub struct EncryptedString(String); #[derive(Debug, Clone)] pub struct EncryptedCandidateDetails { - pub name: EncryptedString, - pub surname: EncryptedString, - pub birthplace: EncryptedString, - pub birthdate: EncryptedString, - pub address: EncryptedString, - pub telephone: EncryptedString, - pub citizenship: EncryptedString, - pub email: EncryptedString, - pub sex: EncryptedString, - pub personal_id_number: EncryptedString, - pub study: String, + pub name: Option, + pub surname: Option, + pub birthplace: Option, + pub birthdate: Option, + pub address: Option, + pub telephone: Option, + pub citizenship: Option, + pub email: Option, + pub sex: Option, + pub personal_id_number: Option, + pub study: Option, } #[derive(Debug, Clone)] pub struct EncryptedParentDetails { - pub name: EncryptedString, - pub surname: EncryptedString, - pub telephone: EncryptedString, - pub email: EncryptedString, + pub name: Option, + pub surname: Option, + pub telephone: Option, + pub email: Option, } #[derive(Debug, Clone)] pub struct EncryptedApplicationDetails { @@ -50,9 +50,16 @@ impl EncryptedString { } 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), + crypto::decrypt_password_with_private_key(&self.0, private_key).await + } + + pub async fn decrypt_option( + s: &Option, + private_key: &String, + ) -> Result, ServiceError> { + match s { + Some(s) => Ok(Some(s.decrypt(private_key).await?)), + None => Ok(None), } } @@ -77,6 +84,7 @@ impl TryFrom<&Option> for EncryptedString { } } } + impl From for EncryptedString { fn from(s: String) -> Self { Self(s) @@ -115,72 +123,68 @@ impl EncryptedCandidateDetails { Ok( EncryptedCandidateDetails { - name: d.0, - surname: d.1, - birthplace: d.2, - birthdate: d.3, - address: d.4, - telephone: d.5, - citizenship: d.6, - email: d.7, - sex: d.8, - personal_id_number: d.9, - study: form.study.clone(), + name: Some(d.0), + surname: Some(d.1), + birthplace: Some(d.2), + birthdate: Some(d.3), + address: Some(d.4), + telephone: Some(d.5), + citizenship: Some(d.6), + email: Some(d.7), + sex: Some(d.8), + personal_id_number: Some(d.9), + study: Some(form.study.clone()), } ) } - pub async fn decrypt(self, priv_key: &String) -> Result { + 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 - self.citizenship.decrypt(priv_key), // 6 - self.email.decrypt(priv_key), // 7 - self.sex.decrypt(priv_key), // 8 - self.personal_id_number.decrypt(priv_key),// 9 + EncryptedString::decrypt_option(&self.name, priv_key), // 0 + EncryptedString::decrypt_option(&self.surname, priv_key), // 1 + EncryptedString::decrypt_option(&self.birthplace, priv_key), // 2 + EncryptedString::decrypt_option(&self.birthdate, priv_key), // 3 + EncryptedString::decrypt_option(&self.address, priv_key), // 4 + EncryptedString::decrypt_option(&self.telephone, priv_key), // 5 + EncryptedString::decrypt_option(&self.citizenship, priv_key), // 6 + EncryptedString::decrypt_option(&self.email, priv_key), // 7 + EncryptedString::decrypt_option(&self.sex, priv_key), // 8 + EncryptedString::decrypt_option(&self.personal_id_number, priv_key),// 9 )?; Ok(CandidateDetails { - name: d.0, - surname: d.1, - birthplace: d.2, - birthdate: NaiveDate::parse_from_str(&d.3, NAIVE_DATE_FMT).unwrap(), - address: d.4, - telephone: d.5, - citizenship: d.6, - email: d.7, - sex: d.8, - personal_id_number: d.9, - study: self.study, + name: d.0.unwrap_or_default(), + surname: d.1.unwrap_or_default(), + birthplace: d.2.unwrap_or_default(), + birthdate: NaiveDate::parse_from_str(&d.3.unwrap_or_default(), NAIVE_DATE_FMT).unwrap_or(NaiveDate::from_ymd(1, 1, 1)), + address: d.4.unwrap_or_default(), + telephone: d.5.unwrap_or_default(), + citizenship: d.6.unwrap_or_default(), + email: d.7.unwrap_or_default(), + sex: d.8.unwrap_or_default(), + personal_id_number: d.9.unwrap_or_default(), + study: self.study.clone().unwrap_or_default(), } ) } } -impl TryFrom<&candidate::Model> for EncryptedCandidateDetails { - type Error = ServiceError; - - fn try_from( +impl From<&candidate::Model> for EncryptedCandidateDetails { + fn from( candidate: &candidate::Model, - ) -> Result { - Ok( - EncryptedCandidateDetails { - name: EncryptedString::try_from(&candidate.name)?, - surname: EncryptedString::try_from(&candidate.surname)?, - birthplace: EncryptedString::try_from(&candidate.birthplace)?, - birthdate: EncryptedString::try_from(&candidate.birthdate)?, - address: EncryptedString::try_from(&candidate.address)?, - telephone: EncryptedString::try_from(&candidate.telephone)?, - citizenship: EncryptedString::try_from(&candidate.citizenship)?, - email: EncryptedString::try_from(&candidate.email)?, - sex: EncryptedString::try_from(&candidate.sex)?, - personal_id_number: EncryptedString::from(candidate.personal_identification_number.to_owned()), - study: candidate.study.as_ref().ok_or(ServiceError::CandidateDetailsNotSet)?.to_string(), - } - ) + ) -> Self { + EncryptedCandidateDetails { + name: EncryptedString::try_from(&candidate.name).ok(), + surname: EncryptedString::try_from(&candidate.surname).ok(), + birthplace: EncryptedString::try_from(&candidate.birthplace).ok(), + birthdate: EncryptedString::try_from(&candidate.birthdate).ok(), + address: EncryptedString::try_from(&candidate.address).ok(), + telephone: EncryptedString::try_from(&candidate.telephone).ok(), + citizenship: EncryptedString::try_from(&candidate.citizenship).ok(), + email: EncryptedString::try_from(&candidate.email).ok(), + sex: EncryptedString::try_from(&candidate.sex).ok(), + personal_id_number: Some(EncryptedString::from(candidate.personal_identification_number.to_owned())), + study: candidate.study.clone(), + } } } @@ -198,44 +202,42 @@ impl EncryptedParentDetails { Ok( EncryptedParentDetails { - name: d.0, - surname: d.1, - telephone: d.2, - email: d.3, + name: Some(d.0), + surname: Some(d.1), + telephone: Some(d.2), + email: Some(d.3), } ) } pub async fn decrypt(&self, priv_key: &String) -> Result { let d = tokio::try_join!( - self.name.decrypt(&priv_key), - self.surname.decrypt(&priv_key), - self.telephone.decrypt(&priv_key), - self.email.decrypt(&priv_key), + EncryptedString::decrypt_option(&self.name, &priv_key), + EncryptedString::decrypt_option(&self.surname, &priv_key), + EncryptedString::decrypt_option(&self.telephone, &priv_key), + EncryptedString::decrypt_option(&self.email, &priv_key), )?; Ok(ParentDetails { - name: d.0, - surname: d.1, - telephone: d.2, - email: d.3, + name: d.0.unwrap_or_default(), + surname: d.1.unwrap_or_default(), + telephone: d.2.unwrap_or_default(), + email: d.3.unwrap_or_default(), } ) } } -impl TryFrom<&parent::Model> for EncryptedParentDetails { - type Error = ServiceError; - - fn try_from( +impl From<&parent::Model> for EncryptedParentDetails { + fn from( parent: &parent::Model, - ) -> Result { - Ok(EncryptedParentDetails { - name: EncryptedString::try_from(&parent.name)?, - surname: EncryptedString::try_from(&parent.surname)?, - telephone: EncryptedString::try_from(&parent.telephone)?, - email: EncryptedString::try_from(&parent.email)?, - } - ) + ) -> Self { + EncryptedParentDetails { + name: EncryptedString::try_from(&parent.name).ok(), + surname: EncryptedString::try_from(&parent.surname).ok(), + telephone: EncryptedString::try_from(&parent.telephone).ok(), + email: EncryptedString::try_from(&parent.email).ok(), + } + } } @@ -273,20 +275,18 @@ impl EncryptedApplicationDetails { } } -impl TryFrom<(&candidate::Model, Vec)> for EncryptedApplicationDetails { - type Error = ServiceError; - - fn try_from( +impl From<(&candidate::Model, Vec)> for EncryptedApplicationDetails { + fn from( (candidate, parents): (&candidate::Model, Vec), - ) -> Result { + ) -> Self { let enc_parents = parents.iter() - .map(|m| EncryptedParentDetails::try_from(m)) - .collect::, ServiceError>>()?; + .map(|m| EncryptedParentDetails::from(m)) + .collect::>(); - Ok(EncryptedApplicationDetails { - candidate: EncryptedCandidateDetails::try_from(candidate)?, + EncryptedApplicationDetails { + candidate: EncryptedCandidateDetails::from(candidate), parents: enc_parents, - }) + } } } @@ -298,30 +298,30 @@ impl TryFrom for EncryptedApplicationDetails { ) -> Result { Ok(EncryptedApplicationDetails { candidate: EncryptedCandidateDetails { - name: EncryptedString::try_from(&cp.name)?, - surname: EncryptedString::try_from(&cp.surname)?, - birthplace: EncryptedString::try_from(&cp.birthplace)?, - birthdate: EncryptedString::try_from(&cp.birthdate)?, - address: EncryptedString::try_from(&cp.address)?, - telephone: EncryptedString::try_from(&cp.telephone)?, - citizenship: EncryptedString::try_from(&cp.citizenship)?, - email: EncryptedString::try_from(&cp.email)?, - sex: EncryptedString::try_from(&cp.sex)?, - personal_id_number: EncryptedString::try_from(&cp.personal_identification_number)?, - study: cp.study.ok_or(ServiceError::CandidateDetailsNotSet)?, + name: EncryptedString::try_from(&cp.name).ok(), + surname: EncryptedString::try_from(&cp.surname).ok(), + birthplace: EncryptedString::try_from(&cp.birthplace).ok(), + birthdate: EncryptedString::try_from(&cp.birthdate).ok(), + address: EncryptedString::try_from(&cp.address).ok(), + telephone: EncryptedString::try_from(&cp.telephone).ok(), + citizenship: EncryptedString::try_from(&cp.citizenship).ok(), + email: EncryptedString::try_from(&cp.email).ok(), + sex: EncryptedString::try_from(&cp.sex).ok(), + personal_id_number: EncryptedString::try_from(&cp.personal_identification_number).ok(), + study: cp.study.ok_or(ServiceError::CandidateDetailsNotSet).ok(), }, parents: vec![EncryptedParentDetails { - name: EncryptedString::try_from(&cp.parent_name)?, - surname: EncryptedString::try_from(&cp.parent_surname)?, - telephone: EncryptedString::try_from(&cp.parent_telephone)?, - email: EncryptedString::try_from(&cp.parent_email)?, + name: EncryptedString::try_from(&cp.parent_name).ok(), + surname: EncryptedString::try_from(&cp.parent_surname).ok(), + telephone: EncryptedString::try_from(&cp.parent_telephone).ok(), + email: EncryptedString::try_from(&cp.parent_email).ok(), }] }) } } -pub async fn decrypt_if_exists( +/* pub async fn decrypt_if_exists( private_key: &String, encrypted_string: Option, ) -> Result { @@ -329,7 +329,7 @@ pub async fn decrypt_if_exists( Ok(encrypted_string) => Ok(encrypted_string.decrypt(private_key).await?), Err(_) => Ok(String::from("")), } -} +} */ #[cfg(test)] pub mod tests { @@ -419,19 +419,19 @@ pub mod tests { .unwrap(); assert_eq!( - crypto::decrypt_password_with_private_key(&encrypted_details.candidate.name.0, PRIVATE_KEY) + crypto::decrypt_password_with_private_key(&encrypted_details.candidate.name.unwrap().0, PRIVATE_KEY) .await .unwrap(), "name" ); assert_eq!( - crypto::decrypt_password_with_private_key(&encrypted_details.candidate.email.0, PRIVATE_KEY) + crypto::decrypt_password_with_private_key(&encrypted_details.candidate.email.unwrap().0, PRIVATE_KEY) .await .unwrap(), "email" ); assert_eq!( - crypto::decrypt_password_with_private_key(&encrypted_details.candidate.sex.0, PRIVATE_KEY) + crypto::decrypt_password_with_private_key(&encrypted_details.candidate.sex.unwrap().0, PRIVATE_KEY) .await .unwrap(), "sex" diff --git a/core/src/services/application_service.rs b/core/src/services/application_service.rs index 7d54ad3..16b8be9 100644 --- a/core/src/services/application_service.rs +++ b/core/src/services/application_service.rs @@ -43,10 +43,11 @@ impl ApplicationService { private_key: String, db: &DbConn, candidate: candidate::Model, - // parents: Vec, ) -> Result { + println!("Decrypting all details: privkey: {}", private_key); + let parents = Query::find_candidate_parents(db, &candidate).await?; - let enc_details = EncryptedApplicationDetails::try_from((&candidate, parents))?; + let enc_details = EncryptedApplicationDetails::from((&candidate, parents)); enc_details.decrypt(private_key).await } diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 96ef1f0..cd53f9e 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -111,32 +111,38 @@ impl CandidateService { let new_password_hash = crypto::hash_password(new_password_plain.clone()).await?; let (pubkey, priv_key_plain_text) = crypto::create_identity(); - let encrypted_priv_key = crypto::encrypt_password(priv_key_plain_text, + let encrypted_priv_key = crypto::encrypt_password(priv_key_plain_text.clone(), new_password_plain.to_string() ).await?; + Self::delete_old_sessions(db, &candidate, 0).await?; let candidate = Mutation::update_candidate_password_and_keys(db, candidate, new_password_hash, - pubkey, + pubkey.clone(), encrypted_priv_key ).await?; + // user might no have filled his details yet, but personal id number is filled from beginning let personal_id_number = EncryptedString::from(candidate.personal_identification_number.clone()) .decrypt(&admin_private_key) .await?; + + let recipients = get_recipients(db, &pubkey).await?; - let enc_details_opt = EncryptedApplicationDetails::try_from( - (&candidate, parents) - ); - - if let Ok(enc_details) = enc_details_opt { - let application_details = enc_details.decrypt(admin_private_key).await?; - ApplicationService::add_all_details(db, candidate, &application_details).await?; + let dec_details = EncryptedApplicationDetails::from((&candidate, parents.clone())) + .decrypt(admin_private_key).await?; + let enc_details = EncryptedApplicationDetails::new(&dec_details, recipients).await?; + + let candidate = Mutation::add_candidate_details(db, candidate, enc_details.candidate).await?; + for i in 0..enc_details.parents.len() { + Mutation::add_parent_details(db, parents[i].clone(), enc_details.parents[i].clone()).await?; } + let details = ApplicationService::decrypt_all_details(priv_key_plain_text, db, candidate).await?; + Ok( CreateCandidateResponse { application_id: id, From b6ac8f431f20057b96f786046fa2b09f189efd4f Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 8 Jan 2023 14:28:09 +0100 Subject: [PATCH 2/4] feat: delete parents based on form --- core/src/database/mutation/parent.rs | 6 +++++ core/src/models/candidate_details.rs | 1 - core/src/services/candidate_service.rs | 35 +++----------------------- core/src/services/parent_service.rs | 10 ++++++-- 4 files changed, 17 insertions(+), 35 deletions(-) diff --git a/core/src/database/mutation/parent.rs b/core/src/database/mutation/parent.rs index 51b1fae..b31b269 100644 --- a/core/src/database/mutation/parent.rs +++ b/core/src/database/mutation/parent.rs @@ -15,6 +15,12 @@ impl Mutation { .await } + pub async fn delete_parent(db: &DbConn, parent: Model) -> Result { + parent + .delete(db) + .await + } + pub async fn add_parent_details( db: &DbConn, parent: Model, diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index 3f41344..579b9e1 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -237,7 +237,6 @@ impl From<&parent::Model> for EncryptedParentDetails { telephone: EncryptedString::try_from(&parent.telephone).ok(), email: EncryptedString::try_from(&parent.email).ok(), } - } } diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index cd53f9e..0ca5e75 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -10,35 +10,8 @@ use crate::{ Mutation, Query, models::{candidate::{BaseCandidateResponse, CreateCandidateResponse}, auth::AuthenticableTrait}, utils::db::get_recipients, }; -use super::{session_service::SessionService, application_service::ApplicationService, portfolio_service::PortfolioService}; +use super::{session_service::SessionService, portfolio_service::PortfolioService}; -// TODO validation - -/* pub struct FieldOfStudy { - pub short_name: String, - pub full_name: String, - pub code: i32, -} - -impl FieldOfStudy { - pub fn new(short_name: String, full_name: String, code: i32) -> Self { - Self { - short_name, - full_name, - code, - } - } - - pub fn code_str(&self) -> String { - format!("{:04}", self.code) - } -} - -pub enum FieldsOfStudy { - KB(FieldOfStudy), - IT(FieldOfStudy), - G(FieldOfStudy), -} */ const FIELD_OF_STUDY_PREFIXES: [&str; 3] = ["101", "102", "103"]; @@ -136,17 +109,15 @@ impl CandidateService { .decrypt(admin_private_key).await?; let enc_details = EncryptedApplicationDetails::new(&dec_details, recipients).await?; - let candidate = Mutation::add_candidate_details(db, candidate, enc_details.candidate).await?; + Mutation::add_candidate_details(db, candidate, enc_details.candidate).await?; for i in 0..enc_details.parents.len() { Mutation::add_parent_details(db, parents[i].clone(), enc_details.parents[i].clone()).await?; } - let details = ApplicationService::decrypt_all_details(priv_key_plain_text, db, candidate).await?; - Ok( CreateCandidateResponse { application_id: id, - personal_id_number: personal_id_number, + personal_id_number, password: new_password_plain, } ) diff --git a/core/src/services/parent_service.rs b/core/src/services/parent_service.rs index c3710f6..be2b2f5 100644 --- a/core/src/services/parent_service.rs +++ b/core/src/services/parent_service.rs @@ -22,10 +22,11 @@ impl ParentService { parents_details: &Vec, recipients: &Vec, ) -> Result, ServiceError> { - let found_parents = Query::find_candidate_parents(db, ref_candidate).await?; - if found_parents.len() > 2 { + if parents_details.len() > 2 { return Err(ServiceError::ParentOverflow); } + + let found_parents = Query::find_candidate_parents(db, ref_candidate).await?; let mut result = vec![]; for i in 0..parents_details.len() { @@ -38,6 +39,11 @@ impl ParentService { result.push(parent); } + // delete parents that are not in the form + for i in parents_details.len()..found_parents.len() { + Mutation::delete_parent(db, found_parents[i].to_owned()).await?; + } + Ok(result) } } From 95dc6bc3d94ca52530ffde643e8e9c94d273f527 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 8 Jan 2023 14:31:55 +0100 Subject: [PATCH 3/4] refactor: update_candidate_details method name --- core/src/database/mutation/candidate.rs | 9 +++++---- core/src/services/candidate_service.rs | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/src/database/mutation/candidate.rs b/core/src/database/mutation/candidate.rs index e0b37d9..d5d853e 100644 --- a/core/src/database/mutation/candidate.rs +++ b/core/src/database/mutation/candidate.rs @@ -26,7 +26,7 @@ impl Mutation { .insert(db) .await?; - info!("CANDIDATE CREATED"); + info!("CANDIDATE {} CREATED", application_id); Ok(insert) } @@ -60,11 +60,12 @@ impl Mutation { Ok(update) } - pub async fn add_candidate_details( + pub async fn update_candidate_details( db: &DbConn, user: candidate::Model, enc_candidate: EncryptedCandidateDetails, ) -> Result { + let application = user.application; let mut user: candidate::ActiveModel = user.into(); user.name = Set(enc_candidate.name.map(|e| e.into())); user.surname = Set(enc_candidate.surname.map(|e| e.into())); @@ -82,7 +83,7 @@ impl Mutation { let update = user.update(db).await?; - info!("CANDIDATE DETAILS ADDED"); + info!("CANDIDATE {} DETAILS UPDATED", application); Ok(update) } @@ -140,7 +141,7 @@ mod tests { vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()], ).await.unwrap(); - Mutation::add_candidate_details(&db, candidate, encrypted_details.candidate).await.unwrap(); + Mutation::update_candidate_details(&db, candidate, encrypted_details.candidate).await.unwrap(); let candidate = Query::find_candidate_by_id(&db, APPLICATION_ID) .await diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 0ca5e75..3156868 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -109,7 +109,7 @@ impl CandidateService { .decrypt(admin_private_key).await?; let enc_details = EncryptedApplicationDetails::new(&dec_details, recipients).await?; - Mutation::add_candidate_details(db, candidate, enc_details.candidate).await?; + Mutation::update_candidate_details(db, candidate, enc_details.candidate).await?; for i in 0..enc_details.parents.len() { Mutation::add_parent_details(db, parents[i].clone(), enc_details.parents[i].clone()).await?; } @@ -137,7 +137,7 @@ impl CandidateService { recipients: &Vec, ) -> Result { let enc_details = EncryptedCandidateDetails::new(&details, recipients).await?; - let model = Mutation::add_candidate_details(db, candidate, enc_details).await?; + let model = Mutation::update_candidate_details(db, candidate, enc_details).await?; Ok(model) } From 6cacf5e0f304694d5d68df42cd39edab299e4791 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Sun, 8 Jan 2023 14:33:02 +0100 Subject: [PATCH 4/4] refactor: remove unused import --- core/src/database/mutation/session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/database/mutation/session.rs b/core/src/database/mutation/session.rs index 6b476de..e4d11aa 100644 --- a/core/src/database/mutation/session.rs +++ b/core/src/database/mutation/session.rs @@ -1,5 +1,5 @@ use chrono::{Utc, Duration, NaiveDateTime}; -use ::entity::{session, candidate}; +use ::entity::session; use sea_orm::{*, prelude::Uuid}; use crate::Mutation;