diff options
Diffstat (limited to 'src/micropub/mod.rs')
-rw-r--r-- | src/micropub/mod.rs | 173 |
1 files changed, 85 insertions, 88 deletions
diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs index 9838e5a..663702f 100644 --- a/src/micropub/mod.rs +++ b/src/micropub/mod.rs @@ -28,13 +28,13 @@ pub struct MicropubQuery { impl From<StorageError> for MicropubError { fn from(err: StorageError) -> Self { - Self { - error: match err.kind() { + Self::new( + match err.kind() { crate::database::ErrorKind::NotFound => ErrorKind::NotFound, _ => ErrorKind::InternalServerError, }, - error_description: format!("Backend error: {}", err), - } + format!("backend error: {}", err) + ) } } @@ -246,11 +246,10 @@ pub(crate) async fn _post<D: 'static + Storage>( // Security check! Do we have an OAuth2 scope to proceed? if !user.check_scope(&Scope::Create) { - return Err(MicropubError { - error: ErrorKind::InvalidScope, - error_description: "Not enough privileges - try acquiring the \"create\" scope." - .to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidScope, + "Not enough privileges - try acquiring the \"create\" scope." + )); } // Security check #2! Are we posting to our own website? @@ -261,18 +260,18 @@ pub(crate) async fn _post<D: 'static + Storage>( .iter() .any(|url| !url.as_str().unwrap().starts_with(user.me.as_str())) { - return Err(MicropubError { - error: ErrorKind::Forbidden, - error_description: "You're posting to a website that's not yours.".to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::Forbidden, + "You're posting to a website that's not yours." + )); } // Security check #3! Are we overwriting an existing document? if db.post_exists(&uid).await? { - return Err(MicropubError { - error: ErrorKind::AlreadyExists, - error_description: "UID clash was detected, operation aborted.".to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::AlreadyExists, + "UID clash was detected, operation aborted." + )); } // Save the post tracing::debug!("Saving post to database..."); @@ -365,20 +364,20 @@ impl MicropubUpdate { if add.iter().map(|(k, _)| k.as_str()).any(|k| { k.to_lowercase().as_str() == "uid" }) { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Update cannot modify the post UID".to_owned() - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Update cannot modify the post UID" + )); } } if let Some(replace) = &self.replace { if replace.iter().map(|(k, v)| k.as_str()).any(|k| { k.to_lowercase().as_str() == "uid" }) { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Update cannot modify the post UID".to_owned() - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Update cannot modify the post UID" + )); } } let iter = match &self.delete { @@ -392,10 +391,10 @@ impl MicropubUpdate { }; if let Some(mut iter) = iter { if iter.any(|k| k.to_lowercase().as_str() == "uid") { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Update cannot modify the post UID".to_owned() - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Update cannot modify the post UID" + )); } } Ok(()) @@ -456,13 +455,12 @@ async fn post_action<D: Storage, A: AuthBackend>( db: D, user: User<A>, ) -> Result<(), MicropubError> { - let uri = if let Ok(uri) = action.url.parse::<hyper::Uri>() { - uri - } else { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Your URL doesn't parse properly.".to_owned(), - }); + let uri = match action.url.parse::<hyper::Uri>() { + Ok(uri) => uri, + Err(err) => return Err(MicropubError::new( + ErrorKind::InvalidRequest, + format!("url parsing error: {}", err) + )) }; if uri.authority().unwrap() @@ -474,38 +472,38 @@ async fn post_action<D: Storage, A: AuthBackend>( .authority() .unwrap() { - return Err(MicropubError { - error: ErrorKind::Forbidden, - error_description: "Don't tamper with others' posts!".to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::Forbidden, + "Don't tamper with others' posts!" + )); } match action.action { ActionType::Delete => { if !user.check_scope(&Scope::Delete) { - return Err(MicropubError { - error: ErrorKind::InvalidScope, - error_description: "You need a \"delete\" scope for this.".to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidScope, + "You need a \"delete\" scope for this." + )); } db.delete_post(&action.url).await? } ActionType::Update => { if !user.check_scope(&Scope::Update) { - return Err(MicropubError { - error: ErrorKind::InvalidScope, - error_description: "You need an \"update\" scope for this.".to_owned(), - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidScope, + "You need an \"update\" scope for this." + )); } let update = if let Some(update) = action.update { update } else { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Update request is not set.".to_owned(), - }) + return Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Update request is not set." + )); }; update.check_validity()?; @@ -546,18 +544,18 @@ async fn dispatch_body( } else if let Ok(body) = serde_json::from_slice::<serde_json::Value>(&body) { // quick sanity check if !body.is_object() || !body["type"].is_array() { - return Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Invalid MF2-JSON detected: `.` should be an object, `.type` should be an array of MF2 types".to_owned() - }); + return Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Invalid MF2-JSON detected: `.` should be an object, `.type` should be an array of MF2 types" + )); } Ok(PostBody::MF2(body)) } else { - Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Invalid JSON object passed.".to_owned(), - }) + Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Invalid JSON object passed." + )) } } else if content_type == ContentType::form_url_encoded() { if let Ok(body) = serde_urlencoded::from_bytes::<MicropubFormAction>(&body) { @@ -565,14 +563,13 @@ async fn dispatch_body( } else if let Ok(body) = serde_urlencoded::from_bytes::<Vec<(String, String)>>(&body) { Ok(PostBody::MF2(form_to_mf2_json(body))) } else { - Err(MicropubError { - error: ErrorKind::InvalidRequest, - error_description: "Invalid form-encoded data. Try h=entry&content=Hello!" - .to_owned(), - }) + Err(MicropubError::from_static( + ErrorKind::InvalidRequest, + "Invalid form-encoded data. Try h=entry&content=Hello!" + )) } } else { - Err(MicropubError::new( + Err(MicropubError::from_static( ErrorKind::UnsupportedMediaType, "This Content-Type is not recognized. Try application/json instead?", )) @@ -616,7 +613,7 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( let query = if let Some(Query(query)) = query { query } else { - return MicropubError::new( + return MicropubError::from_static( ErrorKind::InvalidRequest, "Invalid query provided. Try ?q=config to see what you can do." ).into_response(); @@ -628,7 +625,7 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( .unwrap() != &host { - return MicropubError::new( + return MicropubError::from_static( ErrorKind::NotAuthorized, "This website doesn't belong to you.", ) @@ -644,9 +641,9 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( Err(err) => { return MicropubError::new( ErrorKind::InternalServerError, - &format!("Error fetching channels: {}", err), + format!("Error fetching channels: {}", err), ) - .into_response() + .into_response() } }; @@ -668,36 +665,36 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( map } }) - .into_response() + .into_response() } QueryType::Source => { match query.url { Some(url) => { match db.get_post(&url).await { Ok(some) => match some { - Some(post) => axum::response::Json(&post).into_response(), - None => MicropubError::new( + Some(post) => { + let mut response = axum::response::Json(&post).into_response(); + + response + }, + None => MicropubError::from_static( ErrorKind::NotFound, "The specified MF2 object was not found in database.", ) - .into_response(), + .into_response(), }, - Err(err) => MicropubError::new( - ErrorKind::InternalServerError, - &format!("Backend error: {}", err), - ) - .into_response(), + Err(err) => MicropubError::from(err).into_response(), } } None => { // Here, one should probably attempt to query at least the main feed and collect posts // Using a pre-made query function can't be done because it does unneeded filtering // Don't implement for now, this is optional - MicropubError::new( + MicropubError::from_static( ErrorKind::InvalidRequest, "Querying for post list is not implemented yet.", ) - .into_response() + .into_response() } } } @@ -705,9 +702,9 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( Ok(chans) => axum::response::Json(json!({ "channels": chans })).into_response(), Err(err) => MicropubError::new( ErrorKind::InternalServerError, - &format!("Error fetching channels: {}", err), + format!("error fetching channels: backend error: {}", err), ) - .into_response(), + .into_response(), }, QueryType::SyndicateTo => { axum::response::Json(json!({ "syndicate-to": [] })).into_response() @@ -718,16 +715,16 @@ pub(crate) async fn query<D: Storage, A: AuthBackend>( Err(err) => { return MicropubError::new( ErrorKind::InternalServerError, - &format!("Error fetching categories: {}", err) + format!("error fetching categories: backend error: {}", err) ).into_response() } }; axum::response::Json(json!({ "categories": categories })).into_response() }, - QueryType::Unknown(q) => return MicropubError { - error: ErrorKind::InvalidRequest, - error_description: format!("Invalid query: {}", q) - }.into_response(), + QueryType::Unknown(q) => return MicropubError::new( + ErrorKind::InvalidRequest, + format!("Invalid query: {}", q) + ).into_response(), } } |