Skip to content

Commit 9759a0c

Browse files
committed
feat: [#799] get user profiles endpoint now supports searching
1 parent b6e4adf commit 9759a0c

File tree

5 files changed

+43
-7
lines changed

5 files changed

+43
-7
lines changed

src/databases/database.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,12 @@ pub trait Database: Sync + Send {
144144
async fn get_user_profile_from_username(&self, username: &str) -> Result<UserProfile, Error>;
145145

146146
/// Get all user profiles in a paginated form as `UserProfilesResponse`.
147-
async fn get_user_profiles_paginated(&self, offset: u64, page_size: u8) -> Result<UserProfilesResponse, Error>;
147+
async fn get_user_profiles_search_paginated(
148+
&self,
149+
search: &Option<String>,
150+
offset: u64,
151+
page_size: u8,
152+
) -> Result<UserProfilesResponse, Error>;
148153

149154
/// Get `UserCompact` from `user_id`.
150155
async fn get_user_compact_from_id(&self, user_id: i64) -> Result<UserCompact, Error>;

src/databases/mysql.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,23 @@ impl Database for Mysql {
155155
.map_err(|_| database::Error::UserNotFound)
156156
}
157157

158-
async fn get_user_profiles_paginated(&self, offset: u64, limit: u8) -> Result<UserProfilesResponse, database::Error> {
159-
let mut query_string = "SELECT * FROM torrust_user_profiles".to_string();
158+
async fn get_user_profiles_search_paginated(
159+
&self,
160+
search: &Option<String>,
161+
offset: u64,
162+
limit: u8,
163+
) -> Result<UserProfilesResponse, database::Error> {
164+
let user_name = match search {
165+
None => "%".to_string(),
166+
Some(v) => format!("%{v}%"),
167+
};
168+
169+
let mut query_string = "SELECT * FROM torrust_user_profiles WHERE username LIKE ?".to_string();
160170

161171
let count_query = format!("SELECT COUNT(*) as count FROM ({query_string}) AS count_table");
162172

163173
let count_result: Result<i64, database::Error> = query_as(&count_query)
174+
.bind(user_name.clone())
164175
.fetch_one(&self.pool)
165176
.await
166177
.map(|(v,)| v)
@@ -171,6 +182,7 @@ impl Database for Mysql {
171182
query_string = format!("{query_string} LIMIT ?, ?");
172183

173184
let res: Vec<UserProfile> = sqlx::query_as::<_, UserProfile>(&query_string)
185+
.bind(user_name.clone())
174186
.bind(i64::saturating_add_unsigned(0, offset))
175187
.bind(limit)
176188
.fetch_all(&self.pool)

src/databases/sqlite.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,23 @@ impl Database for Sqlite {
156156
.map_err(|_| database::Error::UserNotFound)
157157
}
158158

159-
async fn get_user_profiles_paginated(&self, offset: u64, limit: u8) -> Result<UserProfilesResponse, database::Error> {
160-
let mut query_string = "SELECT * FROM torrust_user_profiles".to_string();
159+
async fn get_user_profiles_search_paginated(
160+
&self,
161+
search: &Option<String>,
162+
offset: u64,
163+
limit: u8,
164+
) -> Result<UserProfilesResponse, database::Error> {
165+
let user_name = match search {
166+
None => "%".to_string(),
167+
Some(v) => format!("%{v}%"),
168+
};
169+
170+
let mut query_string = "SELECT * FROM torrust_user_profiles WHERE username LIKE ?".to_string();
161171

162172
let count_query = format!("SELECT COUNT(*) as count FROM ({query_string}) AS count_table");
163173

164174
let count_result: Result<i64, database::Error> = query_as(&count_query)
175+
.bind(user_name.clone())
165176
.fetch_one(&self.pool)
166177
.await
167178
.map(|(v,)| v)
@@ -172,6 +183,7 @@ impl Database for Sqlite {
172183
query_string = format!("{query_string} LIMIT ?, ?");
173184

174185
let res: Vec<UserProfile> = sqlx::query_as::<_, UserProfile>(&query_string)
186+
.bind(user_name.clone())
175187
.bind(i64::saturating_add_unsigned(0, offset))
176188
.bind(limit)
177189
.fetch_all(&self.pool)

src/services/authorization.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ impl Default for CasbinConfiguration {
273273
guest, GetTorrentInfo
274274
guest, GenerateTorrentInfoListing
275275
guest, GetCanonicalInfoHash
276+
guest, GenerateUserProfilesListing
276277
",
277278
),
278279
}

src/services/user.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ fn no_email() -> String {
3636
pub struct ListingRequest {
3737
pub page_size: Option<u8>,
3838
pub page: Option<u32>,
39+
pub search: Option<String>,
3940
}
4041

4142
/// Internal specification for user profiles listings.
4243
#[derive(Debug, Deserialize)]
4344
pub struct ListingSpecification {
4445
pub offset: u64,
4546
pub page_size: u8,
47+
pub search: Option<String>,
4648
}
4749

4850
pub struct RegistrationService {
@@ -401,7 +403,11 @@ impl ListingService {
401403

402404
let offset = u64::from(page * u32::from(page_size));
403405

404-
ListingSpecification { offset, page_size }
406+
ListingSpecification {
407+
search: request.search.clone(),
408+
offset,
409+
page_size,
410+
}
405411
}
406412
}
407413

@@ -504,7 +510,7 @@ impl DbUserProfileRepository {
504510
/// It returns an error if there is a database error.
505511
pub async fn generate_listing(&self, specification: &ListingSpecification) -> Result<UserProfilesResponse, Error> {
506512
self.database
507-
.get_user_profiles_paginated(specification.offset, specification.page_size)
513+
.get_user_profiles_search_paginated(&specification.search, specification.offset, specification.page_size)
508514
.await
509515
}
510516
}

0 commit comments

Comments
 (0)