Skip to content

Commit 39a315a

Browse files
committed
fix(developer): full refactor
1 parent b5597f7 commit 39a315a

File tree

11 files changed

+479
-602
lines changed

11 files changed

+479
-602
lines changed

src/database/repository/developers.rs

+314-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,87 @@
1-
use crate::types::api::ApiError;
2-
use crate::types::models::developer::FetchedDeveloper;
3-
use sqlx::PgConnection;
1+
use crate::types::api::{ApiError, PaginatedData};
2+
use crate::types::models::developer::{ModDeveloper, Developer};
3+
use futures::TryFutureExt;
4+
use sqlx::{PgConnection, Postgres, QueryBuilder};
5+
use std::collections::hash_map::Entry;
6+
use std::collections::HashMap;
7+
8+
pub async fn index(
9+
query: Option<&String>,
10+
page: i64,
11+
per_page: i64,
12+
conn: &mut PgConnection,
13+
) -> Result<PaginatedData<Developer>, ApiError> {
14+
let limit = per_page;
15+
let offset = (page - 1) * per_page;
16+
17+
let display_name_query = query.map(|str| format!("%{}%", str));
18+
19+
let result = sqlx::query_as!(
20+
Developer,
21+
"SELECT
22+
id,
23+
username,
24+
display_name,
25+
verified,
26+
admin
27+
FROM developers
28+
WHERE (
29+
($1 = '' OR username = $1)
30+
OR ($2 = '' OR display_name ILIKE $2)
31+
)
32+
GROUP BY id
33+
LIMIT $3
34+
OFFSET $4",
35+
query,
36+
display_name_query,
37+
limit,
38+
offset
39+
)
40+
.fetch_all(&mut *conn)
41+
.await
42+
.map_err(|e| {
43+
log::error!("Failed to fetch developers: {}", e);
44+
ApiError::DbError
45+
})?;
46+
47+
let count = index_count(query, &mut *conn).await?;
48+
49+
Ok(PaginatedData {
50+
data: result,
51+
count,
52+
})
53+
}
54+
55+
pub async fn index_count(query: Option<&String>, conn: &mut PgConnection) -> Result<i64, ApiError> {
56+
let display_name_query = query.map(|str| format!("%{}%", str));
57+
58+
Ok(sqlx::query!(
59+
"SELECT COUNT(id)
60+
FROM developers
61+
WHERE (
62+
($1 = '' OR username = $1)
63+
OR ($2 = '' OR display_name ILIKE $2)
64+
)",
65+
query,
66+
display_name_query
67+
)
68+
.fetch_one(&mut *conn)
69+
.await
70+
.map_err(|e| {
71+
log::error!("Failed to fetch developer count: {}", e);
72+
ApiError::DbError
73+
})?
74+
.count
75+
.unwrap_or(0))
76+
}
477

