about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2022-07-10 14:52:43 +0300
committerVika <vika@fireburn.ru>2022-07-10 14:52:43 +0300
commit3a7af37527c7752b42d518ec719a479254d6ba96 (patch)
tree5a51a8167d31330bd6af0f82858160a9e2759c6c
parent25183f2ed7802375f15cb0069af7bee6dd2c7afd (diff)
downloadkittybox-3a7af37527c7752b42d518ec719a479254d6ba96.tar.zst
micropub: move MicropubError into kittybox-util
Looks like this shared data structure will be useful to me later when
splitting off the media endpoint into its own crate.
-rw-r--r--kittybox-rs/Cargo.lock3
-rw-r--r--kittybox-rs/src/media/mod.rs16
-rw-r--r--kittybox-rs/src/micropub/mod.rs79
-rw-r--r--kittybox-rs/util/Cargo.toml8
-rw-r--r--kittybox-rs/util/src/error.rs90
-rw-r--r--kittybox-rs/util/src/lib.rs3
6 files changed, 112 insertions, 87 deletions
diff --git a/kittybox-rs/Cargo.lock b/kittybox-rs/Cargo.lock
index 05008ad..0a31753 100644
--- a/kittybox-rs/Cargo.lock
+++ b/kittybox-rs/Cargo.lock
@@ -1560,7 +1560,10 @@ dependencies = [
 name = "kittybox-util"
 version = "0.1.0"
 dependencies = [
+ "axum-core",
+ "http",
  "serde",
+ "serde_json",
 ]
 
 [[package]]
diff --git a/kittybox-rs/src/media/mod.rs b/kittybox-rs/src/media/mod.rs
index e9e91ac..4a253d0 100644
--- a/kittybox-rs/src/media/mod.rs
+++ b/kittybox-rs/src/media/mod.rs
@@ -2,20 +2,13 @@ use axum::{
     extract::{Extension, Host, multipart::{Multipart, MultipartError}, Path},
     response::{IntoResponse, Response}, headers::HeaderValue,
 };
-use crate::{micropub::{MicropubError, ErrorType}, tokenauth::User};
+use kittybox_util::error::{MicropubError, ErrorType};
+use crate::tokenauth::User;
 
 pub mod storage;
 use storage::{MediaStore, MediaStoreError, Metadata, ErrorKind};
 pub use storage::file::FileStore;
 
-impl From<MultipartError> for MicropubError {
-    fn from(err: MultipartError) -> Self {
-        Self {
-            error: ErrorType::InvalidRequest,
-            error_description: format!("multipart/form-data error: {}", err)
-        }
-    }
-}
 impl From<MediaStoreError> for MicropubError {
     fn from(err: MediaStoreError) -> Self {
         Self {
@@ -47,7 +40,10 @@ pub async fn upload<S: MediaStore>(
             }.into_response();
         },
         Err(err) => {
-            return MicropubError::from(err).into_response();
+            return MicropubError {
+                error: ErrorType::InternalServerError,
+                error_description: format!("Error while parsing multipart/form-data: {}", err)
+            }.into_response();
         },
     };
     let metadata: Metadata = (&field).into();
diff --git a/kittybox-rs/src/micropub/mod.rs b/kittybox-rs/src/micropub/mod.rs
index 1fa442a..1d81505 100644
--- a/kittybox-rs/src/micropub/mod.rs
+++ b/kittybox-rs/src/micropub/mod.rs
@@ -11,6 +11,8 @@ use serde_json::json;
 use std::fmt::Display;
 use tracing::{debug, error, info, warn};
 
+use kittybox_util::{MicropubError, ErrorType};
+
 #[derive(Serialize, Deserialize, Debug, PartialEq)]
 #[serde(rename_all = "kebab-case")]
 enum QueryType {
@@ -26,25 +28,6 @@ pub struct MicropubQuery {
     url: Option<String>,
 }
 
-#[derive(Serialize, Deserialize, PartialEq, Debug)]
-#[serde(rename_all = "snake_case")]
-pub(crate) enum ErrorType {
-    AlreadyExists,
-    Forbidden,
-    InternalServerError,
-    InvalidRequest,
-    InvalidScope,
-    NotAuthorized,
-    NotFound,
-    UnsupportedMediaType,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub(crate) struct MicropubError {
-    pub(crate) error: ErrorType,
-    pub(crate) error_description: String,
-}
-
 impl From<StorageError> for MicropubError {
     fn from(err: StorageError) -> Self {
         Self {
@@ -57,64 +40,6 @@ impl From<StorageError> for MicropubError {
     }
 }
 
-impl std::error::Error for MicropubError {}
-
-impl Display for MicropubError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.write_str("Micropub error: ")?;
-        f.write_str(&self.error_description)
-    }
-}
-
-impl From<&MicropubError> for StatusCode {
-    fn from(err: &MicropubError) -> Self {
-        use ErrorType::*;
-        match err.error {
-            AlreadyExists => StatusCode::CONFLICT,
-            Forbidden => StatusCode::FORBIDDEN,
-            InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
-            InvalidRequest => StatusCode::BAD_REQUEST,
-            InvalidScope => StatusCode::UNAUTHORIZED,
-            NotAuthorized => StatusCode::UNAUTHORIZED,
-            NotFound => StatusCode::NOT_FOUND,
-            UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
-        }
-    }
-}
-impl From<MicropubError> for StatusCode {
-    fn from(err: MicropubError) -> Self {
-        (&err).into()
-    }
-}
-
-impl axum::response::IntoResponse for MicropubError {
-    fn into_response(self) -> axum::response::Response {
-        axum::response::IntoResponse::into_response((
-            StatusCode::from(&self),
-            axum::response::Json(self),
-        ))
-    }
-}
-
-impl From<serde_json::Error> for MicropubError {
-    fn from(err: serde_json::Error) -> Self {
-        use ErrorType::*;
-        Self {
-            error: InvalidRequest,
-            error_description: err.to_string(),
-        }
-    }
-}
-
-impl MicropubError {
-    fn new(error: ErrorType, error_description: &str) -> Self {
-        Self {
-            error,
-            error_description: error_description.to_owned(),
-        }
-    }
-}
-
 mod util;
 pub(crate) use util::normalize_mf2;
 
diff --git a/kittybox-rs/util/Cargo.toml b/kittybox-rs/util/Cargo.toml
index 31c6bca..cdad17f 100644
--- a/kittybox-rs/util/Cargo.toml
+++ b/kittybox-rs/util/Cargo.toml
@@ -10,3 +10,11 @@ edition = "2021"
 version = "^1.0.125"
 features = ["derive"]
 
+[dependencies.serde_json]
+version = "^1.0.64"
+
+[dependencies.axum-core]
+version = "^0.2.6"
+
+[dependencies.http]
+version = "^0.2.7"
\ No newline at end of file
diff --git a/kittybox-rs/util/src/error.rs b/kittybox-rs/util/src/error.rs
new file mode 100644
index 0000000..79f43ef
--- /dev/null
+++ b/kittybox-rs/util/src/error.rs
@@ -0,0 +1,90 @@
+use serde::{Deserialize, Serialize};
+use http::StatusCode;
+use axum_core::response::{Response, IntoResponse};
+
+#[derive(Serialize, Deserialize, PartialEq, Debug)]
+#[serde(rename_all = "snake_case")]
+pub enum ErrorType {
+    /// An erroneous attempt to create something that already exists.
+    AlreadyExists,
+    /// Current user is expressly forbidden from performing this action.
+    Forbidden,
+    /// The Micropub server experienced an internal error.
+    InternalServerError,
+    /// The request was invalid or malformed.
+    InvalidRequest,
+    /// The provided OAuth2 scopes were insufficient to allow performing this action.
+    InvalidScope,
+    /// There was no token or other means of authorization in the request.
+    NotAuthorized,
+    /// Whatever was requested was not found.
+    NotFound,
+    /// The request payload was of a type unsupported by the Micropub endpoint.
+    UnsupportedMediaType,
+}
+
+/// Representation of the Micropub API error.
+#[derive(Serialize, Deserialize, Debug)]
+pub struct MicropubError {
+    pub error: ErrorType,
+    pub error_description: String,
+}
+
+impl std::error::Error for MicropubError {}
+
+impl std::fmt::Display for MicropubError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str("Micropub error: ")?;
+        f.write_str(&self.error_description)
+    }
+}
+
+impl From<serde_json::Error> for MicropubError {
+    fn from(err: serde_json::Error) -> Self {
+        use ErrorType::*;
+        Self {
+            error: InvalidRequest,
+            error_description: err.to_string(),
+        }
+    }
+}
+
+impl MicropubError {
+    pub fn new(error: ErrorType, error_description: &str) -> Self {
+        Self {
+            error,
+            error_description: error_description.to_owned(),
+        }
+    }
+}
+
+impl From<&MicropubError> for StatusCode {
+    fn from(err: &MicropubError) -> Self {
+        use ErrorType::*;
+        match err.error {
+            AlreadyExists => StatusCode::CONFLICT,
+            Forbidden => StatusCode::FORBIDDEN,
+            InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
+            InvalidRequest => StatusCode::BAD_REQUEST,
+            InvalidScope => StatusCode::UNAUTHORIZED,
+            NotAuthorized => StatusCode::UNAUTHORIZED,
+            NotFound => StatusCode::NOT_FOUND,
+            UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
+        }
+    }
+}
+impl From<MicropubError> for StatusCode {
+    fn from(err: MicropubError) -> Self {
+        (&err).into()
+    }
+}
+
+impl IntoResponse for MicropubError {
+    fn into_response(self) -> Response {
+        IntoResponse::into_response((
+            StatusCode::from(&self),
+            [("Content-Type", "application/json")],
+            serde_json::to_string(&self).unwrap(),
+        ))
+    }
+}
diff --git a/kittybox-rs/util/src/lib.rs b/kittybox-rs/util/src/lib.rs
index bc41689..debe589 100644
--- a/kittybox-rs/util/src/lib.rs
+++ b/kittybox-rs/util/src/lib.rs
@@ -16,3 +16,6 @@ pub struct MicropubChannel {
     /// The channel's user-friendly name used to recognize it in lists.
     pub name: String,
 }
+
+pub mod error;
+pub use error::{ErrorType, MicropubError};