Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/controllers/user/other.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use axum::Json;
use axum::extract::Path;
use axum_extra::json;
use axum_extra::response::ErasedJson;
Expand All @@ -12,6 +13,11 @@ use crate::util::errors::AppResult;
use crate::views::EncodablePublicUser;
use crates_io_diesel_helpers::lower;

#[derive(Debug, Serialize, utoipa::ToSchema)]
pub struct GetResponse {
pub user: EncodablePublicUser,
}

/// Find user by login.
#[utoipa::path(
get,
Expand All @@ -20,9 +26,12 @@ use crates_io_diesel_helpers::lower;
("user" = String, Path, description = "Login name of the user"),
),
tag = "users",
responses((status = 200, description = "Successful Response")),
responses((status = 200, description = "Successful Response", body = inline(GetResponse))),
)]
pub async fn find_user(state: AppState, Path(user_name): Path<String>) -> AppResult<ErasedJson> {
pub async fn find_user(
state: AppState,
Path(user_name): Path<String>,
) -> AppResult<Json<GetResponse>> {
let mut conn = state.db_read_prefer_primary().await?;

use crate::schema::users::dsl::{gh_login, id, users};
Expand All @@ -34,7 +43,7 @@ pub async fn find_user(state: AppState, Path(user_name): Path<String>) -> AppRes
.first(&mut conn)
.await?;

Ok(json!({ "user": EncodablePublicUser::from(user) }))
Ok(Json(GetResponse { user: user.into() }))
}

/// Get user stats.
Expand Down
57 changes: 57 additions & 0 deletions src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,48 @@ expression: response.json()
"description"
],
"type": "object"
},
"User": {
"properties": {
"avatar": {
"description": "The user's avatar URL, if set.",
"example": "https://avatars2.githubusercontent.com/u/1234567?v=4",
"type": [
"string",
"null"
]
},
"id": {
"description": "An opaque identifier for the user.",
"example": 42,
"format": "int32",
"type": "integer"
},
"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"
]
},
"url": {
"description": "The user's GitHub profile URL.",
"example": "https://github.com/ghost",
"type": "string"
}
},
"required": [
"id",
"login",
"url"
],
"type": "object"
}
},
"securitySchemes": {
Expand Down Expand Up @@ -2004,6 +2046,21 @@ expression: response.json()
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"user": {
"$ref": "#/components/schemas/User"
}
},
"required": [
"user"
],
"type": "object"
}
}
},
"description": "Successful Response"
}
},
Expand Down
19 changes: 16 additions & 3 deletions src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,14 +522,27 @@ impl EncodablePrivateUser {
}
}

/// The serialization format for the `User` model.
/// Same as private user, except no email field
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)]
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, utoipa::ToSchema)]
#[schema(as = User)]
pub struct EncodablePublicUser {
/// An opaque identifier for the user.
#[schema(example = 42)]
pub id: i32,

/// The user's login name.
#[schema(example = "ghost")]
pub login: String,

/// The user's display name, if set.
#[schema(example = "Kate Morgan")]
pub name: Option<String>,

/// The user's avatar URL, if set.
#[schema(example = "https://avatars2.githubusercontent.com/u/1234567?v=4")]
pub avatar: Option<String>,

/// The user's GitHub profile URL.
#[schema(example = "https://github.com/ghost")]
pub url: String,
}

Expand Down