Skip to content

Commit 3b303f6

Browse files
committed
controllers/crate_owner_invitation: Extract ListQueryParams struct
1 parent 4443a10 commit 3b303f6

File tree

2 files changed

+88
-4
lines changed

2 files changed

+88
-4
lines changed

src/controllers/crate_owner_invitation.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::app::AppState;
22
use crate::auth::AuthCheck;
33
use crate::auth::Authentication;
4-
use crate::controllers::helpers::pagination::{Page, PaginationOptions};
4+
use crate::controllers::helpers::pagination::{Page, PaginationOptions, PaginationQueryParams};
55
use crate::models::{Crate, CrateOwnerInvitation, Rights, User};
66
use crate::schema::{crate_owner_invitations, crates, users};
77
use crate::util::errors::{bad_request, forbidden, internal, AppResult};
@@ -10,7 +10,7 @@ use crate::views::{
1010
EncodableCrateOwnerInvitation, EncodableCrateOwnerInvitationV1, EncodablePublicUser,
1111
InvitationResponse,
1212
};
13-
use axum::extract::Path;
13+
use axum::extract::{FromRequestParts, Path, Query};
1414
use axum::Json;
1515
use axum_extra::json;
1616
use axum_extra::response::ErasedJson;
@@ -70,23 +70,40 @@ pub async fn list_crate_owner_invitations_for_user(
7070
}))
7171
}
7272

73+
#[derive(Debug, Deserialize, FromRequestParts, utoipa::IntoParams)]
74+
#[from_request(via(Query))]
75+
#[into_params(parameter_in = Query)]
76+
pub struct ListQueryParams {
77+
/// Filter crate owner invitations by crate name.
78+
///
79+
/// Only crate owners can query pending invitations for their crate.
80+
crate_name: Option<String>,
81+
82+
/// The ID of the user who was invited to be a crate owner.
83+
///
84+
/// This parameter needs to match the authenticated user's ID.
85+
invitee_id: Option<i32>,
86+
}
87+
7388
/// List all crate owner invitations for a crate or user.
7489
#[utoipa::path(
7590
get,
7691
path = "/api/private/crate_owner_invitations",
92+
params(ListQueryParams, PaginationQueryParams),
7793
tag = "owners",
7894
responses((status = 200, description = "Successful Response")),
7995
)]
8096
pub async fn list_crate_owner_invitations(
8197
app: AppState,
98+
params: ListQueryParams,
8299
req: Parts,
83100
) -> AppResult<Json<PrivateListResponse>> {
84101
let mut conn = app.db_read().await?;
85102
let auth = AuthCheck::only_cookie().check(&req, &mut conn).await?;
86103

87-
let filter = if let Some(crate_name) = req.query().get("crate_name") {
104+
let filter = if let Some(crate_name) = params.crate_name {
88105
ListFilter::CrateName(crate_name.clone())
89-
} else if let Some(id) = req.query().get("invitee_id").and_then(|i| i.parse().ok()) {
106+
} else if let Some(id) = params.invitee_id {
90107
ListFilter::InviteeId(id)
91108
} else {
92109
return Err(bad_request("missing or invalid filter"));

src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,73 @@ snapshot_kind: text
2323
"/api/private/crate_owner_invitations": {
2424
"get": {
2525
"operationId": "list_crate_owner_invitations",
26+
"parameters": [
27+
{
28+
"description": "Filter crate owner invitations by crate name.\n\nOnly crate owners can query pending invitations for their crate.",
29+
"in": "query",
30+
"name": "crate_name",
31+
"required": false,
32+
"schema": {
33+
"type": [
34+
"string",
35+
"null"
36+
]
37+
}
38+
},
39+
{
40+
"description": "The ID of the user who was invited to be a crate owner.\n\nThis parameter needs to match the authenticated user's ID.",
41+
"in": "query",
42+
"name": "invitee_id",
43+
"required": false,
44+
"schema": {
45+
"format": "int32",
46+
"type": [
47+
"integer",
48+
"null"
49+
]
50+
}
51+
},
52+
{
53+
"description": "The page number to request.\n\nThis parameter is mutually exclusive with `seek` and not supported for\nall requests.",
54+
"in": "query",
55+
"name": "page",
56+
"required": false,
57+
"schema": {
58+
"format": "int32",
59+
"minimum": 1,
60+
"type": [
61+
"integer",
62+
"null"
63+
]
64+
}
65+
},
66+
{
67+
"description": "The number of items to request per page.",
68+
"in": "query",
69+
"name": "per_page",
70+
"required": false,
71+
"schema": {
72+
"format": "int32",
73+
"minimum": 1,
74+
"type": [
75+
"integer",
76+
"null"
77+
]
78+
}
79+
},
80+
{
81+
"description": "The seek key to request.\n\nThis parameter is mutually exclusive with `page` and not supported for\nall requests.\n\nThe seek key can usually be found in the `meta.next_page` field of\npaginated responses.",
82+
"in": "query",
83+
"name": "seek",
84+
"required": false,
85+
"schema": {
86+
"type": [
87+
"string",
88+
"null"
89+
]
90+
}
91+
}
92+
],
2693
"responses": {
2794
"200": {
2895
"description": "Successful Response"

0 commit comments

Comments
 (0)