about summary refs log tree commit diff
path: root/src/micropub/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/micropub/mod.rs')
-rw-r--r--src/micropub/mod.rs173
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(),
     }
 }