From 97711358eb35727d13a270a355e73fb07b452369 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 19:04:52 -0400 Subject: [PATCH 01/29] Init Cargo --- server/Cargo.lock | 7 +++++++ server/Cargo.toml | 7 +++++++ server/src/main.rs | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 server/Cargo.lock create mode 100644 server/Cargo.toml create mode 100644 server/src/main.rs diff --git a/server/Cargo.lock b/server/Cargo.lock new file mode 100644 index 0000000..3bde68f --- /dev/null +++ b/server/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "personal-tracker-server" +version = "0.1.0" diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000..6272760 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "personal-tracker-server" +version = "0.1.0" +edition = "2021" +license = "GPL-3.0-only" + +[dependencies] diff --git a/server/src/main.rs b/server/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/server/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} -- 2.45.2 From 95c1cf2930d2d80e9a2c15d4bd2d99ee500a4f07 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 19:24:52 -0400 Subject: [PATCH 02/29] Implement Basic Web Server --- server/Cargo.lock | 1313 ++++++++++++++++++++++++++++++++++++++++++++ server/Cargo.toml | 1 + server/src/main.rs | 15 +- 3 files changed, 1327 insertions(+), 2 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 3bde68f..eccf688 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -2,6 +2,1319 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-http" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.60", +] + +[[package]] +name = "actix-router" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" +dependencies = [ + "bytestring", + "http", + "regex", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2", + "time", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "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 = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "bytestring" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +dependencies = [ + "bytes", +] + +[[package]] +name = "cc" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "personal-tracker-server" version = "0.1.0" +dependencies = [ + "actix-web", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "serde_json" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/server/Cargo.toml b/server/Cargo.toml index 6272760..a9c41c4 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" license = "GPL-3.0-only" [dependencies] +actix-web = "4.5.1" diff --git a/server/src/main.rs b/server/src/main.rs index e7a11a9..e8a9cdc 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,3 +1,14 @@ -fn main() { - println!("Hello, world!"); +use actix_web::{App, get, HttpResponse, HttpServer, Responder}; + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + HttpServer::new(|| App::new().service(hello)) + .bind(("127.0.0.1", 8000))? + .run() + .await +} + +#[get("/")] +async fn hello() -> impl Responder { + HttpResponse::Ok().body("Hello World!") } -- 2.45.2 From ce121cbf232ee2f166c41be491a501d8bb99ae04 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 19:33:47 -0400 Subject: [PATCH 03/29] Print copyright and server message on startup --- server/Cargo.lock | 17 +++++++++++++++++ server/Cargo.toml | 1 + server/src/main.rs | 11 ++++++++++- server/src/util.rs | 9 +++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 server/src/util.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index eccf688..4c4d4be 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -328,6 +328,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -591,6 +601,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.154" @@ -724,6 +740,7 @@ name = "personal-tracker-server" version = "0.1.0" dependencies = [ "actix-web", + "colored", ] [[package]] diff --git a/server/Cargo.toml b/server/Cargo.toml index a9c41c4..48ac010 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -6,3 +6,4 @@ license = "GPL-3.0-only" [dependencies] actix-web = "4.5.1" +colored = "2.1.0" diff --git a/server/src/main.rs b/server/src/main.rs index e8a9cdc..781782f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,9 +1,18 @@ use actix_web::{App, get, HttpResponse, HttpServer, Responder}; +mod util; + #[actix_web::main] async fn main() -> std::io::Result<()> { + util::print_copyright_notice(); + + let port = 8000; + let bind_addr = "127.0.0.1"; + + util::notice_println(format!("Starting server on {}:{}", bind_addr, port)); + HttpServer::new(|| App::new().service(hello)) - .bind(("127.0.0.1", 8000))? + .bind((bind_addr, port))? .run() .await } diff --git a/server/src/util.rs b/server/src/util.rs new file mode 100644 index 0000000..df4747b --- /dev/null +++ b/server/src/util.rs @@ -0,0 +1,9 @@ +use colored::Colorize; + +pub fn print_copyright_notice() { + println!("{}", "Personal Tracker Server Copyright (C) 2024 Luke Harding \nThis program comes with ABSOLUTELY NO WARRANTY\nThis is free software, and you are welcome to redistribute it under certain conditions\n".italic()); +} + +pub fn notice_println(msg: impl Into) { + println!("{}", msg.into().green().bold()); +} -- 2.45.2 From 73c97a2c5af61402963a42359435bc434249c1f0 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 19:49:26 -0400 Subject: [PATCH 04/29] Add new warn_println() fn --- server/src/util.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/util.rs b/server/src/util.rs index df4747b..cfbddaf 100644 --- a/server/src/util.rs +++ b/server/src/util.rs @@ -7,3 +7,7 @@ pub fn print_copyright_notice() { pub fn notice_println(msg: impl Into) { println!("{}", msg.into().green().bold()); } + +pub fn warn_println(msg: impl Into) { + eprintln!("{}", msg.into().yellow().bold()); +} -- 2.45.2 From 2bff93ff435dbfc285fee46471466dacd07590fd Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 19:49:48 -0400 Subject: [PATCH 05/29] Allow use of custom port and bind_addr. --- server/src/main.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index 781782f..84703e4 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,13 +1,31 @@ +use std::env; + use actix_web::{App, get, HttpResponse, HttpServer, Responder}; +use crate::util::warn_println; + mod util; #[actix_web::main] async fn main() -> std::io::Result<()> { util::print_copyright_notice(); - let port = 8000; - let bind_addr = "127.0.0.1"; + // Default Server Values + let mut port = 8000; + let mut bind_addr = String::from("127.0.0.1"); + + // If env variable for port or bind_addr is present use that instead of default. + if let Ok(env_port) = env::var("PORT") { + if let Ok(env_port) = env_port.parse::() { + port = env_port; + } else { + warn_println("Failed to parse PORT env variable using default value."); + } + } + + if let Ok(env_addr) = env::var("BIND_ADDR") { + bind_addr = env_addr; + } util::notice_println(format!("Starting server on {}:{}", bind_addr, port)); -- 2.45.2 From b0cedf28662ac22685efb9eb42d91c5846d97bee Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 20:09:52 -0400 Subject: [PATCH 06/29] Add copyright identifiers --- server/src/main.rs | 7 ++++--- server/src/util.rs | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index 84703e4..66002c1 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,9 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-Only +// Copyright (C) 2024 Luke Harding + use std::env; use actix_web::{App, get, HttpResponse, HttpServer, Responder}; -use crate::util::warn_println; - mod util; #[actix_web::main] @@ -19,7 +20,7 @@ async fn main() -> std::io::Result<()> { if let Ok(env_port) = env_port.parse::() { port = env_port; } else { - warn_println("Failed to parse PORT env variable using default value."); + util::warn_println("Failed to parse PORT env variable using default value."); } } diff --git a/server/src/util.rs b/server/src/util.rs index cfbddaf..151e20a 100644 --- a/server/src/util.rs +++ b/server/src/util.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-Only +// Copyright (C) 2024 Luke Harding + use colored::Colorize; pub fn print_copyright_notice() { -- 2.45.2 From 969791f127b2b60ad6a86028724487d9d45da9c9 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 20:52:48 -0400 Subject: [PATCH 07/29] Add postgres container for development --- server/.env.example | 3 +++ server/README.md | 5 +++++ server/compose-dev.yaml | 13 +++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 server/.env.example create mode 100644 server/README.md create mode 100644 server/compose-dev.yaml diff --git a/server/.env.example b/server/.env.example new file mode 100644 index 0000000..72a2fbc --- /dev/null +++ b/server/.env.example @@ -0,0 +1,3 @@ +DB_PASSWORD= +DB_USER= +DB_HOST= \ No newline at end of file diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..8f4c491 --- /dev/null +++ b/server/README.md @@ -0,0 +1,5 @@ +# Personal Tracker Server + +The server! + +## Developer Setup diff --git a/server/compose-dev.yaml b/server/compose-dev.yaml new file mode 100644 index 0000000..be84230 --- /dev/null +++ b/server/compose-dev.yaml @@ -0,0 +1,13 @@ +# Docker Compose for Development Machines + +services: + postgres: + container_name: personal-tracker-dev-db + image: postgres:16 + ports: + - 127.0.0.1:5432:5432 + volumes: + - ./dev-db/postgres:/var/lib/postgresql/data + environment: + POSTGRES_USER: "${DB_USER}" + POSTGRES_PASSWORD: "${DB_PASSWORD}" \ No newline at end of file -- 2.45.2 From 2ca439ac6d854b7bdd46c2cc47313541295afc49 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 20:59:35 -0400 Subject: [PATCH 08/29] Add PORT and BIND_ADDR envs to .env --- server/.env.example | 3 +++ server/Cargo.lock | 7 +++++++ server/Cargo.toml | 1 + server/src/main.rs | 7 +++++++ 4 files changed, 18 insertions(+) diff --git a/server/.env.example b/server/.env.example index 72a2fbc..e7bc2ae 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,3 +1,6 @@ +PORT= +BIND_ADDR= + DB_PASSWORD= DB_USER= DB_HOST= \ No newline at end of file diff --git a/server/Cargo.lock b/server/Cargo.lock index 4c4d4be..fedbae6 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -415,6 +415,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -741,6 +747,7 @@ version = "0.1.0" dependencies = [ "actix-web", "colored", + "dotenvy", ] [[package]] diff --git a/server/Cargo.toml b/server/Cargo.toml index 48ac010..32a6ed8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -7,3 +7,4 @@ license = "GPL-3.0-only" [dependencies] actix-web = "4.5.1" colored = "2.1.0" +dotenvy = "0.15.7" diff --git a/server/src/main.rs b/server/src/main.rs index 66002c1..b6fadc9 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,6 +5,8 @@ use std::env; use actix_web::{App, get, HttpResponse, HttpServer, Responder}; +use crate::util::warn_println; + mod util; #[actix_web::main] @@ -15,6 +17,11 @@ async fn main() -> std::io::Result<()> { let mut port = 8000; let mut bind_addr = String::from("127.0.0.1"); + // Load .env + if let Err(e) = dotenvy::dotenv() { + warn_println(format!("Failed to load dotenv: {}", e)) + }; + // If env variable for port or bind_addr is present use that instead of default. if let Ok(env_port) = env::var("PORT") { if let Ok(env_port) = env_port.parse::() { -- 2.45.2 From 0e7f15786ddd04481dc0ca5a63e9e99ec95c36d4 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 21:09:35 -0400 Subject: [PATCH 09/29] Change .env to include DB_NAME variable and DATABASE_URL --- server/.env.example | 3 ++- server/compose-dev.yaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server/.env.example b/server/.env.example index e7bc2ae..2fc7541 100644 --- a/server/.env.example +++ b/server/.env.example @@ -3,4 +3,5 @@ BIND_ADDR= DB_PASSWORD= DB_USER= -DB_HOST= \ No newline at end of file +DB_NAME= +DATABASE_URL= \ No newline at end of file diff --git a/server/compose-dev.yaml b/server/compose-dev.yaml index be84230..e8e931f 100644 --- a/server/compose-dev.yaml +++ b/server/compose-dev.yaml @@ -10,4 +10,5 @@ services: - ./dev-db/postgres:/var/lib/postgresql/data environment: POSTGRES_USER: "${DB_USER}" - POSTGRES_PASSWORD: "${DB_PASSWORD}" \ No newline at end of file + POSTGRES_PASSWORD: "${DB_PASSWORD}" + POSTGRES_DB: "${DB_NAME}" \ No newline at end of file -- 2.45.2 From 2f856a30227341ca5d720b092e667d9b0d578255 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 21:10:11 -0400 Subject: [PATCH 10/29] Make util use uniform --- server/src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index b6fadc9..784d650 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,8 +5,6 @@ use std::env; use actix_web::{App, get, HttpResponse, HttpServer, Responder}; -use crate::util::warn_println; - mod util; #[actix_web::main] @@ -19,7 +17,7 @@ async fn main() -> std::io::Result<()> { // Load .env if let Err(e) = dotenvy::dotenv() { - warn_println(format!("Failed to load dotenv: {}", e)) + util::warn_println(format!("Failed to load dotenv: {}", e)) }; // If env variable for port or bind_addr is present use that instead of default. -- 2.45.2 From ba1bddc72c78d0be9dacbe406ad1e645417403b9 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 21:10:56 -0400 Subject: [PATCH 11/29] Diesel initial setup --- server/Cargo.lock | 56 +++++++++++++++++++ server/Cargo.toml | 1 + server/diesel.toml | 9 +++ server/migrations/.keep | 0 .../down.sql | 6 ++ .../up.sql | 36 ++++++++++++ 6 files changed, 108 insertions(+) create mode 100644 server/diesel.toml create mode 100644 server/migrations/.keep create mode 100644 server/migrations/00000000000000_diesel_initial_setup/down.sql create mode 100644 server/migrations/00000000000000_diesel_initial_setup/up.sql diff --git a/server/Cargo.lock b/server/Cargo.lock index fedbae6..8c7fa77 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -296,6 +296,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -405,6 +411,40 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "diesel" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" +dependencies = [ + "bitflags", + "byteorder", + "diesel_derives", + "itoa", + "pq-sys", +] + +[[package]] +name = "diesel_derives" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14701062d6bed917b5c7103bdffaee1e4609279e240488ad24e7bd979ca6866c" +dependencies = [ + "diesel_table_macro_syntax", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" +dependencies = [ + "syn 2.0.60", +] + [[package]] name = "digest" version = "0.10.7" @@ -747,6 +787,7 @@ version = "0.1.0" dependencies = [ "actix-web", "colored", + "diesel", "dotenvy", ] @@ -780,6 +821,15 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pq-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0052426df997c0cbd30789eb44ca097e3541717a7b8fa36b1c464ee7edebd" +dependencies = [ + "vcpkg", +] + [[package]] name = "proc-macro2" version = "1.0.81" @@ -1144,6 +1194,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/server/Cargo.toml b/server/Cargo.toml index 32a6ed8..2aa1d23 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -7,4 +7,5 @@ license = "GPL-3.0-only" [dependencies] actix-web = "4.5.1" colored = "2.1.0" +diesel = { version = "2.1.6", features = ["postgres"] } dotenvy = "0.15.7" diff --git a/server/diesel.toml b/server/diesel.toml new file mode 100644 index 0000000..c028f4a --- /dev/null +++ b/server/diesel.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId"] + +[migrations_directory] +dir = "migrations" diff --git a/server/migrations/.keep b/server/migrations/.keep new file mode 100644 index 0000000..e69de29 diff --git a/server/migrations/00000000000000_diesel_initial_setup/down.sql b/server/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/server/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/server/migrations/00000000000000_diesel_initial_setup/up.sql b/server/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..d68895b --- /dev/null +++ b/server/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,36 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; -- 2.45.2 From 9a637b888f9f8e81be44419e27dc1ce3995fe6cf Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 22:07:30 -0400 Subject: [PATCH 12/29] Create task table migration --- server/migrations/2024-05-03-015925_create_tasks/down.sql | 2 ++ server/migrations/2024-05-03-015925_create_tasks/up.sql | 7 +++++++ server/src/main.rs | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 server/migrations/2024-05-03-015925_create_tasks/down.sql create mode 100644 server/migrations/2024-05-03-015925_create_tasks/up.sql diff --git a/server/migrations/2024-05-03-015925_create_tasks/down.sql b/server/migrations/2024-05-03-015925_create_tasks/down.sql new file mode 100644 index 0000000..60b9f8a --- /dev/null +++ b/server/migrations/2024-05-03-015925_create_tasks/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE tasks; \ No newline at end of file diff --git a/server/migrations/2024-05-03-015925_create_tasks/up.sql b/server/migrations/2024-05-03-015925_create_tasks/up.sql new file mode 100644 index 0000000..960c1d0 --- /dev/null +++ b/server/migrations/2024-05-03-015925_create_tasks/up.sql @@ -0,0 +1,7 @@ +-- Your SQL goes here +CREATE TABLE IF NOT EXISTS tasks ( + id UUID PRIMARY KEY, + title TEXT NOT NULL, + description TEXT NOT NULL, + complete BOOLEAN NOT NULL DEFAULT FALSE +); \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index 784d650..0db0bf4 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -25,7 +25,7 @@ async fn main() -> std::io::Result<()> { if let Ok(env_port) = env_port.parse::() { port = env_port; } else { - util::warn_println("Failed to parse PORT env variable using default value."); + util::warn_println("Failed to parse PORT env variable; using default value."); } } -- 2.45.2 From a9bcfe154a9a98324aea48f7571631e793ad9fa8 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 23:22:30 -0400 Subject: [PATCH 13/29] Add due date to migration --- server/migrations/2024-05-03-015925_create_tasks/up.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/migrations/2024-05-03-015925_create_tasks/up.sql b/server/migrations/2024-05-03-015925_create_tasks/up.sql index 960c1d0..034138c 100644 --- a/server/migrations/2024-05-03-015925_create_tasks/up.sql +++ b/server/migrations/2024-05-03-015925_create_tasks/up.sql @@ -3,5 +3,6 @@ CREATE TABLE IF NOT EXISTS tasks ( id UUID PRIMARY KEY, title TEXT NOT NULL, description TEXT NOT NULL, - complete BOOLEAN NOT NULL DEFAULT FALSE + complete BOOLEAN NOT NULL DEFAULT FALSE, + due_date TIMESTAMP NOT NULL ); \ No newline at end of file -- 2.45.2 From 61329db39ffbcb4f7446831d7fcf15533923bd29 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 23:22:52 -0400 Subject: [PATCH 14/29] Add error println --- server/src/util.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/util.rs b/server/src/util.rs index 151e20a..7aa90fe 100644 --- a/server/src/util.rs +++ b/server/src/util.rs @@ -14,3 +14,7 @@ pub fn notice_println(msg: impl Into) { pub fn warn_println(msg: impl Into) { eprintln!("{}", msg.into().yellow().bold()); } + +pub fn err_println(msg: impl Into) { + eprintln!("{}", msg.into().red().bold()); +} -- 2.45.2 From 1fb09255283718738fa503c29c0adb6e5aa7d0bf Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Thu, 2 May 2024 23:24:14 -0400 Subject: [PATCH 15/29] Add migration check and db connection check to startup --- server/Cargo.lock | 243 +++++++++++++++++++++++++++++++++++++++++++ server/Cargo.toml | 5 +- server/src/db/mod.rs | 21 ++++ server/src/main.rs | 28 ++++- server/src/models.rs | 17 +++ server/src/schema.rs | 11 ++ 6 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 server/src/db/mod.rs create mode 100644 server/src/models.rs create mode 100644 server/src/schema.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index 8c7fa77..ddd4d16 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -233,6 +233,21 @@ dependencies = [ "alloc-no-stdlib", ] +[[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 = "autocfg" version = "1.2.0" @@ -296,6 +311,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -334,6 +355,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "colored" version = "2.1.0" @@ -361,6 +396,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -419,9 +460,11 @@ checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" dependencies = [ "bitflags", "byteorder", + "chrono", "diesel_derives", "itoa", "pq-sys", + "uuid", ] [[package]] @@ -436,6 +479,17 @@ dependencies = [ "syn 2.0.60", ] +[[package]] +name = "diesel_migrations" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6036b3f0120c5961381b570ee20a02432d7e2d27ea60de9578799cf9156914ac" +dependencies = [ + "diesel", + "migrations_internals", + "migrations_macros", +] + [[package]] name = "diesel_table_macro_syntax" version = "0.1.0" @@ -606,6 +660,29 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +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 = "idna" version = "0.5.0" @@ -641,6 +718,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -698,6 +784,27 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "migrations_internals" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f23f71580015254b020e856feac3df5878c2c7a8812297edd6c0a485ac9dada" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "migrations_macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce3325ac70e67bbab5bd837a31cae01f1a6db64e0e744a33cb03a543469ef08" +dependencies = [ + "migrations_internals", + "proc-macro2", + "quote", +] + [[package]] name = "mime" version = "0.3.17" @@ -731,6 +838,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + [[package]] name = "object" version = "0.32.2" @@ -786,9 +902,12 @@ name = "personal-tracker-server" version = "0.1.0" dependencies = [ "actix-web", + "chrono", "colored", "diesel", + "diesel_migrations", "dotenvy", + "uuid", ] [[package]] @@ -980,6 +1099,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1136,6 +1264,40 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" @@ -1194,6 +1356,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -1212,6 +1383,69 @@ 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.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1351,6 +1585,15 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/server/Cargo.toml b/server/Cargo.toml index 2aa1d23..a88b703 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -6,6 +6,9 @@ license = "GPL-3.0-only" [dependencies] actix-web = "4.5.1" +chrono = "0.4.38" colored = "2.1.0" -diesel = { version = "2.1.6", features = ["postgres"] } +diesel = { version = "2.1.6", features = ["postgres", "uuid", "chrono"] } +diesel_migrations = { version = "2.1.0", features = ["postgres"] } dotenvy = "0.15.7" +uuid = { version = "1.8.0", features = ["v4"] } diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs new file mode 100644 index 0000000..639f412 --- /dev/null +++ b/server/src/db/mod.rs @@ -0,0 +1,21 @@ +use std::{env, error}; + +use diesel::{Connection, PgConnection}; +use diesel::pg::Pg; +use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; + +pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); + +pub fn establish_connection() -> Result> { + let database_url = env::var("DATABASE_URL")?; + + Ok(PgConnection::establish(&database_url)?) +} + +pub fn run_migrations( + connection: &mut impl MigrationHarness, +) -> Result<(), Box> { + connection.run_pending_migrations(MIGRATIONS)?; + + Ok(()) +} diff --git a/server/src/main.rs b/server/src/main.rs index 0db0bf4..55dcb33 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,20 +1,25 @@ // SPDX-License-Identifier: GPL-3.0-Only // Copyright (C) 2024 Luke Harding -use std::env; +use std::{env, io}; use actix_web::{App, get, HttpResponse, HttpServer, Responder}; -mod util; +pub mod db; +pub mod models; +pub mod schema; +pub mod util; #[actix_web::main] -async fn main() -> std::io::Result<()> { +async fn main() -> io::Result<()> { util::print_copyright_notice(); // Default Server Values let mut port = 8000; let mut bind_addr = String::from("127.0.0.1"); + util::notice_println("Loading Environment Variables"); + // Load .env if let Err(e) = dotenvy::dotenv() { util::warn_println(format!("Failed to load dotenv: {}", e)) @@ -33,6 +38,23 @@ async fn main() -> std::io::Result<()> { bind_addr = env_addr; } + util::notice_println("Connecting to DB."); + let mut conn = match db::establish_connection() { + Ok(conn) => conn, + Err(e) => { + util::err_println("Failed to connect to DB. Aborting."); + eprintln!("{}", e); + return Ok(()); + } + }; + + util::notice_println("Running Migrations"); + if let Err(e) = db::run_migrations(&mut conn) { + util::err_println("Failed to run migrations. Aborting."); + eprintln!("{}", e); + return Ok(()); + } + util::notice_println(format!("Starting server on {}:{}", bind_addr, port)); HttpServer::new(|| App::new().service(hello)) diff --git a/server/src/models.rs b/server/src/models.rs new file mode 100644 index 0000000..883eef0 --- /dev/null +++ b/server/src/models.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-Only +// Copyright (C) 2024 Luke Harding + +use chrono::NaiveDateTime; +use diesel::prelude::*; +use uuid::Uuid; + +#[derive(Queryable, Selectable)] +#[diesel(table_name = crate::schema::tasks)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Task { + pub id: Uuid, + pub title: String, + pub description: String, + pub complete: bool, + pub due_date: NaiveDateTime, +} diff --git a/server/src/schema.rs b/server/src/schema.rs new file mode 100644 index 0000000..50a840e --- /dev/null +++ b/server/src/schema.rs @@ -0,0 +1,11 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + tasks (id) { + id -> Uuid, + title -> Text, + description -> Text, + complete -> Bool, + due_date -> Timestamp, + } +} -- 2.45.2 From d7e5dd7df48027be55eed058319e3899316c7c2b Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 01:01:06 -0400 Subject: [PATCH 16/29] Add empty string checks to PORT and BIND_ADDR env vars --- server/src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index 55dcb33..5767f39 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -29,13 +29,15 @@ async fn main() -> io::Result<()> { if let Ok(env_port) = env::var("PORT") { if let Ok(env_port) = env_port.parse::() { port = env_port; - } else { + } else if !env_port.is_empty() { util::warn_println("Failed to parse PORT env variable; using default value."); } } if let Ok(env_addr) = env::var("BIND_ADDR") { - bind_addr = env_addr; + if !env_addr.is_empty() { + bind_addr = env_addr; + } } util::notice_println("Connecting to DB."); -- 2.45.2 From 7681079cb145d6908984a48e92b01b5f67886802 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 01:04:30 -0400 Subject: [PATCH 17/29] Relocate model and schema to the db module --- server/src/db/mod.rs | 3 +++ server/src/{ => db}/models.rs | 2 +- server/src/{ => db}/schema.rs | 0 server/src/main.rs | 2 -- 4 files changed, 4 insertions(+), 3 deletions(-) rename server/src/{ => db}/models.rs (88%) rename server/src/{ => db}/schema.rs (100%) diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 639f412..7a2d337 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -4,6 +4,9 @@ use diesel::{Connection, PgConnection}; use diesel::pg::Pg; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; +pub mod models; +pub mod schema; + pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); pub fn establish_connection() -> Result> { diff --git a/server/src/models.rs b/server/src/db/models.rs similarity index 88% rename from server/src/models.rs rename to server/src/db/models.rs index 883eef0..9b26e0a 100644 --- a/server/src/models.rs +++ b/server/src/db/models.rs @@ -6,7 +6,7 @@ use diesel::prelude::*; use uuid::Uuid; #[derive(Queryable, Selectable)] -#[diesel(table_name = crate::schema::tasks)] +#[diesel(table_name = crate::db::schema::tasks)] #[diesel(check_for_backend(diesel::pg::Pg))] pub struct Task { pub id: Uuid, diff --git a/server/src/schema.rs b/server/src/db/schema.rs similarity index 100% rename from server/src/schema.rs rename to server/src/db/schema.rs diff --git a/server/src/main.rs b/server/src/main.rs index 5767f39..4b265e8 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -6,8 +6,6 @@ use std::{env, io}; use actix_web::{App, get, HttpResponse, HttpServer, Responder}; pub mod db; -pub mod models; -pub mod schema; pub mod util; #[actix_web::main] -- 2.45.2 From 14de8cd47926386c2517e7189670822015e88a0b Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 01:08:32 -0400 Subject: [PATCH 18/29] Move schema back to correct place. oops --- server/src/db/mod.rs | 4 +++- server/src/db/models.rs | 2 +- server/src/main.rs | 1 + server/src/{db => }/schema.rs | 0 4 files changed, 5 insertions(+), 2 deletions(-) rename server/src/{db => }/schema.rs (100%) diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 7a2d337..93e248f 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-Only +// Copyright (C) 2024 Luke Harding + use std::{env, error}; use diesel::{Connection, PgConnection}; @@ -5,7 +8,6 @@ use diesel::pg::Pg; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; pub mod models; -pub mod schema; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); diff --git a/server/src/db/models.rs b/server/src/db/models.rs index 9b26e0a..883eef0 100644 --- a/server/src/db/models.rs +++ b/server/src/db/models.rs @@ -6,7 +6,7 @@ use diesel::prelude::*; use uuid::Uuid; #[derive(Queryable, Selectable)] -#[diesel(table_name = crate::db::schema::tasks)] +#[diesel(table_name = crate::schema::tasks)] #[diesel(check_for_backend(diesel::pg::Pg))] pub struct Task { pub id: Uuid, diff --git a/server/src/main.rs b/server/src/main.rs index 4b265e8..7ee175e 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -7,6 +7,7 @@ use actix_web::{App, get, HttpResponse, HttpServer, Responder}; pub mod db; pub mod util; +pub mod schema; #[actix_web::main] async fn main() -> io::Result<()> { diff --git a/server/src/db/schema.rs b/server/src/schema.rs similarity index 100% rename from server/src/db/schema.rs rename to server/src/schema.rs -- 2.45.2 From 517794d0dbc775344927532bae6f82bc4abbbfd7 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 10:38:54 -0400 Subject: [PATCH 19/29] Add get_tasks endpoint --- server/Cargo.lock | 5 +++++ server/Cargo.toml | 8 +++++--- server/src/api/mod.rs | 16 ++++++++++++++++ server/src/db/mod.rs | 12 +++++++++++- server/src/db/models.rs | 3 ++- server/src/main.rs | 12 ++++-------- 6 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 server/src/api/mod.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index ddd4d16..a73f78e 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -365,6 +365,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-targets 0.52.5", ] @@ -464,6 +465,7 @@ dependencies = [ "diesel_derives", "itoa", "pq-sys", + "serde_json", "uuid", ] @@ -907,6 +909,8 @@ dependencies = [ "diesel", "diesel_migrations", "dotenvy", + "serde", + "serde_json", "uuid", ] @@ -1363,6 +1367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", + "serde", ] [[package]] diff --git a/server/Cargo.toml b/server/Cargo.toml index a88b703..b9e2316 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -6,9 +6,11 @@ license = "GPL-3.0-only" [dependencies] actix-web = "4.5.1" -chrono = "0.4.38" +chrono = { version = "0.4.38", features = ["serde"] } colored = "2.1.0" -diesel = { version = "2.1.6", features = ["postgres", "uuid", "chrono"] } +diesel = { version = "2.1.6", features = ["postgres", "uuid", "chrono", "serde_json"] } diesel_migrations = { version = "2.1.0", features = ["postgres"] } dotenvy = "0.15.7" -uuid = { version = "1.8.0", features = ["v4"] } +serde = { version = "1.0.200", features = ["derive"] } +serde_json = "1.0.116" +uuid = { version = "1.8.0", features = ["v4", "serde"] } diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs new file mode 100644 index 0000000..83248b0 --- /dev/null +++ b/server/src/api/mod.rs @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-Only +// Copyright (C) 2024 Luke Harding + +use actix_web::{get, HttpResponse, Responder}; + +use crate::db; + +#[get("/get_tasks")] +pub async fn get_tasks() -> impl Responder { + let tasks = match db::get_tasks().await { + Ok(tasks) => tasks, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + HttpResponse::Ok().json(tasks) +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 93e248f..79e245e 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -3,10 +3,12 @@ use std::{env, error}; -use diesel::{Connection, PgConnection}; +use diesel::{Connection, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper}; use diesel::pg::Pg; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; +use models::Task; + pub mod models; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); @@ -24,3 +26,11 @@ pub fn run_migrations( Ok(()) } + +pub async fn get_tasks() -> Result, Box> { + use crate::schema::tasks::dsl::*; + + let conn = &mut establish_connection()?; + + Ok(tasks.select(Task::as_select()).load(conn)?) +} diff --git a/server/src/db/models.rs b/server/src/db/models.rs index 883eef0..9bf8642 100644 --- a/server/src/db/models.rs +++ b/server/src/db/models.rs @@ -3,9 +3,10 @@ use chrono::NaiveDateTime; use diesel::prelude::*; +use serde::{Deserialize, Serialize}; use uuid::Uuid; -#[derive(Queryable, Selectable)] +#[derive(Queryable, Selectable, Serialize, Deserialize)] #[diesel(table_name = crate::schema::tasks)] #[diesel(check_for_backend(diesel::pg::Pg))] pub struct Task { diff --git a/server/src/main.rs b/server/src/main.rs index 7ee175e..1162c84 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -3,11 +3,12 @@ use std::{env, io}; -use actix_web::{App, get, HttpResponse, HttpServer, Responder}; +use actix_web::{App, HttpServer}; +mod api; pub mod db; -pub mod util; pub mod schema; +pub mod util; #[actix_web::main] async fn main() -> io::Result<()> { @@ -58,13 +59,8 @@ async fn main() -> io::Result<()> { util::notice_println(format!("Starting server on {}:{}", bind_addr, port)); - HttpServer::new(|| App::new().service(hello)) + HttpServer::new(|| App::new().service(api::get_tasks)) .bind((bind_addr, port))? .run() .await } - -#[get("/")] -async fn hello() -> impl Responder { - HttpResponse::Ok().body("Hello World!") -} -- 2.45.2 From 9d492f6f9195ae80468c668b8dfd873abb48eb66 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 12:05:46 -0400 Subject: [PATCH 20/29] Add database_url to app state --- server/src/api/mod.rs | 10 +++++++--- server/src/db/mod.rs | 10 ++++------ server/src/main.rs | 30 ++++++++++++++++++++++++------ 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 83248b0..b47657d 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,13 +1,17 @@ // SPDX-License-Identifier: GPL-3.0-Only // Copyright (C) 2024 Luke Harding -use actix_web::{get, HttpResponse, Responder}; +use actix_web::{get, HttpResponse, Responder, web}; use crate::db; +pub struct AppState { + pub database_url: String, +} + #[get("/get_tasks")] -pub async fn get_tasks() -> impl Responder { - let tasks = match db::get_tasks().await { +pub async fn get_tasks(data: web::Data) -> impl Responder { + let tasks = match db::get_tasks(data.database_url.clone()).await { Ok(tasks) => tasks, Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), }; diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 79e245e..f9804f1 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-Only // Copyright (C) 2024 Luke Harding -use std::{env, error}; +use std::error; use diesel::{Connection, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper}; use diesel::pg::Pg; @@ -13,9 +13,7 @@ pub mod models; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); -pub fn establish_connection() -> Result> { - let database_url = env::var("DATABASE_URL")?; - +pub fn establish_connection(database_url: &String) -> Result> { Ok(PgConnection::establish(&database_url)?) } @@ -27,10 +25,10 @@ pub fn run_migrations( Ok(()) } -pub async fn get_tasks() -> Result, Box> { +pub async fn get_tasks(database_url: String) -> Result, Box> { use crate::schema::tasks::dsl::*; - let conn = &mut establish_connection()?; + let conn = &mut establish_connection(&database_url)?; Ok(tasks.select(Task::as_select()).load(conn)?) } diff --git a/server/src/main.rs b/server/src/main.rs index 1162c84..76c90ca 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -3,7 +3,9 @@ use std::{env, io}; -use actix_web::{App, HttpServer}; +use actix_web::{App, HttpServer, web}; + +use crate::api::AppState; mod api; pub mod db; @@ -17,6 +19,7 @@ async fn main() -> io::Result<()> { // Default Server Values let mut port = 8000; let mut bind_addr = String::from("127.0.0.1"); + let mut database_url = String::new(); util::notice_println("Loading Environment Variables"); @@ -40,8 +43,17 @@ async fn main() -> io::Result<()> { } } + if let Ok(env_database) = env::var("DATABASE_URL") { + if !env_database.is_empty() { + database_url = env_database; + } else { + util::err_println("No DATABASE_URL found. Aborting,"); + return Ok(()); + } + } + util::notice_println("Connecting to DB."); - let mut conn = match db::establish_connection() { + let mut conn = match db::establish_connection(&database_url) { Ok(conn) => conn, Err(e) => { util::err_println("Failed to connect to DB. Aborting."); @@ -59,8 +71,14 @@ async fn main() -> io::Result<()> { util::notice_println(format!("Starting server on {}:{}", bind_addr, port)); - HttpServer::new(|| App::new().service(api::get_tasks)) - .bind((bind_addr, port))? - .run() - .await + HttpServer::new(move || { + App::new() + .app_data(web::Data::new(AppState { + database_url: database_url.clone(), + })) + .service(api::get_tasks) + }) + .bind((bind_addr, port))? + .run() + .await } -- 2.45.2 From 2074d4b4769215c869d3aec71b46cab9c97a3ec0 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 12:24:46 -0400 Subject: [PATCH 21/29] Add get_task endpoint --- server/src/api/mod.rs | 13 +++++++++++++ server/src/db/mod.rs | 13 ++++++++++++- server/src/main.rs | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index b47657d..8e8c0f2 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -2,6 +2,7 @@ // Copyright (C) 2024 Luke Harding use actix_web::{get, HttpResponse, Responder, web}; +use uuid::Uuid; use crate::db; @@ -18,3 +19,15 @@ pub async fn get_tasks(data: web::Data) -> impl Responder { HttpResponse::Ok().json(tasks) } + +#[get("/get_task/{uuid}")] +pub async fn get_task(data: web::Data, path: web::Path) -> impl Responder { + let uuid = path.into_inner(); + + let task = match db::get_task(data.database_url.clone(), uuid).await { + Ok(task) => task, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + HttpResponse::Ok().json(task) +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index f9804f1..fdf2bcb 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -3,9 +3,12 @@ use std::error; -use diesel::{Connection, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper}; +use diesel::{ + Connection, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper, +}; use diesel::pg::Pg; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; +use uuid::Uuid; use models::Task; @@ -32,3 +35,11 @@ pub async fn get_tasks(database_url: String) -> Result, Box Result> { + use crate::schema::tasks::dsl::*; + + let conn = &mut establish_connection(&database_url)?; + + Ok(tasks.filter(id.eq(uuid)).first(conn)?) +} diff --git a/server/src/main.rs b/server/src/main.rs index 76c90ca..8cbd5cd 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -77,6 +77,7 @@ async fn main() -> io::Result<()> { database_url: database_url.clone(), })) .service(api::get_tasks) + .service(api::get_task) }) .bind((bind_addr, port))? .run() -- 2.45.2 From f94e356f8e2f29c40281aaa8ca04070f7319b162 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 12:48:12 -0400 Subject: [PATCH 22/29] Add v1 namespace for versioned api --- server/src/api/mod.rs | 27 +++++---------------------- server/src/api/v1.rs | 33 +++++++++++++++++++++++++++++++++ server/src/main.rs | 3 +-- 3 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 server/src/api/v1.rs diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 8e8c0f2..26b7892 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,33 +1,16 @@ // SPDX-License-Identifier: GPL-3.0-Only // Copyright (C) 2024 Luke Harding -use actix_web::{get, HttpResponse, Responder, web}; -use uuid::Uuid; +use actix_web::web; -use crate::db; +pub mod v1; pub struct AppState { pub database_url: String, } -#[get("/get_tasks")] -pub async fn get_tasks(data: web::Data) -> impl Responder { - let tasks = match db::get_tasks(data.database_url.clone()).await { - Ok(tasks) => tasks, - Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), - }; +pub fn configure(cfg: &mut web::ServiceConfig) { + let scope = web::scope("/api").configure(v1::configure); - HttpResponse::Ok().json(tasks) -} - -#[get("/get_task/{uuid}")] -pub async fn get_task(data: web::Data, path: web::Path) -> impl Responder { - let uuid = path.into_inner(); - - let task = match db::get_task(data.database_url.clone(), uuid).await { - Ok(task) => task, - Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), - }; - - HttpResponse::Ok().json(task) + cfg.service(scope); } diff --git a/server/src/api/v1.rs b/server/src/api/v1.rs new file mode 100644 index 0000000..b5c92d8 --- /dev/null +++ b/server/src/api/v1.rs @@ -0,0 +1,33 @@ +use actix_web::{get, HttpResponse, Responder, web}; +use uuid::Uuid; + +use crate::api::AppState; +use crate::db; + +pub fn configure(cfg: &mut web::ServiceConfig) { + let scope = web::scope("/v1").service(get_task).service(get_tasks); + + cfg.service(scope); +} + +#[get("/get_tasks")] +pub async fn get_tasks(data: web::Data) -> impl Responder { + let tasks = match db::get_tasks(data.database_url.clone()).await { + Ok(tasks) => tasks, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + HttpResponse::Ok().json(tasks) +} + +#[get("/get_task/{uuid}")] +pub async fn get_task(data: web::Data, path: web::Path) -> impl Responder { + let uuid = path.into_inner(); + + let task = match db::get_task(data.database_url.clone(), uuid).await { + Ok(task) => task, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + HttpResponse::Ok().json(task) +} diff --git a/server/src/main.rs b/server/src/main.rs index 8cbd5cd..5271d28 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -76,8 +76,7 @@ async fn main() -> io::Result<()> { .app_data(web::Data::new(AppState { database_url: database_url.clone(), })) - .service(api::get_tasks) - .service(api::get_task) + .configure(api::configure) }) .bind((bind_addr, port))? .run() -- 2.45.2 From c6edcbd0096c34f5ff51c212d980f90171940786 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 13:10:48 -0400 Subject: [PATCH 23/29] Setup create_task endpoint --- server/src/api/v1.rs | 36 ++++++++++++++++++++++++++++++++++-- server/src/db/mod.rs | 26 ++++++++++++++++++++++++++ server/src/db/models.rs | 11 +++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/server/src/api/v1.rs b/server/src/api/v1.rs index b5c92d8..4d9d2fc 100644 --- a/server/src/api/v1.rs +++ b/server/src/api/v1.rs @@ -1,11 +1,16 @@ -use actix_web::{get, HttpResponse, Responder, web}; +use actix_web::{get, HttpResponse, post, Responder, web}; +use chrono::NaiveDateTime; +use serde::Deserialize; use uuid::Uuid; use crate::api::AppState; use crate::db; pub fn configure(cfg: &mut web::ServiceConfig) { - let scope = web::scope("/v1").service(get_task).service(get_tasks); + let scope = web::scope("/v1") + .service(get_task) + .service(get_tasks) + .service(create_task); cfg.service(scope); } @@ -31,3 +36,30 @@ pub async fn get_task(data: web::Data, path: web::Path) -> impl HttpResponse::Ok().json(task) } + +#[derive(Deserialize)] +struct JsonTask { + pub title: String, + pub description: String, + pub due_date: NaiveDateTime, +} + +#[post("/create_task")] +pub async fn create_task(data: web::Data, task: web::Json) -> impl Responder { + let uuid = Uuid::new_v4(); + + let new_task = match db::create_task( + data.database_url.clone(), + uuid, + &task.title, + &task.description, + task.due_date, + ) + .await + { + Ok(task) => task, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + HttpResponse::Ok().json(new_task) +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index fdf2bcb..8529bf8 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -3,6 +3,7 @@ use std::error; +use chrono::NaiveDateTime; use diesel::{ Connection, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper, }; @@ -12,6 +13,9 @@ use uuid::Uuid; use models::Task; +use crate::db::models::NewTask; +use crate::schema::tasks; + pub mod models; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); @@ -43,3 +47,25 @@ pub async fn get_task(database_url: String, uuid: Uuid) -> Result Result> { + let conn = &mut establish_connection(&database_url)?; + + let new_task = NewTask { + id: uuid, + title, + description, + due_date, + }; + + Ok(diesel::insert_into(tasks::table) + .values(&new_task) + .returning(Task::as_returning()) + .get_result(conn)?) +} diff --git a/server/src/db/models.rs b/server/src/db/models.rs index 9bf8642..3f15750 100644 --- a/server/src/db/models.rs +++ b/server/src/db/models.rs @@ -6,6 +6,8 @@ use diesel::prelude::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; +use crate::schema::tasks; + #[derive(Queryable, Selectable, Serialize, Deserialize)] #[diesel(table_name = crate::schema::tasks)] #[diesel(check_for_backend(diesel::pg::Pg))] @@ -16,3 +18,12 @@ pub struct Task { pub complete: bool, pub due_date: NaiveDateTime, } + +#[derive(Insertable, Deserialize, Serialize)] +#[diesel(table_name = tasks)] +pub struct NewTask<'a> { + pub id: Uuid, + pub title: &'a str, + pub description: &'a str, + pub due_date: NaiveDateTime, +} -- 2.45.2 From ff3d302f1898d4b62d55f8037f627de9943c13c0 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 14:39:47 -0400 Subject: [PATCH 24/29] Use UUIDv7 as primary key --- server/Cargo.lock | 7 +++++++ server/Cargo.toml | 2 +- server/src/api/v1.rs | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index a73f78e..323f8f7 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -248,6 +248,12 @@ dependencies = [ "libc", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "autocfg" version = "1.2.0" @@ -1366,6 +1372,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ + "atomic", "getrandom", "serde", ] diff --git a/server/Cargo.toml b/server/Cargo.toml index b9e2316..24d6f57 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -13,4 +13,4 @@ diesel_migrations = { version = "2.1.0", features = ["postgres"] } dotenvy = "0.15.7" serde = { version = "1.0.200", features = ["derive"] } serde_json = "1.0.116" -uuid = { version = "1.8.0", features = ["v4", "serde"] } +uuid = { version = "1.8.0", features = ["v7", "serde"] } diff --git a/server/src/api/v1.rs b/server/src/api/v1.rs index 4d9d2fc..8433f7e 100644 --- a/server/src/api/v1.rs +++ b/server/src/api/v1.rs @@ -46,7 +46,7 @@ struct JsonTask { #[post("/create_task")] pub async fn create_task(data: web::Data, task: web::Json) -> impl Responder { - let uuid = Uuid::new_v4(); + let uuid = Uuid::now_v7(); let new_task = match db::create_task( data.database_url.clone(), -- 2.45.2 From 99f4dd4b42aa4aa54424774d6339cb8ad54872e6 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 15:17:00 -0400 Subject: [PATCH 25/29] Add delete_task --- server/src/api/v1.rs | 21 +++++++++++++++++++-- server/src/db/mod.rs | 17 +++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/server/src/api/v1.rs b/server/src/api/v1.rs index 8433f7e..e9ed242 100644 --- a/server/src/api/v1.rs +++ b/server/src/api/v1.rs @@ -1,4 +1,4 @@ -use actix_web::{get, HttpResponse, post, Responder, web}; +use actix_web::{delete, get, HttpResponse, post, Responder, web}; use chrono::NaiveDateTime; use serde::Deserialize; use uuid::Uuid; @@ -10,7 +10,8 @@ pub fn configure(cfg: &mut web::ServiceConfig) { let scope = web::scope("/v1") .service(get_task) .service(get_tasks) - .service(create_task); + .service(create_task) + .service(delete_task); cfg.service(scope); } @@ -63,3 +64,19 @@ pub async fn create_task(data: web::Data, task: web::Json) - HttpResponse::Ok().json(new_task) } + +#[delete("/delete_task/{uuid}")] +pub async fn delete_task(data: web::Data, path: web::Path) -> impl Responder { + let uuid = path.into_inner(); + + let result = match db::delete_task(data.database_url.clone(), uuid).await { + Ok(result) => result, + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + }; + + if result > 0 { + HttpResponse::Ok().body(uuid.to_string()) + } else { + HttpResponse::NotFound().body("Unable to delete. Not found.") + } +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 8529bf8..ef13ae7 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -33,19 +33,18 @@ pub fn run_migrations( } pub async fn get_tasks(database_url: String) -> Result, Box> { - use crate::schema::tasks::dsl::*; - let conn = &mut establish_connection(&database_url)?; - Ok(tasks.select(Task::as_select()).load(conn)?) + Ok(tasks::dsl::tasks.select(Task::as_select()).load(conn)?) } pub async fn get_task(database_url: String, uuid: Uuid) -> Result> { - use crate::schema::tasks::dsl::*; - let conn = &mut establish_connection(&database_url)?; - Ok(tasks.filter(id.eq(uuid)).first(conn)?) + Ok(tasks::dsl::tasks + .find(uuid) + .select(Task::as_select()) + .first(conn)?) } pub async fn create_task( @@ -69,3 +68,9 @@ pub async fn create_task( .returning(Task::as_returning()) .get_result(conn)?) } + +pub async fn delete_task(database_url: String, uuid: Uuid) -> Result> { + let conn = &mut establish_connection(&database_url)?; + + Ok(diesel::delete(tasks::dsl::tasks.filter(tasks::dsl::id.eq(uuid))).execute(conn)?) +} -- 2.45.2 From ac99eb4f9de708e43adc0ff85d0d76ac6ef426b5 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 19:41:03 +0000 Subject: [PATCH 26/29] Fix use for dsl --- server/src/db/mod.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index ef13ae7..eaae32b 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -33,15 +33,19 @@ pub fn run_migrations( } pub async fn get_tasks(database_url: String) -> Result, Box> { + use tasks::dsl::*; + let conn = &mut establish_connection(&database_url)?; - Ok(tasks::dsl::tasks.select(Task::as_select()).load(conn)?) + Ok(tasks.select(Task::as_select()).load(conn)?) } pub async fn get_task(database_url: String, uuid: Uuid) -> Result> { + use tasks::dsl::*; + let conn = &mut establish_connection(&database_url)?; - Ok(tasks::dsl::tasks + Ok(tasks .find(uuid) .select(Task::as_select()) .first(conn)?) @@ -70,7 +74,9 @@ pub async fn create_task( } pub async fn delete_task(database_url: String, uuid: Uuid) -> Result> { + use tasks::dsl::*; + let conn = &mut establish_connection(&database_url)?; - Ok(diesel::delete(tasks::dsl::tasks.filter(tasks::dsl::id.eq(uuid))).execute(conn)?) + Ok(diesel::delete(tasks.filter(id.eq(uuid))).execute(conn)?) } -- 2.45.2 From 6671f81a9ac0cf77562ab2350457a0199dde8d82 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Fri, 3 May 2024 16:20:48 -0400 Subject: [PATCH 27/29] Fix dsl again --- server/src/db/mod.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index eaae32b..76c9e12 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -14,7 +14,7 @@ use uuid::Uuid; use models::Task; use crate::db::models::NewTask; -use crate::schema::tasks; +use crate::schema; pub mod models; @@ -33,7 +33,7 @@ pub fn run_migrations( } pub async fn get_tasks(database_url: String) -> Result, Box> { - use tasks::dsl::*; + use schema::tasks::dsl::*; let conn = &mut establish_connection(&database_url)?; @@ -41,14 +41,11 @@ pub async fn get_tasks(database_url: String) -> Result, Box Result> { - use tasks::dsl::*; + use schema::tasks::dsl::*; let conn = &mut establish_connection(&database_url)?; - Ok(tasks - .find(uuid) - .select(Task::as_select()) - .first(conn)?) + Ok(tasks.find(uuid).select(Task::as_select()).first(conn)?) } pub async fn create_task( @@ -67,14 +64,14 @@ pub async fn create_task( due_date, }; - Ok(diesel::insert_into(tasks::table) + Ok(diesel::insert_into(schema::tasks::table) .values(&new_task) .returning(Task::as_returning()) .get_result(conn)?) } pub async fn delete_task(database_url: String, uuid: Uuid) -> Result> { - use tasks::dsl::*; + use schema::tasks::dsl::*; let conn = &mut establish_connection(&database_url)?; -- 2.45.2 From f2107568f0731987ae05b69212c76823d75184de Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Sat, 4 May 2024 15:17:42 -0400 Subject: [PATCH 28/29] Change establish_connection to use &str as opposed to &String --- server/src/db/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 76c9e12..cff24e2 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -20,8 +20,8 @@ pub mod models; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); -pub fn establish_connection(database_url: &String) -> Result> { - Ok(PgConnection::establish(&database_url)?) +pub fn establish_connection(database_url: &str) -> Result> { + Ok(PgConnection::establish(database_url)?) } pub fn run_migrations( -- 2.45.2 From 96c251c1ca07c2df0ddfe091198be843ca4fc1d2 Mon Sep 17 00:00:00 2001 From: Luke Harding Date: Sat, 4 May 2024 15:54:11 -0400 Subject: [PATCH 29/29] Add new update_task endpoint; Change database_url to &str; P.S. Worked first time --- server/src/api/v1.rs | 53 +++++++++++++++++++++++----------- server/src/db/mod.rs | 69 +++++++++++++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/server/src/api/v1.rs b/server/src/api/v1.rs index e9ed242..10d3217 100644 --- a/server/src/api/v1.rs +++ b/server/src/api/v1.rs @@ -1,4 +1,4 @@ -use actix_web::{delete, get, HttpResponse, post, Responder, web}; +use actix_web::{delete, get, HttpResponse, patch, post, Responder, web}; use chrono::NaiveDateTime; use serde::Deserialize; use uuid::Uuid; @@ -11,14 +11,15 @@ pub fn configure(cfg: &mut web::ServiceConfig) { .service(get_task) .service(get_tasks) .service(create_task) - .service(delete_task); + .service(delete_task) + .service(update_task); cfg.service(scope); } #[get("/get_tasks")] pub async fn get_tasks(data: web::Data) -> impl Responder { - let tasks = match db::get_tasks(data.database_url.clone()).await { + let tasks = match db::get_tasks(&data.database_url).await { Ok(tasks) => tasks, Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), }; @@ -30,7 +31,7 @@ pub async fn get_tasks(data: web::Data) -> impl Responder { pub async fn get_task(data: web::Data, path: web::Path) -> impl Responder { let uuid = path.into_inner(); - let task = match db::get_task(data.database_url.clone(), uuid).await { + let task = match db::get_task(&data.database_url, uuid).await { Ok(task) => task, Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), }; @@ -39,25 +40,20 @@ pub async fn get_task(data: web::Data, path: web::Path) -> impl } #[derive(Deserialize)] -struct JsonTask { +pub struct JsonNewTask { pub title: String, pub description: String, pub due_date: NaiveDateTime, } #[post("/create_task")] -pub async fn create_task(data: web::Data, task: web::Json) -> impl Responder { - let uuid = Uuid::now_v7(); +pub async fn create_task( + data: web::Data, + task: web::Json, +) -> impl Responder { + let task = task.into_inner(); - let new_task = match db::create_task( - data.database_url.clone(), - uuid, - &task.title, - &task.description, - task.due_date, - ) - .await - { + let new_task = match db::create_task(&data.database_url, task).await { Ok(task) => task, Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), }; @@ -69,7 +65,7 @@ pub async fn create_task(data: web::Data, task: web::Json) - pub async fn delete_task(data: web::Data, path: web::Path) -> impl Responder { let uuid = path.into_inner(); - let result = match db::delete_task(data.database_url.clone(), uuid).await { + let result = match db::delete_task(&data.database_url, uuid).await { Ok(result) => result, Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), }; @@ -80,3 +76,26 @@ pub async fn delete_task(data: web::Data, path: web::Path) -> im HttpResponse::NotFound().body("Unable to delete. Not found.") } } + +#[derive(Deserialize)] +pub struct JsonPatchTask { + pub title: Option, + pub description: Option, + pub complete: Option, + pub due_date: Option, +} + +#[patch("/update_task/{uuid}")] +pub async fn update_task( + data: web::Data, + path: web::Path, + new_values: web::Json, +) -> impl Responder { + let new_values = new_values.into_inner(); + let uuid = path.into_inner(); + + match db::update_task(&data.database_url, uuid, new_values).await { + Ok(task) => HttpResponse::Ok().json(task), + Err(e) => HttpResponse::InternalServerError().body(e.to_string()), + } +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index cff24e2..21ddafc 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -3,7 +3,6 @@ use std::error; -use chrono::NaiveDateTime; use diesel::{ Connection, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper, }; @@ -13,6 +12,7 @@ use uuid::Uuid; use models::Task; +use crate::api::v1::{JsonNewTask, JsonPatchTask}; use crate::db::models::NewTask; use crate::schema; @@ -32,36 +32,33 @@ pub fn run_migrations( Ok(()) } -pub async fn get_tasks(database_url: String) -> Result, Box> { +pub async fn get_tasks(database_url: &str) -> Result, Box> { use schema::tasks::dsl::*; - let conn = &mut establish_connection(&database_url)?; + let conn = &mut establish_connection(database_url)?; Ok(tasks.select(Task::as_select()).load(conn)?) } -pub async fn get_task(database_url: String, uuid: Uuid) -> Result> { +pub async fn get_task(database_url: &str, uuid: Uuid) -> Result> { use schema::tasks::dsl::*; - let conn = &mut establish_connection(&database_url)?; + let conn = &mut establish_connection(database_url)?; Ok(tasks.find(uuid).select(Task::as_select()).first(conn)?) } pub async fn create_task( - database_url: String, - uuid: Uuid, - title: &str, - description: &str, - due_date: NaiveDateTime, + database_url: &str, + task: JsonNewTask, ) -> Result> { - let conn = &mut establish_connection(&database_url)?; + let conn = &mut establish_connection(database_url)?; let new_task = NewTask { - id: uuid, - title, - description, - due_date, + id: Uuid::now_v7(), + title: &task.title, + description: &task.description, + due_date: task.due_date, }; Ok(diesel::insert_into(schema::tasks::table) @@ -70,10 +67,48 @@ pub async fn create_task( .get_result(conn)?) } -pub async fn delete_task(database_url: String, uuid: Uuid) -> Result> { +pub async fn delete_task(database_url: &str, uuid: Uuid) -> Result> { use schema::tasks::dsl::*; - let conn = &mut establish_connection(&database_url)?; + let conn = &mut establish_connection(database_url)?; Ok(diesel::delete(tasks.filter(id.eq(uuid))).execute(conn)?) } + +pub async fn update_task( + database_url: &str, + uuid: Uuid, + new_values: JsonPatchTask, +) -> Result> { + use schema::tasks::dsl::*; + + let conn = &mut establish_connection(database_url)?; + + let mut current_task = get_task(database_url, uuid).await?; + + if let Some(new_title) = new_values.title { + current_task.title = new_title; + } + + if let Some(new_description) = new_values.description { + current_task.description = new_description; + } + + if let Some(new_complete) = new_values.complete { + current_task.complete = new_complete; + } + + if let Some(new_due_date) = new_values.due_date { + current_task.due_date = new_due_date; + } + + Ok(diesel::update(tasks.find(uuid)) + .set(( + title.eq(current_task.title), + description.eq(current_task.description), + complete.eq(current_task.complete), + due_date.eq(current_task.due_date), + )) + .returning(Task::as_returning()) + .get_result(conn)?) +} -- 2.45.2