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, + } +}