diff --git a/server/src/auth/login.rs b/server/src/auth/login.rs index 2b32002..77dab39 100644 --- a/server/src/auth/login.rs +++ b/server/src/auth/login.rs @@ -1,29 +1,28 @@ -use axum::{Extension, Json}; +use axum::{extract::rejection::JsonRejection, Extension, Json}; use homedisk_database::{Database, Error, User}; use homedisk_types::{ auth::login::{Request, Response}, config::types::Config, errors::{AuthError, ServerError}, }; -use rust_utilities::crypto::jsonwebtoken::{Claims, Token}; + +use crate::middleware::{create_token, validate_json}; pub async fn handle( db: Extension, config: Extension, - request: Json, + request: Result, JsonRejection>, ) -> Result, ServerError> { + let request = validate_json::(request)?; + let user = User::new(&request.username, &request.password); let response = match db.find_user(&user.username, &user.password).await { Ok(res) => { - let token = Token::new( - config.jwt.secret.as_bytes(), - Claims::new(res.id, config.jwt.expires), - ) - .unwrap(); + let token = create_token(res, config.jwt.secret.as_bytes(), config.jwt.expires)?; Response::LoggedIn { - access_token: token.encoded, + access_token: token, } } diff --git a/server/src/auth/register.rs b/server/src/auth/register.rs index 5970f48..6e73e54 100644 --- a/server/src/auth/register.rs +++ b/server/src/auth/register.rs @@ -1,29 +1,28 @@ -use axum::{Extension, Json}; +use axum::{extract::rejection::JsonRejection, Extension, Json}; use homedisk_database::{Database, User}; use homedisk_types::{ auth::login::{Request, Response}, config::types::Config, errors::{AuthError, ServerError}, }; -use rust_utilities::crypto::jsonwebtoken::{Claims, Token}; + +use crate::middleware::{create_token, validate_json}; pub async fn handle( db: Extension, config: Extension, - request: Json, + request: Result, JsonRejection>, ) -> Result, ServerError> { + let request = validate_json::(request)?; + let user = User::new(&request.username, &request.password); let response = match db.create_user(&user).await { Ok(_) => { - let token = Token::new( - config.jwt.secret.as_bytes(), - Claims::new(user.id, config.jwt.expires), - ) - .unwrap(); + let token = create_token(user, config.jwt.secret.as_bytes(), config.jwt.expires)?; Response::LoggedIn { - access_token: token.encoded, + access_token: token, } } diff --git a/server/src/lib.rs b/server/src/lib.rs index a042dd9..93a5eb1 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,4 +1,5 @@ pub mod auth; +pub mod middleware; mod error; diff --git a/server/src/middleware/auth.rs b/server/src/middleware/auth.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/server/src/middleware/auth.rs @@ -0,0 +1 @@ + diff --git a/server/src/middleware/jwt.rs b/server/src/middleware/jwt.rs new file mode 100644 index 0000000..4711cda --- /dev/null +++ b/server/src/middleware/jwt.rs @@ -0,0 +1,12 @@ +use homedisk_database::User; +use homedisk_types::errors::{AuthError, ServerError}; +use rust_utilities::crypto::jsonwebtoken::{Claims, Token}; + +pub fn create_token(user: User, secret: &[u8], expires: i64) -> Result { + let token = Token::new(secret, Claims::new(user.id, expires)); + + match token { + Ok(token) => Ok(token.encoded), + Err(_) => Err(ServerError::AuthError(AuthError::TokenGenerate)), + } +} diff --git a/server/src/middleware/mod.rs b/server/src/middleware/mod.rs new file mode 100644 index 0000000..f695602 --- /dev/null +++ b/server/src/middleware/mod.rs @@ -0,0 +1,5 @@ +mod auth; +mod jwt; +mod validate_json; + +pub use {auth::*, jwt::*, validate_json::*}; diff --git a/server/src/middleware/validate_json.rs b/server/src/middleware/validate_json.rs new file mode 100644 index 0000000..0a8255d --- /dev/null +++ b/server/src/middleware/validate_json.rs @@ -0,0 +1,15 @@ +use axum::{extract::rejection::JsonRejection, Json}; +use homedisk_types::errors::ServerError; + +pub fn validate_json( + payload: Result, JsonRejection>, +) -> Result, ServerError> { + match payload { + Ok(payload) => Ok(payload), + Err(JsonRejection::MissingJsonContentType(_)) => Err(ServerError::MissingJsonContentType), + Err(JsonRejection::JsonDataError(_)) => Err(ServerError::JsonDataError), + Err(JsonRejection::JsonSyntaxError(_)) => Err(ServerError::JsonSyntaxError), + Err(JsonRejection::BytesRejection(_)) => Err(ServerError::BytesRejection), + Err(err) => Err(ServerError::Other(err.to_string())), + } +} diff --git a/types/src/errors/mod.rs b/types/src/errors/mod.rs index a8b5a91..1a31f2f 100644 --- a/types/src/errors/mod.rs +++ b/types/src/errors/mod.rs @@ -12,6 +12,21 @@ pub enum ServerError { #[error("too may requests, please slow down")] TooManyRequests, + + #[error("missing json content type")] + MissingJsonContentType, + + #[error("error deserialize json")] + JsonDataError, + + #[error("json syntax error")] + JsonSyntaxError, + + #[error("failed to extract the request body")] + BytesRejection, + + #[error("unexcepted error")] + Other(String), } #[cfg(feature = "axum")] @@ -27,6 +42,12 @@ impl axum::response::IntoResponse for ServerError { AuthError::TokenGenerate => StatusCode::INTERNAL_SERVER_ERROR, AuthError::UnknowError(_) => StatusCode::INTERNAL_SERVER_ERROR, }, + + Self::MissingJsonContentType => StatusCode::BAD_REQUEST, + Self::JsonDataError => StatusCode::BAD_REQUEST, + Self::JsonSyntaxError => StatusCode::BAD_REQUEST, + Self::BytesRejection => StatusCode::INTERNAL_SERVER_ERROR, + Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR, }; let mut response = axum::Json(self).into_response();