feat: add user management API with endpoint to retrieve current user information

This commit is contained in:
GW_MC
2025-12-20 12:27:10 +08:00
parent b0b765b8fa
commit e59e7ca4c8
6 changed files with 147 additions and 3 deletions

View File

@@ -2,6 +2,7 @@ pub mod tag {
/// Health tag constant /// Health tag constant
pub const HEALTH_TAG: &str = "Health"; pub const HEALTH_TAG: &str = "Health";
pub const AUTH_TAG: &str = "Authentication"; pub const AUTH_TAG: &str = "Authentication";
pub const USER_TAG: &str = "User";
} }
#[derive(utoipa::OpenApi)] #[derive(utoipa::OpenApi)]
@@ -11,16 +12,21 @@ pub mod tag {
// Authentication paths // Authentication paths
crate::routes::api::auth::login::login, crate::routes::api::auth::login::login,
crate::routes::api::auth::init_admin::init_admin, crate::routes::api::auth::init_admin::init_admin,
// User management paths
crate::routes::api::restricted::user::me::get_user_info,
), ),
components( components(
schemas(crate::routes::api::health::info::HealthInfo), schemas(crate::routes::api::health::info::HealthInfo),
// Authentication schemas // Authentication schemas
schemas(crate::routes::api::auth::login::LoginRequest), schemas(crate::routes::api::auth::login::LoginRequest),
schemas(crate::routes::api::auth::init_admin::AdminInitRequest), schemas(crate::routes::api::auth::init_admin::AdminInitRequest),
// User management schemas
schemas(crate::routes::api::restricted::user::me::UserInfo),
), ),
tags( tags(
(name = tag::HEALTH_TAG, description = "Health information API"), (name = tag::HEALTH_TAG, description = "Health information API"),
(name = tag::AUTH_TAG, description = "Authentication API") (name = tag::AUTH_TAG, description = "Authentication API"),
(name = tag::USER_TAG, description = "User management API")
) )
)] )]
pub struct ApiDoc; pub struct ApiDoc;

View File

@@ -1,3 +1,5 @@
pub mod user;
use std::sync::Arc; use std::sync::Arc;
use axum::Router; use axum::Router;
@@ -6,8 +8,7 @@ use crate::{middlewares::require_auth::require_auth, routes::AppState};
pub fn get_restricted_router(state: Arc<AppState>) -> Router { pub fn get_restricted_router(state: Arc<AppState>) -> Router {
Router::new() Router::new()
// .nest("/user", user::get_user_router(state.clone()))
//
.layer(axum::middleware::from_fn_with_state( .layer(axum::middleware::from_fn_with_state(
state.clone(), state.clone(),
require_auth, require_auth,

View File

@@ -0,0 +1,13 @@
pub mod me;
use std::sync::Arc;
use axum::Router;
use crate::routes::AppState;
pub fn get_user_router(state: Arc<AppState>) -> Router {
Router::new()
.route("/me", axum::routing::get(me::get_user_info))
.with_state(state)
}

View File

@@ -0,0 +1,64 @@
use std::sync::Arc;
use axum::{
Extension, Json,
extract::State,
http::StatusCode,
response::{IntoResponse, Response},
};
use serde::{Deserialize, Serialize};
use tracing::error;
use crate::{
middlewares::request_info::RequestInfo,
routes::{AppState, api::openapi::tag::USER_TAG},
};
/// System health information
#[derive(Serialize, Deserialize, utoipa::ToSchema)]
pub struct UserInfo {
/// User ID
pub id: uuid::Uuid,
/// Username
pub username: String,
}
/// Get current user information
///
/// Returns the information of the currently authenticated user.
#[utoipa::path(
get,
path = "/api/user/me",
responses(
(status = 200, description = "User information retrieved successfully", body = UserInfo),
(status = 401, description = "Unauthorized"),
(status = 500, description = "Internal server error"),
),
tag = USER_TAG,
)]
pub async fn get_user_info(
State(app_state): State<Arc<AppState>>,
request_info: Extension<Arc<RequestInfo>>,
) -> Response {
let user_id = match request_info.user_id {
Some(id) => id,
None => {
error!("User ID not found in request info");
return (StatusCode::UNAUTHORIZED).into_response();
}
};
match app_state.service.user.get_user_by_id(user_id, None).await {
Ok(user) => {
let user_info = UserInfo {
id: user.id,
username: user.username,
};
(StatusCode::OK, Json(user_info)).into_response()
}
Err(err) => {
error!("Error fetching user info: {}", err);
(StatusCode::INTERNAL_SERVER_ERROR).into_response()
}
}
}

View File

@@ -105,6 +105,34 @@
} }
} }
} }
},
"/api/user/me": {
"get": {
"tags": [
"User"
],
"summary": "Get current user information",
"description": "Returns the information of the currently authenticated user.",
"operationId": "get_user_info",
"responses": {
"200": {
"description": "User information retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserInfo"
}
}
}
},
"401": {
"description": "Unauthorized"
},
"500": {
"description": "Internal server error"
}
}
}
} }
}, },
"components": { "components": {
@@ -183,6 +211,25 @@
"type": "string" "type": "string"
} }
} }
},
"UserInfo": {
"type": "object",
"description": "System health information",
"required": [
"id",
"username"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "User ID"
},
"username": {
"type": "string",
"description": "Username"
}
}
} }
} }
}, },
@@ -194,6 +241,10 @@
{ {
"name": "Authentication", "name": "Authentication",
"description": "Authentication API" "description": "Authentication API"
},
{
"name": "User",
"description": "User management API"
} }
] ]
} }

View File

@@ -9,6 +9,7 @@ export namespace Schemas {
version: string; version: string;
}; };
export type LoginRequest = { password: string; username: string }; export type LoginRequest = { password: string; username: string };
export type UserInfo = { id: string; username: string };
// </Schemas> // </Schemas>
} }
@@ -41,6 +42,13 @@ export namespace Endpoints {
parameters: never; parameters: never;
responses: { 200: Schemas.HealthInfo; 404: unknown }; responses: { 200: Schemas.HealthInfo; 404: unknown };
}; };
export type get_Get_user_info = {
method: "GET";
path: "/api/user/me";
requestFormat: "json";
parameters: never;
responses: { 200: Schemas.UserInfo; 401: unknown; 500: unknown };
};
// </Endpoints> // </Endpoints>
} }
@@ -53,6 +61,7 @@ export type EndpointByMethod = {
}; };
get: { get: {
"/api/health/info": Endpoints.get_Get_health_info; "/api/health/info": Endpoints.get_Get_health_info;
"/api/user/me": Endpoints.get_Get_user_info;
}; };
}; };