From db9d8022663845b9710b013908d7a8d90941d334 Mon Sep 17 00:00:00 2001 From: Fleeym <61891787+Fleeym@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:55:45 +0300 Subject: [PATCH] add /v1/developers index --- src/endpoints/developers.rs | 34 ++++++++++++ src/main.rs | 1 + src/types/models/developer.rs | 96 ++++++++++++++++++++++++++++++++- src/types/models/mod_entity.rs | 2 +- src/types/models/mod_version.rs | 46 +--------------- 5 files changed, 131 insertions(+), 48 deletions(-) diff --git a/src/endpoints/developers.rs b/src/endpoints/developers.rs index 2718a64..18c5ce3 100644 --- a/src/endpoints/developers.rs +++ b/src/endpoints/developers.rs @@ -60,6 +60,40 @@ struct UpdateDeveloperPath { id: i32, } +#[derive(Deserialize)] +struct DeveloperIndexQuery { + query: Option, + page: Option, + per_page: Option, +} + +#[get("v1/developers")] +pub async fn developer_index( + data: web::Data, + query: web::Query, +) -> Result { + let mut pool = data.db.acquire().await.or(Err(ApiError::DbAcquireError))?; + + let mut page = query.page.unwrap_or(1); + if page < 1 { + page = 1 + } + let mut per_page = query.per_page.unwrap_or(15); + if per_page < 1 { + per_page = 1 + } + if per_page > 100 { + per_page = 100 + } + + let result = Developer::get_index(&query.query, page, per_page, &mut pool).await?; + + Ok(web::Json(ApiResponse { + error: "".to_string(), + payload: result, + })) +} + #[post("v1/mods/{id}/developers")] pub async fn add_developer_to_mod( data: web::Data, diff --git a/src/main.rs b/src/main.rs index 28a9644..5ab7b4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,6 +106,7 @@ async fn main() -> anyhow::Result<()> { .service(endpoints::mod_versions::update_version) .service(endpoints::auth::github::poll_github_login) .service(endpoints::auth::github::start_github_login) + .service(endpoints::developers::developer_index) .service(endpoints::developers::add_developer_to_mod) .service(endpoints::developers::remove_dev_from_mod) .service(endpoints::developers::delete_tokens) diff --git a/src/types/models/developer.rs b/src/types/models/developer.rs index 9504b1a..8029e32 100644 --- a/src/types/models/developer.rs +++ b/src/types/models/developer.rs @@ -3,7 +3,7 @@ use std::collections::{hash_map::Entry, HashMap}; use serde::{Deserialize, Serialize}; use sqlx::{PgConnection, Postgres, QueryBuilder}; -use crate::types::api::ApiError; +use crate::types::api::{ApiError, PaginatedData}; #[derive(Deserialize, Serialize, Clone, Debug)] pub struct Developer { @@ -22,7 +22,7 @@ pub struct DeveloperProfile { pub admin: bool, } -#[derive(Clone)] +#[derive(sqlx::FromRow, Clone)] pub struct FetchedDeveloper { pub id: i32, pub username: String, @@ -32,6 +32,98 @@ pub struct FetchedDeveloper { } impl Developer { + pub async fn get_index( + query: &Option, + page: i64, + per_page: i64, + pool: &mut PgConnection, + ) -> Result, ApiError> { + let limit = per_page; + let offset = (page - 1) * per_page; + + let name_query: Option = query.as_ref().map(|q| format!("%{}%", q)); + + let mut builder: QueryBuilder = QueryBuilder::new( + r#" + SELECT + id, + username, + display_name, + verified, + admin + FROM developers + "#, + ); + + let mut counter: QueryBuilder = QueryBuilder::new( + r#" + SELECT COUNT(id) + FROM developers + "#, + ); + + if name_query.is_some() { + let sql = "WHERE username LIKE "; + builder.push(sql); + counter.push(sql); + builder.push_bind(name_query.clone().unwrap()); + counter.push(name_query.clone().unwrap()); + let sql = " OR WHERE display_name LIKE "; + builder.push(sql); + counter.push(sql); + builder.push(name_query.clone().unwrap()); + counter.push(name_query.clone().unwrap()); + } + + builder.push(" GROUP BY id"); + let sql = " LIMIT "; + builder.push(sql); + builder.push_bind(limit); + let sql = " OFFSET "; + builder.push(sql); + builder.push_bind(offset); + + let result = match builder + .build_query_as::() + .fetch_all(&mut *pool) + .await + { + Ok(r) => r, + Err(e) => { + log::error!("{}", e); + return Err(ApiError::DbError); + } + }; + + let result: Vec = result + .into_iter() + .map(|x| DeveloperProfile { + id: x.id, + username: x.username, + display_name: x.display_name, + verified: x.verified, + admin: x.admin, + }) + .collect(); + + let count = match counter + .build_query_scalar() + .fetch_optional(&mut *pool) + .await + { + Ok(Some(c)) => c, + Ok(None) => 0, + Err(e) => { + log::error!("{}", e); + return Err(ApiError::DbError); + } + }; + + Ok(PaginatedData { + data: result, + count, + }) + } pub async fn create( github_id: i64, username: String, diff --git a/src/types/models/mod_entity.rs b/src/types/models/mod_entity.rs index 28029ca..079cd44 100644 --- a/src/types/models/mod_entity.rs +++ b/src/types/models/mod_entity.rs @@ -8,7 +8,7 @@ use crate::{ mod_json::ModJson, models::{ dependency::{Dependency, FetchedDependency}, - incompatibility::{FetchedIncompatibility, Incompatibility, IncompatibilityImportance}, + incompatibility::{FetchedIncompatibility, Incompatibility}, mod_version::ModVersion, mod_version_status::ModVersionStatusEnum, }, }, diff --git a/src/types/models/mod_version.rs b/src/types/models/mod_version.rs index 56e2dcc..8c0ef38 100644 --- a/src/types/models/mod_version.rs +++ b/src/types/models/mod_version.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use chrono::Utc; use serde::Serialize; @@ -691,48 +691,4 @@ impl ModVersion { Ok(()) } - - /** - * @param to_check - map containing HASHSET OF VERSIONS> - * @returns same map structure, with mods that were found and their versions - */ - pub async fn check_if_many_exist( - to_check: HashMap>, - pool: &mut PgConnection, - ) -> Result>, ApiError> { - let mut ret: HashMap> = HashMap::new(); - let mut ids: Vec = vec![]; - let mut versions: Vec = vec![]; - for i in to_check { - ids.push(i.0); - for j in i.1 { - versions.push(j); - } - } - - let r = match sqlx::query!( - r#"SELECT mod_id, version - FROM mod_versions - WHERE mod_id = ANY($1) - AND version = ANY($2)"#, - &ids, - &versions - ) - .fetch_all(&mut *pool) - .await - { - Ok(r) => r, - Err(e) => { - log::error!("Failed to check if mods / versions exist"); - log::error!("{}", e); - return Err(ApiError::DbError); - } - }; - - for i in r { - ret.entry(i.mod_id).or_default().insert(i.version); - } - - Ok(ret) - } }