From 497345f2e9ec8839075ff0bcb633876a77079364 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Tue, 25 Oct 2022 19:34:30 +0200 Subject: [PATCH] feat: improve error handling --- api/src/lib.rs | 18 +++++++++++++---- core/src/error.rs | 16 ++++++++++----- core/src/services/candidate_service.rs | 27 +++++++++++++++++--------- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/api/src/lib.rs b/api/src/lib.rs index 26e2210..004f83a 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -2,10 +2,11 @@ extern crate rocket; use guard::candidate_jwt::TokenRequest; +use portfolio_core::error::ServiceError; use portfolio_core::services::candidate_service::CandidateService; use requests::LoginRequest; use rocket::http::Status; -use rocket::{Rocket, Build}; +use rocket::{Rocket, Build, custom}; use rocket::serde::json::Json; use rocket::fairing::{self, AdHoc}; use rocket::response::status::Custom; @@ -27,6 +28,10 @@ pub use entity::candidate::Entity as Candidate; use portfolio_core::crypto::random_8_char_string; +fn custom_err_from_service_err(err: ServiceError) -> Custom { + Custom(Status::InternalServerError, err.1.to_string()) +} + #[post("/", data = "")] async fn create(conn: Connection<'_, Db>, post_form: Json) -> Result> { let db = conn.into_inner(); @@ -50,10 +55,15 @@ async fn login(conn: Connection<'_, Db>, login_form: Json) -> Resu login_form.application_id, login_form.password.to_owned()).await; - if jwt.is_some() { - return Ok(jwt.unwrap()) + if jwt.is_ok() { + return Ok( + jwt.ok().unwrap() + ); + } else { + return Err( + custom_err_from_service_err(jwt.err().unwrap()) + ) } - Err(Custom(Status::Unauthorized, "Invalid credentials".to_string())) } #[get("/whoami")] diff --git a/core/src/error.rs b/core/src/error.rs index a76d2ec..36cb105 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -2,8 +2,14 @@ pub struct Status { pub code: u16, } -pub const InvalidCredentialsError: ServiceError = ServiceError(Status { code: 401 }, - "Invalid credentials".to_string()); -pub const JwtError: ServiceError = ServiceError(Status { code: 500 }, - "Error while encoding JWT".to_string()); -pub struct ServiceError(pub Status, pub R); \ No newline at end of file +pub const INVALID_CREDENTIALS_ERROR: ServiceError = ServiceError(Status { code: 401 }, + "Invalid credentials"); +pub const JWT_ERROR: ServiceError = ServiceError(Status { code: 500 }, + "Error while encoding JWT"); + +pub const USER_NOT_FOUND_ERROR: ServiceError = ServiceError(Status { code: 404 }, + "User not found"); + +pub const DB_ERROR: ServiceError = ServiceError(Status { code: 500 }, + "Database error"); +pub struct ServiceError<'a>(pub Status, pub &'a str); \ No newline at end of file diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 4ccd003..fb7eda4 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -1,23 +1,28 @@ use jsonwebtoken::{Header, EncodingKey}; use sea_orm::DatabaseConnection; -use crate::{crypto, Query, token::candidate_token::CandidateToken}; +use crate::{crypto, Query, token::candidate_token::CandidateToken, error::{ServiceError, USER_NOT_FOUND_ERROR, INVALID_CREDENTIALS_ERROR, JWT_ERROR, DB_ERROR}}; pub struct CandidateService; impl CandidateService { - pub async fn login(db: &DatabaseConnection, id: i32, password: String) -> Option { - let candidate = Query::find_candidate_by_id(db, id).await - .unwrap() - .unwrap(); + pub async fn login(db: &DatabaseConnection, id: i32, password: String) -> Result { + let candidate = match Query::find_candidate_by_id(db, id).await { + Ok(candidate) => match candidate { + Some(candidate) => candidate, + None => return Err(USER_NOT_FOUND_ERROR) + }, + Err(_) => {return Err(DB_ERROR)} + }; let valid = crypto::verify_password(&password,&candidate.code ) .expect("Invalid password"); if !valid { - return None; + return Err(INVALID_CREDENTIALS_ERROR) } + let payload = CandidateToken::generate("candidate.name.unwrap()".to_owned(), "candidate.surname.unwrap()".to_owned()); @@ -26,7 +31,11 @@ impl CandidateService { &payload, &EncodingKey::from_secret(&[0]) ).ok(); - jwt + + match jwt { + Some(jwt) => Ok(jwt), + None => Err(JWT_ERROR) + } + + } } - -}