summaryrefslogtreecommitdiff
path: root/src/routes/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/mod.rs')
-rw-r--r--src/routes/mod.rs185
1 files changed, 185 insertions, 0 deletions
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<Body>) -> Result<Response<Body>, 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<Response<Body>, TwinHError> {
+ todo!()
+}
+
+async fn login() -> Result<Response<Body>, TwinHError> {
+ Ok(Response::new(
+ templates::REGISTRY.render("login", &"").unwrap().into(),
+ ))
+}
+
+async fn login_google() -> Result<Response<Body>, 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<Body>) -> Result<Response<Body>, TwinHError> {
+ let query = req.uri().query().unwrap_or_default();
+ let query = serde_urlencoded::de::from_str::<GoogleOAuthQuery>(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<Body>) -> Result<Response<Body>, TwinHError> {
+ let cars = repo::get_all_cars().unwrap();
+ todo!()
+}
+
+async fn index(req: Request<Body>) -> Result<Response<Body>, TwinHError> {
+ let query = req.uri().query().unwrap_or_default();
+ let filter = serde_urlencoded::de::from_str::<PartsQuery>(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<String>,
+ year: Option<String>,
+ model: Option<String>,
+ engine: Option<String>,
+}
+
+#[derive(Debug, Serialize, Default)]
+struct PartsData {
+ makes: Option<Vec<String>>,
+ years: Option<Vec<String>>,
+ models: Option<Vec<String>>,
+ engines: Option<Vec<String>>,
+ selected_make: Option<String>,
+ selected_year: Option<String>,
+ selected_model: Option<String>,
+ selected_engine: Option<String>,
+ parts: Option<Vec<String>>,
+}