refactor: make the serverside error handling more robust
This commit is contained in:
		
							
								
								
									
										157
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										157
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -29,6 +29,15 @@ dependencies = [ | ||||
|  "zerocopy", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "aho-corasick" | ||||
| version = "1.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "allocator-api2" | ||||
| version = "0.2.18" | ||||
| @@ -94,7 +103,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -178,7 +187,7 @@ dependencies = [ | ||||
|  "heck 0.4.1", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -469,7 +478,7 @@ dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "strsim", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -480,7 +489,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" | ||||
| dependencies = [ | ||||
|  "darling_core", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -525,7 +534,7 @@ dependencies = [ | ||||
|  "dsl_auto_type", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -534,7 +543,7 @@ version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" | ||||
| dependencies = [ | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -620,7 +629,7 @@ dependencies = [ | ||||
|  "prettyplease", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -730,7 +739,7 @@ dependencies = [ | ||||
|  "convert_case", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -833,7 +842,7 @@ dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "slab", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -847,7 +856,7 @@ dependencies = [ | ||||
|  "krates", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
|  "tracing", | ||||
| ] | ||||
|  | ||||
| @@ -923,7 +932,7 @@ dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "server_fn_macro", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -943,7 +952,7 @@ dependencies = [ | ||||
|  "heck 0.5.0", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -979,7 +988,7 @@ dependencies = [ | ||||
|  "darling", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1112,7 +1121,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1872,7 +1881,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1923,7 +1932,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro-error" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | ||||
| dependencies = [ | ||||
|  "proc-macro-error-attr", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 1.0.109", | ||||
|  "version_check", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro-error-attr" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "version_check", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1983,6 +2016,35 @@ dependencies = [ | ||||
|  "bitflags", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.10.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-automata", | ||||
|  "regex-syntax", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "regex-automata" | ||||
| version = "0.4.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-syntax", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.8.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc-demangle" | ||||
| version = "0.1.24" | ||||
| @@ -2078,7 +2140,7 @@ checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2122,7 +2184,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2181,7 +2243,7 @@ dependencies = [ | ||||
|  "convert_case", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
|  "xxhash-rust", | ||||
| ] | ||||
|  | ||||
| @@ -2192,7 +2254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "556e4fd51eb9ee3e7d9fb0febec6cef486dcbc8f7f427591dfcfebee1abe1ad4" | ||||
| dependencies = [ | ||||
|  "server_fn_macro", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2256,7 +2318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "edc90d3e8623d29a664cd8dba5078b600dd203444f00b9739f744e4c6e7aeaf2" | ||||
| dependencies = [ | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2317,6 +2379,16 @@ version = "0.11.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "1.0.109" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "unicode-ident", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "2.0.74" | ||||
| @@ -2357,7 +2429,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2400,6 +2472,7 @@ dependencies = [ | ||||
|  "dioxus-logger", | ||||
|  "dotenvy", | ||||
|  "serde", | ||||
|  "validator", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2428,7 +2501,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2543,7 +2616,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2692,6 +2765,36 @@ version = "0.7.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" | ||||
|  | ||||
| [[package]] | ||||
| name = "validator" | ||||
| version = "0.18.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "db79c75af171630a3148bd3e6d7c4f42b6a9a014c2945bc5ed0020cbb8d9478e" | ||||
| dependencies = [ | ||||
|  "idna", | ||||
|  "once_cell", | ||||
|  "regex", | ||||
|  "serde", | ||||
|  "serde_derive", | ||||
|  "serde_json", | ||||
|  "url", | ||||
|  "validator_derive", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "validator_derive" | ||||
| version = "0.18.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "55591299b7007f551ed1eb79a684af7672c19c3193fb9e0a31936987bb2438ec" | ||||
| dependencies = [ | ||||
|  "darling", | ||||
|  "once_cell", | ||||
|  "proc-macro-error", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "valuable" | ||||
| version = "0.1.0" | ||||
| @@ -2738,7 +2841,7 @@ dependencies = [ | ||||
|  "once_cell", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
|  | ||||
| @@ -2772,7 +2875,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
|  "wasm-bindgen-backend", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
| @@ -2934,5 +3037,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.74", | ||||
| ] | ||||
|   | ||||
| @@ -15,6 +15,7 @@ dioxus = { version = "0.5", features = ["fullstack", "router"] } | ||||
| dioxus-logger = "0.5.1" | ||||
| dotenvy = "0.15.7" | ||||
| serde = "1.0.208" | ||||
| validator = { version = "0.18.1", features = ["derive"] } | ||||
|  | ||||
| [features] | ||||
| default = [] | ||||
|   | ||||
| @@ -10,7 +10,7 @@ pub(crate) fn Home() -> Element { | ||||
|         ProjectForm { | ||||
|             onsubmit: move |title| { | ||||
|                 spawn(async move { | ||||
|                     let _ = create_project(title).await; | ||||
|                     create_project(title).await; | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,13 +1,14 @@ | ||||
| use crate::models::project::NewProject; | ||||
| use dioxus::core_macro::{component, rsx}; | ||||
| use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn ProjectForm(onsubmit: EventHandler<String>) -> Element { | ||||
| pub(crate) fn ProjectForm(onsubmit: EventHandler<NewProject>) -> Element { | ||||
|     rsx! { | ||||
|         form { | ||||
|             onsubmit: move |event| { | ||||
|                 onsubmit(event.values().get("title").unwrap().as_value()); | ||||
|                 onsubmit(NewProject::new(event.values().get("title").unwrap().as_value())); | ||||
|             }, | ||||
|             input { | ||||
|                 r#type: "text", | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/errors/error.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/errors/error.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::fmt::Display; | ||||
| use std::str::FromStr; | ||||
|  | ||||
| #[derive(Serialize, Deserialize, Debug)] | ||||
| pub enum Error { | ||||
|     ServerInternal, | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl Display for Error { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Error::ServerInternal => write!(f, "internal server error"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl FromStr for Error { | ||||
|     type Err = (); | ||||
|  | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         Ok(match s { | ||||
|             "internal server error" => Error::ServerInternal, | ||||
|             _ => return Err(()), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/errors/error_vec.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/errors/error_vec.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| use std::fmt::Display; | ||||
| use std::str::FromStr; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct ErrorVec<T> { | ||||
|     errors: Vec<T>, | ||||
| } | ||||
|  | ||||
| impl<T> From<ErrorVec<T>> for Vec<T> { | ||||
|     fn from(e: ErrorVec<T>) -> Self { | ||||
|         e.errors | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> From<Vec<T>> for ErrorVec<T> { | ||||
|     fn from(e: Vec<T>) -> Self { | ||||
|         ErrorVec { errors: e } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl<T: Display> Display for ErrorVec<T> { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!( | ||||
|             f, | ||||
|             "{}", | ||||
|             self.errors | ||||
|                 .iter() | ||||
|                 .map(|e| e.to_string()) | ||||
|                 .collect::<Vec<String>>() | ||||
|                 .join("\n") | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl<T> FromStr for ErrorVec<T> { | ||||
|     type Err = (); | ||||
|  | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         Ok(ErrorVec { errors: Vec::new() }) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								src/errors/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/errors/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| pub(crate) mod error; | ||||
| pub(crate) mod error_vec; | ||||
| pub(crate) mod project_create_error; | ||||
							
								
								
									
										50
									
								
								src/errors/project_create_error.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/errors/project_create_error.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| use crate::errors::error::Error; | ||||
| use crate::errors::error_vec::ErrorVec; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::fmt::Display; | ||||
| use std::str::FromStr; | ||||
| use validator::{ValidationErrors, ValidationErrorsKind}; | ||||
|  | ||||
| #[derive(Serialize, Deserialize, Debug)] | ||||
| pub enum ProjectCreateError { | ||||
|     TitleTooShort, | ||||
|     Error(Error), | ||||
| } | ||||
|  | ||||
| impl From<ValidationErrors> for ErrorVec<ProjectCreateError> { | ||||
|     fn from(e: ValidationErrors) -> Self { | ||||
|         e.errors() | ||||
|             .iter() | ||||
|             .flat_map(|(&field, error_kind)| match field { | ||||
|                 "title_length" => match error_kind { | ||||
|                     ValidationErrorsKind::Field(validation_errors) => validation_errors | ||||
|                         .iter() | ||||
|                         .map(|validation_error| match validation_error.code.as_ref() { | ||||
|                             "length" => ProjectCreateError::TitleTooShort, | ||||
|                             _ => ProjectCreateError::Error(Error::ServerInternal), | ||||
|                         }) | ||||
|                         .collect::<Vec<ProjectCreateError>>(), | ||||
|                     _ => panic!("unexpected error kind"), | ||||
|                 }, | ||||
|                 _ => panic!("unexpected field name"), | ||||
|             }) | ||||
|             .collect::<Vec<ProjectCreateError>>() | ||||
|             .into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl Display for ProjectCreateError { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "{}", dbg!(self)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // has to be implemented for Dioxus server functions | ||||
| impl FromStr for ProjectCreateError { | ||||
|     type Err = (); | ||||
|  | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         Ok(ProjectCreateError::Error(Error::ServerInternal)) | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| #![allow(non_snake_case)] | ||||
|  | ||||
| mod components; | ||||
| mod errors; | ||||
| mod models; | ||||
| mod route; | ||||
| mod schema; | ||||
|   | ||||
| @@ -1,6 +1,10 @@ | ||||
| use crate::schema::projects; | ||||
| use diesel::prelude::*; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use validator::Validate; | ||||
|  | ||||
| const TITLE_LENGTH_MIN: u64 = 1; | ||||
| const TITLE_LENGTH_MAX: u64 = 255; | ||||
|  | ||||
| #[derive(Queryable, Selectable, Serialize, Deserialize)] | ||||
| #[diesel(table_name = crate::schema::projects)] | ||||
| @@ -20,8 +24,19 @@ impl Project { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Insertable, Serialize, Deserialize)] | ||||
| #[derive(Insertable, Serialize, Deserialize, Validate, Clone, Debug)] | ||||
| #[diesel(table_name = projects)] | ||||
| pub struct NewProject<'a> { | ||||
|     pub title: &'a str, | ||||
| pub struct NewProject { | ||||
|     #[validate(length( | ||||
|         min = "TITLE_LENGTH_MIN", | ||||
|         max = "TITLE_LENGTH_MAX", | ||||
|         code = "title_length" | ||||
|     ))] | ||||
|     pub title: String, | ||||
| } | ||||
|  | ||||
| impl NewProject { | ||||
|     pub fn new(title: String) -> Self { | ||||
|         Self { title } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,10 +3,10 @@ use diesel::prelude::*; | ||||
| use dotenvy::dotenv; | ||||
| use std::env; | ||||
|  | ||||
| pub(crate) fn establish_database_connection() -> PgConnection { | ||||
| pub(crate) fn establish_database_connection() -> ConnectionResult<PgConnection> { | ||||
|     dotenv().ok(); | ||||
|  | ||||
|     let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); | ||||
|     let database_url = | ||||
|         env::var("DATABASE_URL").expect("The environment variable DATABASE_URL must be set."); | ||||
|     PgConnection::establish(&database_url) | ||||
|         .unwrap_or_else(|_| panic!("error connecting to {}", database_url)) | ||||
| } | ||||
|   | ||||
| @@ -1,21 +1,33 @@ | ||||
| use crate::errors::error::Error; | ||||
| use crate::errors::error_vec::ErrorVec; | ||||
| use crate::errors::project_create_error::ProjectCreateError; | ||||
| use crate::models::project::{NewProject, Project}; | ||||
| use crate::server::database_connection::establish_database_connection; | ||||
| use diesel::{RunQueryDsl, SelectableHelper}; | ||||
| use dioxus::prelude::*; | ||||
| use validator::Validate; | ||||
|  | ||||
| #[server] | ||||
| pub(crate) async fn create_project(title: String) -> Result<Project, ServerFnError> { | ||||
| pub(crate) async fn create_project( | ||||
|     new_project: NewProject, | ||||
| ) -> Result<Project, ServerFnError<ErrorVec<ProjectCreateError>>> { | ||||
|     use crate::schema::projects; | ||||
|  | ||||
|     let mut connection = establish_database_connection(); | ||||
|     new_project | ||||
|         .validate() | ||||
|         .map_err::<ErrorVec<ProjectCreateError>, _>(|errors| errors.into())?; | ||||
|  | ||||
|     let new_project = NewProject { | ||||
|         title: title.as_str(), | ||||
|     }; | ||||
|     let mut connection = | ||||
|         establish_database_connection().or::<ErrorVec<ProjectCreateError>>(Err(vec![ | ||||
|             ProjectCreateError::Error(Error::ServerInternal), | ||||
|         ] | ||||
|         .into()))?; | ||||
|  | ||||
|     Ok(diesel::insert_into(projects::table) | ||||
|     let new_project = diesel::insert_into(projects::table) | ||||
|         .values(&new_project) | ||||
|         .returning(Project::as_returning()) | ||||
|         .get_result(&mut connection) | ||||
|         .expect("error saving a new project")) | ||||
|         .expect("error saving a new project"); | ||||
|  | ||||
|     Ok(new_project) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user