mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-16 21:11:06 +00:00
Merge pull request #125 from EETagent/password_reset_fix
Fix Password reset, improve EncryptedApplication data structure
This commit is contained in:
commit
9a9d4355a8
9 changed files with 193 additions and 203 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ impl Mutation {
|
|||
.insert(db)
|
||||
.await?;
|
||||
|
||||
info!("CANDIDATE CREATED");
|
||||
info!("CANDIDATE {} CREATED", application_id);
|
||||
Ok(insert)
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ impl Mutation {
|
|||
pub_key: String,
|
||||
priv_key_enc: String,
|
||||
) -> Result<candidate::Model, DbErr> {
|
||||
let application = candidate.application;
|
||||
let mut candidate: candidate::ActiveModel = candidate.into();
|
||||
candidate.code = Set(new_password_hash);
|
||||
candidate.public_key = Set(pub_key);
|
||||
|
|
@ -55,33 +56,34 @@ impl Mutation {
|
|||
|
||||
let update = candidate.update(db).await?;
|
||||
|
||||
warn!("CANDIDATE PASSWORD CHANGED");
|
||||
warn!("CANDIDATE {} PASSWORD CHANGED", application);
|
||||
Ok(update)
|
||||
}
|
||||
|
||||
pub async fn add_candidate_details(
|
||||
pub async fn update_candidate_details(
|
||||
db: &DbConn,
|
||||
user: candidate::Model,
|
||||
enc_candidate: EncryptedCandidateDetails,
|
||||
) -> Result<candidate::Model, sea_orm::DbErr> {
|
||||
let application = user.application;
|
||||
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());
|
||||
|
||||
let update = user.update(db).await?;
|
||||
|
||||
info!("CANDIDATE DETAILS ADDED");
|
||||
info!("CANDIDATE {} DETAILS UPDATED", application);
|
||||
|
||||
Ok(update)
|
||||
}
|
||||
|
|
@ -139,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
|
||||
|
|
|
|||
|
|
@ -15,16 +15,22 @@ impl Mutation {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_parent(db: &DbConn, parent: Model) -> Result<DeleteResult, DbErr> {
|
||||
parent
|
||||
.delete(db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn add_parent_details(
|
||||
db: &DbConn,
|
||||
parent: Model,
|
||||
enc_parent: EncryptedParentDetails,
|
||||
) -> Result<Model, sea_orm::DbErr> {
|
||||
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());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use chrono::{Utc, Duration, NaiveDateTime};
|
||||
use ::entity::{session, candidate};
|
||||
use ::entity::session;
|
||||
use sea_orm::{*, prelude::Uuid};
|
||||
|
||||
use crate::Mutation;
|
||||
|
|
|
|||
|
|
@ -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<Self, ServiceError> {
|
||||
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<SubmissionProgress>,
|
||||
) -> Result<Self, ServiceError> {
|
||||
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),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EncryptedString>,
|
||||
pub surname: Option<EncryptedString>,
|
||||
pub birthplace: Option<EncryptedString>,
|
||||
pub birthdate: Option<EncryptedString>,
|
||||
pub address: Option<EncryptedString>,
|
||||
pub telephone: Option<EncryptedString>,
|
||||
pub citizenship: Option<EncryptedString>,
|
||||
pub email: Option<EncryptedString>,
|
||||
pub sex: Option<EncryptedString>,
|
||||
pub personal_id_number: Option<EncryptedString>,
|
||||
pub study: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EncryptedParentDetails {
|
||||
pub name: EncryptedString,
|
||||
pub surname: EncryptedString,
|
||||
pub telephone: EncryptedString,
|
||||
pub email: EncryptedString,
|
||||
pub name: Option<EncryptedString>,
|
||||
pub surname: Option<EncryptedString>,
|
||||
pub telephone: Option<EncryptedString>,
|
||||
pub email: Option<EncryptedString>,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EncryptedApplicationDetails {
|
||||
|
|
@ -50,9 +50,16 @@ impl EncryptedString {
|
|||
}
|
||||
|
||||
pub async fn decrypt(&self, private_key: &String) -> Result<String, ServiceError> {
|
||||
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<EncryptedString>,
|
||||
private_key: &String,
|
||||
) -> Result<Option<String>, ServiceError> {
|
||||
match s {
|
||||
Some(s) => Ok(Some(s.decrypt(private_key).await?)),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +84,7 @@ impl TryFrom<&Option<String>> for EncryptedString {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> 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<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
|
||||
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<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.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,41 @@ 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<ParentDetails, ServiceError> {
|
||||
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<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)?,
|
||||
}
|
||||
)
|
||||
) -> 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 +274,18 @@ impl EncryptedApplicationDetails {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<(&candidate::Model, Vec<parent::Model>)> for EncryptedApplicationDetails {
|
||||
type Error = ServiceError;
|
||||
|
||||
fn try_from(
|
||||
impl From<(&candidate::Model, Vec<parent::Model>)> for EncryptedApplicationDetails {
|
||||
fn from(
|
||||
(candidate, parents): (&candidate::Model, Vec<parent::Model>),
|
||||
) -> Result<Self, Self::Error> {
|
||||
) -> Self {
|
||||
let enc_parents = parents.iter()
|
||||
.map(|m| EncryptedParentDetails::try_from(m))
|
||||
.collect::<Result<Vec<EncryptedParentDetails>, ServiceError>>()?;
|
||||
.map(|m| EncryptedParentDetails::from(m))
|
||||
.collect::<Vec<EncryptedParentDetails>>();
|
||||
|
||||
Ok(EncryptedApplicationDetails {
|
||||
candidate: EncryptedCandidateDetails::try_from(candidate)?,
|
||||
EncryptedApplicationDetails {
|
||||
candidate: EncryptedCandidateDetails::from(candidate),
|
||||
parents: enc_parents,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,30 +297,30 @@ 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)?,
|
||||
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<String>,
|
||||
) -> Result<String, ServiceError> {
|
||||
|
|
@ -329,7 +328,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 +418,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"
|
||||
|
|
|
|||
|
|
@ -43,10 +43,11 @@ impl ApplicationService {
|
|||
private_key: String,
|
||||
db: &DbConn,
|
||||
candidate: candidate::Model,
|
||||
// parents: Vec<parent::Model>,
|
||||
) -> Result<ApplicationDetails, ServiceError> {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"];
|
||||
|
||||
|
|
@ -111,36 +84,40 @@ 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?;
|
||||
|
||||
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?;
|
||||
}
|
||||
|
||||
Ok(
|
||||
CreateCandidateResponse {
|
||||
application_id: id,
|
||||
personal_id_number: personal_id_number,
|
||||
personal_id_number,
|
||||
password: new_password_plain,
|
||||
}
|
||||
)
|
||||
|
|
@ -160,7 +137,7 @@ impl CandidateService {
|
|||
recipients: &Vec<String>,
|
||||
) -> Result<entity::candidate::Model, ServiceError> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ impl ParentService {
|
|||
parents_details: &Vec<ParentDetails>,
|
||||
recipients: &Vec<String>,
|
||||
) -> Result<Vec<parent::Model>, 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue