From 3c9003b42fb710382deb480455f0d16c6bfb25fa Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 13:09:27 +0530 Subject: [PATCH 1/7] get individual user --- web_server/src/main.rs | 69 ++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/web_server/src/main.rs b/web_server/src/main.rs index c167df6cb..e070f7199 100644 --- a/web_server/src/main.rs +++ b/web_server/src/main.rs @@ -2,13 +2,14 @@ mod extensions; mod structs; use axum::{ - extract::State, + extract::{Path, State}, http::StatusCode, routing::{get, post}, Json, Router, }; use extensions::PairExt; -use std::{net::SocketAddr, slice::Iter, sync::Arc}; +use sqlite::ConnectionWithFullMutex; +use std::{net::SocketAddr, sync::Arc}; use structs::User; struct AppState { @@ -24,12 +25,11 @@ async fn main() { // build our application with a route let app = Router::new() - // `GET /` goes to `root` - .route("/", get(root)) - // `POST /users` goes to `create_user` .route("/users", post(create_user)) .with_state(shared_state.clone()) - .route("/users", get(get_users)) + .route("/users", get(get_all_users)) + .with_state(shared_state.clone()) + .route("/users/:user_id", get(get_user)) .with_state(shared_state.clone()); // run our app with hyper @@ -42,26 +42,18 @@ async fn main() { .await .unwrap(); } -// basic handler that responds with a static string -async fn root() -> &'static str { - "Hello, World!" -} -async fn get_users(State(state): State>) -> (StatusCode, Json>) { - let query = "SELECT * FROM users;"; +fn get_users(id: Option, conn: &ConnectionWithFullMutex) -> Result, sqlite::Error> { + let query = match id { + Some(id) => format!("SELECT * FROM users WHERE id={};", id), + None => "SELECT * FROM users;".to_owned(), + }; let mut users = Vec::new(); - let result = state.conn.iterate(query, |pairs| { + conn.iterate(query, |pairs| { let mut pairs = pairs.into_iter(); let user = User { - id: Some( - pairs.next_field(), - // .expect("should exist") - // .1 - // .expect("should be not null") - // .parse() - // .expect("Should parse"), - ), + id: Some(pairs.next_field()), name: pairs.next_field(), about: pairs.next_field(), github: pairs.next_field(), @@ -69,21 +61,38 @@ async fn get_users(State(state): State>) -> (StatusCode, Json>) -> (StatusCode, Json>) { + let users = match get_users(None, &state.conn) { + Ok(users) => users, + Err(e) => { + println!("{e}"); + return (StatusCode::INTERNAL_SERVER_ERROR, Json(vec![])); + } }; (StatusCode::OK, Json(users)) } -async fn create_user( - // this argument tells axum to parse the request body - // as JSON into a `CreateUser` type +async fn get_user( + Path(id): Path, State(state): State>, - Json(payload): Json, -) -> StatusCode { +) -> Result<(StatusCode, Json), StatusCode> { + let Ok(mut users) = get_users(Some(id), &state.conn) else { + todo!() + }; + if users.len() < 1 { + return Err(StatusCode::NO_CONTENT); + } else if users.len() > 1 { + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + let user = users.remove(0); + Ok((StatusCode::OK, Json(user))) +} + +async fn create_user(State(state): State>, Json(payload): Json) -> StatusCode { // TODO: // Verify Email // Verify Github From 2526013ef9abb56a253a5ba26bc10a10b44a086a Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 13:14:35 +0530 Subject: [PATCH 2/7] removed chrono --- web_server/Cargo.lock | 146 ------------------------------------------ web_server/Cargo.toml | 1 - 2 files changed, 147 deletions(-) diff --git a/web_server/Cargo.lock b/web_server/Cargo.lock index a1789e9dc..892013474 100644 --- a/web_server/Cargo.lock +++ b/web_server/Cargo.lock @@ -26,21 +26,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "async-trait" version = "0.1.74" @@ -128,12 +113,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - [[package]] name = "bytes" version = "1.5.0" @@ -155,26 +134,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - [[package]] name = "fnv" version = "1.0.7" @@ -292,44 +251,12 @@ dependencies = [ "want", ] -[[package]] -name = "iana-time-zone" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" -[[package]] -name = "js-sys" -version = "0.3.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -415,15 +342,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -924,66 +842,11 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" - [[package]] name = "web_server" version = "0.1.0" dependencies = [ "axum", - "chrono", "serde", "serde_json", "sqlite", @@ -1014,15 +877,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/web_server/Cargo.toml b/web_server/Cargo.toml index 3fec2429c..930759568 100644 --- a/web_server/Cargo.toml +++ b/web_server/Cargo.toml @@ -13,7 +13,6 @@ serde_json = "1.0.68" tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -chrono = "0.4.31" [profile.release] opt-level = 'z' # Optimize for size From 0c7dcb707cd021804d78a6903f00d0a0afdd8e01 Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 13:14:54 +0530 Subject: [PATCH 3/7] added different state for different paths in release and debug mode --- web_server/src/main.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/web_server/src/main.rs b/web_server/src/main.rs index e070f7199..6b7c3133f 100644 --- a/web_server/src/main.rs +++ b/web_server/src/main.rs @@ -16,11 +16,25 @@ struct AppState { conn: sqlite::ConnectionWithFullMutex, } +impl AppState { + #[cfg(debug_assertions)] + fn new() -> Self { + Self { + conn: sqlite::Connection::open_with_full_mutex("../data.db") + .expect("file should exist"), + } + } + + #[cfg(not(debug_assertions))] + //TODO: make it create db with tables if they don't exist already + fn new() -> Self { + todo!() + } +} + #[tokio::main] async fn main() { - let shared_state = Arc::new(AppState { - conn: sqlite::Connection::open_with_full_mutex("../data.db").expect("file should exist"), - }); + let shared_state = Arc::new(AppState::new()); tracing_subscriber::fmt::init(); // build our application with a route From b61ac5ae63594bdbc2c4943764c0cbc3aad28342 Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 16:58:45 +0530 Subject: [PATCH 4/7] added projects with user --- data.db | Bin 45056 -> 53248 bytes web_server/src/main.rs | 35 ++++++++++++++++++++++++++++++++--- web_server/src/structs.rs | 6 +++--- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/data.db b/data.db index 662df3d208973c9c0b089d28d1b8aabc7ffbce2b..57c3f83da6dcbb738b064c5d9da8e32ec2666672 100644 GIT binary patch delta 1097 zcmZp8z|^pSd4jZ{Bm)BjFA#G9F%uArPSi10m1NM%y1>ho&A`Rk#lXLg`zGH8u62Cn zoLyYCyfb<8_?!7P_%${*vTy`)Wiv8~>+3T%>y{)Y<)juD<|M_Jq~;dHgSqjB7y``B zL9UJ=t_mTJPCl**N*MB!4{+K{{>&?)tHZ^ql%83VQJNH=lbM&T#2Mlm5u)Jd55%E9 zJ|NlD+{DZri1_4-oWhg6xD+RMalYnY<7WeUgn?mmE!P7kVG(gn9yW1XaYlyByp+_6 z;zCV<$%(ug(majP{Osc5;*8CrV7HbQrxq213FgU5c$3Mrznm|famD2Oe4cEMf^6cU z`jcz{6;(y7&|C0Y3{|TT;yZDXxzcDCsV7Lt^%FPJ2pOc%3S(c-qC_gJT zxulqbnOS`EFMlorF$Mt!20mGI2sD$Gub%NSX>Ma+VBAQuj(U)ewETQb|JP#;0H7tl zIJMx?AuS8EBn%pum^NY8X2rnpgdBYg3~ML%^&7JQW2p?ru%CRi-&zVN0s@Rc%*lTS z83F@*E5DHmCnr!!kAnk9YOu2dNhLN=hLB-p1(IScAR`5snSmr16DY^CaBXHxU={!- nsXq+-e}HCu;^$*#=HvvG2#ox%82DcS#UAjBi832ho&A`do#lXLg`zGH8u62Cn zyj{HUoLyYCT-loi1#WQ|@J2BTitFn$HhY&OCgr3S7v?0zm+(e0`~eFB8K1!newgg! zF3#5+DXA4eg_$LrYq=gUv9OA3@=Pw^)sW_D%;IJj7Z+!2HU=v%Elw>e1{0i5P{r z-{4&fdB<|)PCMd&}5y&{& tZ_URAieUZ^4E%rizwv(nDu2W;$jZ#f$jl5PnV6WFIXSsDGYb6Y2LM>)kTd`Q diff --git a/web_server/src/main.rs b/web_server/src/main.rs index 6b7c3133f..c02efad2b 100644 --- a/web_server/src/main.rs +++ b/web_server/src/main.rs @@ -10,7 +10,7 @@ use axum::{ use extensions::PairExt; use sqlite::ConnectionWithFullMutex; use std::{net::SocketAddr, sync::Arc}; -use structs::User; +use structs::{Project, User}; struct AppState { conn: sqlite::ConnectionWithFullMutex, @@ -57,6 +57,26 @@ async fn main() { .unwrap(); } +fn get_projects( + user_id: u128, + conn: &ConnectionWithFullMutex, +) -> Result, sqlite::Error> { + let query = format!("SELECT * FROM projects WHERE user_id={}", user_id); + let mut projects = vec![]; + conn.iterate(query, |pairs| { + let mut pairs = pairs.into_iter(); + let project = Project { + id: Some(pairs.next_field()), + name: pairs.next_field(), + //TODO: add tasks + tasks: None, + }; + projects.push(project); + true + })?; + Ok(projects) +} + fn get_users(id: Option, conn: &ConnectionWithFullMutex) -> Result, sqlite::Error> { let query = match id { Some(id) => format!("SELECT * FROM users WHERE id={};", id), @@ -65,13 +85,22 @@ fn get_users(id: Option, conn: &ConnectionWithFullMutex) -> Result projects, + Err(e) => { + println!("{e}"); + // return true is basically continue here + return true; + } + }; let user = User { - id: Some(pairs.next_field()), + id: Some(user_id), name: pairs.next_field(), about: pairs.next_field(), github: pairs.next_field(), email: pairs.next_field(), + projects: Some(projects), }; users.push(user); true diff --git a/web_server/src/structs.rs b/web_server/src/structs.rs index 5a6927d65..7ac57b400 100644 --- a/web_server/src/structs.rs +++ b/web_server/src/structs.rs @@ -8,14 +8,14 @@ pub struct User { pub about: String, pub github: String, pub email: String, - // projects: Vec, + pub projects: Option>, } #[derive(Serialize, Deserialize, Debug)] pub struct Project { pub id: Option, pub name: String, - // tasks: Vec, + pub tasks: Option>, } #[derive(Serialize, Deserialize, Debug)] @@ -37,7 +37,7 @@ pub struct Task { pub deadline: String, pub priority: Priority, pub progress: Progress, - // subtasks: Vec, + pub subtasks: Option>, } #[derive(Serialize, Deserialize, Debug)] From 9f07f0b5043e1a9790b09a53af80b65ad98093bf Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 17:38:15 +0530 Subject: [PATCH 5/7] adding projects to db --- data.db | Bin 53248 -> 53248 bytes web_server/src/main.rs | 36 +++++++++++++++++++++++++++++++++--- web_server/src/structs.rs | 2 +- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/data.db b/data.db index 57c3f83da6dcbb738b064c5d9da8e32ec2666672..dcb2fff5323cb94509d7836928e91b3a9052c98a 100644 GIT binary patch delta 68 zcmV-K0K5NypaX!Q1CSd58j&1B0UEJjqz?uG5AgsG@v{*S=MN7J0R#Xa32<_6YGq?| aAThEa?Jofdv+hq8P_qQE0uZwXu=*dnx)p~2 delta 44 zcmZozz}&Ead4e>f &'static str { + println!("Hello, World!"); + "Hello, World!" +} fn get_projects( - user_id: u128, + user_id: u32, conn: &ConnectionWithFullMutex, ) -> Result, sqlite::Error> { let query = format!("SELECT * FROM projects WHERE user_id={}", user_id); @@ -77,7 +84,7 @@ fn get_projects( Ok(projects) } -fn get_users(id: Option, conn: &ConnectionWithFullMutex) -> Result, sqlite::Error> { +fn get_users(id: Option, conn: &ConnectionWithFullMutex) -> Result, sqlite::Error> { let query = match id { Some(id) => format!("SELECT * FROM users WHERE id={};", id), None => "SELECT * FROM users;".to_owned(), @@ -120,7 +127,7 @@ async fn get_all_users(State(state): State>) -> (StatusCode, Json< } async fn get_user( - Path(id): Path, + Path(id): Path, State(state): State>, ) -> Result<(StatusCode, Json), StatusCode> { let Ok(mut users) = get_users(Some(id), &state.conn) else { @@ -161,3 +168,26 @@ async fn create_user(State(state): State>, Json(payload): Json, + State(state): State>, + Json(payload): Json, +) -> StatusCode { + // TODO: + // Verify Email + // Verify Github + // get pfp from github? + + let Project { name, .. } = payload; + + let cmd = format!(r#"INSERT INTO projects(name, user_id) VALUES ("{name}", {user_id})"#); + match state.conn.execute(cmd) { + Ok(_) => StatusCode::CREATED, + // TODO: replace with better status code + Err(err) => { + println!("{}", err); + StatusCode::INTERNAL_SERVER_ERROR + } + } +} diff --git a/web_server/src/structs.rs b/web_server/src/structs.rs index 7ac57b400..9128863ae 100644 --- a/web_server/src/structs.rs +++ b/web_server/src/structs.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; // the output to our `create_user` handler #[derive(Serialize, Deserialize, Debug)] pub struct User { - pub id: Option, + pub id: Option, pub name: String, pub about: String, pub github: String, From ffe4c1b6256333476550e0b532588561febcec19 Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 18:26:03 +0530 Subject: [PATCH 6/7] added get and create tasks --- web_server/src/main.rs | 68 +++++++++++++++++++++++++++++++++++---- web_server/src/structs.rs | 50 ++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/web_server/src/main.rs b/web_server/src/main.rs index 5775622a6..3a828768a 100644 --- a/web_server/src/main.rs +++ b/web_server/src/main.rs @@ -10,7 +10,7 @@ use axum::{ use extensions::PairExt; use sqlite::ConnectionWithFullMutex; use std::{net::SocketAddr, sync::Arc}; -use structs::{Project, User}; +use structs::{Project, Task, User}; struct AppState { conn: sqlite::ConnectionWithFullMutex, @@ -47,6 +47,8 @@ async fn main() { .route("/users/:user_id", get(get_user)) .with_state(shared_state.clone()) .route("/users/:user_id/projects", post(create_project)) + .with_state(shared_state.clone()) + .route("/projects/:project_id/tasks", post(create_task)) .with_state(shared_state.clone()); // run our app with hyper @@ -64,6 +66,26 @@ async fn root() -> &'static str { println!("Hello, World!"); "Hello, World!" } + +fn get_tasks(project_id: u32, conn: &ConnectionWithFullMutex) -> Result, sqlite::Error> { + let query = format!("SELECT * FROM tasks WHERE project_id={}", project_id); + let mut tasks = vec![]; + conn.iterate(query, |pairs| { + let mut pairs = pairs.into_iter(); + let project = Task { + id: Some(pairs.next_field()), + title: pairs.next_field(), + deadline: pairs.next_field(), + priority: pairs.next_field(), + progress: pairs.next_field(), + //TODO: Subtasks + subtasks: None, + }; + tasks.push(project); + true + })?; + Ok(tasks) +} fn get_projects( user_id: u32, conn: &ConnectionWithFullMutex, @@ -72,8 +94,18 @@ fn get_projects( let mut projects = vec![]; conn.iterate(query, |pairs| { let mut pairs = pairs.into_iter(); + + let project_id = pairs.next_field(); + let tasks = match get_tasks(project_id, conn) { + Ok(tasks) => tasks, + Err(e) => { + println!("{e}"); + // return true is basically continue here + return true; + } + }; let project = Project { - id: Some(pairs.next_field()), + id: Some(project_id), name: pairs.next_field(), //TODO: add tasks tasks: None, @@ -174,11 +206,6 @@ async fn create_project( State(state): State>, Json(payload): Json, ) -> StatusCode { - // TODO: - // Verify Email - // Verify Github - // get pfp from github? - let Project { name, .. } = payload; let cmd = format!(r#"INSERT INTO projects(name, user_id) VALUES ("{name}", {user_id})"#); @@ -191,3 +218,30 @@ async fn create_project( } } } + +async fn create_task( + Path(project_id): Path, + State(state): State>, + Json(payload): Json, +) -> StatusCode { + let Task { + id, + title, + deadline, + priority, + progress, + .. + } = payload; + + let cmd = format!( + r#"INSERT INTO tasks(title, deadline, priority, progress, user_id) VALUES ("{title}","{deadline}", "{priority}", "{progress}" {project_id})"# + ); + match state.conn.execute(cmd) { + Ok(_) => StatusCode::CREATED, + // TODO: replace with better status code + Err(err) => { + println!("{}", err); + StatusCode::INTERNAL_SERVER_ERROR + } + } +} diff --git a/web_server/src/structs.rs b/web_server/src/structs.rs index 9128863ae..bd7431592 100644 --- a/web_server/src/structs.rs +++ b/web_server/src/structs.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use serde::{Deserialize, Serialize}; // the output to our `create_user` handler @@ -46,3 +48,51 @@ pub struct SubTask { pub text: String, pub is_completed: bool, } + +impl std::fmt::Display for Priority { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Priority::Low => write!(f, "LOW"), + Priority::Med => write!(f, "MEDIUM"), + Priority::High => write!(f, "HIGH"), + } + } +} + +impl std::fmt::Display for Progress { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Progress::NotStarted => write!(f, "NOT_STARTED"), + Progress::InProgress => write!(f, "IN_PROGRESS"), + Progress::Completed => write!(f, "COMPLETED"), + } + } +} + +impl FromStr for Priority { + type Err = (); + + fn from_str(s: &str) -> Result { + let priority = match s { + "LOW" => Priority::Low, + "MEDIUM" => Priority::Med, + "HIGH" => Priority::High, + _ => Err(())?, + }; + Ok(priority) + } +} + +impl FromStr for Progress { + type Err = (); + + fn from_str(s: &str) -> Result { + let progress = match s { + "NOT_STARTED" => Progress::NotStarted, + "IN_PROGRESS" => Progress::InProgress, + "COMPLETED" => Progress::Completed, + _ => Err(())?, + }; + Ok(progress) + } +} From d8c641f031cc9060403aade6e6d665c7edb4606f Mon Sep 17 00:00:00 2001 From: Arjun Pratap Date: Sun, 5 Nov 2023 19:09:46 +0530 Subject: [PATCH 7/7] more type safe API --- data.db | Bin 53248 -> 53248 bytes web_server/src/extensions.rs | 12 ++++++++++-- web_server/src/main.rs | 10 +++++----- web_server/src/structs.rs | 31 +++++++++++++++++++++---------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/data.db b/data.db index dcb2fff5323cb94509d7836928e91b3a9052c98a..e4a3aa2ceeed82b03c44af8b77949c421a649ef2 100644 GIT binary patch delta 999 zcmb7DO-vI(6rSBJEj#V@QE06J8kRPs@>BY!VB#MnppXz~6r&eX7rMYg+pXONB*uUO z7h)o1VuA@K+>8k!YOmZ)jA@JqE*^+SxOgz(WTLZMj0C-y&71w+y!qbGH@k~l+~O9u zR_AI!2np0Gsj<}R3T^SG2Gl~q5!+Qf z&Aj%8!_3M8#ALu0!=%9|9{ciCAQk;^?I3=vM^>k zb1?+CXweltO&H!y?m2?kpUW$1UeV|MaMg*ttZ9Bya>PlC!$;0yfjEVMVpiZ8 z3%#*7%&sKBR<{FX{>PgAz z;Bd2xVt?@!j8s*!uz{ci8%0;uQ|LI)T9GFZYVA?xq)9obiISL_Ny#Zy*0MoeoRnr| zQO(LJ8rId!eAh%qQqt|D6uwflCyoGMA6Z}*!2#^Td-zO~ZbO3SI4?7!$$5?CD=0Lz zVC`1USNU6IIHKR4xo>AVA5T@7lE-w7PKbGvi77-?#)2$GSL7R55y$boP-GH6p^&gu zFf?K_BZWl8dY9F@iQpq_(hk;Op`Ep%V527hDOFVUNjWbXwPKN2JQR(EVjX?`H~I#L zhLg93yKfHn_C#Zh4MiJk0+5sQ<7z%5jw^XhKS7FyA{PdR?wsTp9kO%|_yI?>@`(o( z>(;&iuHYDkWsR=iZCMQA%V%lNhj8Xku$*TP!5$pa?ms|F4cE$?Qk?a0QGQm^q^v%v K9Nz-{A$|eVTp8p5 delta 967 zcmbVLO-vI(6rSnUc6YnG(+YL@Yg{3OHbItxkw_p=Nkd4KC;<{RS{J&7ZMVCny9GHQ z1n|NMnRxKlgo7NEs6Ci?@}P+)Lc9?VYV-nUL*hwi3yDZ?X7Xm<``*m^-n=)nRHT-Q z)OvlO4gkOtVTrhi1Ru9{HrIi+^e)e40L!cawC&pyUb5T59J9tQ@K1RIt)MUpmjZq_ zeUr^Vmnh3{<)W=j=&CiNPb6$Ln@g0x{6)B2J84^CR+2O)tI_yid_)?K1w7)IjPIeEzKW_OIw~NiYXe8cDKqMt zttOO$ZAJn($2XRqp}T$$L^}ZOkXF4%ct`GqR4H)(C)!x@(E9-GqeJwO_}-!`=n!0> zD<}x+g9S^?Ta3>|g&1=4v`R9kDN1C@IJ*hk{UzA`8^N+#OOgV90EE!#L3qvxF8CdP zlH1$>z*mmqBg$e`^Z97XH1VF?;@Hb;kW{A&(^7{)HuO(r6-{p=PlFtr{l8;<&5^2DET1kI z(v7^*Z7aDGv`1uSDy2)> { T: FromStr, ::Err: std::fmt::Debug, { - self.next() + match self + .next() .expect("should exist") .1 .expect("should be not null") .parse() - .expect("Should parse") + { + Ok(value) => value, + Err(e) => { + println!("{e:?}"); + panic!(); + } + } + // .expect("Should parse") } } diff --git a/web_server/src/main.rs b/web_server/src/main.rs index 3a828768a..041e32a62 100644 --- a/web_server/src/main.rs +++ b/web_server/src/main.rs @@ -79,7 +79,7 @@ fn get_tasks(project_id: u32, conn: &ConnectionWithFullMutex) -> Result, conn: &ConnectionWithFullMutex) -> Result>, Json(payload): Json, ) -> StatusCode { + //TODO: verifuy deadline format let Task { - id, title, deadline, priority, @@ -234,7 +234,7 @@ async fn create_task( } = payload; let cmd = format!( - r#"INSERT INTO tasks(title, deadline, priority, progress, user_id) VALUES ("{title}","{deadline}", "{priority}", "{progress}" {project_id})"# + r#"INSERT INTO tasks(title, deadline, priority, progress, project_id) VALUES ("{title}","{deadline}", "{priority}", "{progress}", {project_id})"# ); match state.conn.execute(cmd) { Ok(_) => StatusCode::CREATED, diff --git a/web_server/src/structs.rs b/web_server/src/structs.rs index bd7431592..57cfac7d9 100644 --- a/web_server/src/structs.rs +++ b/web_server/src/structs.rs @@ -10,26 +10,36 @@ pub struct User { pub about: String, pub github: String, pub email: String, - pub projects: Option>, + #[serde(default)] + pub projects: Vec, } #[derive(Serialize, Deserialize, Debug)] pub struct Project { pub id: Option, pub name: String, - pub tasks: Option>, + #[serde(default)] + pub tasks: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub enum Priority { + #[serde(alias = "LOW")] + #[default] Low, + #[serde(alias = "MEDIUM")] Med, + #[serde(alias = "HIGH")] High, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub enum Progress { + #[serde(alias = "NOT_STARTED")] + #[default] NotStarted, + #[serde(alias = "IN_PROGRESS")] InProgress, + #[serde(alias = "COMPLETED")] Completed, } #[derive(Serialize, Deserialize, Debug)] @@ -38,10 +48,11 @@ pub struct Task { pub title: String, pub deadline: String, pub priority: Priority, + #[serde(default)] pub progress: Progress, - pub subtasks: Option>, + #[serde(default)] + pub subtasks: Vec, } - #[derive(Serialize, Deserialize, Debug)] pub struct SubTask { pub id: Option, @@ -70,28 +81,28 @@ impl std::fmt::Display for Progress { } impl FromStr for Priority { - type Err = (); + type Err = String; fn from_str(s: &str) -> Result { let priority = match s { "LOW" => Priority::Low, "MEDIUM" => Priority::Med, "HIGH" => Priority::High, - _ => Err(())?, + _ => Err(format!("Priority cannot be parsed from {s}"))?, }; Ok(priority) } } impl FromStr for Progress { - type Err = (); + type Err = String; fn from_str(s: &str) -> Result { let progress = match s { "NOT_STARTED" => Progress::NotStarted, "IN_PROGRESS" => Progress::InProgress, "COMPLETED" => Progress::Completed, - _ => Err(())?, + _ => Err(format!("Progress cannot be parsed from {s}"))?, }; Ok(progress) }