diff --git a/.changes/refactor-list.md b/.changes/refactor-list.md new file mode 100644 index 0000000..68dafee --- /dev/null +++ b/.changes/refactor-list.md @@ -0,0 +1,5 @@ +--- +"algohub-server": patch:refactor +--- + +Refactored `list` method for account owned problems. diff --git a/Cargo.lock b/Cargo.lock index 8d5c165..6953d59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "algohub-server" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "chrono", diff --git a/src/routes/problem.rs b/src/routes/problem.rs index f51afca..66e69f2 100644 --- a/src/routes/problem.rs +++ b/src/routes/problem.rs @@ -129,17 +129,12 @@ pub async fn get( })) } -#[derive(Serialize, Deserialize, Default)] -#[serde(crate = "rocket::serde")] -pub struct ProblemFilter { - pub limit: Option, -} - #[derive(Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct ListProblem { - pub auth: OwnedCredentials, - pub filter: Option, + pub id: Option, + pub auth: Option, + pub limit: Option, } #[post("/list", data = "")] @@ -147,15 +142,20 @@ pub async fn list( db: &State>, data: Json, ) -> Result> { - if !session::verify(db, &data.auth.id, &data.auth.token).await { - return Err(Error::Unauthorized(Json("Invalid token".into()))); - } + let authed_id = if let Some(auth) = &data.auth { + if !session::verify(db, &auth.id, &auth.token).await { + return Err(Error::Unauthorized(Json("Invalid token".into()))); + }; + Some(auth.id.clone()) + } else { + None + }; let data = data.into_inner(); - let problems = problem::list(db, &data.auth.id, data.filter) + + let problems = problem::list_for_account(db, data.id, authed_id, data.limit) .await .map_err(|e| Error::ServerError(Json(e.to_string().into())))?; - println!("{:?}", problems); Ok(Json(Response { success: true, diff --git a/src/utils/problem.rs b/src/utils/problem.rs index 32d0401..d952a11 100644 --- a/src/utils/problem.rs +++ b/src/utils/problem.rs @@ -2,10 +2,7 @@ use anyhow::Result; use serde::Deserialize; use surrealdb::{engine::remote::ws::Client, Surreal}; -use crate::{ - models::problem::Problem, - routes::problem::{ProblemData, ProblemFilter}, -}; +use crate::{models::problem::Problem, routes::problem::ProblemData}; pub async fn create(db: &Surreal, problem: ProblemData<'_>) -> Result> { Ok(db @@ -35,24 +32,39 @@ where Ok(db.select(("problem", id)).await?) } -pub async fn list( +const LIST_QUERY: &str = r#" +IF $authed THEN + IF $limit THEN + SELECT * FROM problem WHERE owner = type::thing("account", $id) LIMIT $limit + ELSE + SELECT * FROM problem WHERE owner = type::thing("account", $id) + END; +ELSE + IF $limit THEN + SELECT * FROM problem WHERE owner = type::thing("account", $id) AND private = false LIMIT $limit + ELSE + SELECT * FROM problem WHERE owner = type::thing("account", $id) AND private = false + END; +END;"#; + +pub async fn list_for_account( db: &Surreal, - id: &str, - filter: Option, + account_id: Option, + authed_id: Option, + limit: Option, ) -> Result> where for<'de> M: Deserialize<'de>, { - let filter = filter.unwrap_or(ProblemFilter::default()); - let mut response = if let Some(limit) = filter.limit { - db.query("SELECT * FROM problem WHERE owner = type::thing(\"account\", $id) LIMIT $limit") - .bind(("id", id.to_string())) - .bind(("limit", limit)) - } else { - db.query("SELECT * FROM problem WHERE owner = type::thing(\"account\", $id)") - .bind(("id", id.to_string())) - } - .await?; + let mut response = db + .query(LIST_QUERY) + .bind(( + "authed", + authed_id.is_some() && account_id.is_some() && authed_id == account_id, + )) + .bind(("id", account_id)) + .bind(("limit", limit)) + .await?; Ok(response.take(0)?) } diff --git a/tests/problem.rs b/tests/problem.rs index 20352ec..5899c25 100644 --- a/tests/problem.rs +++ b/tests/problem.rs @@ -6,7 +6,7 @@ use algohub_server::{ }, routes::{ account::{RegisterData, RegisterResponse}, - problem::{ListProblem, ProblemData, ProblemFilter, ProblemResponse}, + problem::{ListProblem, ProblemData, ProblemResponse}, }, }; use anyhow::Result; @@ -84,11 +84,12 @@ async fn test_problem() -> Result<()> { let response = client .post("/problem/list") .json(&ListProblem { - auth: OwnedCredentials { + id: Some(id.clone()), + auth: Some(OwnedCredentials { id: id.clone(), token: token.clone(), - }, - filter: None, + }), + limit: None, }) .dispatch() .await; @@ -108,11 +109,12 @@ async fn test_problem() -> Result<()> { let response = client .post("/problem/list") .json(&ListProblem { - auth: OwnedCredentials { + id: Some(id.clone()), + auth: Some(OwnedCredentials { id: id.clone(), token: token.clone(), - }, - filter: Some(ProblemFilter { limit: Some(3) }), + }), + limit: Some(3), }) .dispatch() .await;