From b27e575641d1398ef1571fef2bc9e890851d0ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E5=90=91=E5=A4=9C?= <46275354+fu050409@users.noreply.github.com> Date: Wed, 4 Dec 2024 21:03:36 +0800 Subject: [PATCH 1/2] feat(problem): optimize endpoints (#47) --- .changes/problem.md | 5 ++++ Cargo.lock | 54 ++++++++++++++++++++-------------------- Cargo.toml | 6 +++-- src/models/asset.rs | 1 + src/models/problem.rs | 17 +++++++++++++ src/models/submission.rs | 3 ++- src/routes/asset.rs | 47 +++++++++++++++------------------- src/routes/problem.rs | 26 ++++++++++++++++++- src/utils/problem.rs | 13 +++++----- src/utils/submission.rs | 3 ++- 10 files changed, 110 insertions(+), 65 deletions(-) create mode 100644 .changes/problem.md diff --git a/.changes/problem.md b/.changes/problem.md new file mode 100644 index 0000000..01f3f8a --- /dev/null +++ b/.changes/problem.md @@ -0,0 +1,5 @@ +--- +"algohub-server": patch:feat +--- + +Optimize endpoints for problem updates. diff --git a/Cargo.lock b/Cargo.lock index e2f5872..13552c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "algohub-server" -version = "0.1.9" +version = "0.1.10" dependencies = [ "anyhow", "chrono", @@ -226,7 +226,7 @@ dependencies = [ "fnv", "futures-timer", "futures-util", - "http 1.1.0", + "http 1.2.0", "indexmap 2.7.0", "mime", "multer", @@ -1000,9 +1000,9 @@ dependencies = [ [[package]] name = "eval-stack" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da0079f339d7a393172c036cd9d9b3b2e3df2e9e8fdde7ad35a82b128601f74" +checksum = "0b725b38496ca71300512270e9f01aedab900fc8fa660b4b33355bf05d45051b" dependencies = [ "anyhow", "libc", @@ -1455,9 +1455,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1482,7 +1482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1493,7 +1493,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1549,7 +1549,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "httparse", "itoa", @@ -1566,7 +1566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", + "http 1.2.0", "hyper 1.5.1", "hyper-util", "rustls", @@ -1586,7 +1586,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "hyper 1.5.1", "pin-project-lite", @@ -2128,7 +2128,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http 1.2.0", "httparse", "memchr", "mime", @@ -2643,7 +2643,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tracing", ] @@ -2662,7 +2662,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror 2.0.4", "tinyvec", "tracing", "web-time", @@ -2873,7 +2873,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "hyper 1.5.1", @@ -3894,11 +3894,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.4", ] [[package]] @@ -3914,9 +3914,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" dependencies = [ "proc-macro2", "quote", @@ -3935,9 +3935,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -3956,9 +3956,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -4000,9 +4000,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -4206,7 +4206,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand", diff --git a/Cargo.toml b/Cargo.toml index abcc319..e312ee3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,10 @@ license = "AGPL-3.0-only" [dependencies] anyhow = "1.0.92" chrono = { version = "0.4.38", features = ["serde"] } -eval-stack = { version = "0.2.0", features = ["serde"] } +eval-stack = { version = "0.3.1", default-features = false, features = [ + "serde", +] } rocket = { version = "0.5.1", features = ["json"] } serde = { version = "1.0.214", features = ["derive"] } -surrealdb = "2.1.0" +surrealdb = "2.1.2" uuid = { version = "1.11.0", features = ["v4"] } diff --git a/src/models/asset.rs b/src/models/asset.rs index 0f8deaa..cf29125 100644 --- a/src/models/asset.rs +++ b/src/models/asset.rs @@ -27,6 +27,7 @@ pub struct CreateAsset<'a> { #[derive(Serialize, Deserialize)] pub struct UserContent { pub id: String, + pub name: String, } pub struct AssetFile(pub(crate) NamedFile); diff --git a/src/models/problem.rs b/src/models/problem.rs index 0ef2bf4..b788b00 100644 --- a/src/models/problem.rs +++ b/src/models/problem.rs @@ -116,6 +116,21 @@ impl From> for Problem { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct OwnedUserTestCase { + pub input: String, + pub output: String, +} + +impl From for OwnedUserTestCase { + fn from(value: TestCase) -> Self { + OwnedUserTestCase { + input: value.input.id.to_string(), + output: value.output.id.to_string(), + } + } +} + #[derive(Debug, Deserialize, Serialize)] pub struct UserProblem { pub id: String, @@ -129,6 +144,7 @@ pub struct UserProblem { pub time_limit: u64, pub memory_limit: u64, + pub test_cases: Vec, pub creator: String, pub owner: UserRecordId, @@ -153,6 +169,7 @@ impl From for UserProblem { hint: value.hint, time_limit: value.time_limit, memory_limit: value.memory_limit, + test_cases: value.test_cases.into_iter().map(Into::into).collect(), creator: value.creator.id.to_string(), owner: value.owner.into(), categories: value.categories, diff --git a/src/models/submission.rs b/src/models/submission.rs index 0f34b04..deb04d8 100644 --- a/src/models/submission.rs +++ b/src/models/submission.rs @@ -18,7 +18,8 @@ pub struct Submission { pub problem: Thing, pub code: String, pub status: Status, - pub results: Vec, + pub judge_details: Vec, + pub judge_result: Option, pub creator: Thing, pub contest: Option, diff --git a/src/routes/asset.rs b/src/routes/asset.rs index c596498..e68eae4 100644 --- a/src/routes/asset.rs +++ b/src/routes/asset.rs @@ -24,9 +24,7 @@ pub async fn upload( data: Form>, ) -> Result { if !session::verify(db, data.auth.id, data.auth.token).await { - return Err(Error::Unauthorized(Json( - "Failed to grant access permission".into(), - ))); + return Err(Error::Unauthorized(Json("Invalid credentials".into()))); } let file_extension = data @@ -41,9 +39,7 @@ pub async fn upload( .join(data.auth.id); if !user_path.exists() { - create_dir_all(&user_path) - .await - .map_err(|e| Error::ServerError(Json(e.to_string().into())))?; + create_dir_all(&user_path).await?; } let file_name = format!("{}.{}", uuid::Uuid::new_v4(), file_extension); let file_path = user_path.join(&file_name); @@ -61,22 +57,22 @@ pub async fn upload( .await .map_err(|e| Error::ServerError(Json(format!("Failed to save file: {}", e).into())))?; - let asset = asset::create( - db, - data.owner.clone(), - data.file - .name() - .unwrap_or(&uuid::Uuid::new_v4().to_string()), - file_path, - ) - .await - .map_err(|e| Error::ServerError(Json(e.into())))? - .ok_or(Error::ServerError(Json("Failed to create asset".into())))?; + let asset_name = data + .file + .name() + .map(|name| name.to_string()) + .unwrap_or(uuid::Uuid::new_v4().to_string()); + + let asset = asset::create(db, data.owner.clone(), &asset_name, file_path) + .await? + .ok_or(Error::ServerError(Json("Failed to create asset".into())))?; + Ok(Json(Response { success: true, message: "Content updated successfully".into(), data: Some(UserContent { id: asset.id.unwrap().id.to_string(), + name: asset_name, }), })) } @@ -88,26 +84,23 @@ pub async fn get(db: &State>, id: &str) -> Option { Some(AssetFile(NamedFile::open(&asset.path).await.ok()?)) } -#[post("/delete/", data = "")] +#[delete("/delete/", data = "")] pub async fn delete( db: &State>, id: &str, - auth: Form>, + auth: Json>, ) -> Result { if !session::verify(db, auth.id, auth.token).await { - return Err(Error::Unauthorized(Json( - "Failed to grant access permission".into(), - ))); + return Err(Error::Unauthorized(Json("Invalid credentials".into()))); } let asset = asset::get_by_id(db, id) - .await - .map_err(Error::from)? + .await? .ok_or(Error::NotFound(Json("Asset not found".into())))?; - rocket::tokio::fs::remove_file(&asset.path) - .await - .map_err(|e| Error::ServerError(Json(format!("Failed to delete file: {}", e).into())))?; + let _ = rocket::tokio::fs::remove_file(&asset.path).await; + + asset::delete(db, id).await?; Ok(Json(Response { success: true, diff --git a/src/routes/problem.rs b/src/routes/problem.rs index 47151b6..05a7e91 100644 --- a/src/routes/problem.rs +++ b/src/routes/problem.rs @@ -148,6 +148,30 @@ pub async fn list( })) } +#[post("/update/", data = "")] +pub async fn update( + db: &State>, + id: &str, + problem: Json>, +) -> Result { + if !session::verify(db, problem.id, problem.token).await { + return Err(Error::Unauthorized(Json("Invalid credentials".into()))); + } + + problem::update(db, id, problem.into_inner()) + .await + .map_err(|e| Error::ServerError(Json(e.to_string().into())))? + .ok_or(Error::ServerError(Json( + "Failed to update problem, please try again later.".into(), + )))?; + + Ok(Json(Response { + success: true, + message: "Problem updated successfully".to_string(), + data: None, + })) +} + #[delete("/delete/", data = "")] pub async fn delete( db: &State>, @@ -177,5 +201,5 @@ pub async fn delete( pub fn routes() -> Vec { use rocket::routes; - routes![create, get, list, delete] + routes![create, get, update, list, delete] } diff --git a/src/utils/problem.rs b/src/utils/problem.rs index 6e0b46b..ae7f508 100644 --- a/src/utils/problem.rs +++ b/src/utils/problem.rs @@ -11,13 +11,14 @@ pub async fn create(db: &Surreal, problem: CreateProblem<'_>) -> Result< .await?) } -pub async fn update(db: &Surreal, problem: Problem) -> Result> { +pub async fn update( + db: &Surreal, + id: &str, + problem: CreateProblem<'_>, +) -> Result> { Ok(db - .update(( - "problem", - problem.id.clone().expect("empty id").id.to_string(), - )) - .content(problem) + .update(("problem", id)) + .content(Into::::into(problem)) .await?) } diff --git a/src/utils/submission.rs b/src/utils/submission.rs index 02b06da..4245b2e 100644 --- a/src/utils/submission.rs +++ b/src/utils/submission.rs @@ -21,7 +21,8 @@ pub async fn create( status: Status::InQueue, creator: ("account", account_id).into(), - results: vec![], + judge_details: vec![], + judge_result: None, contest: None, From 81269bfc0e66b5cab35305d25e259e079478b773 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 21:43:32 +0800 Subject: [PATCH 2/2] release: bump versions (#48) publish new versions Co-authored-by: fu050409 <46275354+fu050409@users.noreply.github.com> --- .changes/problem.md | 5 ----- CHANGELOG.md | 6 ++++++ Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changes/problem.md diff --git a/.changes/problem.md b/.changes/problem.md deleted file mode 100644 index 01f3f8a..0000000 --- a/.changes/problem.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"algohub-server": patch:feat ---- - -Optimize endpoints for problem updates. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b3158f..bd0005f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## \[0.1.11] + +### New Features + +- [`b27e575`](https://github.com/swpu-acm/online-judge/commit/b27e575641d1398ef1571fef2bc9e890851d0ec1) ([#47](https://github.com/swpu-acm/online-judge/pull/47) by [@fu050409](https://github.com/swpu-acm/online-judge/../../fu050409)) Optimize endpoints for problem updates. + ## \[0.1.10] ### New Features diff --git a/Cargo.toml b/Cargo.toml index e312ee3..20233e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "algohub-server" -version = "0.1.10" +version = "0.1.11" edition = "2021" description = "Extremely fast async online judge backend based on Rust" readme = "README.md"