Return paginated admin users metadata

This commit is contained in:
RWDai
2026-05-20 16:51:46 +08:00
parent 8440846bae
commit 5130da9710
2 changed files with 40 additions and 19 deletions

View File

@@ -37,16 +37,20 @@ pub(in super::super) async fn build_admin_list_users_response(
.map(|value| value.trim().to_string()) .map(|value| value.trim().to_string())
.filter(|value| !value.is_empty()); .filter(|value| !value.is_empty());
let paged_rows = state let query = aether_data::repository::users::UserExportListQuery {
.list_export_users_page(&aether_data::repository::users::UserExportListQuery {
skip, skip,
limit, limit,
role: role.clone(), role: role.clone(),
is_active, is_active,
search, search,
group_id, group_id,
}) };
.await?; let (paged_rows_result, total_result) = tokio::join!(
state.list_export_users_page(&query),
state.count_export_users(&query),
);
let paged_rows = paged_rows_result?;
let total = total_result?;
let user_ids = paged_rows let user_ids = paged_rows
.iter() .iter()
.map(|row| row.id.clone()) .map(|row| row.id.clone())
@@ -116,7 +120,15 @@ pub(in super::super) async fn build_admin_list_users_response(
)); ));
} }
Ok(Json(payload).into_response()) let has_more = (skip as u64).saturating_add(payload.len() as u64) < total;
Ok(Json(json!({
"items": payload,
"total": total,
"skip": skip,
"limit": limit,
"has_more": has_more,
}))
.into_response())
} }
pub(in super::super) async fn build_admin_get_user_response( pub(in super::super) async fn build_admin_get_user_response(

View File

@@ -300,7 +300,11 @@ async fn gateway_handles_admin_users_root_locally_with_trusted_admin_principal()
assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.status(), StatusCode::OK);
let payload: serde_json::Value = response.json().await.expect("json body should parse"); let payload: serde_json::Value = response.json().await.expect("json body should parse");
let items = payload.as_array().expect("list payload should be array"); assert_eq!(payload["total"], 1);
assert_eq!(payload["skip"], 0);
assert_eq!(payload["limit"], 20);
assert_eq!(payload["has_more"], false);
let items = payload["items"].as_array().expect("items should be array");
assert_eq!(items.len(), 1); assert_eq!(items.len(), 1);
assert_eq!(items[0]["id"], "user-1"); assert_eq!(items[0]["id"], "user-1");
assert_eq!(items[0]["email"], "alice@example.com"); assert_eq!(items[0]["email"], "alice@example.com");
@@ -332,9 +336,10 @@ async fn gateway_handles_admin_users_root_locally_with_trusted_admin_principal()
.json() .json()
.await .await
.expect("search json body should parse"); .expect("search json body should parse");
let search_items = search_payload assert_eq!(search_payload["total"], 1);
let search_items = search_payload["items"]
.as_array() .as_array()
.expect("search list payload should be array"); .expect("search items should be array");
assert_eq!(search_items.len(), 1); assert_eq!(search_items.len(), 1);
assert_eq!(search_items[0]["id"], "user-3"); assert_eq!(search_items[0]["id"], "user-3");
assert_eq!(search_items[0]["email"], "carol@example.com"); assert_eq!(search_items[0]["email"], "carol@example.com");
@@ -355,9 +360,10 @@ async fn gateway_handles_admin_users_root_locally_with_trusted_admin_principal()
.json() .json()
.await .await
.expect("id search json body should parse"); .expect("id search json body should parse");
let id_search_items = id_search_payload assert_eq!(id_search_payload["total"], 1);
let id_search_items = id_search_payload["items"]
.as_array() .as_array()
.expect("id search list payload should be array"); .expect("id search items should be array");
assert_eq!(id_search_items.len(), 1); assert_eq!(id_search_items.len(), 1);
assert_eq!(id_search_items[0]["id"], "user-3"); assert_eq!(id_search_items[0]["id"], "user-3");
@@ -377,9 +383,11 @@ async fn gateway_handles_admin_users_root_locally_with_trusted_admin_principal()
.json() .json()
.await .await
.expect("limited search json body should parse"); .expect("limited search json body should parse");
let limited_search_items = limited_search_payload assert_eq!(limited_search_payload["total"], 3);
assert_eq!(limited_search_payload["has_more"], true);
let limited_search_items = limited_search_payload["items"]
.as_array() .as_array()
.expect("limited search list payload should be array"); .expect("limited search items should be array");
assert_eq!(limited_search_items.len(), 2); assert_eq!(limited_search_items.len(), 2);
assert_eq!(*upstream_hits.lock().expect("mutex should lock"), 0); assert_eq!(*upstream_hits.lock().expect("mutex should lock"), 0);
@@ -1057,7 +1065,8 @@ async fn gateway_handles_admin_users_root_locally_with_bearer_admin_session() {
assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.status(), StatusCode::OK);
let payload: serde_json::Value = response.json().await.expect("json body should parse"); let payload: serde_json::Value = response.json().await.expect("json body should parse");
let items = payload.as_array().expect("list payload should be array"); assert_eq!(payload["total"], 1);
let items = payload["items"].as_array().expect("items should be array");
assert_eq!(items.len(), 1); assert_eq!(items.len(), 1);
assert_eq!(items[0]["id"], "user-1"); assert_eq!(items[0]["id"], "user-1");
assert_eq!(items[0]["email"], "alice@example.com"); assert_eq!(items[0]["email"], "alice@example.com");