Skip to content

Commit

Permalink
impl get many for loader version
Browse files Browse the repository at this point in the history
  • Loading branch information
qimiko committed Nov 23, 2024
1 parent 7e03d11 commit f9c89ae
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 16 deletions.
68 changes: 56 additions & 12 deletions src/endpoints/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ use crate::{
api::{ApiError, ApiResponse},
models::{
gd_version_alias::GDVersionAlias,
loader_version::{LoaderVersion, LoaderVersionCreate},
loader_version::{
LoaderVersion,
LoaderVersionCreate,
LoaderGDVersion,
GetVersionsQuery
},
mod_gd_version::{GDVersionEnum, VerPlatform}
}
},
Expand All @@ -19,7 +24,7 @@ use crate::{

#[derive(Deserialize)]
struct GetOneQuery {
platform: Option<String>,
platform: Option<VerPlatform>,
gd: Option<String>,
#[serde(default)]
prerelease: bool,
Expand All @@ -39,25 +44,19 @@ pub async fn get_one(
let mut pool = data.db.acquire().await.or(Err(ApiError::DbAcquireError))?;

let version = if path.version == "latest" {
let platform = query.platform.as_ref()
.map(|s| VerPlatform::from_str(s))
.transpose()
.map_err(|_| ApiError::BadRequest("Invalid platform".to_string()))?;


let gd = if let Some(i) = &query.gd {
if let Ok(g) = GDVersionEnum::from_str(i) {
Some(g)
} else {
let platform = platform
let platform = query.platform
.ok_or_else(|| ApiError::BadRequest("Platform is required when a version alias is given".to_string()))?;
Some(GDVersionAlias::find(platform, i, &mut pool).await?)
}
} else {
None
};

LoaderVersion::get_latest(gd, platform, query.prerelease, &mut pool).await?
LoaderVersion::get_latest(gd, query.platform, query.prerelease, &mut pool).await?
} else {
LoaderVersion::get_one(&path.version, &mut pool).await?
};
Expand All @@ -68,10 +67,18 @@ pub async fn get_one(
}))
}

#[derive(Deserialize)]
struct CreateVersionBody {
pub tag: String,
pub gd: LoaderGDVersion,
#[serde(default)]
pub prerelease: bool
}

