diff --git a/.gitignore b/.gitignore index ccb5166..9e0010c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target -.vscode \ No newline at end of file +.vscode +*.db \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 62d39ce..b99d836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -269,6 +269,23 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] +name = "ahash" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796540673305a66d127804eef19ad696f1f204b8c1025aaca4958c17eab32877" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.15" @@ -289,6 +306,15 @@ dependencies = [ "syn", ] +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -396,6 +422,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + [[package]] name = "bumpalo" version = "3.7.0" @@ -435,6 +467,28 @@ dependencies = [ "bytes 1.0.1", ] +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" +dependencies = [ + "cargo-platform", + "semver 0.11.0", + "semver-parser 0.10.2", + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.0.69" @@ -529,6 +583,24 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -538,6 +610,26 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.5" @@ -591,6 +683,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "either" version = "1.6.1" @@ -691,6 +789,7 @@ checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -713,6 +812,17 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" +[[package]] +name = "futures-executor" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.16" @@ -878,12 +988,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hashlink" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d99cf782f0dc4372d26846bec3de7804ceb5df083c2d4462c0b8d2330e894fa8" +dependencies = [ + "hashbrown 0.9.1", +] + [[package]] name = "heck" version = "0.3.3" @@ -902,6 +1030,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hostname" version = "0.3.1" @@ -987,7 +1121,7 @@ dependencies = [ "hyper", "native-tls", "tokio 1.10.0", - "tokio-native-tls", + "tokio-native-tls 0.3.0", ] [[package]] @@ -996,7 +1130,9 @@ version = "0.1.0" dependencies = [ "actix-web", "reqwest", + "sqlx", "tera", + "url", "uuid", ] @@ -1036,7 +1172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -1114,9 +1250,20 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" + +[[package]] +name = "libsqlite3-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] [[package]] name = "linked-hash-map" @@ -1181,6 +1328,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6595bb28ed34f43c3fe088e48f6cfb2e033cab45f25a5384d5fdf564fbc8c4b2" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1284,6 +1437,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nom" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +dependencies = [ + "memchr", + "minimal-lexical", + "version_check", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -1704,7 +1868,7 @@ dependencies = [ "serde", "serde_urlencoded", "tokio 1.10.0", - "tokio-native-tls", + "tokio-native-tls 0.3.0", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1810,6 +1974,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ "semver-parser 0.10.2", + "serde", ] [[package]] @@ -1890,7 +2055,7 @@ checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", - "cpufeatures", + "cpufeatures 0.1.5", "digest 0.9.0", "opaque-debug 0.3.0", ] @@ -1901,6 +2066,19 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "sha2" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures 0.2.1", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1952,6 +2130,103 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "sqlformat" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684001e7985ec1a9a66963b77ed151ef22a7876b3fdd7e37a57ec774f54b7d96" +dependencies = [ + "lazy_static", + "maplit", + "nom", + "regex", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a98f9bf17b690f026b6fec565293a995b46dfbd6293debcb654dcffd2d1b34" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36bb6a2ca3345a86493bc3b71eabc2c6c16a8bb1aa476cf5303bee27f67627d7" +dependencies = [ + "ahash 0.6.3", + "atoi", + "bitflags", + "byteorder", + "bytes 0.5.6", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils", + "either", + "futures-channel", + "futures-core", + "futures-util", + "hashlink", + "hex", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "parking_lot", + "percent-encoding", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "url", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5ada8b3b565331275ce913368565a273a74faf2a34da58c4dc010ce3286844" +dependencies = [ + "cargo_metadata", + "dotenv", + "either", + "futures", + "heck", + "lazy_static", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63fc5454c9dd7aaea3a0eeeb65ca40d06d0d8e7413a8184f7c3a3ffa5056190b" +dependencies = [ + "actix-rt", + "actix-threadpool", + "native-tls", + "once_cell", + "tokio 0.2.25", + "tokio-native-tls 0.1.0", +] + [[package]] name = "standback" version = "0.2.17" @@ -2010,6 +2285,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "syn" version = "1.0.75" @@ -2162,9 +2447,11 @@ dependencies = [ "memchr", "mio 0.6.23", "mio-uds", + "num_cpus", "pin-project-lite 0.1.12", "signal-hook-registry", "slab", + "tokio-macros", "winapi 0.3.9", ] @@ -2184,6 +2471,27 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tokio-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd608593a919a8e05a7d1fc6df885e40f6a88d3a70a3a7eff23ff27964eda069" +dependencies = [ + "native-tls", + "tokio 0.2.25", +] + [[package]] name = "tokio-native-tls" version = "0.3.0" @@ -2393,6 +2701,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "url" version = "2.2.2" @@ -2537,6 +2851,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "whoami" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7741161a40200a867c96dfa5574544efa4178cf4c8f770b62dd1cc0362d7ae1" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "widestring" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index f8314b8..97eb62d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,8 @@ edition = "2018" [dependencies] actix-web = "3" uuid = { version = "0.8.2", features = ["v4"] } +url = "2.2" reqwest = { version = "0.11", features = ["blocking"] } -tera = "1.12.1" \ No newline at end of file +tera = "1.12.1" + +sqlx = { version = "0.4.2", features = [ "sqlite", "runtime-actix-native-tls" ] } \ No newline at end of file diff --git a/db/create_db.sh b/db/create_db.sh new file mode 100755 index 0000000..24ad994 --- /dev/null +++ b/db/create_db.sh @@ -0,0 +1 @@ +sqlite3 db.db < create_db.sql \ No newline at end of file diff --git a/db/create_db.sql b/db/create_db.sql new file mode 100644 index 0000000..2aacd6c --- /dev/null +++ b/db/create_db.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS LINKS( + UUID TEXT NOT NULL PRIMARY KEY, + DESTINATION TEXT NOT NULL +); \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cfa77a1..ee32b2a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,13 @@ use std::collections::HashMap; use actix_web::{error, web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder, Result}; +use sqlx::{Pool, Sqlite, SqlitePool}; use tera::Tera; use uuid::Uuid; +mod model; +use model::Link; + const REDIRECT_TIMEOUT_S: i32 = 2; async fn make_ics_request(req: HttpRequest) -> impl Responder { @@ -136,16 +140,41 @@ async fn edit_process( async fn index_process( tmpl: web::Data, query: web::Query>, + db_pool: web::Data>, ) -> Result { if query.get("create").is_some() { - let uuid = Uuid::nil(); + let uuid = Uuid::new_v4(); // TODO: add actuall logic and use proper uuid - redirect_to_edit_page( - tmpl, - "Create was successful".to_string(), - uuid, - REDIRECT_TIMEOUT_S, - ) + match query.get("link") { + // TODO: actually parse link to url to make sure its valid + Some(destination) => { + let insert_link = Link { + uuid: uuid.to_string(), + destination: destination.to_string(), + }; + + match Link::create(insert_link, db_pool).await { + Ok(link) => match Uuid::parse_str(&link.uuid) { + Ok(uuid) => redirect_to_edit_page( + tmpl, + "Create was successful".to_string(), + uuid, + REDIRECT_TIMEOUT_S, + ), + Err(e) => error_page(tmpl, format!("uuid parsing error {}", e.to_string())), + }, + // TODO: actually redirect to index page to try again + Err(e) => error_page(tmpl, format!("db error: {}", e.to_string())), + } + } + None => { + // TODO: actually redirect back to index page + error_page( + tmpl, + "link attribute not set please enter a link".to_string(), + ) + } + } } else if query.get("edit").is_some() { let uuid = Uuid::nil(); // TODO: add actuall logic and use proper uuid @@ -174,11 +203,17 @@ async fn index(tmpl: web::Data) -> Result { async fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "actix_web=info"); + let database_url = "sqlite://db/db.db"; //env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file"); + let db_pool = SqlitePool::connect(&database_url) + .await + .expect("could not create db pool"); + println!("Listening on: 127.0.0.1:8080, open browser and visit have a try!"); - HttpServer::new(|| { + HttpServer::new(move || { let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); App::new() + .data(db_pool.clone()) // pass database pool to application so we can access it inside handlers .data(tera) .route("/{id}/events.ics", web::get().to(make_ics_request)) .service(web::resource("/").route(web::get().to(index))) diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..f837dfa --- /dev/null +++ b/src/model.rs @@ -0,0 +1,25 @@ +use actix_web::web; +use sqlx::sqlite::SqliteRow; +use sqlx::{Pool, Row, Sqlite}; +use url::Url; +use uuid::Uuid; + +// Change to strings if to much headache +pub struct Link { + pub uuid: String, + pub destination: String, +} + +impl Link { + pub async fn create(link: Link, pool: web::Data>) -> Result { + let mut tx = pool.begin().await?; + sqlx::query("INSERT INTO links (uuid, destination) VALUES ($1, $2);") + .bind(&link.uuid) + .bind(&link.destination) + .execute(&mut tx) + .await?; + + tx.commit().await?; + Ok(link) + } +}