feat: Enable pagination for the users list route

This commit is contained in:
timedout
2026-05-26 14:30:34 -04:00
committed by Ginger
parent 374a216fc8
commit 61a3749c24
4 changed files with 42 additions and 24 deletions
+3 -3
View File
@@ -1,10 +1,10 @@
use axum::extract::State; use axum::extract::State;
use conduwuit::{info, utils::ReadyExt, warn, Err, Result}; use conduwuit::{Err, Result, info, utils::ReadyExt, warn};
use futures::{FutureExt, StreamExt}; use futures::{FutureExt, StreamExt};
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomAliasId}; use ruma::{OwnedRoomAliasId, events::room::message::RoomMessageEventContent};
use ruminuwuity::admin::continuwuity::rooms; use ruminuwuity::admin::continuwuity::rooms;
use crate::{client::leave_room, Ruma}; use crate::{Ruma, client::leave_room};
/// # `PUT /_continuwuity/admin/v1/rooms/{roomID}/ban` /// # `PUT /_continuwuity/admin/v1/rooms/{roomID}/ban`
/// ///
+12 -6
View File
@@ -1,5 +1,5 @@
use axum::extract::State; use axum::extract::State;
use conduwuit::Err; use conduwuit::{Err, utils::stream::WidebandExt};
use futures::StreamExt; use futures::StreamExt;
use ruminuwuity::admin::continuwuity::users; use ruminuwuity::admin::continuwuity::users;
use tokio::join; use tokio::join;
@@ -19,8 +19,12 @@ pub(crate) async fn list_users_route(
return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
} }
let mut users = Vec::new(); let users = services
while let Some(user_id) = services.users.list_local_users().next().await { .users
.list_local_users()
.skip(body.offset.unwrap_or_default())
.take(body.limit.unwrap_or(100).min(100))
.wide_filter_map(|user_id| async move {
let (deactivated, suspended, locked, admin, login_disabled) = join!( let (deactivated, suspended, locked, admin, login_disabled) = join!(
services.users.is_deactivated(&user_id), services.users.is_deactivated(&user_id),
services.users.is_suspended(&user_id), services.users.is_suspended(&user_id),
@@ -28,15 +32,17 @@ pub(crate) async fn list_users_route(
services.users.is_admin(&user_id), services.users.is_admin(&user_id),
services.users.is_login_disabled(&user_id), services.users.is_login_disabled(&user_id),
); );
users.push(users::list::v1::User { Some(users::list::v1::User {
user_id: user_id.clone(), user_id: user_id.clone(),
deactivated: deactivated.unwrap_or_default(), deactivated: deactivated.unwrap_or_default(),
suspended: suspended.unwrap_or_default(), suspended: suspended.unwrap_or_default(),
locked: locked.unwrap_or_default(), locked: locked.unwrap_or_default(),
admin, admin,
login_disabled, login_disabled,
}); })
} })
.collect()
.await;
Ok(users::list::v1::Response::new(users)) Ok(users::list::v1::Response::new(users))
} }
+1 -1
View File
@@ -284,7 +284,7 @@ pub fn build(router: Router<State>, state: State) -> Router<State> {
router = router router = router
.ruma_route(&admin_api::users::list_users_route) .ruma_route(&admin_api::users::list_users_route)
.ruma_route(&admin_api::rooms::ban_room) .ruma_route(&admin_api::rooms::ban_room)
.ruma_route(&admin_api::rooms::list_rooms) .ruma_route(&admin_api::rooms::list_rooms);
}; };
router router
@@ -7,7 +7,7 @@ pub mod v1 {
use serde::Deserialize; use serde::Deserialize;
metadata! { metadata! {
method: PUT, method: GET,
rate_limited: false, rate_limited: false,
authentication: AccessToken, authentication: AccessToken,
history: { history: {
@@ -30,6 +30,18 @@ pub mod v1 {
#[ruma_api(query)] #[ruma_api(query)]
#[serde(default, skip_serializing_if = "ruma::serde::is_default")] #[serde(default, skip_serializing_if = "ruma::serde::is_default")]
pub include_suspended: bool, pub include_suspended: bool,
/// The maximum number of results to return in this page. Maximum (and
/// default) is 100.
#[ruma_api(query)]
#[serde(default, skip_serializing_if = "ruma::serde::is_default")]
pub limit: Option<usize>,
/// The number of results to skip over before returning results. Default
/// is 0.
#[ruma_api(query)]
#[serde(default, skip_serializing_if = "ruma::serde::is_default")]
pub offset: Option<usize>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, serde::Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Deserialize, serde::Serialize)]