diff --git a/src/controllers/token.rs b/src/controllers/token.rs index 30e5e9c13a4..8bd7f41ea22 100644 --- a/src/controllers/token.rs +++ b/src/controllers/token.rs @@ -1,6 +1,6 @@ use crate::models::ApiToken; use crate::schema::api_tokens; -use crate::util::{rfc3339, BytesRequest}; +use crate::util::rfc3339; use crate::views::EncodableApiTokenWithToken; use crate::app::AppState; @@ -18,7 +18,6 @@ use diesel::prelude::*; use diesel_async::async_connection_wrapper::AsyncConnectionWrapper; use http::request::Parts; use http::StatusCode; -use serde_json as json; use serde_json::Value; #[derive(Deserialize)] @@ -65,33 +64,32 @@ pub async fn list( .await } -/// Handles the `PUT /me/tokens` route. -pub async fn new(app: AppState, req: BytesRequest) -> AppResult> { - let (parts, body) = req.0.into_parts(); +/// The incoming serialization format for the `ApiToken` model. +#[derive(Deserialize)] +pub struct NewApiToken { + name: String, + crate_scopes: Option>, + endpoint_scopes: Option>, + #[serde(default, with = "rfc3339::option")] + expired_at: Option, +} +/// The incoming serialization format for the `ApiToken` model. +#[derive(Deserialize)] +pub struct NewApiTokenRequest { + api_token: NewApiToken, +} + +/// Handles the `PUT /me/tokens` route. +pub async fn new( + app: AppState, + parts: Parts, + Json(new): Json, +) -> AppResult> { let conn = app.db_write().await?; spawn_blocking(move || { let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into(); - /// The incoming serialization format for the `ApiToken` model. - #[derive(Deserialize)] - struct NewApiToken { - name: String, - crate_scopes: Option>, - endpoint_scopes: Option>, - #[serde(default, with = "rfc3339::option")] - expired_at: Option, - } - - /// The incoming serialization format for the `ApiToken` model. - #[derive(Deserialize)] - struct NewApiTokenRequest { - api_token: NewApiToken, - } - - let new: NewApiTokenRequest = json::from_slice(&body) - .map_err(|e| bad_request(format!("invalid new token request: {e:?}")))?; - let name = &new.api_token.name; if name.is_empty() { return Err(bad_request("name must have a value")); diff --git a/src/tests/routes/me/tokens/create.rs b/src/tests/routes/me/tokens/create.rs index 8a5b26514e5..d8aaa51ceda 100644 --- a/src/tests/routes/me/tokens/create.rs +++ b/src/tests/routes/me/tokens/create.rs @@ -23,8 +23,8 @@ async fn create_token_invalid_request() { let (app, _, user) = TestApp::init().with_user(); let invalid: &[u8] = br#"{ "name": "" }"#; let response = user.put::<()>("/api/v1/me/tokens", invalid).await; - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)"}]}"#); + assert_eq!(response.status(), StatusCode::UNPROCESSABLE_ENTITY); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Failed to deserialize the JSON body into the target type: missing field `api_token` at line 1 column 14"}]}"#); assert!(app.emails().is_empty()); }