diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index 39cea7f..88a63d4 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -210,7 +210,7 @@ pub async fn submit_portfolio( let candidate: entity::candidate::Model = session.into(); - let submit = PortfolioService::submit(candidate.clone(), &db).await; + let submit = PortfolioService::submit(&candidate, &db).await; if submit.is_err() { let e = submit.err().unwrap(); diff --git a/core/src/database/query/session.rs b/core/src/database/query/session.rs index 8d5b753..a9223fc 100644 --- a/core/src/database/query/session.rs +++ b/core/src/database/query/session.rs @@ -21,14 +21,14 @@ impl Query { AdminSession::find_by_id(uuid).one(db).await } - pub async fn find_related_candidate_sessions(db: &DbConn, candidate: candidate::Model) -> Result, DbErr> { + pub async fn find_related_candidate_sessions(db: &DbConn, candidate: &candidate::Model) -> Result, DbErr> { candidate.find_related(Session) .order_by_asc(session::Column::UpdatedAt) .all(db) .await } - pub async fn find_related_admin_sessions(db: &DbConn, admin: admin::Model) -> Result, DbErr> { + pub async fn find_related_admin_sessions(db: &DbConn, admin: &admin::Model) -> Result, DbErr> { admin.find_related(admin_session::Entity) .order_by_asc(admin_session::Column::UpdatedAt) .all(db) @@ -126,10 +126,10 @@ mod tests { .await .unwrap(); - let sessions = Query::find_related_candidate_sessions(&db, candidate).await.unwrap(); + let sessions = Query::find_related_candidate_sessions(&db, &candidate).await.unwrap(); assert_eq!(sessions.len(), 1); - let sessions = Query::find_related_admin_sessions(&db, admin).await.unwrap(); + let sessions = Query::find_related_admin_sessions(&db, &admin).await.unwrap(); assert_eq!(sessions.len(), 1); } } diff --git a/core/src/models/auth.rs b/core/src/models/auth.rs index 45bc5eb..299401f 100644 --- a/core/src/models/auth.rs +++ b/core/src/models/auth.rs @@ -1,5 +1,4 @@ use async_trait::async_trait; -use entity::session; use sea_orm::{prelude::Uuid, DbConn}; use crate::error::ServiceError; @@ -12,6 +11,6 @@ pub trait AuthenticableTrait { async fn login(db: &DbConn, user: i32, password: String, ip_addr: String) -> Result<(String, String), ServiceError>; async fn auth(db: &DbConn, session_id: Uuid) -> Result; async fn logout(db: &DbConn, session: Self::Session) -> Result<(), ServiceError>; - async fn new_session(db: &DbConn, user: Self::User, ip_addr: String, password: String) -> Result; - async fn delete_old_sessions(db: &DbConn, user: Self::User, keep_n_recent: usize) -> Result<(), ServiceError>; + async fn new_session(db: &DbConn, user: &Self::User, ip_addr: String, password: String) -> Result; + async fn delete_old_sessions(db: &DbConn, user: &Self::User, keep_n_recent: usize) -> Result<(), ServiceError>; } \ No newline at end of file diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index 96fe25f..4fa29e4 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -67,12 +67,12 @@ impl Into for EncryptedString { } } -impl TryFrom> for EncryptedString { +impl TryFrom<&Option> for EncryptedString { type Error = ServiceError; - fn try_from(s: Option) -> Result { + fn try_from(s: &Option) -> Result { match s { - Some(s) => Ok(Self(s)), + Some(s) => Ok(Self(s.to_owned())), None => Err(ServiceError::CandidateDetailsNotSet), } } @@ -160,25 +160,25 @@ impl EncryptedCandidateDetails { ) } } -impl TryFrom for EncryptedCandidateDetails { +impl TryFrom<&candidate::Model> for EncryptedCandidateDetails { type Error = ServiceError; fn try_from( - candidate: candidate::Model, + 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), - study: candidate.study.ok_or(ServiceError::CandidateDetailsNotSet)?, + 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(), } ) } @@ -230,10 +230,10 @@ impl TryFrom for EncryptedParentDetails { 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)?, + name: EncryptedString::try_from(&parent.name)?, + surname: EncryptedString::try_from(&parent.surname)?, + telephone: EncryptedString::try_from(&parent.telephone)?, + email: EncryptedString::try_from(&parent.email)?, } ) } @@ -273,11 +273,11 @@ impl EncryptedApplicationDetails { } } -impl TryFrom<(candidate::Model, Vec)> for EncryptedApplicationDetails { +impl TryFrom<(&candidate::Model, Vec)> for EncryptedApplicationDetails { type Error = ServiceError; fn try_from( - (candidate, parents): (candidate::Model, Vec), + (candidate, parents): (&candidate::Model, Vec), ) -> Result { let enc_parents = parents.iter() .map(|m| EncryptedParentDetails::try_from(m.clone())) @@ -298,23 +298,23 @@ 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)?, + 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)?, }, 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)?, + surname: EncryptedString::try_from(&cp.parent_surname)?, + telephone: EncryptedString::try_from(&cp.parent_telephone)?, + email: EncryptedString::try_from(&cp.parent_email)?, }] }) @@ -325,7 +325,7 @@ pub async fn decrypt_if_exists( private_key: &String, encrypted_string: Option, ) -> Result { - match EncryptedString::try_from(encrypted_string) { + match EncryptedString::try_from(&encrypted_string) { Ok(encrypted_string) => Ok(encrypted_string.decrypt(private_key).await?), Err(_) => Ok(String::from("")), } @@ -462,7 +462,7 @@ pub mod tests { let (candidate, parents) = put_user_data(&db).await; - let encrypted_details = EncryptedApplicationDetails::try_from((candidate, parents)).unwrap(); + let encrypted_details = EncryptedApplicationDetails::try_from((&candidate, parents)).unwrap(); let application_details = encrypted_details .decrypt(PRIVATE_KEY.to_string()) // decrypt with admin's private key diff --git a/core/src/services/admin_service.rs b/core/src/services/admin_service.rs index 6d30950..059848c 100644 --- a/core/src/services/admin_service.rs +++ b/core/src/services/admin_service.rs @@ -36,7 +36,7 @@ impl AuthenticableTrait for AdminService { let admin = Query::find_admin_by_id(db, admin_id).await?.ok_or(ServiceError::InvalidCredentials)?; let session_id = Self::new_session(db, - admin.clone(), + &admin, password.clone(), ip_addr ) @@ -70,7 +70,7 @@ impl AuthenticableTrait for AdminService { async fn new_session( db: &DbConn, - admin: admin::Model, + admin: &admin::Model, password: String, ip_addr: String, ) -> Result { @@ -82,13 +82,13 @@ impl AuthenticableTrait for AdminService { let session = Mutation::insert_admin_session(db, admin.id, random_uuid, ip_addr).await?; - Self::delete_old_sessions(db, admin, 1).await?; + Self::delete_old_sessions(db, &admin, 1).await?; Ok(session.id.to_string()) } async fn delete_old_sessions( db: &DbConn, - admin: admin::Model, + admin: &admin::Model, keep_n_recent: usize, ) -> Result<(), ServiceError> { let sessions = Query::find_related_admin_sessions(db, admin) diff --git a/core/src/services/application_service.rs b/core/src/services/application_service.rs index 933d223..7d54ad3 100644 --- a/core/src/services/application_service.rs +++ b/core/src/services/application_service.rs @@ -29,10 +29,12 @@ impl ApplicationService { ) -> Result<(candidate::Model, Vec), ServiceError> { let recipients = get_recipients(db, &candidate.public_key).await?; + let candidate = CandidateService::add_candidate_details(db, candidate, &form.candidate, &recipients).await?; + let parents = ParentService::add_parents_details(db, &candidate, &form.parents, &recipients).await?; Ok( ( - CandidateService::add_candidate_details(db, candidate.clone(), &form.candidate, &recipients).await?, - ParentService::add_parents_details(db, candidate, &form.parents, &recipients).await? + candidate, + parents ) ) } @@ -44,7 +46,7 @@ impl ApplicationService { // parents: Vec, ) -> Result { let parents = Query::find_candidate_parents(db, &candidate).await?; - let enc_details = EncryptedApplicationDetails::try_from((candidate, parents))?; + let enc_details = EncryptedApplicationDetails::try_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 badc1de..0c384a1 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -115,7 +115,7 @@ impl CandidateService { new_password_plain.to_string() ).await?; - Self::delete_old_sessions(db, candidate.clone(), 0).await?; + Self::delete_old_sessions(db, &candidate, 0).await?; let candidate = Mutation::update_candidate_password_and_keys(db, candidate, new_password_hash, @@ -129,7 +129,7 @@ impl CandidateService { .await?; let enc_details_opt = EncryptedApplicationDetails::try_from( - (candidate.clone(), parents) + (&candidate, parents) ); if let Ok(enc_details) = enc_details_opt { @@ -224,13 +224,15 @@ impl CandidateService { FIELD_OF_STUDY_PREFIXES.contains(&field_of_study_prefix) } - pub async fn extend_session_duration_to_14_days(db: &DbConn, session: session::Model) -> Result<(), ServiceError> { + pub async fn extend_session_duration_to_14_days(db: &DbConn, session: session::Model) -> Result { let now = chrono::Utc::now().naive_utc(); if now >= session.updated_at.checked_add_signed(Duration::days(1)).ok_or(ServiceError::Unauthorized)? { let new_expires_at = now.checked_add_signed(Duration::days(14)).ok_or(ServiceError::Unauthorized)?; - Mutation::update_session_expiration(db, session, new_expires_at).await?; + + Ok(Mutation::update_session_expiration(db, session, new_expires_at).await?) + } else { + Ok(session) } - Ok(()) } } @@ -249,7 +251,7 @@ impl AuthenticableTrait for CandidateService { .await? .ok_or(ServiceError::CandidateNotFound)?; - let session_id = Self::new_session(db, candidate.clone(), password.clone(), ip_addr).await?; + let session_id = Self::new_session(db, &candidate, password.clone(), ip_addr).await?; let private_key = Self::decrypt_private_key(candidate, password).await?; Ok((session_id, private_key)) @@ -282,7 +284,7 @@ impl AuthenticableTrait for CandidateService { async fn new_session( db: &DbConn, - candidate: candidate::Model, + candidate: &candidate::Model, password: String, ip_addr: String, ) -> Result { @@ -294,16 +296,16 @@ impl AuthenticableTrait for CandidateService { let session = Mutation::insert_candidate_session(db, random_uuid, candidate.application, ip_addr).await?; - Self::delete_old_sessions(db, candidate, 3).await?; + Self::delete_old_sessions(db, &candidate, 3).await?; Ok(session.id.to_string()) } async fn delete_old_sessions( db: &DbConn, - candidate: candidate::Model, + candidate: &candidate::Model, keep_n_recent: usize, ) -> Result<(), ServiceError> { - let sessions = Query::find_related_candidate_sessions(db, candidate) + let sessions = Query::find_related_candidate_sessions(db, &candidate) .await? .iter() .map(|s| s.clone().into_active_model()) @@ -317,7 +319,7 @@ impl AuthenticableTrait for CandidateService { #[cfg(test)] pub mod tests { - use sea_orm::{DbConn}; + use sea_orm::DbConn; use crate::models::auth::AuthenticableTrait; use crate::models::candidate_details::tests::assert_all_application_details; @@ -455,7 +457,7 @@ pub mod tests { let form = APPLICATION_DETAILS.lock().unwrap().clone(); - let (candidate, parents) = ApplicationService::add_all_details(&db, candidate.clone(), &form) + let (candidate, parents) = ApplicationService::add_all_details(&db, candidate, &form) .await .unwrap(); @@ -482,7 +484,7 @@ pub mod tests { let dec_priv_key = crypto::decrypt_password(enc_candidate.private_key.clone(), password) .await .unwrap(); - let enc_details = EncryptedApplicationDetails::try_from((enc_candidate, enc_parent)) + let enc_details = EncryptedApplicationDetails::try_from((&enc_candidate, enc_parent)) .ok() .unwrap(); let dec_details = enc_details.decrypt(dec_priv_key).await.ok().unwrap(); diff --git a/core/src/services/parent_service.rs b/core/src/services/parent_service.rs index 0ba5779..10bc7c0 100644 --- a/core/src/services/parent_service.rs +++ b/core/src/services/parent_service.rs @@ -18,11 +18,11 @@ impl ParentService { pub async fn add_parents_details( db: &DbConn, - ref_candidate: candidate::Model, + ref_candidate: &candidate::Model, parents_details: &Vec, recipients: &Vec, ) -> Result, ServiceError> { - let found_parents = Query::find_candidate_parents(db, &ref_candidate).await?; + let found_parents = Query::find_candidate_parents(db, ref_candidate).await?; if found_parents.len() > 2 { return Err(ServiceError::ParentOverflow); } @@ -108,12 +108,12 @@ mod tests { let form = APPLICATION_DETAILS_TWO_PARENTS.lock().unwrap().clone(); - let (candidate, parents) = ApplicationService::add_all_details(&db, candidate.clone(), &form) + let (candidate, parents) = ApplicationService::add_all_details(&db, candidate, &form) .await .unwrap(); let priv_key = crypto::decrypt_password(candidate.private_key.clone(), plain_text_password).await.unwrap(); - let dec_details = EncryptedApplicationDetails::try_from((candidate, parents)) + let dec_details = EncryptedApplicationDetails::try_from((&candidate, parents)) .unwrap() .decrypt(priv_key) .await diff --git a/core/src/services/portfolio_service.rs b/core/src/services/portfolio_service.rs index f43714b..6ae6f4b 100644 --- a/core/src/services/portfolio_service.rs +++ b/core/src/services/portfolio_service.rs @@ -268,7 +268,7 @@ impl PortfolioService { /// Move files from cache to final directory and delete cache afterwards - pub async fn submit(candidate: candidate::Model, db: &DbConn) -> Result<(), ServiceError> { + pub async fn submit(candidate: &candidate::Model, db: &DbConn) -> Result<(), ServiceError> { let candidate_id = candidate.application; let path = Self::get_file_store_path().join(&candidate_id.to_string()).to_path_buf(); let cache_path = path.join("cache"); @@ -307,9 +307,9 @@ impl PortfolioService { archive.shutdown().await?; let admin_public_keys = Query::get_all_admin_public_keys(db).await?; - let candidate_public_key = candidate.public_key; + let candidate_public_key = &candidate.public_key; let mut admin_public_keys_refrence: Vec<&str> = admin_public_keys.iter().map(|s| &**s).collect(); - let mut recipients = vec![&*candidate_public_key]; + let mut recipients = vec![&**candidate_public_key]; recipients.append(&mut admin_public_keys_refrence); let final_path = path.join(FileType::PortfolioZip.as_str()); @@ -629,7 +629,7 @@ mod tests { PortfolioService::add_portfolio_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); PortfolioService::add_portfolio_zip_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); - PortfolioService::submit(candidate, &db).await.unwrap(); + PortfolioService::submit(&candidate, &db).await.unwrap(); assert!(tokio::fs::metadata(application_dir.join("PORTFOLIO.age")).await.is_ok()); @@ -648,7 +648,7 @@ mod tests { PortfolioService::add_portfolio_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); PortfolioService::add_portfolio_zip_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); - PortfolioService::submit(candidate, &db).await.unwrap(); + PortfolioService::submit(&candidate, &db).await.unwrap(); assert!(tokio::fs::metadata(application_dir.join("PORTFOLIO.age")).await.is_ok()); @@ -671,7 +671,7 @@ mod tests { PortfolioService::add_portfolio_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); PortfolioService::add_portfolio_zip_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); - PortfolioService::submit(candidate.clone(), &db).await.unwrap(); + PortfolioService::submit(&candidate, &db).await.unwrap(); assert!(PortfolioService::is_portfolio_submitted(APPLICATION_ID).await); @@ -683,7 +683,7 @@ mod tests { PortfolioService::add_portfolio_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); PortfolioService::add_portfolio_zip_to_cache(APPLICATION_ID, vec![0]).await.unwrap(); - PortfolioService::submit(candidate.clone(), &db).await.unwrap(); + PortfolioService::submit(&candidate, &db).await.unwrap(); tokio::fs::remove_file(application_dir.join("PORTFOLIO.age")).await.unwrap(); @@ -714,7 +714,7 @@ mod tests { .await .unwrap(); - PortfolioService::submit(candidate, &db) + PortfolioService::submit(&candidate, &db) .await .unwrap(); diff --git a/core/src/services/session_service.rs b/core/src/services/session_service.rs index 16e05c6..3d4e3dc 100644 --- a/core/src/services/session_service.rs +++ b/core/src/services/session_service.rs @@ -88,7 +88,7 @@ mod tests { // correct password let session = CandidateService::new_session( db, - candidate, + &candidate, "Tajny_kod".to_string(), "127.0.0.1".to_string(), ) @@ -119,7 +119,7 @@ mod tests { // incorrect password assert!(CandidateService::new_session( db, - candidate_form, + &candidate_form, "Spatny_kod".to_string(), "127.0.0.1".to_string() ) diff --git a/core/src/utils/csv.rs b/core/src/utils/csv.rs index be3467f..216ade4 100644 --- a/core/src/utils/csv.rs +++ b/core/src/utils/csv.rs @@ -42,7 +42,7 @@ pub async fn export( let application = candidate.application; let parents = Query::find_candidate_parents(db, &candidate).await?; - let row: Row = match EncryptedApplicationDetails::try_from((candidate, parents)) { + let row: Row = match EncryptedApplicationDetails::try_from((&candidate, parents)) { Ok(d) => Row::from( d .decrypt(private_key.to_string())