mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-10 02:01:51 +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
|
||||
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
||||
.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(
|
||||
private_key,
|
||||
db,
|
||||
candidate
|
||||
&application,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.map_err(to_custom_error)?;
|
||||
|
|
@ -194,7 +193,7 @@ pub async fn delete_candidate(
|
|||
.await
|
||||
.map_err(|e| to_custom_error(ServiceError::DbError(e)))?
|
||||
.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
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ pub async fn whoami(conn: Connection<'_, Db>, session: ApplicationAuth) -> Resul
|
|||
|
||||
let private_key = session.get_private_key();
|
||||
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);
|
||||
let response = NewCandidateResponse::from_encrypted(&private_key, candidate).await
|
||||
.map_err(to_custom_error)?;
|
||||
|
|
@ -95,9 +95,9 @@ pub async fn post_details(
|
|||
let db = conn.into_inner();
|
||||
let form = details.into_inner();
|
||||
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
|
||||
.map_err(to_custom_error)?;
|
||||
|
||||
|
|
@ -112,9 +112,13 @@ pub async fn get_details(
|
|||
let db = conn.into_inner();
|
||||
let private_key = session.get_private_key();
|
||||
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
|
||||
.map(|x| Json(x))
|
||||
.map_err(to_custom_error);
|
||||
|
|
@ -218,7 +222,7 @@ pub async fn submit_portfolio(
|
|||
let db = conn.into_inner();
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,11 +44,12 @@ impl Mutation {
|
|||
|
||||
pub async fn update_candidate_details(
|
||||
db: &DbConn,
|
||||
user: candidate::Model,
|
||||
candidate: candidate::Model,
|
||||
enc_candidate: EncryptedCandidateDetails,
|
||||
encrypted_by_id: i32,
|
||||
) -> Result<candidate::Model, sea_orm::DbErr> {
|
||||
let application = user.id;
|
||||
let mut candidate: candidate::ActiveModel = user.into();
|
||||
let application = candidate.id;
|
||||
let mut candidate: candidate::ActiveModel = candidate.into();
|
||||
|
||||
candidate.name = Set(enc_candidate.name.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.health_insurance = Set(enc_candidate.health_insurance.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());
|
||||
|
||||
|
|
@ -128,7 +130,7 @@ mod tests {
|
|||
vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||
).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)
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl Query {
|
|||
|
||||
pub async fn find_related_candidate(
|
||||
db: &DbConn,
|
||||
application: application::Model,
|
||||
application: &application::Model,
|
||||
) -> Result<Option<candidate::Model>, DbErr> {
|
||||
application
|
||||
.find_related(candidate::Entity)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ pub enum ServiceError {
|
|||
UserAlreadyExists,
|
||||
#[error("Candidate not found")]
|
||||
CandidateNotFound,
|
||||
#[error("Resource is locked")]
|
||||
Locked,
|
||||
#[error("Parrent not found")]
|
||||
ParentNotFound,
|
||||
#[error("Database error")]
|
||||
|
|
@ -69,7 +71,7 @@ pub enum ServiceError {
|
|||
impl ServiceError {
|
||||
pub fn code(&self) -> u16 {
|
||||
match self {
|
||||
// 40X
|
||||
// 4XX
|
||||
ServiceError::InvalidApplicationId => 400,
|
||||
ServiceError::ParentOverflow => 400,
|
||||
ServiceError::Unauthorized => 401,
|
||||
|
|
@ -79,6 +81,7 @@ impl ServiceError {
|
|||
ServiceError::CandidateNotFound => 404,
|
||||
ServiceError::IncompletePortfolio => 406,
|
||||
ServiceError::UserAlreadyExists => 409,
|
||||
ServiceError::Locked => 423,
|
||||
// 500
|
||||
ServiceError::ParentNotFound => 500,
|
||||
ServiceError::DbError(_) => 500,
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ impl ApplicationService {
|
|||
|
||||
pub async fn find_related_candidate(
|
||||
db: &DbConn,
|
||||
application: application::Model,
|
||||
application: &application::Model,
|
||||
) -> Result<candidate::Model, ServiceError> {
|
||||
let candidate = Query::find_related_candidate(db, application).await?;
|
||||
if let Some(candidate) = candidate {
|
||||
|
|
@ -172,13 +172,13 @@ impl ApplicationService {
|
|||
|
||||
pub async fn add_all_details(
|
||||
db: &DbConn,
|
||||
public_key: &String,
|
||||
application: &application::Model,
|
||||
candidate: candidate::Model,
|
||||
form: &ApplicationDetails,
|
||||
) -> Result<(candidate::Model, Vec<parent::Model>), ServiceError> {
|
||||
|
||||
let recipients = get_recipients(db, public_key).await?;
|
||||
let candidate = CandidateService::add_candidate_details(db, candidate, &form.candidate, &recipients).await?;
|
||||
let recipients = get_recipients(db, &application.public_key).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?;
|
||||
Ok(
|
||||
(
|
||||
|
|
@ -191,8 +191,15 @@ impl ApplicationService {
|
|||
pub async fn decrypt_all_details(
|
||||
private_key: String,
|
||||
db: &DbConn,
|
||||
candidate: candidate::Model,
|
||||
application: &application::Model,
|
||||
restrict_access: bool,
|
||||
) -> 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 enc_details = EncryptedApplicationDetails::from((&candidate, parents));
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,15 @@ impl CandidateService {
|
|||
candidate: candidate::Model,
|
||||
details: &CandidateDetails,
|
||||
recipients: &Vec<String>,
|
||||
encrypted_by: i32,
|
||||
) -> Result<entity::candidate::Model, ServiceError> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -148,11 +154,11 @@ pub mod tests {
|
|||
"0000001111".to_string()
|
||||
).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 (candidate, parents) = ApplicationService::add_all_details(&db, &application.public_key, candidate, &form)
|
||||
let (candidate, parents) = ApplicationService::add_all_details(&db, &application, candidate, &form)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ pub struct Model {
|
|||
pub personal_identification_number: String,
|
||||
pub school_name: Option<String>,
|
||||
pub health_insurance: Option<String>,
|
||||
pub encrypted_by_id: Option<i32>,
|
||||
pub created_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::SchoolName).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::UpdatedAt).date_time().not_null())
|
||||
.to_owned(),
|
||||
|
|
@ -64,6 +65,7 @@ pub enum Candidate {
|
|||
PersonalIdentificationNumber,
|
||||
SchoolName,
|
||||
HealthInsurance,
|
||||
EncryptedById,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue