Skip to content

Commit

Permalink
feat(problem): support problem filter (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 authored Nov 27, 2024
1 parent d9fb9f8 commit 5cfb4c4
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changes/problem-filter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"algohub-server": patch:feat
---

Support for filtering problems by filter options.
9 changes: 8 additions & 1 deletion src/models/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ pub struct UpdateAt {

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Credential<'c> {
pub struct Credentials<'c> {
pub id: &'c str,
pub token: &'c str,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct OwnedCredentials {
pub id: String,
pub token: String,
}
24 changes: 19 additions & 5 deletions src/routes/problem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
error::Error,
problem::{Mode, Problem, ProblemDetail, Sample},
response::Response,
Credential,
OwnedCredentials,
},
utils::{problem, session},
Result,
Expand Down Expand Up @@ -129,16 +129,30 @@ pub async fn get(
}))
}

#[post("/list", data = "<auth>")]
#[derive(Serialize, Deserialize, Default)]
#[serde(crate = "rocket::serde")]
pub struct ProblemFilter {
pub limit: Option<u8>,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct ListProblem {
pub auth: OwnedCredentials,
pub filter: Option<ProblemFilter>,
}

#[post("/list", data = "<data>")]
pub async fn list(
db: &State<Surreal<Client>>,
auth: Json<Credential<'_>>,
data: Json<ListProblem>,
) -> Result<Vec<ProblemDetail>> {
if !session::verify(db, auth.id, auth.token).await {
if !session::verify(db, &data.auth.id, &data.auth.token).await {
return Err(Error::Unauthorized(Json("Invalid token".into())));
}

let problems = problem::list(db, auth.id)
let data = data.into_inner();
let problems = problem::list(db, &data.auth.id, data.filter)
.await
.map_err(|e| Error::ServerError(Json(e.to_string().into())))?;
println!("{:?}", problems);
Expand Down
28 changes: 21 additions & 7 deletions src/utils/problem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use anyhow::Result;
use serde::Deserialize;
use surrealdb::{engine::remote::ws::Client, Surreal};

use crate::{models::problem::Problem, routes::problem::ProblemData};
use crate::{
models::problem::Problem,
routes::problem::{ProblemData, ProblemFilter},
};

pub async fn create(db: &Surreal<Client>, problem: ProblemData<'_>) -> Result<Option<Problem>> {
Ok(db
Expand Down Expand Up @@ -32,13 +35,24 @@ where
Ok(db.select(("problem", id)).await?)
}

pub async fn list<M>(db: &Surreal<Client>, id: &str) -> Result<Vec<M>>
pub async fn list<M>(
db: &Surreal<Client>,
id: &str,
filter: Option<ProblemFilter>,
) -> Result<Vec<M>>
where
for<'de> M: Deserialize<'de>,
{
Ok(db
.query("SELECT * FROM problem WHERE owner = type::thing(\"account\", $id)")
.bind(("id", id.to_string()))
.await?
.take(0)?)
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?;

Ok(response.take(0)?)
}
37 changes: 32 additions & 5 deletions tests/problem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use algohub_server::{
models::{
problem::{Mode, ProblemDetail},
response::{Empty, Response},
Credential,
OwnedCredentials,
},
routes::{
account::{Authenticate, RegisterData, RegisterResponse},
problem::{ProblemData, ProblemResponse},
problem::{ListProblem, ProblemData, ProblemFilter, ProblemResponse},
},
};
use anyhow::Result;
Expand Down Expand Up @@ -83,9 +83,12 @@ async fn test_problem() -> Result<()> {

let response = client
.post("/problem/list")
.json(&Credential {
id: &id,
token: &token,
.json(&ListProblem {
auth: OwnedCredentials {
id: id.clone(),
token: token.clone(),
},
filter: None,
})
.dispatch()
.await;
Expand All @@ -102,6 +105,30 @@ async fn test_problem() -> Result<()> {
assert!(success);
assert_eq!(data.len(), 10);

let response = client
.post("/problem/list")
.json(&ListProblem {
auth: OwnedCredentials {
id: id.clone(),
token: token.clone(),
},
filter: Some(ProblemFilter { limit: Some(3) }),
})
.dispatch()
.await;

let Response {
success,
message: _,
data,
} = response
.into_json::<Response<Vec<ProblemDetail>>>()
.await
.unwrap();
let data = data.unwrap();
assert!(success);
assert_eq!(data.len(), 3);

client
.post(format!("/account/delete/{}", id))
.json(&Authenticate { token: &token })
Expand Down

0 comments on commit 5cfb4c4

Please sign in to comment.