diff options
author | Adam T. Carpenter <atc@53hor.net> | 2021-04-02 18:23:45 -0400 |
---|---|---|
committer | Adam T. Carpenter <atc@53hor.net> | 2021-04-02 18:23:45 -0400 |
commit | b1c45640a72300433800c8370657335616f8c541 (patch) | |
tree | ad7df1bfa6f59390ad227183364b308ab2137ed0 | |
parent | 7633bf5855ae5359d0fe280970e5c5c210c536b3 (diff) | |
download | twinh-b1c45640a72300433800c8370657335616f8c541.tar.xz twinh-b1c45640a72300433800c8370657335616f8c541.zip |
replaced mongo with sled, added some basic functional google oauth2 code
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | src/handlers/mod.rs | 115 | ||||
-rw-r--r-- | src/main.rs | 13 | ||||
-rw-r--r-- | src/models/mod.rs | 7 | ||||
-rw-r--r-- | src/templates/mod.rs | 8 |
5 files changed, 126 insertions, 24 deletions
@@ -7,13 +7,14 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bincode = "1.3" env_logger = "0.8" handlebars = "3.5" hyper = { version = "0.14", default-features = false, features = ["full"] } +hyper-rustls = "0.22" log = "0.4" -mongodb = "1.2" once_cell = "1.7" -serde = "1.0" -serde_json = "1.0" +serde = { version = "1.0", features = ["derive"]} serde_urlencoded = "0.7" +sled = "0.34" tokio = { version = "1.2", default-features = false, features = ["full"] } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index efd99f5..1aba908 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,18 +1,18 @@ use crate::templates; use handlebars::Handlebars; +use hyper::body::HttpBody as _; use hyper::Method; use hyper::StatusCode; use hyper::{Body, Request, Response}; use serde::{Deserialize, Serialize}; use std::convert::Infallible; // TODO: -pub async fn router( - req: Request<Body>, - _client: mongodb::Client, -) -> Result<Response<Body>, Infallible> { +pub async fn router(req: Request<Body>) -> Result<Response<Body>, Infallible> { match (req.method(), req.uri().path()) { - (&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new("Welcome!".into())), - (&Method::GET, "/parts") | (&Method::GET, "/parts/index.html") => get_parts(req).await, + (&Method::GET, "/") | (&Method::GET, "/index.html") => index(req).await, + (&Method::GET, "/login") | (&Method::GET, "/login/index.html") => login().await, + (&Method::GET, "/login/google") => login_google().await, + (&Method::GET, "/login/google/code") => login_google_code(req).await, _ => Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body("Not found.".into()) @@ -20,7 +20,102 @@ pub async fn router( } } -async fn get_parts(req: Request<Body>) -> Result<Response<Body>, Infallible> { +async fn login() -> Result<Response<Body>, Infallible> { + Ok(Response::new(templates::LOGIN_T.into())) +} + +async fn login_google() -> Result<Response<Body>, Infallible> { + 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>, Infallible> { + 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 index(req: Request<Body>) -> Result<Response<Body>, Infallible> { let query = req.uri().query().unwrap_or_default(); let filter = serde_urlencoded::de::from_str::<PartsQuery>(query).unwrap(); let mut reg = Handlebars::new(); @@ -49,6 +144,12 @@ async fn get_parts(req: Request<Body>) -> Result<Response<Body>, Infallible> { } #[derive(Debug, Deserialize)] +struct GoogleOAuthQuery { + code: String, + state: String, +} + +#[derive(Debug, Deserialize)] struct PartsQuery { make: Option<String>, year: Option<String>, diff --git a/src/main.rs b/src/main.rs index a2af455..168a5f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,17 +13,8 @@ mod templates; async fn main() -> Result<(), Box<dyn std::error::Error>> { let addr = config::INSTANCE.addr; - let client = mongodb::Client::with_uri_str(&config::INSTANCE.db_uri).await?; - - let make_svc = make_service_fn(move |_conn| { - let client = client.clone(); - - async { - Ok::<_, Infallible>(service_fn(move |req| { - handlers::router(req, client.to_owned()) - })) - } - }); + let make_svc = + make_service_fn(move |_conn| async { Ok::<_, Infallible>(service_fn(handlers::router)) }); let server = Server::bind(&addr).serve(make_svc); let graceful = server.with_graceful_shutdown(shutdown_signal()); diff --git a/src/models/mod.rs b/src/models/mod.rs index 1a4d1df..5830a1b 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -2,12 +2,13 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Car { - year: u16, // I'll worry about this in 65534 AD. + doors: u8, + engine: Engine, make: String, model: String, - engine: Engine, - doors: u8, transmission: Transmission, + trim: String, + year: u16, // I'll worry about this in 65534 AD. } #[derive(Serialize, Deserialize)] diff --git a/src/templates/mod.rs b/src/templates/mod.rs index 1a594fb..3a6eb2b 100644 --- a/src/templates/mod.rs +++ b/src/templates/mod.rs @@ -1 +1,9 @@ pub static INDEX_T: &str = include_str!("index.html"); +pub static LOGIN_T: &str = include_str!("login.html"); +pub const CATALOG_L: &str = "/#menu"; +pub const PARTS_L: &str = "/parts"; +pub const PARTS_CSV_L: &str = "/parts.csv"; +pub const CARS_L: &str = "/cars"; +pub const CARS_CSV_L: &str = "/cars.csv"; +pub const SUGGESTIONS_L: &str = "/suggestions"; +pub const LOGIN_L: &str = "/login"; |