From b7015c0b3d79195225f633e58acc27dbb649588f Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 15 Sep 2025 10:37:34 +0200 Subject: [PATCH] Allow filtering guest/non-guest users --- crates/handlers/src/admin/v1/users/list.rs | 14 +++++++++++++ crates/storage-pg/src/user/mod.rs | 4 ++++ crates/storage/src/user/mod.rs | 23 ++++++++++++++++++++++ docs/api/spec.json | 16 +++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/crates/handlers/src/admin/v1/users/list.rs b/crates/handlers/src/admin/v1/users/list.rs index 021e39f37..17b652c82 100644 --- a/crates/handlers/src/admin/v1/users/list.rs +++ b/crates/handlers/src/admin/v1/users/list.rs @@ -54,6 +54,10 @@ pub struct FilterParams { #[serde(rename = "filter[admin]")] admin: Option, + /// Retrieve users with (or without) the `legacy_guest` flag set + #[serde(rename = "filter[legacy-guest]")] + legacy_guest: Option, + /// Retrieve the items with the given status /// /// Defaults to retrieve all users, including locked ones. @@ -75,6 +79,10 @@ impl std::fmt::Display for FilterParams { write!(f, "{sep}filter[admin]={admin}")?; sep = '&'; } + if let Some(legacy_guest) = self.legacy_guest { + write!(f, "{sep}filter[legacy-guest]={legacy_guest}")?; + sep = '&'; + } if let Some(status) = self.status { write!(f, "{sep}filter[status]={status}")?; sep = '&'; @@ -143,6 +151,12 @@ pub async fn handler( None => filter, }; + let filter = match params.legacy_guest { + Some(true) => filter.guest_only(), + Some(false) => filter.non_guest_only(), + None => filter, + }; + let filter = match params.status { Some(UserStatus::Active) => filter.active_only(), Some(UserStatus::Locked) => filter.locked_only(), diff --git a/crates/storage-pg/src/user/mod.rs b/crates/storage-pg/src/user/mod.rs index c88c60d3d..1af09a455 100644 --- a/crates/storage-pg/src/user/mod.rs +++ b/crates/storage-pg/src/user/mod.rs @@ -116,6 +116,10 @@ impl Filter for UserFilter<'_> { .add_option(self.can_request_admin().map(|can_request_admin| { Expr::col((Users::Table, Users::CanRequestAdmin)).eq(can_request_admin) })) + .add_option( + self.is_guest() + .map(|is_guest| Expr::col((Users::Table, Users::IsGuest)).eq(is_guest)), + ) } } diff --git a/crates/storage/src/user/mod.rs b/crates/storage/src/user/mod.rs index 0294d83b4..8a5949e81 100644 --- a/crates/storage/src/user/mod.rs +++ b/crates/storage/src/user/mod.rs @@ -75,6 +75,7 @@ impl UserState { pub struct UserFilter<'a> { state: Option, can_request_admin: Option, + is_guest: Option, _phantom: std::marker::PhantomData<&'a ()>, } @@ -120,6 +121,20 @@ impl UserFilter<'_> { self } + /// Filter for guest users + #[must_use] + pub fn guest_only(mut self) -> Self { + self.is_guest = Some(true); + self + } + + /// Filter for non-guest users + #[must_use] + pub fn non_guest_only(mut self) -> Self { + self.is_guest = Some(false); + self + } + /// Get the state filter /// /// Returns [`None`] if no state filter was set @@ -135,6 +150,14 @@ impl UserFilter<'_> { pub fn can_request_admin(&self) -> Option { self.can_request_admin } + + /// Get the is guest filter + /// + /// Returns [`None`] if no is guest filter was set + #[must_use] + pub fn is_guest(&self) -> Option { + self.is_guest + } } /// A [`UserRepository`] helps interacting with [`User`] saved in the storage diff --git a/docs/api/spec.json b/docs/api/spec.json index 37ad58e05..0e8acdded 100644 --- a/docs/api/spec.json +++ b/docs/api/spec.json @@ -904,6 +904,17 @@ }, "style": "form" }, + { + "in": "query", + "name": "filter[legacy-guest]", + "description": "Retrieve users with (or without) the `legacy_guest` flag set", + "schema": { + "description": "Retrieve users with (or without) the `legacy_guest` flag set", + "type": "boolean", + "nullable": true + }, + "style": "form" + }, { "in": "query", "name": "filter[status]", @@ -3877,6 +3888,11 @@ "type": "boolean", "nullable": true }, + "filter[legacy-guest]": { + "description": "Retrieve users with (or without) the `legacy_guest` flag set", + "type": "boolean", + "nullable": true + }, "filter[status]": { "description": "Retrieve the items with the given status\n\nDefaults to retrieve all users, including locked ones.\n\n* `active`: Only retrieve active users\n\n* `locked`: Only retrieve locked users (includes deactivated users)\n\n* `deactivated`: Only retrieve deactivated users", "$ref": "#/components/schemas/UserStatus",