diff --git a/src/controllers/crate_owner_invitation.rs b/src/controllers/crate_owner_invitation.rs index abf282cc9d..730485f5b9 100644 --- a/src/controllers/crate_owner_invitation.rs +++ b/src/controllers/crate_owner_invitation.rs @@ -5,7 +5,7 @@ use crate::controllers::helpers::pagination::{Page, PaginationOptions}; use crate::models::{Crate, CrateOwnerInvitation, Rights, User}; use crate::schema::{crate_owner_invitations, crates, users}; use crate::util::errors::{bad_request, forbidden, internal, AppResult}; -use crate::util::{BytesRequest, RequestUtils}; +use crate::util::RequestUtils; use crate::views::{ EncodableCrateOwnerInvitation, EncodableCrateOwnerInvitationV1, EncodablePublicUser, InvitationResponse, @@ -279,7 +279,7 @@ struct ResponseMeta { } #[derive(Deserialize)] -struct OwnerInvitation { +pub struct OwnerInvitation { crate_owner_invite: InvitationResponse, } @@ -295,13 +295,9 @@ struct OwnerInvitation { )] pub async fn handle_crate_owner_invitation( state: AppState, - req: BytesRequest, + parts: Parts, + Json(crate_invite): Json, ) -> AppResult { - let (parts, body) = req.0.into_parts(); - - let crate_invite: OwnerInvitation = - serde_json::from_slice(&body).map_err(|_| bad_request("invalid json request"))?; - let crate_invite = crate_invite.crate_owner_invite; let mut conn = state.db_write().await?; diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index d79aa5a058..8c3caf9fa0 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -16,7 +16,6 @@ use crate::models::krate::CrateName; use crate::models::{CrateOwner, Follow, OwnerKind, User, Version, VersionOwnerAction}; use crate::schema::{crate_owners, crates, emails, follows, users, versions}; use crate::util::errors::{bad_request, AppResult}; -use crate::util::BytesRequest; use crate::views::{EncodableMe, EncodablePrivateUser, EncodableVersion, OwnedCrate}; /// Get the currently authenticated user. @@ -140,6 +139,12 @@ pub async fn confirm_user_email(state: AppState, Path(token): Path) -> A ok_true() } +#[derive(Deserialize)] +pub struct CrateEmailNotifications { + id: i32, + email_notifications: bool, +} + /// Update email notification settings for the authenticated user. /// /// This endpoint was implemented for an experimental feature that was never @@ -151,19 +156,14 @@ pub async fn confirm_user_email(state: AppState, Path(token): Path) -> A responses((status = 200, description = "Successful Response")), )] #[deprecated] -pub async fn update_email_notifications(app: AppState, req: BytesRequest) -> AppResult { +pub async fn update_email_notifications( + app: AppState, + parts: Parts, + Json(updates): Json>, +) -> AppResult { use diesel::pg::upsert::excluded; - let (parts, body) = req.0.into_parts(); - - #[derive(Deserialize)] - struct CrateEmailNotifications { - id: i32, - email_notifications: bool, - } - - let updates: HashMap = serde_json::from_slice::>(&body) - .map_err(|_| bad_request("invalid json request"))? + let updates: HashMap = updates .iter() .map(|c| (c.id, c.email_notifications)) .collect(); diff --git a/src/controllers/util.rs b/src/controllers/util.rs index 0ded2b7d2f..4b47fdd083 100644 --- a/src/controllers/util.rs +++ b/src/controllers/util.rs @@ -1,7 +1,6 @@ use crate::middleware::app::RequestApp; use crate::middleware::log_request::RequestLogExt; use crate::util::errors::{forbidden, AppResult}; -use crate::util::BytesRequest; use http::request::Parts; use http::{header, Extensions, HeaderMap, HeaderValue, Method, Request, Uri, Version}; @@ -73,21 +72,3 @@ impl RequestPartsExt for Request { self.extensions() } } - -impl RequestPartsExt for BytesRequest { - fn method(&self) -> &Method { - self.0.method() - } - fn uri(&self) -> &Uri { - self.0.uri() - } - fn version(&self) -> Version { - self.0.version() - } - fn headers(&self) -> &HeaderMap { - self.0.headers() - } - fn extensions(&self) -> &Extensions { - self.0.extensions() - } -} diff --git a/src/util.rs b/src/util.rs index af559000d2..67a389851f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,6 @@ -pub use self::bytes_request::BytesRequest; pub use self::io_util::{read_fill, read_le_u32}; pub use self::request_helpers::*; -mod bytes_request; pub mod diesel; pub mod errors; mod io_util; diff --git a/src/util/bytes_request.rs b/src/util/bytes_request.rs deleted file mode 100644 index 697bdfe7df..0000000000 --- a/src/util/bytes_request.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::middleware::log_request::ErrorField; -use axum::body::Bytes; -use axum::extract::{FromRequest, Request}; -use axum::response::{IntoResponse, Response}; -use axum::{async_trait, Extension, RequestExt}; -use derive_more::{Deref, DerefMut}; -use http::StatusCode; -use http_body_util::{BodyExt, LengthLimitError}; -use std::error::Error; - -#[derive(Debug, Deref, DerefMut)] -pub struct BytesRequest(pub Request); - -#[async_trait] -impl FromRequest for BytesRequest -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request(req: Request, _state: &S) -> Result { - let req = req.with_limited_body(); - let (parts, body) = req.into_parts(); - - let collected = body.collect().await.map_err(|err| { - let box_error = err.into_inner(); - match box_error.downcast::() { - Ok(_) => StatusCode::PAYLOAD_TOO_LARGE.into_response(), - Err(err) => server_error_response(&*err), - } - })?; - let bytes = collected.to_bytes(); - - let request = Request::from_parts(parts, bytes); - - Ok(BytesRequest(request)) - } -} - -/// Logs an error message and returns a generic status 500 response -fn server_error_response(error: &E) -> Response { - error!(%error, "Internal Server Error"); - - sentry::capture_error(error); - - ( - StatusCode::INTERNAL_SERVER_ERROR, - Extension(ErrorField(error.to_string())), - "Internal Server Error", - ) - .into_response() -} - -#[cfg(test)] -mod tests { - use super::BytesRequest; - use axum::extract::DefaultBodyLimit; - use axum::routing::get; - use axum::Router; - use http::{Request, StatusCode}; - use tower::ServiceExt; - - #[tokio::test] - async fn content_length_too_large() { - const BODY_SIZE_LIMIT: usize = 4096; - - fn app() -> Router { - async fn bytes_request(_req: BytesRequest) {} - - Router::new() - .route("/", get(bytes_request)) - .layer(DefaultBodyLimit::max(BODY_SIZE_LIMIT)) - } - - let body = vec![0; BODY_SIZE_LIMIT + 1]; - let body = axum::body::Body::from(body); - let request = Request::get("/").body(body).unwrap(); - let response = app().oneshot(request).await.unwrap(); - - assert_eq!(response.status(), StatusCode::PAYLOAD_TOO_LARGE); - - let body = vec![0; BODY_SIZE_LIMIT]; - let body = axum::body::Body::from(body); - let request = Request::get("/").body(body).unwrap(); - let response = app().oneshot(request).await.unwrap(); - - assert_eq!(response.status(), StatusCode::OK); - } -}