diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index 7c7775b..0dcb1ce 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -102,6 +102,7 @@ pub async fn post_details( ) -> Result, Custom> { let db = conn.into_inner(); let form = details.into_inner(); + form.candidate.validate_self().map_err(to_custom_error)?; let application: application::Model = session.into(); let candidate = ApplicationService::find_related_candidate(&db, &application).await.map_err(to_custom_error)?; // TODO diff --git a/core/src/error.rs b/core/src/error.rs index ee3ac40..22685ec 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -16,6 +16,8 @@ pub enum ServiceError { ExpiredSession, #[error("Missing details")] MissingDetails, + #[error("Validation error: {0}")] + ValidationError(#[from] validator::ValidationErrors), #[error("User already exists")] UserAlreadyExists, #[error("Candidate not found")] @@ -85,6 +87,7 @@ impl ServiceError { ServiceError::InvalidApplicationId => 400, ServiceError::ParentOverflow => 400, ServiceError::MissingDetails => 400, + ServiceError::ValidationError(_) => 400, ServiceError::Unauthorized => 401, ServiceError::InvalidCredentials => 401, ServiceError::ExpiredSession => 401, diff --git a/core/src/models/candidate.rs b/core/src/models/candidate.rs index 5eb16f8..521cade 100644 --- a/core/src/models/candidate.rs +++ b/core/src/models/candidate.rs @@ -1,6 +1,7 @@ use chrono::NaiveDate; use entity::{application, candidate}; use serde::{Deserialize, Serialize}; +use validator::Validate; use crate::{ error::ServiceError, @@ -57,28 +58,47 @@ pub struct CreateCandidateResponse { pub password: String, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Validate, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct CandidateDetails { + #[validate(length(min = 1, max = 255))] pub name: String, + #[validate(length(min = 1, max = 255))] pub surname: String, + #[validate(length(min = 1, max = 255))] pub birth_surname: String, + #[validate(length(min = 1, max = 255))] pub birthplace: String, pub birthdate: NaiveDate, + #[validate(length(min = 1, max = 255))] pub address: String, pub letter_address: String, + #[validate(length(min = 1, max = 31))] pub telephone: String, + #[validate(length(min = 1, max = 255))] pub citizenship: String, + #[validate(email)] pub email: String, pub sex: String, + #[validate(length(min = 1, max = 255))] pub personal_id_number: String, + #[validate(length(min = 1, max = 255))] pub school_name: String, + #[validate(length(min = 1, max = 255))] pub health_insurance: String, pub grades: GradeList, pub first_school: School, pub second_school: School, pub test_language: String, } +impl CandidateDetails { + pub fn validate_self(&self) -> Result<(), ServiceError> { + self.first_school.validate()?; + self.second_school.validate()?; + self.validate() + .map_err(ServiceError::ValidationError) + } +} #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ParentDetails { diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index e3f95b0..836e903 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -227,7 +227,6 @@ impl EncryptedCandidateDetails { self.personal_id_number.is_some() && self.school_name.is_some() && self.health_insurance.is_some() && - self.grades_json.is_some() && self.first_school.is_some() && self.second_school.is_some() diff --git a/core/src/models/school.rs b/core/src/models/school.rs index 27c18d6..a04b84d 100644 --- a/core/src/models/school.rs +++ b/core/src/models/school.rs @@ -1,8 +1,13 @@ use serde::{Serialize, Deserialize}; +use validator::Validate; -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +use crate::error::ServiceError; + +#[derive(Debug, Clone, Serialize, Deserialize, Validate, PartialEq, Eq)] pub struct School { + #[validate(length(min = 1, max = 255))] name: String, + #[validate(length(min = 1, max = 255))] field: String, } @@ -13,6 +18,11 @@ impl School { ) } + pub fn validate_self(&self) -> Result<(), ServiceError> { + self.validate() + .map_err(ServiceError::ValidationError) + } + pub fn name(&self) -> &str { &self.name }