Skip to content

Commit 1d87349

Browse files
authored
controllers/token: Replace BytesRequest with Json extractor (#9564)
1 parent b5363d9 commit 1d87349

File tree

2 files changed

+24
-26
lines changed

2 files changed

+24
-26
lines changed

src/controllers/token.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::models::ApiToken;
22
use crate::schema::api_tokens;
3-
use crate::util::{rfc3339, BytesRequest};
3+
use crate::util::rfc3339;
44
use crate::views::EncodableApiTokenWithToken;
55

66
use crate::app::AppState;
@@ -18,7 +18,6 @@ use diesel::prelude::*;
1818
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
1919
use http::request::Parts;
2020
use http::StatusCode;
21-
use serde_json as json;
2221
use serde_json::Value;
2322

2423
#[derive(Deserialize)]
@@ -65,33 +64,32 @@ pub async fn list(
6564
.await
6665
}
6766

68-
/// Handles the `PUT /me/tokens` route.
69-
pub async fn new(app: AppState, req: BytesRequest) -> AppResult<Json<Value>> {
70-
let (parts, body) = req.0.into_parts();
67+
/// The incoming serialization format for the `ApiToken` model.
68+
#[derive(Deserialize)]
69+
pub struct NewApiToken {
70+
name: String,
71+
crate_scopes: Option<Vec<String>>,
72+
endpoint_scopes: Option<Vec<String>>,
73+
#[serde(default, with = "rfc3339::option")]
74+
expired_at: Option<NaiveDateTime>,
75+
}
7176

77+
/// The incoming serialization format for the `ApiToken` model.
78+
#[derive(Deserialize)]
79+
pub struct NewApiTokenRequest {
80+
api_token: NewApiToken,
81+
}
82+
83+
/// Handles the `PUT /me/tokens` route.
84+
pub async fn new(
85+
app: AppState,
86+
parts: Parts,
87+
Json(new): Json<NewApiTokenRequest>,
88+
) -> AppResult<Json<Value>> {
7289
let conn = app.db_write().await?;
7390
spawn_blocking(move || {
7491
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
7592

76-
/// The incoming serialization format for the `ApiToken` model.
77-
#[derive(Deserialize)]
78-
struct NewApiToken {
79-
name: String,
80-
crate_scopes: Option<Vec<String>>,
81-
endpoint_scopes: Option<Vec<String>>,
82-
#[serde(default, with = "rfc3339::option")]
83-
expired_at: Option<NaiveDateTime>,
84-
}
85-
86-
/// The incoming serialization format for the `ApiToken` model.
87-
#[derive(Deserialize)]
88-
struct NewApiTokenRequest {
89-
api_token: NewApiToken,
90-
}
91-
92-
let new: NewApiTokenRequest = json::from_slice(&body)
93-
.map_err(|e| bad_request(format!("invalid new token request: {e:?}")))?;
94-
9593
let name = &new.api_token.name;
9694
if name.is_empty() {
9795
return Err(bad_request("name must have a value"));

src/tests/routes/me/tokens/create.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ async fn create_token_invalid_request() {
2323
let (app, _, user) = TestApp::init().with_user();
2424
let invalid: &[u8] = br#"{ "name": "" }"#;
2525
let response = user.put::<()>("/api/v1/me/tokens", invalid).await;
26-
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
27-
assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)"}]}"#);
26+
assert_eq!(response.status(), StatusCode::UNPROCESSABLE_ENTITY);
27+
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"}]}"#);
2828
assert!(app.emails().is_empty());
2929
}
3030

0 commit comments

Comments
 (0)