Merge pull request #106 from EETagent/fix_password_reset

Cloning fixes
This commit is contained in:
Sebastian Pravda 2022-12-23 22:51:13 +01:00 committed by GitHub
commit 0bc37245c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 106 deletions

View file

@ -210,7 +210,7 @@ pub async fn submit_portfolio(
let candidate: entity::candidate::Model = session.into(); 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() { if submit.is_err() {
let e = submit.err().unwrap(); let e = submit.err().unwrap();

View file

@ -88,7 +88,7 @@ mod tests {
.await .await
.unwrap(); .unwrap();
Mutation::add_parent_details(&db, parent.clone(), encrypted_details.parents[0].clone()) let parent = Mutation::add_parent_details(&db, parent, encrypted_details.parents[0].clone())
.await .await
.unwrap(); .unwrap();

View file

@ -13,7 +13,7 @@ impl Query {
let public_keys = admins let public_keys = admins
.iter() .iter()
.map(|admin| admin.public_key.clone()) .map(|admin| admin.public_key.to_owned())
.collect(); .collect();
Ok(public_keys) Ok(public_keys)

View file

@ -21,14 +21,14 @@ impl Query {
AdminSession::find_by_id(uuid).one(db).await AdminSession::find_by_id(uuid).one(db).await
} }
pub async fn find_related_candidate_sessions(db: &DbConn, candidate: candidate::Model) -> Result<Vec<session::Model>, DbErr> { pub async fn find_related_candidate_sessions(db: &DbConn, candidate: &candidate::Model) -> Result<Vec<session::Model>, DbErr> {
candidate.find_related(Session) candidate.find_related(Session)
.order_by_asc(session::Column::UpdatedAt) .order_by_asc(session::Column::UpdatedAt)
.all(db) .all(db)
.await .await
} }
pub async fn find_related_admin_sessions(db: &DbConn, admin: admin::Model) -> Result<Vec<admin_session::Model>, DbErr> { pub async fn find_related_admin_sessions(db: &DbConn, admin: &admin::Model) -> Result<Vec<admin_session::Model>, DbErr> {
admin.find_related(admin_session::Entity) admin.find_related(admin_session::Entity)
.order_by_asc(admin_session::Column::UpdatedAt) .order_by_asc(admin_session::Column::UpdatedAt)
.all(db) .all(db)
@ -126,10 +126,10 @@ mod tests {
.await .await
.unwrap(); .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); 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); assert_eq!(sessions.len(), 1);
} }
} }

View file

@ -1,5 +1,4 @@
use async_trait::async_trait; use async_trait::async_trait;
use entity::session;
use sea_orm::{prelude::Uuid, DbConn}; use sea_orm::{prelude::Uuid, DbConn};
use crate::error::ServiceError; 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 login(db: &DbConn, user: i32, password: String, ip_addr: String) -> Result<(String, String), ServiceError>;
async fn auth(db: &DbConn, session_id: Uuid) -> Result<Self::User, ServiceError>; async fn auth(db: &DbConn, session_id: Uuid) -> Result<Self::User, ServiceError>;
async fn logout(db: &DbConn, session: Self::Session) -> Result<(), ServiceError>; 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<String, ServiceError>; async fn new_session(db: &DbConn, user: &Self::User, ip_addr: String, password: String) -> Result<String, ServiceError>;
async fn delete_old_sessions(db: &DbConn, user: Self::User, keep_n_recent: usize) -> Result<(), ServiceError>; async fn delete_old_sessions(db: &DbConn, user: &Self::User, keep_n_recent: usize) -> Result<(), ServiceError>;
} }

View file

