diff --git a/Cargo.lock b/Cargo.lock index 6b95a11..62d39ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -997,6 +997,7 @@ dependencies = [ "actix-web", "reqwest", "tera", + "uuid", ] [[package]] @@ -2404,6 +2405,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.3", +] + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index 5fad20e..f8314b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,6 @@ edition = "2018" [dependencies] actix-web = "3" +uuid = { version = "0.8.2", features = ["v4"] } reqwest = { version = "0.11", features = ["blocking"] } tera = "1.12.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 3eb7956..cfa77a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,16 @@ use std::collections::HashMap; use actix_web::{error, web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder, Result}; use tera::Tera; +use uuid::Uuid; + +const REDIRECT_TIMEOUT_S: i32 = 2; async fn make_ics_request(req: HttpRequest) -> impl Responder { - let id = req.match_info().get("id").unwrap_or("World"); + let id = req.match_info().get("id").unwrap_or(""); let body = match id { "1" => { + // TODO: load url based on id from database and make request let res = match reqwest::blocking::get("https://cloud.timeedit.net/uu/web/schema/ri6QX6089X8061QQ88Z4758Z08y37424838828461554904Y684XX09894Q8721784ZnX6503.ics") { Ok(r) => match r.text() { Ok(res) => res, @@ -23,52 +27,143 @@ async fn make_ics_request(req: HttpRequest) -> impl Responder { HttpResponse::Ok().content_type("text/calendar").body(body) } -async fn edit( - tmpl: web::Data, - query: web::Query>, -) -> Result { - let mut s = "".to_string(); - - if query.get("create").is_some() { - if let Some(link) = query.get("link") { - // submitted form - let proxy_link = &"Insert link here".to_owned(); - - let mut ctx = tera::Context::new(); - ctx.insert("link", &link.to_owned()); - ctx.insert("proxy_link", proxy_link); - s = tmpl - .render("edit.html", &ctx) - .map_err(|_| error::ErrorInternalServerError("Template error"))?; - } - // create new link - } else if query.get("edit").is_some() { - if let Some(link) = query.get("link") { - // submitted form - let proxy_link = &"Insert link here".to_owned(); - - let mut ctx = tera::Context::new(); - ctx.insert("link", &link.to_owned()); - ctx.insert("proxy_link", proxy_link); - s = tmpl - .render("edit.html", &ctx) - .map_err(|_| error::ErrorInternalServerError("Template error"))?; - } - // edit existing link - } else if query.get("replace").is_some() { - // replace link - s = "Replace".to_string(); - } else { - s = tmpl - .render("error.html", &tera::Context::new()) - .map_err(|_| error::ErrorInternalServerError("Template error"))? - } +fn error_page(tmpl: web::Data, msg: String) -> Result { + let mut ctx = tera::Context::new(); + ctx.insert("message", &msg); + let s = tmpl + .render("error.html", &ctx) + .map_err(|_| error::ErrorInternalServerError("Template error"))?; Ok(HttpResponse::Ok().content_type("text/html").body(s)) } +// This is the new edit page: +async fn edit_page( + tmpl: web::Data, + query: web::Query>, +) -> Result { + // one uuid: 9228c1a4-8956-4f1c-8b5f-53cc575bd78 + if let Some(uuid_str) = query.get("uuid") { + // TODO: based on uuid get link from database + let link = "this is the link from the db".to_string(); + match Uuid::parse_str(uuid_str) { + Ok(uuid) => { + let mut ctx = tera::Context::new(); + ctx.insert("link", &link); + ctx.insert("uuid", &uuid.to_string()); + let s = tmpl + .render("edit.html", &ctx) + .map_err(|_| error::ErrorInternalServerError("Template error"))?; + + Ok(HttpResponse::Ok().content_type("text/html").body(s)) + } + Err(err) => error_page(tmpl, format!("uuid parsing error: {}", err.to_string())), + } + } else { + error_page(tmpl, "uuid parameter missing".to_string()) + } +} + +fn redirect_to_page( + tmpl: web::Data, + message: String, + link: String, + time_s: i32, +) -> Result { + let mut ctx = tera::Context::new(); + ctx.insert("message", &message); + ctx.insert("link", &link); + ctx.insert("time", &time_s); + let s = tmpl + .render("redirect.html", &ctx) + .map_err(|_| error::ErrorInternalServerError("Template error"))?; + + Ok(HttpResponse::Ok().content_type("text/html").body(s)) +} + +fn redirect_to_edit_page( + tmpl: web::Data, + message: String, + uuid: Uuid, + time_s: i32, +) -> Result { + let mut ctx = tera::Context::new(); + ctx.insert("message", &message); + let link = format!("/edit?uuid={}", uuid.to_string()); + ctx.insert("time", &time_s); + redirect_to_page(tmpl, message, link, time_s) +} + +/* +fn redirect_to_index_page( + tmpl: web::Data, + query: web::Query>, + message: String, + uuid: Uuid, + time_s: i32, +) -> Result { + // TODO: add option to prefill link +} +*/ + +async fn edit_process( + tmpl: web::Data, + query: web::Query>, +) -> Result { + // TODO: implement handling + if let Some(uuid_str) = query.get("uuid") { + if let Some(link) = query.get("link") { + match Uuid::parse_str(uuid_str) { + Ok(uuid) => { + // TODO: actually save entry in database + redirect_to_edit_page( + tmpl, + "Edit successful!".to_string(), + uuid, + REDIRECT_TIMEOUT_S, + ) + } + Err(err) => error_page(tmpl, format!("uuid parsing error: {}", err.to_string())), + } + } else { + error_page(tmpl, "link parameter missing".to_string()) + } + } else { + error_page(tmpl, "uuid parameter missing".to_string()) + } +} + +async fn index_process( + tmpl: web::Data, + query: web::Query>, +) -> Result { + if query.get("create").is_some() { + let uuid = Uuid::nil(); + // TODO: add actuall logic and use proper uuid + redirect_to_edit_page( + tmpl, + "Create was successful".to_string(), + uuid, + REDIRECT_TIMEOUT_S, + ) + } else if query.get("edit").is_some() { + let uuid = Uuid::nil(); + // TODO: add actuall logic and use proper uuid + redirect_to_edit_page( + tmpl, + "Entry found in database!".to_string(), + uuid, + REDIRECT_TIMEOUT_S, + ) + } else { + error_page(tmpl, "missing create or edit form submission!".to_string()) + } +} + // store tera template in application state async fn index(tmpl: web::Data) -> Result { + // TODO: add option to prefill link with parameter + let s = tmpl .render("index.html", &tera::Context::new()) .map_err(|_| error::ErrorInternalServerError("Template error"))?; @@ -87,7 +182,9 @@ async fn main() -> std::io::Result<()> { .data(tera) .route("/{id}/events.ics", web::get().to(make_ics_request)) .service(web::resource("/").route(web::get().to(index))) - .service(web::resource("/edit").route(web::get().to(edit))) + .service(web::resource("/edit").route(web::get().to(edit_page))) + .service(web::resource("/index_process").route(web::get().to(index_process))) + .service(web::resource("/edit_process").route(web::get().to(edit_process))) }) .bind("127.0.0.1:8080")? .run() diff --git a/templates/edit.html b/templates/edit.html index a1b8afb..43149f6 100644 --- a/templates/edit.html +++ b/templates/edit.html @@ -7,14 +7,15 @@ -

Hi, your link is {{ proxy_link }}!

- it takes the data from redirects to +

Hi, your link is /{{ uuid }}/events.ics!

+ it takes the data from

-

- - -
-

+
+ + + +
+

\ No newline at end of file diff --git a/templates/error.html b/templates/error.html index 72f8f90..58f848b 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1 +1 @@ -Something went wrong \ No newline at end of file +{{ message }} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 199c10a..9fd6c87 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,7 +9,7 @@

Welcome!

-

+
diff --git a/templates/redirect.html b/templates/redirect.html new file mode 100644 index 0000000..5f6b174 --- /dev/null +++ b/templates/redirect.html @@ -0,0 +1,3 @@ +

{{ message }}

+

Please wait to be redirected or click here!

+ \ No newline at end of file