578
pub async fn fetch_or_insert_github(
679
github_id: i64,
780
username: &str,
881
conn: &mut PgConnection,
9-
) -> Result<FetchedDeveloper, ApiError> {
82+
) -> Result<Developer, ApiError> {
1083
match sqlx::query_as!(
11-
FetchedDeveloper,
84+
Developer,
1285
"SELECT
1386
id,
1487
username,
@@ -34,9 +107,9 @@ async fn insert_github(
34107
github_id: i64,
35108
username: &str,
36109
conn: &mut PgConnection,
37-
) -> Result<FetchedDeveloper, ApiError> {
110+
) -> Result<Developer, ApiError> {
38111
Ok(sqlx::query_as!(
39-
FetchedDeveloper,
112+
Developer,
40113
"INSERT INTO developers(username, display_name, github_user_id)
41114
VALUES ($1, $1, $2)
42115
RETURNING
@@ -56,12 +129,189 @@ async fn insert_github(
56129
})?)
57130
}
58131

132+
pub async fn get_one(
133+
id: i32,
134+
conn: &mut PgConnection,
135+
) -> Result<Option<Developer>, ApiError> {
136+
Ok(sqlx::query_as!(
137+
Developer,
138+
"SELECT
139+
id,
140+
username,
141+
display_name,
142+
verified,
143+
admin
144+
FROM developers
145+
WHERE id = $1",
146+
id
147+
)
148+
.fetch_optional(&mut *conn)
149+
.await
150+
.map_err(|e| {
151+
log::error!("Failed to fetch developer {}: {}", id, e);
152+
ApiError::DbError
153+
})?)
154+
}
155+
156+
pub async fn get_one_by_username(
157+
username: &str,
158+
conn: &mut PgConnection,
159+
) -> Result<Option<Developer>, ApiError> {
160+
Ok(sqlx::query_as!(
161+
Developer,
162+
"SELECT
163+
id,
164+
username,
165+
display_name,
166+
verified,
167+
admin
168+
FROM developers
169+
WHERE username = $1",
170+
username
171+
)
172+
.fetch_optional(&mut *conn)
173+
.await
174+
.map_err(|e| {
175+
log::error!("Failed to fetch developer {}: {}", username, e);
176+
ApiError::DbError
177+
})?)
178+
}
179+
180+
pub async fn get_all_for_mod(
181+
mod_id: &str,
182+
conn: &mut PgConnection,
183+
) -> Result<Vec<ModDeveloper>, ApiError> {
184+
Ok(sqlx::query_as!(
185+
ModDeveloper,
186+
"SELECT
187+
dev.id,
188+
dev.username,
189+
dev.display_name,
190+
md.is_owner
191+
FROM developers dev
192+
INNER JOIN mods_developers md ON dev.id = md.developer_id
193+
WHERE md.mod_id = $1",
194+
mod_id
195+
)
196+
.fetch_all(conn)
197+
.await
198+
.map_err(|e| {
199+
log::error!("Failed to fetch developers for mod {}: {}", mod_id, e);
200+
ApiError::DbError
201+
})?)
202+
}
203+
204+
pub async fn get_all_for_mods(
205+
mod_ids: &[String],
206+
conn: &mut PgConnection,
207+
) -> Result<HashMap<String, Vec<ModDeveloper>>, ApiError> {
208+
if mod_ids.is_empty() {
209+
return Ok(HashMap::new());
210+
}
211+
#[derive(sqlx::FromRow)]
212+
struct QueryResult {
213+
pub mod_id: String,
214+
pub id: i32,
215+
pub username: String,
216+
pub display_name: String,
217+
pub is_owner: bool,
218+
}
219+
220+
let result = sqlx::query_as!(
221+
QueryResult,
222+
"SELECT
223+
dev.id,
224+
dev.username,
225+
dev.display_name,
226+
md.is_owner,
227+
md.mod_id
228+
FROM developers dev
229+
INNER JOIN mods_developers md ON dev.id = md.developer_id
230+
WHERE md.mod_id = ANY($1)",
231+
mod_ids
232+
)
233+
.fetch_all(conn)
234+
.await
235+
.map_err(|e| {
236+
log::error!("Failed to fetch developers for mods: {}", e);
237+
ApiError::DbError
238+
})?;
239+
240+
let mut ret = HashMap::new();
241+
242+
for result_item in result {
243+
ret.entry(result_item.mod_id)
244+
.or_default()
245+
.push(ModDeveloper {
246+
id: result_item.id,
247+
username: result_item.username,
248+
display_name: result_item.display_name,
249+
is_owner: result_item.is_owner,
250+
});
251+
}
252+
253+
Ok(ret)
254+
}
255+
256+
pub async fn has_access_to_mod(
257+
dev_id: i32,
258+
mod_id: &str,
259+
conn: &mut PgConnection,
260+
) -> Result<bool, ApiError> {
261+
Ok(sqlx::query!(
262+
"SELECT developer_id FROM mods_developers
263+
WHERE developer_id = $1
264+
AND mod_id = $2",
265+
dev_id,
266+
mod_id
267+
)
268+
.fetch_optional(&mut *conn)
269+
.await
270+
.map_err(|e| {
271+
log::error!(
272+
"Failed to find mod {} access for developer {}: {}",
273+
mod_id,
274+
dev_id,
275+
e
276+
);
277+
ApiError::DbError
278+
})?
279+
.is_some())
280+
}
281+
282+
pub async fn owns_mod(
283+
dev_id: i32,
284+
mod_id: &str,
285+
conn: &mut PgConnection,
286+
) -> Result<bool, ApiError> {
287+
Ok(sqlx::query!(
288+
"SELECT developer_id FROM mods_developers
289+
WHERE developer_id = $1
290+
AND mod_id = $2
291+
AND is_owner = true",
292+
dev_id,
293+
mod_id
294+
)
295+
.fetch_optional(&mut *conn)
296+
.await
297+
.map_err(|e| {
298+
log::error!(
299+
"Failed to check mod {} owner for developer {}: {}",
300+
mod_id,
301+
dev_id,
302+
e
303+
);
304+
ApiError::DbError
305+
})?
306+
.is_some())
307+
}
308+
59309
pub async fn get_owner_for_mod(
60310
mod_id: &str,
61311
conn: &mut PgConnection,
62-
) -> Result<FetchedDeveloper, ApiError> {
312+
) -> Result<Developer, ApiError> {
63313
Ok(sqlx::query_as!(
64-
FetchedDeveloper,
314+
Developer,
65315
"SELECT
66316
dev.id,
67317
dev.username,
@@ -87,3 +337,58 @@ pub async fn get_owner_for_mod(
87337
}
88338
})?)
89339
}
340+
341+
pub async fn update_status(
342+
dev_id: i32,
343+
verified: bool,
344+
admin: bool,
345+
conn: &mut PgConnection,
346+
) -> Result<Developer, ApiError> {
347+
Ok(sqlx::query_as!(
348+
Developer,
349+
"UPDATE developers
350+
SET admin = $1,
351+
verified = $2
352+
WHERE id = $3
353+
RETURNING
354+
id,
355+
username,
356+
display_name,
357+
verified,
358+
admin",
359+
admin,
360+
verified,
361+
dev_id
362+
)
363+
.fetch_one(&mut *conn)
364+
.map_err(|e| {
365+
log::error!("Failed to update developer {}: {}", dev_id, e);
366+
ApiError::DbError
367+
})?)
368+
}
369+
370+
pub async fn update_profile(
371+
dev_id: i32,
372+
display_name: &str,
373+
conn: &mut PgConnection,
374+
) -> Result<Developer, ApiError> {
375+
Ok(sqlx::query_as!(
376+
Developer,
377+
"UPDATE developers
378+
SET display_name = $1
379+
WHERE id = $2
380+
RETURNING
381+
id,
382+
username,
383+
display_name,
384+
verified,
385+
admin",
386+
display_name,
387+
dev_id
388+
)
389+
.fetch_one(&mut *conn)
390+
.map_err(|e| {
391+
log::error!("Failed to update profile for {}: {}", dev_id, e);
392+
ApiError::DbError
393+
})?)
394+
}

0 commit comments

Comments
 (0)