Skip to content

Commit

Permalink
mod: catchers
Browse files Browse the repository at this point in the history
  • Loading branch information
bennjii committed Nov 19, 2023
1 parent 1b47b38 commit 9b8554a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/catchers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::{guards::UserErrorMessage};
use rocket::{serde::json::{json, Value}, Request, catch};
use crate::guards::JsonValidationError;

#[catch(403)]
pub fn not_authorized() -> Value {
json!([{"label": "unauthorized", "message": "Not authorized to make request"}])
}

#[catch(404)]
pub fn not_found() -> Value {
json!([])
}

#[catch(422)]
pub fn unprocessable_entry(req: &Request) -> Value {
json! [{"label": "failed.request", "message": "failed to service request"}]
}

#[catch(500)]
pub fn internal_server_error(req: &Request) -> Value {
let error_message = req
.local_cache(|| Some(UserErrorMessage("Internal server error".to_owned())));

json! [{"label": "internal.error", "message": error_message}]
}
58 changes: 58 additions & 0 deletions src/guards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use rocket::{
data::{self, Data, FromData, Limits},
http::Status,
request::{self, local_cache, FromRequest, Request},
};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Copy, Clone, Debug)]
pub struct RequestId(pub Option<Uuid>);

#[derive(Debug)]
pub struct JsonValidation<T>(pub T);

#[derive(Debug)]
pub enum JsonValidationError {
ParseError(serde_json::Error),
ReadError
}

#[derive(Serialize, Debug)]
pub struct UserErrorMessage(pub String);

/// A Json Data Guard that runs valiation on the deserialized types via
/// the valiation crate. The validation crate requires the derserialized
/// type have the `Validate` trait.
#[rocket::async_trait]
impl<'r, T> FromData<'r> for JsonValidation<T>
where
T: Deserialize<'r>,
{
type Error = JsonValidationError;

async fn from_data(
req: &'r Request<'_>,
data: Data<'r>,
) -> data::Outcome<'r, Self> {
match data.open(Limits::JSON).into_string().await {
Ok(value) => {
let string = local_cache!(req, value.into_inner());

match serde_json::from_str::<T>(string)
.map_err(|e| JsonValidationError::ParseError(e))
{
Ok(e) =>
data::Outcome::Success(JsonValidation(e)),
Err(e) =>
data::Outcome::Failure((Status::InternalServerError, e))
}
}
Err(_) => {
data::Outcome::Failure(
(Status::InternalServerError, JsonValidationError::ReadError)
)
}
}
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub mod methods;
#[cfg(feature = "process")]
pub mod migrator;
pub mod pool;
pub mod catchers;
pub mod guards;

#[cfg(feature = "process")]
pub use self::entities::*;
Expand Down
7 changes: 7 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub use entities::*;
pub use methods::*;
#[cfg(feature = "sql")]
pub use migrator::*;
use open_stock::{catchers, guards};

#[cfg(feature = "sql")]
extern crate argon2;
Expand Down Expand Up @@ -67,6 +68,12 @@ fn rocket() -> _ {

// All non-documented items attached here.
let mut launcher = build()
.register("/", catchers![
catchers::not_authorized,
catchers::internal_server_error,
catchers::not_found,
catchers::unprocessable_entry
])
.attach(Db::init())
.attach(CORS)
.mount(
Expand Down

0 comments on commit 9b8554a

Please sign in to comment.