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 submit = PortfolioService::submit(candidate.clone(), &db).await;
let submit = PortfolioService::submit(&candidate, &db).await;
if submit.is_err() {
let e = submit.err().unwrap();

View file

@ -88,7 +88,7 @@ mod tests {
.await
.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
.unwrap();

View file

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

View file

@ -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<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)
.order_by_asc(session::Column::UpdatedAt)
.all(db)
.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)
.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);
}
}

View file

@ -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<Self::User, 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 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<String, 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;
fn try_from(s: Option<String>) -> Result<Self, Self::Error> {
fn try_from(s: &Option<String>) -> Result<Self, Self::Error> {
match s {
Some(s) => Ok(Self(s)),
Some(s) => Ok(Self(s.to_owned())),
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!(
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
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
)?;
Ok(CandidateDetails {
@ -160,25 +160,25 @@ impl EncryptedCandidateDetails {
)
}
}
impl TryFrom<candidate::Model> for EncryptedCandidateDetails {
impl TryFrom<&candidate::Model> for EncryptedCandidateDetails {
type Error = ServiceError;
fn try_from(
candidate: candidate::Model,
candidate: &candidate::Model,
) -> Result<Self, Self::Error> {
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(),
}
)
}
@ -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!(
self.name.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;
fn try_from(
parent: parent::Model,
parent: &parent::Model,
) -> Result<Self, Self::Error> {
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)?,
}
)
}
@ -258,12 +258,12 @@ impl EncryptedApplicationDetails {
}
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(
self.parents
.iter()
.map(|d| d.decrypt(priv_key.clone()))
.map(|d| d.decrypt(&priv_key))
).await?;
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;
fn try_from(
(candidate, parents): (candidate::Model, Vec<parent::Model>),
(candidate, parents): (&candidate::Model, Vec<parent::Model>),
) -> Result<Self, Self::Error> {
let enc_parents = parents.iter()
.map(|m| EncryptedParentDetails::try_from(m.clone()))
.map(|m| EncryptedParentDetails::try_from(m))
.collect::<Result<Vec<EncryptedParentDetails>, ServiceError>>()?;
Ok(EncryptedApplicationDetails {
@ -298,23 +298,23 @@ impl TryFrom<Row> for EncryptedApplicationDetails {
) -> Result<Self, Self::Error> {
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<String>,
) -> 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?),
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

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 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<String, ServiceError> {
@ -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)

View file

@ -29,10 +29,12 @@ impl ApplicationService {
) -> Result<(candidate::Model, Vec<parent::Model>), 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<parent::Model>,
) -> Result<ApplicationDetails, ServiceError> {
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
}

View file

@ -115,9 +115,13 @@ impl CandidateService {
new_password_plain.to_string()
).await?;
Self::delete_old_sessions(db, candidate.clone(), 0).await?;
Mutation::update_candidate_password_and_keys(db, candidate.clone(), new_password_hash, pubkey, encrypted_priv_key).await?;
Self::delete_old_sessions(db, &candidate, 0).await?;
let candidate = Mutation::update_candidate_password_and_keys(db,
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
let personal_id_number = EncryptedString::from(candidate.personal_identification_number.clone())
@ -125,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 {
@ -220,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<session::Model, ServiceError> {
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(())
}
}
@ -245,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))
@ -278,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<String, ServiceError> {
@ -290,19 +296,19 @@ 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())
.map(|s| s.to_owned().into_active_model())
.collect();
SessionService::delete_sessions(db, sessions, keep_n_recent).await?;
@ -313,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;
@ -451,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();
@ -478,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();

View file

@ -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<ParentDetails>,
recipients: &Vec<String>,
) -> 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 {
return Err(ServiceError::ParentOverflow);
}
@ -30,11 +30,11 @@ impl ParentService {
let mut result = vec![];
for i in 0..parents_details.len() {
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?,
};
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);
}
@ -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

View file

@ -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();

View file

@ -26,7 +26,7 @@ impl SessionService {
.iter()
.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(())
@ -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()
)

View file

@ -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())