From c00d207f6100f52261910f6bbe11568b9245f329 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Tue, 17 Jan 2023 17:57:54 +0100 Subject: [PATCH] feat: lock candidate delete if candidate already filled application form --- api/src/routes/admin.rs | 14 ++++---------- core/src/services/application_service.rs | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/api/src/routes/admin.rs b/api/src/routes/admin.rs index 8794a20..0291e4b 100644 --- a/api/src/routes/admin.rs +++ b/api/src/routes/admin.rs @@ -2,7 +2,7 @@ use std::net::{SocketAddr, IpAddr, Ipv4Addr}; use portfolio_core::{ crypto::random_12_char_string, - services::{admin_service::AdminService, candidate_service::CandidateService, application_service::ApplicationService, portfolio_service::PortfolioService}, models::{candidate::{CreateCandidateResponse, ApplicationDetails}, auth::AuthenticableTrait, application::ApplicationResponse}, sea_orm::prelude::Uuid, Query, error::ServiceError, utils::csv, + services::{admin_service::AdminService, application_service::ApplicationService, portfolio_service::PortfolioService}, models::{candidate::{CreateCandidateResponse, ApplicationDetails}, auth::AuthenticableTrait, application::ApplicationResponse}, sea_orm::prelude::Uuid, Query, error::ServiceError, utils::csv, }; use requests::{AdminLoginRequest, RegisterRequest}; use rocket::http::{Cookie, Status, CookieJar}; @@ -189,18 +189,12 @@ 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)?; - ApplicationService::delete(db, application).await.map_err(to_custom_error)?; - let remaining_applications = Query::find_applications_by_candidate_id(db, candidate.id).await - .map_err(|e| to_custom_error(ServiceError::DbError(e)))?; + ApplicationService::delete(db, application) + .await + .map_err(to_custom_error) - if remaining_applications.is_empty() { - CandidateService::delete_candidate(db, candidate).await.map_err(to_custom_error)?; - } - - Ok(()) } #[post("/candidate//reset_password")] diff --git a/core/src/services/application_service.rs b/core/src/services/application_service.rs index 3fd93dc..693b0f6 100644 --- a/core/src/services/application_service.rs +++ b/core/src/services/application_service.rs @@ -1,11 +1,12 @@ use async_trait::async_trait; use chrono::Duration; use entity::{candidate, parent, application, session}; +use log::warn; use sea_orm::{DbConn, prelude::Uuid, IntoActiveModel}; -use crate::{error::ServiceError, Query, utils::db::get_recipients, models::candidate_details::EncryptedApplicationDetails, models::{candidate::{ApplicationDetails, CreateCandidateResponse}, candidate_details::EncryptedString, auth::AuthenticableTrait, application::ApplicationResponse}, Mutation, crypto::{hash_password, self}}; +use crate::{error::ServiceError, Query, utils::db::get_recipients, models::candidate_details::EncryptedApplicationDetails, models::{candidate::{ApplicationDetails, CreateCandidateResponse}, candidate_details::{EncryptedString, EncryptedCandidateDetails}, auth::AuthenticableTrait, application::ApplicationResponse}, Mutation, crypto::{hash_password, self}}; -use super::{parent_service::ParentService, candidate_service::CandidateService, session_service::SessionService}; +use super::{parent_service::ParentService, candidate_service::CandidateService, session_service::SessionService, portfolio_service::PortfolioService}; const FIELD_OF_STUDY_PREFIXES: [&str; 3] = ["101", "102", "103"]; @@ -165,7 +166,23 @@ impl ApplicationService { } pub async fn delete(db: &DbConn, application: application::Model) -> Result<(), ServiceError> { + let candidate = ApplicationService::find_related_candidate(db, &application).await?; + + let applications = Query::find_applications_by_candidate_id(db, candidate.id).await?; + if applications.len() <= 1 && + (EncryptedCandidateDetails::from(&candidate).is_filled() || + PortfolioService::get_submission_progress(candidate.id).await?.index() > 1) { + warn!("FAILED TO DELETE APPLICATION {} (CANDIDATE {}) - LOCKED", application.id, candidate.id); + return Err(ServiceError::Forbidden); + } + Mutation::delete_application(db, application).await?; + + let remaining_applications = Query::find_applications_by_candidate_id(db, candidate.id).await?; + if remaining_applications.is_empty() { + CandidateService::delete_candidate(db, candidate).await?; + } + Ok(()) }