#[post("v1/loader/versions")]
pub async fn create_version(
data: web::Data<AppData>,
payload: web::Json<LoaderVersionCreate>,
payload: web::Json<CreateVersionBody>,
auth: Auth,
) -> Result<impl Responder, ApiError> {
let dev = auth.developer()?;
Expand All @@ -82,7 +89,11 @@ pub async fn create_version(
}

let mut transaction = pool.begin().await.or(Err(ApiError::TransactionError))?;
if let Err(e) = LoaderVersion::create_version(payload.into_inner(), &mut transaction).await {
if let Err(e) = LoaderVersion::create_version(LoaderVersionCreate {
tag: payload.tag.clone(),
gd: payload.gd.clone(),
prerelease: payload.prerelease
}, &mut transaction).await {
transaction
.rollback()
.await
Expand All @@ -97,3 +108,36 @@ pub async fn create_version(

Ok(HttpResponse::NoContent())
}

#[derive(Deserialize)]
struct GetManyQuery {
pub gd: Option<GDVersionEnum>,
pub platform: Option<VerPlatform>,
pub per_page: Option<i64>,
pub page: Option<i64>,
pub prerelease: Option<bool>
}

#[get("v1/loader/versions")]
pub async fn get_many(
data: web::Data<AppData>,
query: web::Query<GetManyQuery>,
) -> Result<impl Responder, ApiError> {
let mut pool = data.db.acquire().await.or(Err(ApiError::DbAcquireError))?;

let versions = LoaderVersion::get_many(
GetVersionsQuery {
gd: query.gd,
platform: query.platform,
prerelease: query.prerelease.unwrap_or(true)
},
query.per_page.unwrap_or(10),
query.page.unwrap_or(1),
&mut pool
).await?;

Ok(web::Json(ApiResponse {
error: "".to_string(),
payload: versions,
}))
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ async fn main() -> anyhow::Result<()> {
.service(endpoints::stats::get_stats)
.service(endpoints::loader::get_one)
.service(endpoints::loader::create_version)
.service(endpoints::loader::get_many)
.service(health)
})
.bind((addr, port))?;
Expand Down
84 changes: 80 additions & 4 deletions src/types/models/loader_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ use chrono::SecondsFormat;
use serde::{Deserialize, Serialize};

use sqlx::{
types::chrono::{DateTime, Utc}, PgConnection, Postgres, QueryBuilder
types::chrono::{DateTime, Utc},
PgConnection, Postgres, QueryBuilder
};

#[derive(sqlx::FromRow, Deserialize, Serialize, Debug)]
#[derive(sqlx::FromRow, Deserialize, Serialize, Debug, Clone)]
pub struct LoaderGDVersion {
pub win: Option<GDVersionEnum>,
pub android: Option<GDVersionEnum>,
pub mac: Option<GDVersionEnum>,
}

#[derive(Deserialize, Debug)]
#[derive(Debug)]
pub struct LoaderVersionCreate {
pub tag: String,
pub gd: LoaderGDVersion,
#[serde(default)]
pub prerelease: bool
}

Expand All @@ -42,6 +42,12 @@ pub struct LoaderVersionGetOne {
pub created_at: DateTime<Utc>
}

pub struct GetVersionsQuery {
pub gd: Option<GDVersionEnum>,
pub platform: Option<VerPlatform>,
pub prerelease: bool
}

impl LoaderVersionGetOne {
pub fn into_loader_version(self) -> LoaderVersion {
LoaderVersion {
Expand Down Expand Up @@ -175,4 +181,74 @@ impl LoaderVersion {
}
}
}

pub async fn get_many(
query: GetVersionsQuery,
per_page: i64,
page: i64,
pool: &mut PgConnection
) -> Result<Vec<LoaderVersion>, ApiError> {
let limit = per_page;
let offset = (page - 1) * per_page;

let mut query_builder = QueryBuilder::new(r#"
SELECT mac, win, android, tag, created_at, prerelease FROM geode_versions
"#);

match (query.platform, query.gd) {
(Some(p), Some(g)) => {
match p {
VerPlatform::Android | VerPlatform::Android32 | VerPlatform::Android64 => query_builder.push(" WHERE android="),
VerPlatform::Mac | VerPlatform::MacIntel | VerPlatform::MacArm => query_builder.push(" WHERE mac="),
VerPlatform::Win => query_builder.push(" WHERE win="),
_ => return Err(ApiError::BadRequest("Invalid platform".to_string())),
};

query_builder.push_bind(g);
}
(Some(p), None) => {
match p {
VerPlatform::Android | VerPlatform::Android32 | VerPlatform::Android64 => query_builder.push(" WHERE android IS NOT NULL"),
VerPlatform::Mac | VerPlatform::MacIntel | VerPlatform::MacArm => query_builder.push(" WHERE mac IS NOT NULL"),
VerPlatform::Win => query_builder.push(" WHERE win IS NOT NULL"),
_ => return Err(ApiError::BadRequest("Invalid platform".to_string())),
};
}
(None, Some(g)) => {
query_builder.push(" WHERE android=");
query_builder.push_bind(g);
query_builder.push(" or mac=");
query_builder.push_bind(g);
query_builder.push(" or win=");
query_builder.push_bind(g);
}
_ => {
query_builder.push(" WHERE 1=1");
}
}

if !query.prerelease {
query_builder.push(" AND prerelease=FALSE ");
}

query_builder.push(" ORDER BY created_at DESC ");

query_builder.push(" LIMIT ");
query_builder.push_bind(limit);
query_builder.push(" OFFSET ");
query_builder.push_bind(offset);

match query_builder
.build_query_as::<LoaderVersionGetOne>()
.fetch_all(&mut *pool)
.await
{
Ok(r) =>
Ok(r.into_iter().map(|x| x.into_loader_version()).collect()),
Err(e) => {
log::error!("{:?}", e);
Err(ApiError::DbError)
}
}
}
}

0 comments on commit f9c89ae

Please sign in to comment.