Skip to content

Commit

Permalink
Merge branch 'main' into feat/org
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 authored Nov 28, 2024
2 parents e0c0cbe + e28b7a2 commit 0f95171
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 55 deletions.
7 changes: 7 additions & 0 deletions .changes/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
{
"gitSiteUrl": "https://github.com/swpu-acm/online-judge/",
"changeTags": {
"feat": "New Features",
"fix": "Bug Fixes",
"perf": "Performance Improvements",
"chore": "Chores",
"refactor": "Refactors"
},
"pkgManagers": {
"rust": {
"version": true,
Expand Down
5 changes: 0 additions & 5 deletions .changes/list-problem.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changes/refactor-profile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"algohub-server": patch:refactor
---

Refactor api for getting user profile, allow get user profile anonymously
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## \[0.1.2]

### feat

- [`d9fb9f8`](https://github.com/swpu-acm/online-judge/commit/d9fb9f85319d7a1b33b674902be8bd429735b5d5) ([#8](https://github.com/swpu-acm/online-judge/pull/8) by [@fu050409](https://github.com/swpu-acm/online-judge/../../fu050409)) Add method for listing all problems from specific user.
- [`5cfb4c4`](https://github.com/swpu-acm/online-judge/commit/5cfb4c48ded65a10087e0ebbc6d41cd769e3a64b) ([#11](https://github.com/swpu-acm/online-judge/pull/11) by [@fu050409](https://github.com/swpu-acm/online-judge/../../fu050409)) Support for filtering problems by filter options.

## \[0.1.1]

### feat
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "algohub-server"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Extremely fast async online judge backend based on Rust"
readme = "README.md"
Expand Down
15 changes: 14 additions & 1 deletion src/models/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,20 @@ 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,
}

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Token<'r> {
pub token: &'r str,
}
28 changes: 4 additions & 24 deletions src/routes/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
account::Profile,
error::{Error, ErrorResponse},
response::{Empty, Response},
Record,
Record, Token,
},
utils::{account, session},
Result,
Expand Down Expand Up @@ -104,24 +104,8 @@ pub async fn profile(db: &State<Surreal<Client>>, profile: Json<ProfileData<'_>>
}
}

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

#[post("/profile/<id>", data = "<auth>")]
pub async fn get_profile(
db: &State<Surreal<Client>>,
id: &str,
auth: Json<Authenticate<'_>>,
) -> Result<Profile> {
if !session::verify(db, id, auth.token).await {
return Err(Error::Unauthorized(Json(
"Failed to grant access permission".into(),
)));
}

#[get("/profile/<id>")]
pub async fn get_profile(db: &State<Surreal<Client>>, id: &str) -> Result<Profile> {
let profile = account::get_by_id::<Profile>(db, id)
.await
.map_err(|e| Error::NotFound(Json(e.to_string().into())))?
Expand Down Expand Up @@ -209,11 +193,7 @@ pub async fn upload_content(
}

#[post("/delete/<id>", data = "<auth>")]
pub async fn delete(
db: &State<Surreal<Client>>,
id: &str,
auth: Json<Authenticate<'_>>,
) -> Result<Empty> {
pub async fn delete(db: &State<Surreal<Client>>, id: &str, auth: Json<Token<'_>>) -> Result<Empty> {
if !session::verify(db, id, auth.token).await {
return Err(Error::Unauthorized(Json(
"Failed to grant access permission".into(),
Expand Down
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)?)
}
10 changes: 5 additions & 5 deletions tests/account.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::{fs::File, io::Read, path::Path};

use anyhow::Result;
use algohub_server::{
models::{
account::Profile,
response::{Empty, Response},
Token,
},
routes::account::{Authenticate, ProfileData, RegisterData, RegisterResponse, UploadResponse},
routes::account::{ProfileData, RegisterData, RegisterResponse, UploadResponse},
};
use anyhow::Result;
use rocket::{http::ContentType, local::asynchronous::Client};

pub struct Upload {
Expand Down Expand Up @@ -127,8 +128,7 @@ async fn test_register() -> Result<()> {
assert!(empty_data.is_none());

let response = client
.post(format!("/account/profile/{}", &id))
.json(&Authenticate { token: &token })
.get(format!("/account/profile/{}", &id))
.dispatch()
.await;

Expand Down Expand Up @@ -169,7 +169,7 @@ async fn test_register() -> Result<()> {

let response = client
.post(format!("/account/delete/{}", id))
.json(&Authenticate { token: &token })
.json(&Token { token: &token })
.dispatch()
.await;

Expand Down
41 changes: 34 additions & 7 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, Token,
},
routes::{
account::{Authenticate, RegisterData, RegisterResponse},
problem::{ProblemData, ProblemResponse},
account::{RegisterData, RegisterResponse},
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,9 +105,33 @@ 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 })
.json(&Token { token: &token })
.dispatch()
.await
.into_json::<Response<Empty>>()
Expand Down

0 comments on commit 0f95171

Please sign in to comment.