mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-24 09:01:48 +00:00
feat!: lock candidate details for application entities. who can't decrypt it
This commit is contained in:
parent
fc176348d0
commit
85c6a47232
9 changed files with 48 additions and 24 deletions
|
|
@ -166,13 +166,12 @@ pub async fn get_candidate(
|
||||||
.await
|
.await
|
||||||
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
||||||
.ok_or(to_custom_error(ServiceError::CandidateNotFound))?;
|
.ok_or(to_custom_error(ServiceError::CandidateNotFound))?;
|
||||||
let candidate = ApplicationService::find_related_candidate(db, application).await
|
|
||||||
.map_err(to_custom_error)?;
|
|
||||||
|
|
||||||
let details = ApplicationService::decrypt_all_details(
|
let details = ApplicationService::decrypt_all_details(
|
||||||
private_key,
|
private_key,
|
||||||
db,
|
db,
|
||||||
candidate
|
&application,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(to_custom_error)?;
|
.map_err(to_custom_error)?;
|
||||||
|
|
@ -194,7 +193,7 @@ pub async fn delete_candidate(
|
||||||
.await
|
.await
|
||||||
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
||||||
.ok_or(to_custom_error(ServiceError::CandidateNotFound))?;
|
.ok_or(to_custom_error(ServiceError::CandidateNotFound))?;
|
||||||
let candidate = ApplicationService::find_related_candidate(db, application).await.map_err(to_custom_error)?;
|
let candidate = ApplicationService::find_related_candidate(db, &application).await.map_err(to_custom_error)?;
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ pub async fn whoami(conn: Connection<'_, Db>, session: ApplicationAuth) -> Resul
|
||||||
|
|
||||||
let private_key = session.get_private_key();
|
let private_key = session.get_private_key();
|
||||||
let application: entity::application::Model = session.into();
|
let application: entity::application::Model = session.into();
|
||||||
let candidate = ApplicationService::find_related_candidate(&db, application.clone()).await.map_err(to_custom_error)?; // TODO
|
let candidate = ApplicationService::find_related_candidate(&db, &application).await.map_err(to_custom_error)?; // TODO
|
||||||
println!("candidate: {:?}", candidate);
|
println!("candidate: {:?}", candidate);
|
||||||
let response = NewCandidateResponse::from_encrypted(&private_key, candidate).await
|
let response = NewCandidateResponse::from_encrypted(&private_key, candidate).await
|
||||||
.map_err(to_custom_error)?;
|
.map_err(to_custom_error)?;
|
||||||
|
|
@ -95,9 +95,9 @@ pub async fn post_details(
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
let form = details.into_inner();
|
let form = details.into_inner();
|
||||||
let application: application::Model = session.into();
|
let application: application::Model = session.into();
|
||||||
let candidate = ApplicationService::find_related_candidate(&db, application.clone()).await.map_err(to_custom_error)?; // TODO
|
let candidate = ApplicationService::find_related_candidate(&db, &application).await.map_err(to_custom_error)?; // TODO
|
||||||
|
|
||||||
let _candidate_parent = ApplicationService::add_all_details(db, &application.public_key, candidate, &form)
|
let _candidate_parent = ApplicationService::add_all_details(db, &application, candidate, &form)
|
||||||
.await
|
.await
|
||||||
.map_err(to_custom_error)?;
|
.map_err(to_custom_error)?;
|
||||||
|
|
||||||
|
|
@ -112,9 +112,13 @@ pub async fn get_details(
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
let private_key = session.get_private_key();
|
let private_key = session.get_private_key();
|
||||||
let application: entity::application::Model = session.into();
|
let application: entity::application::Model = session.into();
|
||||||
let candidate = ApplicationService::find_related_candidate(&db, application.clone()).await.map_err(to_custom_error)?; // TODO
|
|
||||||
|
|
||||||
let details = ApplicationService::decrypt_all_details(private_key, db, candidate)
|
let details = ApplicationService::decrypt_all_details(
|
||||||
|
private_key,
|
||||||
|
db,
|
||||||
|
&application,
|
||||||
|
true
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map(|x| Json(x))
|
.map(|x| Json(x))
|
||||||
.map_err(to_custom_error);
|
.map_err(to_custom_error);
|
||||||
|
|
@ -218,7 +222,7 @@ pub async fn submit_portfolio(
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
|
|
||||||
let application: entity::application::Model = session.into();
|
let application: entity::application::Model = session.into();
|
||||||
let candidate = ApplicationService::find_related_candidate(&db, application.clone()).await.map_err(to_custom_error)?; // TODO
|
let candidate = ApplicationService::find_related_candidate(&db, &application).await.map_err(to_custom_error)?; // TODO
|
||||||
|
|
||||||
let submit = PortfolioService::submit(&application.public_key, &candidate, &db).await;
|
let submit = PortfolioService::submit(&application.public_key, &candidate, &db).await;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,12 @@ impl Mutation {
|
||||||
|
|
||||||
pub async fn update_candidate_details(
|
pub async fn update_candidate_details(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
user: candidate::Model,
|
candidate: candidate::Model,
|
||||||
enc_candidate: EncryptedCandidateDetails,
|
enc_candidate: EncryptedCandidateDetails,
|
||||||
|
encrypted_by_id: i32,
|
||||||
) -> Result<candidate::Model, sea_orm::DbErr> {
|
) -> Result<candidate::Model, sea_orm::DbErr> {
|
||||||
let application = user.id;
|
let application = candidate.id;
|
||||||
let mut candidate: candidate::ActiveModel = user.into();
|
let mut candidate: candidate::ActiveModel = candidate.into();
|
||||||
|
|
||||||
candidate.name = Set(enc_candidate.name.map(|e| e.into()));
|
candidate.name = Set(enc_candidate.name.map(|e| e.into()));
|
||||||
candidate.surname = Set(enc_candidate.surname.map(|e| e.into()));
|
candidate.surname = Set(enc_candidate.surname.map(|e| e.into()));
|
||||||
|
|
@ -63,6 +64,7 @@ impl Mutation {
|
||||||
candidate.school_name = Set(enc_candidate.school_name.map(|e| e.into()));
|
candidate.school_name = Set(enc_candidate.school_name.map(|e| e.into()));
|
||||||
candidate.health_insurance = Set(enc_candidate.health_insurance.map(|e| e.into()));
|
candidate.health_insurance = Set(enc_candidate.health_insurance.map(|e| e.into()));
|
||||||
candidate.study = Set(enc_candidate.study.map(|e| e.into()));
|
candidate.study = Set(enc_candidate.study.map(|e| e.into()));
|
||||||
|
candidate.encrypted_by_id = Set(Some(encrypted_by_id));
|
||||||
|
|
||||||
candidate.updated_at = Set(chrono::offset::Local::now().naive_local());
|
candidate.updated_at = Set(chrono::offset::Local::now().naive_local());
|
||||||
|
|
||||||
|
|
@ -128,7 +130,7 @@ mod tests {
|
||||||
vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||||
).await.unwrap();
|
).await.unwrap();
|
||||||
|
|
||||||
let candidate = Mutation::update_candidate_details(&db, candidate, encrypted_details.candidate).await.unwrap();
|
let candidate = Mutation::update_candidate_details(&db, candidate, encrypted_details.candidate, 1).await.unwrap();
|
||||||
|
|
||||||
let candidate = Query::find_candidate_by_id(&db, candidate.id)
|
let candidate = Query::find_candidate_by_id(&db, candidate.id)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ impl Query {
|
||||||
|
|
||||||
pub async fn find_related_candidate(
|
pub async fn find_related_candidate(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
application: application::Model,
|
application: &application::Model,
|
||||||
) -> Result<Option<candidate::Model>, DbErr> {
|
) -> Result<Option<candidate::Model>, DbErr> {
|
||||||
application
|
application
|
||||||
.find_related(candidate::Entity)
|
.find_related(candidate::Entity)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ pub enum ServiceError {
|
||||||
UserAlreadyExists,
|
UserAlreadyExists,
|
||||||
#[error("Candidate not found")]
|
#[error("Candidate not found")]
|
||||||
CandidateNotFound,
|
CandidateNotFound,
|
||||||
|
#[error("Resource is locked")]
|
||||||
|
Locked,
|
||||||
#[error("Parrent not found")]
|
#[error("Parrent not found")]
|
||||||
ParentNotFound,
|
ParentNotFound,
|
||||||
#[error("Database error")]
|
#[error("Database error")]
|
||||||
|
|
@ -69,7 +71,7 @@ pub enum ServiceError {
|
||||||
impl ServiceError {
|
impl ServiceError {
|
||||||
pub fn code(&self) -> u16 {
|
pub fn code(&self) -> u16 {
|
||||||
match self {
|
match self {
|
||||||
// 40X
|
// 4XX
|
||||||
ServiceError::InvalidApplicationId => 400,
|
ServiceError::InvalidApplicationId => 400,
|
||||||
ServiceError::ParentOverflow => 400,
|
ServiceError::ParentOverflow => 400,
|
||||||
ServiceError::Unauthorized => 401,
|
ServiceError::Unauthorized => 401,
|
||||||
|
|
@ -79,6 +81,7 @@ impl ServiceError {
|
||||||
ServiceError::CandidateNotFound => 404,
|
ServiceError::CandidateNotFound => 404,
|
||||||
ServiceError::IncompletePortfolio => 406,
|
ServiceError::IncompletePortfolio => 406,
|
||||||
ServiceError::UserAlreadyExists => 409,
|
ServiceError::UserAlreadyExists => 409,
|
||||||
|
ServiceError::Locked => 423,
|
||||||
// 500
|
// 500
|
||||||
ServiceError::ParentNotFound => 500,
|
ServiceError::ParentNotFound => 500,
|
||||||
ServiceError::DbError(_) => 500,
|
ServiceError::DbError(_) => 500,
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ impl ApplicationService {
|
||||||
|
|
||||||
pub async fn find_related_candidate(
|
pub async fn find_related_candidate(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
application: application::Model,
|
application: &application::Model,
|
||||||
) -> Result<candidate::Model, ServiceError> {
|
) -> Result<candidate::Model, ServiceError> {
|
||||||
let candidate = Query::find_related_candidate(db, application).await?;
|
let candidate = Query::find_related_candidate(db, application).await?;
|
||||||
if let Some(candidate) = candidate {
|
if let Some(candidate) = candidate {
|
||||||
|
|
@ -172,13 +172,13 @@ impl ApplicationService {
|
||||||
|
|
||||||
pub async fn add_all_details(
|
pub async fn add_all_details(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
public_key: &String,
|
application: &application::Model,
|
||||||
candidate: candidate::Model,
|
candidate: candidate::Model,
|
||||||
form: &ApplicationDetails,
|
form: &ApplicationDetails,
|
||||||
) -> Result<(candidate::Model, Vec<parent::Model>), ServiceError> {
|
) -> Result<(candidate::Model, Vec<parent::Model>), ServiceError> {
|
||||||
|
|
||||||
let recipients = get_recipients(db, public_key).await?;
|
let recipients = get_recipients(db, &application.public_key).await?;
|
||||||
let candidate = CandidateService::add_candidate_details(db, candidate, &form.candidate, &recipients).await?;
|
let candidate = CandidateService::add_candidate_details(db, candidate, &form.candidate, &recipients, application.id).await?;
|
||||||
let parents = ParentService::add_parents_details(db, &candidate, &form.parents, &recipients).await?;
|
let parents = ParentService::add_parents_details(db, &candidate, &form.parents, &recipients).await?;
|
||||||
Ok(
|
Ok(
|
||||||
(
|
(
|
||||||
|
|
@ -191,8 +191,15 @@ impl ApplicationService {
|
||||||
pub async fn decrypt_all_details(
|
pub async fn decrypt_all_details(
|
||||||
private_key: String,
|
private_key: String,
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
candidate: candidate::Model,
|
application: &application::Model,
|
||||||
|
restrict_access: bool,
|
||||||
) -> Result<ApplicationDetails, ServiceError> {
|
) -> Result<ApplicationDetails, ServiceError> {
|
||||||
|
let candidate = ApplicationService::find_related_candidate(db, application).await?;
|
||||||
|
|
||||||
|
if restrict_access && candidate.encrypted_by_id.is_some() && candidate.encrypted_by_id != Some(application.id) {
|
||||||
|
return Err(ServiceError::Locked)
|
||||||
|
}
|
||||||
|
|
||||||
let parents = Query::find_candidate_parents(db, &candidate).await?;
|
let parents = Query::find_candidate_parents(db, &candidate).await?;
|
||||||
let enc_details = EncryptedApplicationDetails::from((&candidate, parents));
|
let enc_details = EncryptedApplicationDetails::from((&candidate, parents));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,15 @@ impl CandidateService {
|
||||||
candidate: candidate::Model,
|
candidate: candidate::Model,
|
||||||
details: &CandidateDetails,
|
details: &CandidateDetails,
|
||||||
recipients: &Vec<String>,
|
recipients: &Vec<String>,
|
||||||
|
encrypted_by: i32,
|
||||||
) -> Result<entity::candidate::Model, ServiceError> {
|
) -> Result<entity::candidate::Model, ServiceError> {
|
||||||
let enc_details = EncryptedCandidateDetails::new(&details, recipients).await?;
|
let enc_details = EncryptedCandidateDetails::new(&details, recipients).await?;
|
||||||
let model = Mutation::update_candidate_details(db, candidate, enc_details).await?;
|
let model = Mutation::update_candidate_details(
|
||||||
|
db,
|
||||||
|
candidate,
|
||||||
|
enc_details,
|
||||||
|
encrypted_by
|
||||||
|
).await?;
|
||||||
Ok(model)
|
Ok(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,11 +154,11 @@ pub mod tests {
|
||||||
"0000001111".to_string()
|
"0000001111".to_string()
|
||||||
).await.unwrap();
|
).await.unwrap();
|
||||||
|
|
||||||
let candidate= ApplicationService::find_related_candidate(db, application.to_owned()).await.unwrap();
|
let candidate= ApplicationService::find_related_candidate(db, &application).await.unwrap();
|
||||||
|
|
||||||
let form = APPLICATION_DETAILS.lock().unwrap().clone();
|
let form = APPLICATION_DETAILS.lock().unwrap().clone();
|
||||||
|
|
||||||
let (candidate, parents) = ApplicationService::add_all_details(&db, &application.public_key, candidate, &form)
|
let (candidate, parents) = ApplicationService::add_all_details(&db, &application, candidate, &form)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ pub struct Model {
|
||||||
pub personal_identification_number: String,
|
pub personal_identification_number: String,
|
||||||
pub school_name: Option<String>,
|
pub school_name: Option<String>,
|
||||||
pub health_insurance: Option<String>,
|
pub health_insurance: Option<String>,
|
||||||
|
pub encrypted_by_id: Option<i32>,
|
||||||
pub created_at: DateTime,
|
pub created_at: DateTime,
|
||||||
pub updated_at: DateTime,
|
pub updated_at: DateTime,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ impl MigrationTrait for Migration {
|
||||||
.col(ColumnDef::new(Candidate::PersonalIdentificationNumber).string().not_null())
|
.col(ColumnDef::new(Candidate::PersonalIdentificationNumber).string().not_null())
|
||||||
.col(ColumnDef::new(Candidate::SchoolName).string())
|
.col(ColumnDef::new(Candidate::SchoolName).string())
|
||||||
.col(ColumnDef::new(Candidate::HealthInsurance).string())
|
.col(ColumnDef::new(Candidate::HealthInsurance).string())
|
||||||
|
.col(ColumnDef::new(Candidate::EncryptedById).integer())
|
||||||
.col(ColumnDef::new(Candidate::CreatedAt).date_time().not_null())
|
.col(ColumnDef::new(Candidate::CreatedAt).date_time().not_null())
|
||||||
.col(ColumnDef::new(Candidate::UpdatedAt).date_time().not_null())
|
.col(ColumnDef::new(Candidate::UpdatedAt).date_time().not_null())
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
|
|
@ -64,6 +65,7 @@ pub enum Candidate {
|
||||||
PersonalIdentificationNumber,
|
PersonalIdentificationNumber,
|
||||||
SchoolName,
|
SchoolName,
|
||||||
HealthInsurance,
|
HealthInsurance,
|
||||||
|
EncryptedById,
|
||||||
CreatedAt,
|
CreatedAt,
|
||||||
UpdatedAt,
|
UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue