This commit is contained in:
tsuki 2025-07-29 22:17:40 +08:00
parent d194c0941a
commit 378094744b
3 changed files with 63 additions and 15 deletions

View File

@ -38,12 +38,18 @@ impl QueryRoot {
ctx: &Context<'_>,
offset: Option<i64>,
limit: Option<i64>,
sort_by: Option<String>,
sort_order: Option<String>,
) -> Result<Vec<User>> {
let user_service = ctx.data::<UserService>()?;
info!("users im here");
let offset = offset.unwrap_or(0);
let limit = limit.unwrap_or(20);
user_service.get_all_users(offset, limit).await
let sort_by = sort_by.unwrap_or("created_at".to_string());
let sort_order = sort_order.unwrap_or("desc".to_string());
user_service
.get_all_users(offset, limit, sort_by, sort_order)
.await
}
#[graphql(guard = "RequireRole(Role::User)")]
@ -64,8 +70,21 @@ impl QueryRoot {
}
#[graphql(guard = "RequireRole(Role::Admin)")]
async fn users_info(&self, ctx: &Context<'_>) -> Result<UserInfoRespnose> {
async fn users_info(
&self,
ctx: &Context<'_>,
offset: Option<i64>,
limit: Option<i64>,
) -> Result<UserInfoRespnose> {
let user_service = ctx.data::<UserService>()?;
user_service.users_info().await
let offset = offset.unwrap_or(0);
let limit = limit.unwrap_or(20);
let sort_by = "created_at";
let sort_order = "desc";
user_service
.users_info(offset, limit, sort_by, sort_order)
.await
}
}

View File

@ -67,4 +67,6 @@ pub struct UserInfoRespnose {
pub total_inactive_users: i64,
pub total_admin_users: i64,
pub total_user_users: i64,
pub users: Vec<crate::models::user::User>,
}

View File

@ -177,16 +177,31 @@ impl UserService {
Ok(user)
}
pub async fn get_all_users(&self, offset: i64, limit: i64) -> Result<Vec<User>> {
let users = sqlx::query_as!(
User,
r#"SELECT id, username, email, password_hash, role as "role: Role", invite_code_id, is_activate, created_at, updated_at FROM users LIMIT $1 OFFSET $2"#,
limit,
offset
)
.fetch_all(&self.pool)
.await
.map_err(|e| Error::new(format!("Database error: {}", e)))?;
pub async fn get_all_users(
&self,
offset: i64,
limit: i64,
sort_by: String,
sort_order: String,
) -> Result<Vec<User>> {
// 验证排序字段防止SQL注入
let sort_by = match sort_by.as_str() {
"username" | "email" | "created_at" | "updated_at" | "role" | "is_activate" => sort_by,
_ => "created_at".to_string(), // 默认排序字段
};
let sort_order = if sort_order == "asc" { "ASC" } else { "DESC" };
// 动态构建SQL查询因为列名和排序方向不能参数化
let query = format!(
r#"SELECT id, username, email, password_hash, role as "role: Role", invite_code_id, is_activate, created_at, updated_at FROM users ORDER BY {} {} LIMIT $1 OFFSET $2"#,
sort_by, sort_order
);
let users = sqlx::query_as!(User, &query, limit, offset)
.fetch_all(&self.pool)
.await
.map_err(|e| Error::new(format!("Database error: {}", e)))?;
info!("users: {:?}", users);
@ -281,7 +296,16 @@ impl UserService {
.is_ok())
}
pub async fn users_info(&self) -> Result<UserInfoRespnose> {
pub async fn users_info(
&self,
offset: i64,
limit: i64,
sort_by: impl Into<String>,
sort_order: impl Into<String>,
) -> Result<UserInfoRespnose> {
let sort_by = sort_by.into();
let sort_order = sort_order.into();
let total_users = sqlx::query_scalar!(r#"SELECT COUNT(*) FROM users"#)
.fetch_one(&self.pool)
.await
@ -300,7 +324,7 @@ impl UserService {
.map_err(|e| Error::new(format!("Database error: {}", e)))?;
let total_admin_users =
sqlx::query_scalar!(r#"SELECT COUNT(*) FROM users WHERE role = 'admin'"#)
sqlx::query_scalar!(r#"SELECT COUNT(*) FROM users WHERE role = 'Admin'"#)
.fetch_one(&self.pool)
.await
.map_err(|e| Error::new(format!("Database error: {}", e)))?;
@ -311,12 +335,15 @@ impl UserService {
.await
.map_err(|e| Error::new(format!("Database error: {}", e)))?;
let users = self.get_all_users(offset, limit, sort_by, sort_order).await;
Ok(UserInfoRespnose {
total_users: total_users.unwrap_or(0),
total_active_users: total_active_users.unwrap_or(0),
total_inactive_users: total_inactive_users.unwrap_or(0),
total_admin_users: total_admin_users.unwrap_or(0),
total_user_users: total_user_users.unwrap_or(0),
users: users.unwrap_or_default(),
})
}
}