From 05369b977a2e774bd4d97f66e914ccbb2dd12d92 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Tue, 1 Nov 2022 19:20:49 +0100 Subject: [PATCH] feat: improve error handling return status codes, messages --- api/src/lib.rs | 27 ++++-------- core/src/database/mutation/candidate.rs | 7 +-- core/src/error.rs | 57 +++++++++++++++++++++---- core/src/services/candidate_service.rs | 2 +- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/api/src/lib.rs b/api/src/lib.rs index 89c5775..12acf8b 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -28,10 +28,6 @@ pub use entity::candidate::Entity as Candidate; use portfolio_core::crypto::random_8_char_string; -/* fn custom_err_from_service_err(service_err: ServiceError) -> Custom { - Custom(Status::from_code(service_err.0.code).unwrap_or_default(), service_err.1.to_string()) -} */ - #[post("/", data = "")] async fn create(conn: Connection<'_, Db>, post_form: Json) -> Result> { let db = conn.into_inner(); @@ -39,11 +35,15 @@ async fn create(conn: Connection<'_, Db>, post_form: Json) -> R let plain_text_password = random_8_char_string(); - CandidateService::create(db, form.application_id, &plain_text_password, form.personal_id_number) - .await - .unwrap(); + let candidate = CandidateService::create(db, form.application_id, &plain_text_password, form.personal_id_number) + .await; + + if candidate.is_err() { // TODO cleanup + let e = candidate.err().unwrap(); + return Err(Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())); + } - Ok(plain_text_password) + Ok(plain_text_password) } #[get("/whoami")] @@ -65,16 +65,7 @@ async fn login(conn: Connection<'_, Db>, login_form: Json, ip_addr ) .await; - if session_token.is_ok() { - return Ok( - session_token.ok().unwrap() - ); - } else { - return Err( - // custom_err_from_service_err(session_token.err().unwrap()) - Custom(Status::Unauthorized, "TODO".to_string()) - ) - } + session_token.map_err(|e| Custom(Status::from_code(e.code()).unwrap_or_default(), e.message())) } #[get("/hello")] diff --git a/core/src/database/mutation/candidate.rs b/core/src/database/mutation/candidate.rs index bcde405..f6b80f0 100644 --- a/core/src/database/mutation/candidate.rs +++ b/core/src/database/mutation/candidate.rs @@ -25,9 +25,4 @@ impl Mutation { .insert(db) .await } -} -/* -#[cfg(test)] -mod tests { - #[tokio::fs] -} */ \ No newline at end of file +} \ No newline at end of file diff --git a/core/src/error.rs b/core/src/error.rs index da400ba..0dace48 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -22,7 +22,22 @@ pub const USER_NOT_FOUND_BY_JWT_ID: ServiceError = ServiceError(Status { code: 5 pub const USER_NOT_FOUND_BY_SESSION_ID: ServiceError = ServiceError(Status { code: 500 }, // User got somehow deleted "User not found, please contact technical support"); // Shouldn't ever happen pub struct ServiceError<'a>(pub Status, pub &'a str); */ + +/* pub struct ServiceError { + pub code: u16, + pub message: String, +} + +impl ServiceError { + pub const InvalidCredentials: ServiceError = ServiceError { code: 401, message: "Invalid credentials".to_string() }; + pub const ExpiredSession: ServiceError = ServiceError { code: 401, message: "Session expired, please login again".to_string() }; + pub const JwtError: ServiceError = ServiceError { code: 500, message: "Error while encoding JWT".to_string() }; + pub const UserNotFound: ServiceError = ServiceError { code: 404, message: "User not found".to_string() }; + pub const DbError: ServiceError = ServiceError { code: 500, message: "Database error".to_string() }; + pub const UserNotFoundByJwtId: ServiceError = ServiceError { code: 500, message: "User not found, please contact technical support".to_string() }; + pub const UserNotFoundBySessionId: ServiceError = ServiceError { code: 500, message: "User not found, please contact technical support".to_string() }; +} */ pub enum ServiceError { InvalidCredentials, ExpiredSession, @@ -33,16 +48,40 @@ pub enum ServiceError { UserNotFoundBySessionId, } -impl std::fmt::Debug for ServiceError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl ServiceError { + pub fn code(&self) -> u16 { match self { - ServiceError::InvalidCredentials => write!(f, "Invalid credentials"), - ServiceError::ExpiredSession => write!(f, "Session expired, please login again"), - ServiceError::JwtError => write!(f, "Error while encoding JWT"), - ServiceError::UserNotFound => write!(f, "User not found"), - ServiceError::DbError => write!(f, "Database error"), - ServiceError::UserNotFoundByJwtId => write!(f, "User not found, please contact technical support"), - ServiceError::UserNotFoundBySessionId => write!(f, "User not found, please contact technical support"), + ServiceError::InvalidCredentials => 401, + ServiceError::ExpiredSession => 401, + ServiceError::JwtError => 500, + ServiceError::UserNotFound => 404, + ServiceError::DbError => 500, + ServiceError::UserNotFoundByJwtId => 500, + ServiceError::UserNotFoundBySessionId => 500, } } + + pub fn message(&self) -> String { + match self { + ServiceError::InvalidCredentials => "Invalid credentials".to_string(), + ServiceError::ExpiredSession => "Session expired, please login again".to_string(), + ServiceError::JwtError => "Error while encoding JWT".to_string(), + ServiceError::UserNotFound => "User not found".to_string(), + ServiceError::DbError => "Database error".to_string(), + ServiceError::UserNotFoundByJwtId => "User not found, please contact technical support".to_string(), + ServiceError::UserNotFoundBySessionId => "User not found, please contact technical support".to_string(), + } + } +} + +impl std::fmt::Debug for ServiceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ServiceError {{ code: {}, message: {} }}", self.code(), self.message()) + } +} + +impl std::fmt::Display for ServiceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ServiceError {{ code: {}, message: {} }}", self.code(), self.message()) + } } \ No newline at end of file diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index dc87189..f789418 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -84,7 +84,7 @@ mod tests { let secret_message = "trnka".to_string(); - let candidate = CandidateService::create(&db, 5555555, &plain_text_password, "".to_string()).await.unwrap(); + let candidate = CandidateService::create(&db, 5555555, &plain_text_password, "".to_string()).await.ok().unwrap(); let encrypted_message = crypto::encrypt_password_with_recipients(&secret_message, vec![&candidate.public_key]).await.unwrap();