mirror of
https://github.com/danbulant/Portfolio
synced 2026-07-06 11:30:44 +00:00
feat: improve error handling
This commit is contained in:
parent
4ab6f16774
commit
497345f2e9
3 changed files with 43 additions and 18 deletions
|
|
@ -2,10 +2,11 @@
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
||||||
use guard::candidate_jwt::TokenRequest;
|
use guard::candidate_jwt::TokenRequest;
|
||||||
|
use portfolio_core::error::ServiceError;
|
||||||
use portfolio_core::services::candidate_service::CandidateService;
|
use portfolio_core::services::candidate_service::CandidateService;
|
||||||
use requests::LoginRequest;
|
use requests::LoginRequest;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::{Rocket, Build};
|
use rocket::{Rocket, Build, custom};
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use rocket::fairing::{self, AdHoc};
|
use rocket::fairing::{self, AdHoc};
|
||||||
use rocket::response::status::Custom;
|
use rocket::response::status::Custom;
|
||||||
|
|
@ -27,6 +28,10 @@ pub use entity::candidate::Entity as Candidate;
|
||||||
use portfolio_core::crypto::random_8_char_string;
|
use portfolio_core::crypto::random_8_char_string;
|
||||||
|
|
||||||
|
|
||||||
|
fn custom_err_from_service_err(err: ServiceError) -> Custom<String> {
|
||||||
|
Custom(Status::InternalServerError, err.1.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
#[post("/", data = "<post_form>")]
|
#[post("/", data = "<post_form>")]
|
||||||
async fn create(conn: Connection<'_, Db>, post_form: Json<candidate::Model>) -> Result<String, Custom<String>> {
|
async fn create(conn: Connection<'_, Db>, post_form: Json<candidate::Model>) -> Result<String, Custom<String>> {
|
||||||
let db = conn.into_inner();
|
let db = conn.into_inner();
|
||||||
|
|
@ -50,10 +55,15 @@ async fn login(conn: Connection<'_, Db>, login_form: Json<LoginRequest>) -> Resu
|
||||||
login_form.application_id,
|
login_form.application_id,
|
||||||
login_form.password.to_owned()).await;
|
login_form.password.to_owned()).await;
|
||||||
|
|
||||||
if jwt.is_some() {
|
if jwt.is_ok() {
|
||||||
return Ok(jwt.unwrap())
|
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")]
|
#[get("/whoami")]
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,14 @@ pub struct Status {
|
||||||
pub code: u16,
|
pub code: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const InvalidCredentialsError: ServiceError<String> = ServiceError(Status { code: 401 },
|
pub const INVALID_CREDENTIALS_ERROR: ServiceError = ServiceError(Status { code: 401 },
|
||||||
"Invalid credentials".to_string());
|
"Invalid credentials");
|
||||||
pub const JwtError: ServiceError<String> = ServiceError(Status { code: 500 },
|
pub const JWT_ERROR: ServiceError = ServiceError(Status { code: 500 },
|
||||||
"Error while encoding JWT".to_string());
|
"Error while encoding JWT");
|
||||||
pub struct ServiceError<R>(pub Status, pub R);
|
|
||||||
|
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);
|
||||||
|
|
@ -1,23 +1,28 @@
|
||||||
use jsonwebtoken::{Header, EncodingKey};
|
use jsonwebtoken::{Header, EncodingKey};
|
||||||
use sea_orm::DatabaseConnection;
|
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;
|
pub struct CandidateService;
|
||||||
|
|
||||||
impl CandidateService {
|
impl CandidateService {
|
||||||
pub async fn login(db: &DatabaseConnection, id: i32, password: String) -> Option<String> {
|
pub async fn login(db: &DatabaseConnection, id: i32, password: String) -> Result<String, ServiceError> {
|
||||||
let candidate = Query::find_candidate_by_id(db, id).await
|
let candidate = match Query::find_candidate_by_id(db, id).await {
|
||||||
.unwrap()
|
Ok(candidate) => match candidate {
|
||||||
.unwrap();
|
Some(candidate) => candidate,
|
||||||
|
None => return Err(USER_NOT_FOUND_ERROR)
|
||||||
|
},
|
||||||
|
Err(_) => {return Err(DB_ERROR)}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
let valid = crypto::verify_password(&password,&candidate.code )
|
let valid = crypto::verify_password(&password,&candidate.code )
|
||||||
.expect("Invalid password");
|
.expect("Invalid password");
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
return None;
|
return Err(INVALID_CREDENTIALS_ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = CandidateToken::generate("candidate.name.unwrap()".to_owned(),
|
let payload = CandidateToken::generate("candidate.name.unwrap()".to_owned(),
|
||||||
"candidate.surname.unwrap()".to_owned());
|
"candidate.surname.unwrap()".to_owned());
|
||||||
|
|
||||||
|
|
@ -26,7 +31,11 @@ impl CandidateService {
|
||||||
&payload,
|
&payload,
|
||||||
&EncodingKey::from_secret(&[0])
|
&EncodingKey::from_secret(&[0])
|
||||||
).ok();
|
).ok();
|
||||||
jwt
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
match jwt {
|
||||||
|
Some(jwt) => Ok(jwt),
|
||||||
|
None => Err(JWT_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue