From fce301080c8c40917e1940ec73016ab6feba5129 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 29 Jun 2025 10:23:30 +0200 Subject: [PATCH] feat(gpodder): add user filter for paginated users method --- gpodder/src/models.rs | 5 ++++ gpodder/src/repository/admin.rs | 8 ++++-- gpodder/src/store.rs | 2 +- gpodder_sqlite/src/repository/auth.rs | 37 +++++++++++++++++++-------- otter/src/server/web/users.rs | 4 ++- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/gpodder/src/models.rs b/gpodder/src/models.rs index fb9339b..c37f97f 100644 --- a/gpodder/src/models.rs +++ b/gpodder/src/models.rs @@ -72,3 +72,8 @@ pub struct Page { pub page: u32, pub per_page: u32, } + +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct UserFilter { + pub username: Option, +} diff --git a/gpodder/src/repository/admin.rs b/gpodder/src/repository/admin.rs index 8a3e845..2123026 100644 --- a/gpodder/src/repository/admin.rs +++ b/gpodder/src/repository/admin.rs @@ -7,7 +7,11 @@ pub struct AdminRepository<'a> { } impl<'a> AdminRepository<'a> { - pub fn paginated_users(&self, page: Page) -> Result, AuthErr> { - self.store.paginated_users(page) + pub fn paginated_users( + &self, + page: Page, + filter: &models::UserFilter, + ) -> Result, AuthErr> { + self.store.paginated_users(page, filter) } } diff --git a/gpodder/src/store.rs b/gpodder/src/store.rs index 1daa3c2..7f32374 100644 --- a/gpodder/src/store.rs +++ b/gpodder/src/store.rs @@ -66,7 +66,7 @@ pub trait GpodderAuthStore { fn remove_old_sessions(&self, min_last_seen: DateTime) -> Result; /// Return the given page of users, ordered by username - fn paginated_users(&self, page: Page) -> Result, AuthErr>; + fn paginated_users(&self, page: Page, filter: &UserFilter) -> Result, AuthErr>; } pub trait GpodderDeviceStore { diff --git a/gpodder_sqlite/src/repository/auth.rs b/gpodder_sqlite/src/repository/auth.rs index ced2606..38af31e 100644 --- a/gpodder_sqlite/src/repository/auth.rs +++ b/gpodder_sqlite/src/repository/auth.rs @@ -143,16 +143,31 @@ impl gpodder::GpodderAuthStore for SqliteRepository { .map_err(AuthErr::from) } - fn paginated_users(&self, page: gpodder::Page) -> Result, AuthErr> { - Ok(users::table - .select(User::as_select()) - .order(users::username.asc()) - .offset((page.page * page.per_page) as i64) - .limit(page.per_page as i64) - .get_results(&mut self.pool.get().map_err(DbError::from)?) - .map_err(DbError::from)? - .into_iter() - .map(gpodder::User::from) - .collect()) + fn paginated_users( + &self, + page: gpodder::Page, + filter: &gpodder::UserFilter, + ) -> Result, AuthErr> { + (|| { + let mut query = users::table + .select(User::as_select()) + .order(users::username.asc()) + .offset((page.page * page.per_page) as i64) + .limit(page.per_page as i64) + .into_boxed(); + + if let Some(username) = &filter.username { + // Case insensitive by default for SQLite + query = query.filter(users::username.like(format!("%{username}%"))); + } + + Ok::<_, DbError>( + query + .load_iter(&mut self.pool.get()?)? + .map(|res| res.map(gpodder::User::from)) + .collect::, _>>()?, + ) + })() + .map_err(AuthErr::from) } } diff --git a/otter/src/server/web/users.rs b/otter/src/server/web/users.rs index f5d3467..560bdd2 100644 --- a/otter/src/server/web/users.rs +++ b/otter/src/server/web/users.rs @@ -31,7 +31,9 @@ pub async fn get_users( let next_page = page.next_page(); let user_id = session.user.id; let users = tokio::task::spawn_blocking(move || { - ctx.store.admin(&session.user)?.paginated_users(page.into()) + ctx.store + .admin(&session.user)? + .paginated_users(page.into(), &gpodder::UserFilter::default()) }) .await .unwrap()?;