diff --git a/src/controllers/user/me.rs b/src/controllers/user/me.rs index 44da94f7f3a..2f59fc19a6a 100644 --- a/src/controllers/user/me.rs +++ b/src/controllers/user/me.rs @@ -21,7 +21,7 @@ use crate::views::{EncodableMe, EncodablePrivateUser, EncodableVersion, OwnedCra path = "/api/v1/me", security(("cookie" = [])), tag = "users", - responses((status = 200, description = "Successful Response")), + responses((status = 200, description = "Successful Response", body = inline(EncodableMe))), )] pub async fn get_authenticated_user(app: AppState, req: Parts) -> AppResult> { let mut conn = app.db_read_prefer_primary().await?; diff --git a/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap b/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap index 08a2e4adf30..58c01233c79 100644 --- a/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap +++ b/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap @@ -5,6 +5,82 @@ expression: response.json() { "components": { "schemas": { + "AuthenticatedUser": { + "properties": { + "avatar": { + "description": "The user's avatar URL, if set.", + "example": "https://avatars2.githubusercontent.com/u/1234567?v=4", + "type": [ + "string", + "null" + ] + }, + "email": { + "description": "The user's email address, if set.", + "example": "kate@morgan.dev", + "type": [ + "string", + "null" + ] + }, + "email_verification_sent": { + "description": "Whether the user's email address verification email has been sent.", + "example": true, + "type": "boolean" + }, + "email_verified": { + "description": "Whether the user's email address has been verified.", + "example": true, + "type": "boolean" + }, + "id": { + "description": "An opaque identifier for the user.", + "example": 42, + "format": "int32", + "type": "integer" + }, + "is_admin": { + "description": "Whether the user is a crates.io administrator.", + "example": false, + "type": "boolean" + }, + "login": { + "description": "The user's login name.", + "example": "ghost", + "type": "string" + }, + "name": { + "description": "The user's display name, if set.", + "example": "Kate Morgan", + "type": [ + "string", + "null" + ] + }, + "publish_notifications": { + "description": "Whether the user has opted in to receive publish notifications via email.", + "example": true, + "type": "boolean" + }, + "url": { + "description": "The user's GitHub profile URL.", + "example": "https://github.com/ghost", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "login", + "email_verified", + "email_verification_sent", + "is_admin", + "publish_notifications" + ], + "type": "object" + }, "Category": { "properties": { "category": { @@ -1879,6 +1955,52 @@ expression: response.json() "operationId": "get_authenticated_user", "responses": { "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "owned_crates": { + "description": "The crates that the authenticated user owns.", + "items": { + "properties": { + "email_notifications": { + "deprecated": true, + "type": "boolean" + }, + "id": { + "description": "The opaque identifier of the crate.", + "example": 123, + "format": "int32", + "type": "integer" + }, + "name": { + "description": "The name of the crate.", + "example": "serde", + "type": "string" + } + }, + "required": [ + "id", + "name", + "email_notifications" + ], + "type": "object" + }, + "type": "array" + }, + "user": { + "$ref": "#/components/schemas/AuthenticatedUser", + "description": "The authenticated user." + } + }, + "required": [ + "user", + "owned_crates" + ], + "type": "object" + } + } + }, "description": "Successful Response" } }, diff --git a/src/views.rs b/src/views.rs index d98be88fe52..fd81967622d 100644 --- a/src/views.rs +++ b/src/views.rs @@ -485,33 +485,71 @@ pub struct EncodableApiTokenWithToken { pub plaintext: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, utoipa::ToSchema)] pub struct OwnedCrate { + /// The opaque identifier of the crate. + #[schema(example = 123)] pub id: i32, + + /// The name of the crate. + #[schema(example = "serde")] pub name: String, + + #[schema(deprecated)] pub email_notifications: bool, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, utoipa::ToSchema)] pub struct EncodableMe { + /// The authenticated user. pub user: EncodablePrivateUser, + + /// The crates that the authenticated user owns. + #[schema(inline)] pub owned_crates: Vec, } -/// The serialization format for the `User` model. -/// Same as public user, except for addition of -/// email field -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, utoipa::ToSchema)] +#[schema(as = AuthenticatedUser)] pub struct EncodablePrivateUser { + /// An opaque identifier for the user. + #[schema(example = 42)] pub id: i32, + + /// The user's login name. + #[schema(example = "ghost")] pub login: String, + + /// Whether the user's email address has been verified. + #[schema(example = true)] pub email_verified: bool, + + /// Whether the user's email address verification email has been sent. + #[schema(example = true)] pub email_verification_sent: bool, + + /// The user's display name, if set. + #[schema(example = "Kate Morgan")] pub name: Option, + + /// The user's email address, if set. + #[schema(example = "kate@morgan.dev")] pub email: Option, + + /// The user's avatar URL, if set. + #[schema(example = "https://avatars2.githubusercontent.com/u/1234567?v=4")] pub avatar: Option, + + /// The user's GitHub profile URL. + #[schema(example = "https://github.com/ghost")] pub url: Option, + + /// Whether the user is a crates.io administrator. + #[schema(example = false)] pub is_admin: bool, + + /// Whether the user has opted in to receive publish notifications via email. + #[schema(example = true)] pub publish_notifications: bool, }