From 201a37e8d3d0ef4c59b184c0707ec8ddd301a25a Mon Sep 17 00:00:00 2001 From: "Adam T. Carpenter" Date: Fri, 9 Apr 2021 18:50:55 -0400 Subject: spruced up templates, some repo impl --- src/routes/mod.rs | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 src/routes/mod.rs (limited to 'src/routes/mod.rs') diff --git a/src/routes/mod.rs b/src/routes/mod.rs new file mode 100644 index 0000000..1866e49 --- /dev/null +++ b/src/routes/mod.rs @@ -0,0 +1,185 @@ +use crate::error::TwinHError; +use crate::repo; +use crate::templates; +use hyper::body::HttpBody as _; +use hyper::Method; +use hyper::StatusCode; +use hyper::{Body, Request, Response}; +use serde::{Deserialize, Serialize}; + +pub async fn router(req: Request) -> Result, TwinHError> { + match (req.method(), req.uri().path()) { + (&Method::GET, "/") => index(req).await, + (&Method::GET, "/cars") => cars(req).await, + (&Method::GET, "/login") => login().await, + (&Method::GET, "/login/google") => login_google().await, + (&Method::GET, "/login/google/code") => login_google_code(req).await, + (&Method::GET, "/suggestions") => suggestions().await, + _ => Ok(Response::builder() + .status(StatusCode::NOT_FOUND) + .body("Not found.".into()) + .unwrap()), + } +} + +async fn suggestions() -> Result, TwinHError> { + todo!() +} + +async fn login() -> Result, TwinHError> { + Ok(Response::new( + templates::REGISTRY.render("login", &"").unwrap().into(), + )) +} + +async fn login_google() -> Result, TwinHError> { + let uri = hyper::Uri::builder() + .scheme("https") + .authority("accounts.google.com") + .path_and_query(format!( + "{}?client_id={}&redirect_uri={}&response_type={}&scope={}&state={}", + "/o/oauth2/v2/auth", + "???", + "http://localhost:3000/login/google/code", + "code", + "openid%20profile%20email", + "BLARGH" + )) + .build() + .unwrap(); + let resp = Response::builder() + .header(hyper::header::LOCATION, uri.to_string()) + .status(StatusCode::TEMPORARY_REDIRECT) + .body("".into()) + .unwrap(); + Ok(resp) +} + +#[derive(Serialize)] +struct AuthRequest { + client_id: String, + client_secret: String, + grant_type: &'static str, + redirect_uri: String, + code: String, +} + +impl Default for AuthRequest { + fn default() -> Self { + Self { + client_id: "???".into(), + client_secret: "???".into(), + grant_type: "authorization_code", + redirect_uri: String::new(), + code: String::new(), + } + } +} + +async fn login_google_code(req: Request) -> Result, TwinHError> { + let query = req.uri().query().unwrap_or_default(); + let query = serde_urlencoded::de::from_str::(query).unwrap(); + if query.state != "BLARGH" { + dbg!("tampering?"); + } + + // get access token + let auth_body = AuthRequest { + code: query.code, + redirect_uri: "http://localhost:3000/login/google/code".to_owned(), + ..Default::default() + }; + + let https = hyper_rustls::HttpsConnector::with_native_roots(); + let client: hyper::Client<_, hyper::Body> = hyper::Client::builder().build(https); + + let req = Request::builder() + .method(Method::POST) + .uri("https://oauth2.googleapis.com/token") + .header( + hyper::header::CONTENT_TYPE, + "application/x-www-form-urlencoded", + ) + .body(serde_urlencoded::ser::to_string(auth_body).unwrap().into()) + .unwrap(); + let mut resp = client.request(req).await.unwrap(); + use std::io::prelude::*; + while let Some(chunk) = resp.body_mut().data().await { + std::io::stdout().write_all(&chunk.unwrap()).unwrap(); + } + + let resp = Response::builder() + .header(hyper::header::LOCATION, "/".to_string()) + .status(StatusCode::TEMPORARY_REDIRECT) + .body("Successful login, redirecting...".into()) + .unwrap(); + Ok(resp) +} + +pub struct AccessToken { + access_token: String, + expires_in: String, + scope: String, + token_type: String, +} + +async fn cars(req: Request) -> Result, TwinHError> { + let cars = repo::get_all_cars().unwrap(); + todo!() +} + +async fn index(req: Request) -> Result, TwinHError> { + let query = req.uri().query().unwrap_or_default(); + let filter = serde_urlencoded::de::from_str::(query).unwrap(); + let mut data = PartsData::default(); + data.makes = Some(vec!["Hudson".into(), "Essex".into(), "Terraplane".into()]); + + if let Some(make) = filter.make { + if make.eq("Hudson") { + data.models = Some(vec!["Hornet".into(), "Wasp".into(), "Jet".into()]); + } else if make.eq("Essex") { + data.models = Some(vec!["Super Six".into()]); + } + data.selected_make = Some(make); + } + + data.parts = Some(Vec::new()); + if let Some(model) = filter.model { + data.parts = Some(vec!["1".into(), "2".into(), "3".into()]); + data.selected_model = Some(model); + } + + let body = templates::REGISTRY.render("index", &data).unwrap(); + let resp = Response::builder() + .header(hyper::header::CONTENT_TYPE, "text/html; charset=utf-8") + .body(body.into()) + .unwrap(); + Ok(resp) +} + +#[derive(Debug, Deserialize)] +struct GoogleOAuthQuery { + code: String, + state: String, +} + +#[derive(Debug, Deserialize)] +struct PartsQuery { + make: Option, + year: Option, + model: Option, + engine: Option, +} + +#[derive(Debug, Serialize, Default)] +struct PartsData { + makes: Option>, + years: Option>, + models: Option>, + engines: Option>, + selected_make: Option, + selected_year: Option, + selected_model: Option, + selected_engine: Option, + parts: Option>, +} -- cgit v1.2.3