@ -67,12 +67,12 @@ impl Into<String> for EncryptedString {
} }
} }
impl TryFrom<Option<String>> for EncryptedString { impl TryFrom<&Option<String>> for EncryptedString {
type Error = ServiceError; type Error = ServiceError;
fn try_from(s: Option<String>) -> Result<Self, Self::Error> { fn try_from(s: &Option<String>) -> Result<Self, Self::Error> {
match s { match s {
Some(s) => Ok(Self(s)), Some(s) => Ok(Self(s.to_owned())),
None => Err(ServiceError::CandidateDetailsNotSet), None => Err(ServiceError::CandidateDetailsNotSet),
} }
} }
@ -130,18 +130,18 @@ impl EncryptedCandidateDetails {
) )
} }
pub async fn decrypt(self, priv_key: String) -> Result<CandidateDetails, ServiceError> { pub async fn decrypt(self, priv_key: &String) -> Result<CandidateDetails, ServiceError> {
let d = tokio::try_join!( let d = tokio::try_join!(
self.name.decrypt(&priv_key), // 0 self.name.decrypt(priv_key), // 0
self.surname.decrypt(&priv_key), // 1 self.surname.decrypt(priv_key), // 1
self.birthplace.decrypt(&priv_key), // 2 self.birthplace.decrypt(priv_key), // 2
self.birthdate.decrypt(&priv_key), // 3 self.birthdate.decrypt(priv_key), // 3
self.address.decrypt(&priv_key), // 4 self.address.decrypt(priv_key), // 4
self.telephone.decrypt(&priv_key), // 5 self.telephone.decrypt(priv_key), // 5
self.citizenship.decrypt(&priv_key), // 6 self.citizenship.decrypt(priv_key), // 6
self.email.decrypt(&priv_key), // 7 self.email.decrypt(priv_key), // 7
self.sex.decrypt(&priv_key), // 8 self.sex.decrypt(priv_key), // 8
self.personal_id_number.decrypt(&priv_key),// 9 self.personal_id_number.decrypt(priv_key),// 9
)?; )?;
Ok(CandidateDetails { Ok(CandidateDetails {
@ -160,25 +160,25 @@ impl EncryptedCandidateDetails {
) )
} }
} }
impl TryFrom<candidate::Model> for EncryptedCandidateDetails { impl TryFrom<&candidate::Model> for EncryptedCandidateDetails {
type Error = ServiceError; type Error = ServiceError;
fn try_from( fn try_from(
candidate: candidate::Model, candidate: &candidate::Model,
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
Ok( Ok(
EncryptedCandidateDetails { EncryptedCandidateDetails {
name: EncryptedString::try_from(candidate.name)?, name: EncryptedString::try_from(&candidate.name)?,
surname: EncryptedString::try_from(candidate.surname)?, surname: EncryptedString::try_from(&candidate.surname)?,
birthplace: EncryptedString::try_from(candidate.birthplace)?, birthplace: EncryptedString::try_from(&candidate.birthplace)?,
birthdate: EncryptedString::try_from(candidate.birthdate)?, birthdate: EncryptedString::try_from(&candidate.birthdate)?,
address: EncryptedString::try_from(candidate.address)?, address: EncryptedString::try_from(&candidate.address)?,
telephone: EncryptedString::try_from(candidate.telephone)?, telephone: EncryptedString::try_from(&candidate.telephone)?,
citizenship: EncryptedString::try_from(candidate.citizenship)?, citizenship: EncryptedString::try_from(&candidate.citizenship)?,
email: EncryptedString::try_from(candidate.email)?, email: EncryptedString::try_from(&candidate.email)?,
sex: EncryptedString::try_from(candidate.sex)?, sex: EncryptedString::try_from(&candidate.sex)?,
personal_id_number: EncryptedString::from(candidate.personal_identification_number), personal_id_number: EncryptedString::from(candidate.personal_identification_number.to_owned()),
study: candidate.study.ok_or(ServiceError::CandidateDetailsNotSet)?, study: candidate.study.as_ref().ok_or(ServiceError::CandidateDetailsNotSet)?.to_string(),
} }
) )
} }
@ -206,7 +206,7 @@ impl EncryptedParentDetails {
) )
} }
pub async fn decrypt(&self, priv_key: String) -> Result<ParentDetails, ServiceError> { pub async fn decrypt(&self, priv_key: &String) -> Result<ParentDetails, ServiceError> {
let d = tokio::try_join!( let d = tokio::try_join!(
self.name.decrypt(&priv_key), self.name.decrypt(&priv_key),
self.surname.decrypt(&priv_key), self.surname.decrypt(&priv_key),
@ -223,17 +223,17 @@ impl EncryptedParentDetails {
) )
} }
} }
impl TryFrom<parent::Model> for EncryptedParentDetails { impl TryFrom<&parent::Model> for EncryptedParentDetails {
type Error = ServiceError; type Error = ServiceError;
fn try_from( fn try_from(
parent: parent::Model, parent: &parent::Model,
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
Ok(EncryptedParentDetails { Ok(EncryptedParentDetails {
name: EncryptedString::try_from(parent.name)?, name: EncryptedString::try_from(&parent.name)?,
surname: EncryptedString::try_from(parent.surname)?, surname: EncryptedString::try_from(&parent.surname)?,
telephone: EncryptedString::try_from(parent.telephone)?, telephone: EncryptedString::try_from(&parent.telephone)?,
email: EncryptedString::try_from(parent.email)?, email: EncryptedString::try_from(&parent.email)?,
} }
) )
} }
@ -258,12 +258,12 @@ impl EncryptedApplicationDetails {
} }
pub async fn decrypt(self, priv_key: String) -> Result<ApplicationDetails, ServiceError> { pub async fn decrypt(self, priv_key: String) -> Result<ApplicationDetails, ServiceError> {
let decrypted_candidate = self.candidate.decrypt(priv_key.clone()).await?; let decrypted_candidate = self.candidate.decrypt(&priv_key).await?;
let decrypted_parents = future::try_join_all( let decrypted_parents = future::try_join_all(
self.parents self.parents
.iter() .iter()
.map(|d| d.decrypt(priv_key.clone())) .map(|d| d.decrypt(&priv_key))
).await?; ).await?;
Ok(ApplicationDetails { Ok(ApplicationDetails {
@ -273,14 +273,14 @@ impl EncryptedApplicationDetails {
} }
} }
impl TryFrom<(candidate::Model, Vec<parent::Model>)> for EncryptedApplicationDetails { impl TryFrom<(&candidate::Model, Vec<parent::Model>)> for EncryptedApplicationDetails {
type Error = ServiceError; type Error = ServiceError;
fn try_from( fn try_from(
(candidate, parents): (candidate::Model, Vec<parent::Model>), (candidate, parents): (&candidate::Model, Vec<parent::Model>),
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
let enc_parents = parents.iter() let enc_parents = parents.iter()
.map(|m| EncryptedParentDetails::try_from(m.clone())) .map(|m| EncryptedParentDetails::try_from(m))
.collect::<Result<Vec<EncryptedParentDetails>, ServiceError>>()?; .collect::<Result<Vec<EncryptedParentDetails>, ServiceError>>()?;
Ok(EncryptedApplicationDetails { Ok(EncryptedApplicationDetails {
@ -298,23 +298,23 @@ impl TryFrom<Row> for EncryptedApplicationDetails {
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
Ok(EncryptedApplicationDetails { Ok(EncryptedApplicationDetails {
candidate: EncryptedCandidateDetails { candidate: EncryptedCandidateDetails {
name: EncryptedString::try_from(cp.name)?, name: EncryptedString::try_from(&cp.name)?,
surname: EncryptedString::try_from(cp.surname)?, surname: EncryptedString::try_from(&cp.surname)?,
birthplace: EncryptedString::try_from(cp.birthplace)?, birthplace: EncryptedString::try_from(&cp.birthplace)?,
birthdate: EncryptedString::try_from(cp.birthdate)?, birthdate: EncryptedString::try_from(&cp.birthdate)?,
address: EncryptedString::try_from(cp.address)?, address: EncryptedString::try_from(&cp.address)?,
telephone: EncryptedString::try_from(cp.telephone)?, telephone: EncryptedString::try_from(&cp.telephone)?,
citizenship: EncryptedString::try_from(cp.citizenship)?, citizenship: EncryptedString::try_from(&cp.citizenship)?,
email: EncryptedString::try_from(cp.email)?, email: EncryptedString::try_from(&cp.email)?,
sex: EncryptedString::try_from(cp.sex)?, sex: EncryptedString::try_from(&cp.sex)?,
personal_id_number: EncryptedString::try_from(cp.personal_identification_number)?, personal_id_number: EncryptedString::try_from(&cp.personal_identification_number)?,
study: cp.study.ok_or(ServiceError::CandidateDetailsNotSet)?, study: cp.study.ok_or(ServiceError::CandidateDetailsNotSet)?,
}, },
parents: vec![EncryptedParentDetails { parents: vec![EncryptedParentDetails {
name: EncryptedString::try_from(cp.parent_name)?, name: EncryptedString::try_from(&cp.parent_name)?,
surname: EncryptedString::try_from(cp.parent_surname)?, surname: EncryptedString::try_from(&cp.parent_surname)?,
telephone: EncryptedString::try_from(cp.parent_telephone)?, telephone: EncryptedString::try_from(&cp.parent_telephone)?,
email: EncryptedString::try_from(cp.parent_email)?, email: EncryptedString::try_from(&cp.parent_email)?,
}] }]
}) })
@ -325,7 +325,7 @@ pub async fn decrypt_if_exists(
private_key: &String, private_key: &String,
encrypted_string: Option<String>, encrypted_string: Option<String>,
) -> Result<String, ServiceError> { ) -> Result<String, ServiceError> {
match EncryptedString::try_from(encrypted_string) { match EncryptedString::try_from(&encrypted_string) {
Ok(encrypted_string) => Ok(encrypted_string.decrypt(private_key).await?), Ok(encrypted_string) => Ok(encrypted_string.decrypt(private_key).await?),
Err(_) => Ok(String::from("")), Err(_) => Ok(String::from("")),
} }
@ -462,7 +462,7 @@ pub mod tests {
let (candidate, parents) = put_user_data(&db).await; 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 let application_details = encrypted_details
.decrypt(PRIVATE_KEY.to_string()) // decrypt with admin's private key .decrypt(PRIVATE_KEY.to_string()) // decrypt with admin's private key

View file

@ -36,7 +36,7 @@ impl AuthenticableTrait for AdminService {
let admin = Query::find_admin_by_id(db, admin_id).await?.ok_or(ServiceError::InvalidCredentials)?; let admin = Query::find_admin_by_id(db, admin_id).await?.ok_or(ServiceError::InvalidCredentials)?;
let session_id = Self::new_session(db, let session_id = Self::new_session(db,
admin.clone(), &admin,
password.clone(), password.clone(),
ip_addr ip_addr
) )
@ -70,7 +70,7 @@ impl AuthenticableTrait for AdminService {
async fn new_session( async fn new_session(
db: &DbConn, db: &DbConn,
admin: admin::Model, admin: &admin::Model,
password: String, password: String,
ip_addr: String, ip_addr: String,
) -> Result<String, ServiceError> { ) -> Result<String, ServiceError> {
@ -82,13 +82,13 @@ impl AuthenticableTrait for AdminService {
let session = Mutation::insert_admin_session(db, admin.id, random_uuid, ip_addr).await?; 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()) Ok(session.id.to_string())
} }
async fn delete_old_sessions( async fn delete_old_sessions(
db: &DbConn, db: &DbConn,
admin: admin::Model, admin: &admin::Model,
keep_n_recent: usize, keep_n_recent: usize,
) -> Result<(), ServiceError> { ) -> Result<(), ServiceError> {
let sessions = Query::find_related_admin_sessions(db, admin) let sessions = Query::find_related_admin_sessions(db, admin)

View file

@ -29,10 +29,12 @@ impl ApplicationService {
) -> Result<(candidate::Model, Vec<parent::Model>), ServiceError> { ) -> Result<(candidate::Model, Vec<parent::Model>), ServiceError> {
let recipients = get_recipients(db, &candidate.public_key).await?; 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( Ok(
( (
CandidateService::add_candidate_details(db, candidate.clone(), &form.candidate, &recipients).await?, candidate,
ParentService::add_parents_details(db, candidate, &form.parents, &recipients).await? parents
) )
) )
} }
@ -44,7 +46,7 @@ impl ApplicationService {
// parents: Vec<parent::Model>, // parents: Vec<parent::Model>,
) -> Result<ApplicationDetails, ServiceError> { ) -> Result<ApplicationDetails, ServiceError> {
let parents = Query::find_candidate_parents(db, &candidate).await?; 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 enc_details.decrypt(private_key).await
} }

View file

@ -115,9 +115,13 @@ impl CandidateService {
new_password_plain.to_string() new_password_plain.to_string()
).await?; ).await?;
Self::delete_old_sessions(db, &candidate, 0).await?;
Self::delete_old_sessions(db, candidate.clone(), 0).await?; let candidate = Mutation::update_candidate_password_and_keys(db,
Mutation::update_candidate_password_and_keys(db, candidate.clone(), new_password_hash, pubkey, encrypted_priv_key).await?; candidate,
new_password_hash,
pubkey,
encrypted_priv_key
).await?;
// user might no have filled his details yet, but personal id number is filled from beginning // 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()) let personal_id_number = EncryptedString::from(candidate.personal_identification_number.clone())
@ -125,7 +129,7 @@ impl CandidateService {
.await?; .await?;
let enc_details_opt = EncryptedApplicationDetails::try_from( let enc_details_opt = EncryptedApplicationDetails::try_from(
(candidate.clone(), parents) (&candidate, parents)
); );
if let Ok(enc_details) = enc_details_opt { if let Ok(enc_details) = enc_details_opt {
@ -220,13 +224,15 @@ impl CandidateService {
FIELD_OF_STUDY_PREFIXES.contains(&field_of_study_prefix) 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<session::Model, ServiceError> {
let now = chrono::Utc::now().naive_utc(); let now = chrono::Utc::now().naive_utc();
if now >= session.updated_at.checked_add_signed(Duration::days(1)).ok_or(ServiceError::Unauthorized)? { 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)?; 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(())
} }
} }
@ -245,7 +251,7 @@ impl AuthenticableTrait for CandidateService {
.await? .await?
.ok_or(ServiceError::CandidateNotFound)?; .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?; let private_key = Self::decrypt_private_key(candidate, password).await?;
Ok((session_id, private_key)) Ok((session_id, private_key))
@ -278,7 +284,7 @@ impl AuthenticableTrait for CandidateService {
async fn new_session( async fn new_session(
db: &DbConn, db: &DbConn,
candidate: candidate::Model, candidate: &candidate::Model,
password: String, password: String,
ip_addr: String, ip_addr: String,
) -> Result<String, ServiceError> { ) -> Result<String, ServiceError> {
@ -290,19 +296,19 @@ impl AuthenticableTrait for CandidateService {
let session = Mutation::insert_candidate_session(db, random_uuid, candidate.application, ip_addr).await?; 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()) Ok(session.id.to_string())
} }
async fn delete_old_sessions( async fn delete_old_sessions(
db: &DbConn, db: &DbConn,
candidate: candidate::Model, candidate: &candidate::Model,
keep_n_recent: usize, keep_n_recent: usize,
) -> Result<(), ServiceError> { ) -> Result<(), ServiceError> {
let sessions = Query::find_related_candidate_sessions(db, candidate) let sessions = Query::find_related_candidate_sessions(db, &candidate)
.await? .await?
.iter() .iter()
.map(|s| s.clone().into_active_model()) .map(|s| s.to_owned().into_active_model())
.collect(); .collect();
SessionService::delete_sessions(db, sessions, keep_n_recent).await?; SessionService::delete_sessions(db, sessions, keep_n_recent).await?;
@ -313,7 +319,7 @@ impl AuthenticableTrait for CandidateService {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use sea_orm::{DbConn}; use sea_orm::DbConn;
use crate::models::auth::AuthenticableTrait; use crate::models::auth::AuthenticableTrait;
use crate::models::candidate_details::tests::assert_all_application_details; use crate::models::candidate_details::tests::assert_all_application_details;
@ -451,7 +457,7 @@ pub mod tests {
let form = APPLICATION_DETAILS.lock().unwrap().clone(); 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 .await
.unwrap(); .unwrap();
@ -478,7 +484,7 @@ pub mod tests {
let dec_priv_key = crypto::decrypt_password(enc_candidate.private_key.clone(), password) let dec_priv_key = crypto::decrypt_password(enc_candidate.private_key.clone(), password)
.await .await
.unwrap(); .unwrap();
let enc_details = EncryptedApplicationDetails::try_from((enc_candidate, enc_parent)) let enc_details = EncryptedApplicationDetails::try_from((&enc_candidate, enc_parent))
.ok() .ok()
.unwrap(); .unwrap();
let dec_details = enc_details.decrypt(dec_priv_key).await.ok().unwrap(); let dec_details = enc_details.decrypt(dec_priv_key).await.ok().unwrap();

View file

@ -18,11 +18,11 @@ impl ParentService {
pub async fn add_parents_details( pub async fn add_parents_details(
db: &DbConn, db: &DbConn,
ref_candidate: candidate::Model, ref_candidate: &candidate::Model,
parents_details: &Vec<ParentDetails>, parents_details: &Vec<ParentDetails>,
recipients: &Vec<String>, recipients: &Vec<String>,
) -> Result<Vec<parent::Model>, ServiceError> { ) -> Result<Vec<parent::Model>, 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 { if found_parents.len() > 2 {
return Err(ServiceError::ParentOverflow); return Err(ServiceError::ParentOverflow);
} }
@ -30,11 +30,11 @@ impl ParentService {
let mut result = vec![]; let mut result = vec![];
for i in 0..parents_details.len() { for i in 0..parents_details.len() {
let found_parent = match found_parents.get(i) { let found_parent = match found_parents.get(i) {
Some(parent) => parent.clone(), Some(parent) => parent.to_owned(),
None => ParentService::create(db, ref_candidate.application).await?, None => ParentService::create(db, ref_candidate.application).await?,
}; };
let enc_details = EncryptedParentDetails::new(&parents_details[i], recipients).await?; let enc_details = EncryptedParentDetails::new(&parents_details[i], recipients).await?;
let parent = Mutation::add_parent_details(db, found_parent.clone(), enc_details.clone()).await?; let parent = Mutation::add_parent_details(db, found_parent, enc_details.clone()).await?;
result.push(parent); result.push(parent);
} }
@ -108,12 +108,12 @@ mod tests {
let form = APPLICATION_DETAILS_TWO_PARENTS.lock().unwrap().clone(); 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 .await
.unwrap(); .unwrap();
let priv_key = crypto::decrypt_password(candidate.private_key.clone(), plain_text_password).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() .unwrap()
.decrypt(priv_key) .decrypt(priv_key)
.await .await

View file

@ -268,7 +268,7 @@ impl PortfolioService {
/// Move files from cache to final directory and delete cache afterwards /// 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 candidate_id = candidate.application;
let path = Self::get_file_store_path().join(&candidate_id.to_string()).to_path_buf(); let path = Self::get_file_store_path().join(&candidate_id.to_string()).to_path_buf();
let cache_path = path.join("cache"); let cache_path = path.join("cache");
@ -307,9 +307,9 @@ impl PortfolioService {
archive.shutdown().await?; archive.shutdown().await?;
let admin_public_keys = Query::get_all_admin_public_keys(db).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 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); recipients.append(&mut admin_public_keys_refrence);
let final_path = path.join(FileType::PortfolioZip.as_str()); 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_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap();
PortfolioService::add_portfolio_zip_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()); 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_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap();
PortfolioService::add_portfolio_zip_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()); 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_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap();
PortfolioService::add_portfolio_zip_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); 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_letter_to_cache(APPLICATION_ID, vec![0]).await.unwrap();
PortfolioService::add_portfolio_zip_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(); tokio::fs::remove_file(application_dir.join("PORTFOLIO.age")).await.unwrap();
@ -714,7 +714,7 @@ mod tests {
.await .await
.unwrap(); .unwrap();
PortfolioService::submit(candidate, &db) PortfolioService::submit(&candidate, &db)
.await .await
.unwrap(); .unwrap();

View file

@ -26,7 +26,7 @@ impl SessionService {
.iter() .iter()
.take(sessions.len() - min(sessions.len(), keep_n_recent)) .take(sessions.len() - min(sessions.len(), keep_n_recent))
{ {
Mutation::delete_session(db, session.clone()).await?; Mutation::delete_session(db, session.to_owned()).await?;
} }
Ok(()) Ok(())
@ -88,7 +88,7 @@ mod tests {
// correct password // correct password
let session = CandidateService::new_session( let session = CandidateService::new_session(
db, db,
candidate, &candidate,
"Tajny_kod".to_string(), "Tajny_kod".to_string(),
"127.0.0.1".to_string(), "127.0.0.1".to_string(),
) )
@ -119,7 +119,7 @@ mod tests {
// incorrect password // incorrect password
assert!(CandidateService::new_session( assert!(CandidateService::new_session(
db, db,
candidate_form, &candidate_form,
"Spatny_kod".to_string(), "Spatny_kod".to_string(),
"127.0.0.1".to_string() "127.0.0.1".to_string()
) )

View file

@ -42,7 +42,7 @@ pub async fn export(
let application = candidate.application; let application = candidate.application;
let parents = Query::find_candidate_parents(db, &candidate).await?; 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( Ok(d) => Row::from(
d d
.decrypt(private_key.to_string()) .decrypt(private_key.to_string())