Skip to content

Commit db9d802

Browse files
committed
add /v1/developers index
1 parent 8b0c7ec commit db9d802

File tree

5 files changed

+131
-48
lines changed

5 files changed

+131
-48
lines changed

src/endpoints/developers.rs

+34
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,40 @@ struct UpdateDeveloperPath {
6060
id: i32,
6161
}
6262

63+
#[derive(Deserialize)]
64+
struct DeveloperIndexQuery {
65+
query: Option<String>,
66+
page: Option<i64>,
67+
per_page: Option<i64>,
68+
}
69+
70+
#[get("v1/developers")]
71+
pub async fn developer_index(
72+
data: web::Data<AppData>,
73+
query: web::Query<DeveloperIndexQuery>,
74+
) -> Result<impl Responder, ApiError> {
75+
let mut pool = data.db.acquire().await.or(Err(ApiError::DbAcquireError))?;
76+
77+
let mut page = query.page.unwrap_or(1);
78+
if page < 1 {
79+
page = 1
80+
}
81+
let mut per_page = query.per_page.unwrap_or(15);
82+
if per_page < 1 {
83+
per_page = 1
84+
}
85+
if per_page > 100 {
86+
per_page = 100
87+
}
88+
89+
let result = Developer::get_index(&query.query, page, per_page, &mut pool).await?;
90+
91+
Ok(web::Json(ApiResponse {
92+
error: "".to_string(),
93+
payload: result,
94+
}))
95+
}
96+
6397
#[post("v1/mods/{id}/developers")]
6498
pub async fn add_developer_to_mod(
6599
data: web::Data<AppData>,

src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ async fn main() -> anyhow::Result<()> {
106106
.service(endpoints::mod_versions::update_version)
107107
.service(endpoints::auth::github::poll_github_login)
108108
.service(endpoints::auth::github::start_github_login)
109+
.service(endpoints::developers::developer_index)
109110
.service(endpoints::developers::add_developer_to_mod)
110111
.service(endpoints::developers::remove_dev_from_mod)
111112
.service(endpoints::developers::delete_tokens)

src/types/models/developer.rs

+94-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::{hash_map::Entry, HashMap};
33
use serde::{Deserialize, Serialize};
44
use sqlx::{PgConnection, Postgres, QueryBuilder};
55

6-
use crate::types::api::ApiError;
6+
use crate::types::api::{ApiError, PaginatedData};
77

88
#[derive(Deserialize, Serialize, Clone, Debug)]
99
pub struct Developer {
@@ -22,7 +22,7 @@ pub struct DeveloperProfile {
2222
pub admin: bool,
2323
}
2424

25-
#[derive(Clone)]
25+
#[derive(sqlx::FromRow, Clone)]
2626
pub struct FetchedDeveloper {
2727
pub id: i32,
2828
pub username: String,
@@ -32,6 +32,98 @@ pub struct FetchedDeveloper {
3232
}
3333

3434
impl Developer {
35+
pub async fn get_index(
36+
query: &Option<String>,
37+
page: i64,
38+
per_page: i64,
39+
pool: &mut PgConnection,
40+
) -> Result<PaginatedData<DeveloperProfile>, ApiError> {
41+
let limit = per_page;
42+
let offset = (page - 1) * per_page;
43+
44+
let name_query: Option<String> = query.as_ref().map(|q| format!("%{}%", q));
45+
46+
let mut builder: QueryBuilder<Postgres> = QueryBuilder::new(
47+
r#"
48+
SELECT
49+
id,
50+
username,
51+
display_name,
52+
verified,
53+
admin
54+
FROM developers
55+
"#,
56+
);
57+
58+
let mut counter: QueryBuilder<Postgres> = QueryBuilder::new(
59+
r#"
60+
SELECT COUNT(id)
61+
FROM developers
62+
"#,
63+
);
64+
65+
if name_query.is_some() {
66+
let sql = "WHERE username LIKE ";
67+
builder.push(sql);
68+
counter.push(sql);
69+
builder.push_bind(name_query.clone().unwrap());
70+
counter.push(name_query.clone().unwrap());
71+
let sql = " OR WHERE display_name LIKE ";
72+
builder.push(sql);
73+
counter.push(sql);
74+
builder.push(name_query.clone().unwrap());
75+
counter.push(name_query.clone().unwrap());
76+
}
77+
78+
builder.push(" GROUP BY id");
79+
let sql = " LIMIT ";
80+
builder.push(sql);
81+
builder.push_bind(limit);
82+
let sql = " OFFSET ";
83+
builder.push(sql);
84+
builder.push_bind(offset);
85+
86+
let result = match builder
87+
.build_query_as::<FetchedDeveloper>()
88+
.fetch_all(&mut *pool)
89+
.await
90+
{
91+
Ok(r) => r,
92+
Err(e) => {
93+
log::error!("{}", e);
94+
return Err(ApiError::DbError);
95+
}
96+
};
97+
98+
let result: Vec<DeveloperProfile> = result
99+
.into_iter()
100+
.map(|x| DeveloperProfile {
101+
id: x.id,
102+
username: x.username,
103+
display_name: x.display_name,
104+
verified: x.verified,
105+
admin: x.admin,
106+
})
107+
.collect();
108+
109+
let count = match counter
110+
.build_query_scalar()
111+
.fetch_optional(&mut *pool)
112+
.await
113+
{
114+
Ok(Some(c)) => c,
115+
Ok(None) => 0,
116+
Err(e) => {
117+
log::error!("{}", e);
118+
return Err(ApiError::DbError);
119+
}
120+
};
121+
122+
Ok(PaginatedData {
123+
data: result,
124+
count,
125+
})
126+
}
35127
pub async fn create(
36128
github_id: i64,
37129
username: String,

src/types/models/mod_entity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
mod_json::ModJson,
99
models::{
1010
dependency::{Dependency, FetchedDependency},
11-
incompatibility::{FetchedIncompatibility, Incompatibility, IncompatibilityImportance},
11+
incompatibility::{FetchedIncompatibility, Incompatibility},
1212
mod_version::ModVersion, mod_version_status::ModVersionStatusEnum,
1313
},
1414
},

src/types/models/mod_version.rs

+1-45
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::collections::HashMap;
22

33
use chrono::Utc;
44
use serde::Serialize;
@@ -691,48 +691,4 @@ impl ModVersion {
691691

692692
Ok(())
693693
}
694-
695-
/**
696-
* @param to_check - map containing <MOD_ID -> HASHSET OF VERSIONS>
697-
* @returns same map structure, with mods that were found and their versions
698-
*/
699-
pub async fn check_if_many_exist(
700-
to_check: HashMap<String, HashSet<String>>,
701-
pool: &mut PgConnection,
702-
) -> Result<HashMap<String, HashSet<String>>, ApiError> {
703-
let mut ret: HashMap<String, HashSet<String>> = HashMap::new();
704-
let mut ids: Vec<String> = vec![];
705-
let mut versions: Vec<String> = vec![];
706-
for i in to_check {
707-
ids.push(i.0);
708-
for j in i.1 {
709-
versions.push(j);
710-
}
711-
}
712-
713-
let r = match sqlx::query!(
714-
r#"SELECT mod_id, version
715-
FROM mod_versions
716-
WHERE mod_id = ANY($1)
717-
AND version = ANY($2)"#,
718-
&ids,
719-
&versions
720-
)
721-
.fetch_all(&mut *pool)
722-
.await
723-
{
724-
Ok(r) => r,
725-
Err(e) => {
726-
log::error!("Failed to check if mods / versions exist");
727-
log::error!("{}", e);
728-
return Err(ApiError::DbError);
729-
}
730-
};
731-
732-
for i in r {
733-
ret.entry(i.mod_id).or_default().insert(i.version);
734-
}
735-
736-
Ok(ret)
737-
}
738694
}

0 commit comments

Comments
 (0)